Implement serialization to GVariant.

This commit is contained in:
Daiki Ueno
2011-02-14 14:13:02 +09:00
parent 11026923bd
commit 7916930160
23 changed files with 774 additions and 396 deletions

View File

@ -82,7 +82,6 @@ eek_container_real_deserialize (EekSerializable *self,
GVariant *variant, GVariant *variant,
gsize index) gsize index)
{ {
EekContainerPrivate *priv = EEK_CONTAINER_GET_PRIVATE(self);
GVariant *array, *child; GVariant *array, *child;
GVariantIter iter; GVariantIter iter;
@ -94,9 +93,9 @@ eek_container_real_deserialize (EekSerializable *self,
g_variant_iter_init (&iter, array); g_variant_iter_init (&iter, array);
while (g_variant_iter_next (&iter, "v", &child)) { while (g_variant_iter_next (&iter, "v", &child)) {
EekSerializable *serializable = eek_serializable_deserialize (child); EekSerializable *serializable = eek_serializable_deserialize (child);
priv->children = g_slist_prepend (priv->children, serializable); eek_container_add_child (EEK_CONTAINER(self),
EEK_ELEMENT(serializable));
} }
priv->children = g_slist_reverse (priv->children);
return index; return index;
} }
@ -122,6 +121,7 @@ eek_container_real_add_child (EekContainer *self,
priv->children = g_slist_prepend (priv->children, child); priv->children = g_slist_prepend (priv->children, child);
eek_element_set_parent (child, EEK_ELEMENT(self)); eek_element_set_parent (child, EEK_ELEMENT(self));
g_signal_emit_by_name (self, "child-added", child);
} }
static void static void
@ -137,6 +137,7 @@ eek_container_real_remove_child (EekContainer *self,
g_object_unref (child); g_object_unref (child);
priv->children = g_slist_remove_link (priv->children, head); priv->children = g_slist_remove_link (priv->children, head);
eek_element_set_parent (child, NULL); eek_element_set_parent (child, NULL);
g_signal_emit_by_name (self, "child-removed", child);
} }
static void static void
@ -202,6 +203,10 @@ eek_container_class_init (EekContainerClass *klass)
klass->foreach_child = eek_container_real_foreach_child; klass->foreach_child = eek_container_real_foreach_child;
klass->find = eek_container_real_find; klass->find = eek_container_real_find;
/* signals */
klass->child_added = NULL;
klass->child_removed = NULL;
gobject_class->finalize = eek_container_finalize; gobject_class->finalize = eek_container_finalize;
gobject_class->dispose = eek_container_dispose; gobject_class->dispose = eek_container_dispose;
@ -290,3 +295,11 @@ eek_container_find (EekContainer *container,
func, func,
user_data); user_data);
} }
void
eek_container_add_child (EekContainer *container, EekElement *element)
{
g_return_if_fail (EEK_IS_CONTAINER(container));
g_return_if_fail (EEK_IS_ELEMENT(element));
return EEK_CONTAINER_GET_CLASS(container)->add_child (container, element);
}

View File

@ -81,14 +81,16 @@ struct _EekContainerClass
gpointer pdummy[24]; gpointer pdummy[24];
}; };
GType eek_container_get_type (void) G_GNUC_CONST; GType eek_container_get_type (void) G_GNUC_CONST;
void eek_container_foreach_child (EekContainer *container, void eek_container_foreach_child (EekContainer *container,
EekCallback callback, EekCallback callback,
gpointer user_data); gpointer user_data);
EekElement *eek_container_find (EekContainer *container, EekElement *eek_container_find (EekContainer *container,
EekCompareFunc func, EekCompareFunc func,
gpointer user_data); gpointer user_data);
void eek_container_add_child (EekContainer *container,
EekElement *element);
G_END_DECLS G_END_DECLS
#endif /* EEK_CONTAINER_H */ #endif /* EEK_CONTAINER_H */

View File

@ -89,7 +89,7 @@ eek_element_real_serialize (EekSerializable *self,
{ {
EekElementPrivate *priv = EEK_ELEMENT_GET_PRIVATE(self); EekElementPrivate *priv = EEK_ELEMENT_GET_PRIVATE(self);
g_variant_builder_add (builder, "s", priv->name); g_variant_builder_add (builder, "s", priv->name == NULL ? "" : priv->name);
g_variant_builder_add (builder, "v", _g_variant_new_bounds (&priv->bounds)); g_variant_builder_add (builder, "v", _g_variant_new_bounds (&priv->bounds));
} }

View File

@ -46,7 +46,7 @@ enum {
PROP_SYMBOL_MATRIX, PROP_SYMBOL_MATRIX,
PROP_COLUMN, PROP_COLUMN,
PROP_ROW, PROP_ROW,
PROP_OUTLINE, PROP_OREF,
PROP_LAST PROP_LAST
}; };
@ -74,7 +74,7 @@ struct _EekKeyPrivate
EekSymbolMatrix *symbol_matrix; EekSymbolMatrix *symbol_matrix;
gint column; gint column;
gint row; gint row;
EekOutline *outline; gulong oref;
gboolean is_pressed; gboolean is_pressed;
}; };
@ -86,23 +86,45 @@ _g_variant_new_symbol_matrix (EekSymbolMatrix *symbol_matrix)
GVariantBuilder builder, array; GVariantBuilder builder, array;
gint i, num_symbols = symbol_matrix->num_groups * symbol_matrix->num_levels; gint i, num_symbols = symbol_matrix->num_groups * symbol_matrix->num_levels;
g_variant_builder_init (&builder, G_VARIANT_TYPE ("iiav")); g_variant_builder_init (&builder, G_VARIANT_TYPE ("(iiv)"));
g_variant_builder_add (&builder, "i", symbol_matrix->num_groups); g_variant_builder_add (&builder, "i", symbol_matrix->num_groups);
g_variant_builder_add (&builder, "i", symbol_matrix->num_levels); g_variant_builder_add (&builder, "i", symbol_matrix->num_levels);
g_variant_builder_init (&array, G_VARIANT_TYPE ("av")); g_variant_builder_init (&array, G_VARIANT_TYPE ("av"));
for (i = 0; i < num_symbols; i++) { for (i = 0; i < num_symbols; i++) {
GVariant *symbol = eek_serializable_serialize GVariant *symbol = eek_serializable_serialize
(EEK_SERIALIZABLE(symbol_matrix->data[i])); (EEK_SERIALIZABLE(symbol_matrix->data[i]));
g_variant_builder_add (&builder, "v", symbol); g_variant_builder_add (&array, "v", symbol);
} }
g_variant_builder_add (&builder, "av", g_variant_builder_end (&array)); g_variant_builder_add (&builder, "v", g_variant_builder_end (&array));
return g_variant_builder_end (&builder); return g_variant_builder_end (&builder);
} }
static EekSymbolMatrix * static EekSymbolMatrix *
_g_variant_get_symbol_matrix (GVariant *variant) _g_variant_get_symbol_matrix (GVariant *variant)
{ {
g_return_val_if_reached (NULL); /* TODO */ gint num_groups, num_levels, i;
EekSymbolMatrix *symbol_matrix;
GVariant *array, *child;
GVariantIter iter;
g_variant_get_child (variant, 0, "i", &num_groups);
g_variant_get_child (variant, 1, "i", &num_levels);
symbol_matrix = eek_symbol_matrix_new (num_groups, num_levels);
g_variant_get_child (variant, 2, "v", &array);
g_variant_iter_init (&iter, array);
for (i = 0; i < num_groups * num_levels; i++) {
EekSerializable *serializable;
if (!g_variant_iter_next (&iter, "v", &child)) {
eek_symbol_matrix_free (symbol_matrix);
g_return_val_if_reached (NULL);
}
serializable = eek_serializable_deserialize (child);
symbol_matrix->data[i] = EEK_SYMBOL(serializable);
}
return symbol_matrix;
} }
static void static void
@ -118,6 +140,7 @@ eek_key_real_serialize (EekSerializable *self,
_g_variant_new_symbol_matrix (priv->symbol_matrix)); _g_variant_new_symbol_matrix (priv->symbol_matrix));
g_variant_builder_add (builder, "i", priv->column); g_variant_builder_add (builder, "i", priv->column);
g_variant_builder_add (builder, "i", priv->row); g_variant_builder_add (builder, "i", priv->row);
g_variant_builder_add (builder, "u", priv->oref);
} }
static gsize static gsize
@ -137,6 +160,7 @@ eek_key_real_deserialize (EekSerializable *self,
priv->symbol_matrix = _g_variant_get_symbol_matrix (symbol_matrix); priv->symbol_matrix = _g_variant_get_symbol_matrix (symbol_matrix);
g_variant_get_child (variant, index++, "i", &priv->column); g_variant_get_child (variant, index++, "i", &priv->column);
g_variant_get_child (variant, index++, "i", &priv->row); g_variant_get_child (variant, index++, "i", &priv->row);
g_variant_get_child (variant, index++, "u", &priv->oref);
return index; return index;
} }
@ -208,17 +232,17 @@ eek_key_real_get_index (EekKey *self,
} }
static void static void
eek_key_real_set_outline (EekKey *self, EekOutline *outline) eek_key_real_set_oref (EekKey *self, gulong oref)
{ {
EekKeyPrivate *priv = EEK_KEY_GET_PRIVATE(self); EekKeyPrivate *priv = EEK_KEY_GET_PRIVATE(self);
priv->outline = outline; priv->oref = oref;
} }
static EekOutline * static gulong
eek_key_real_get_outline (EekKey *self) eek_key_real_get_oref (EekKey *self)
{ {
EekKeyPrivate *priv = EEK_KEY_GET_PRIVATE(self); EekKeyPrivate *priv = EEK_KEY_GET_PRIVATE(self);
return priv->outline; return priv->oref;
} }
static gboolean static gboolean
@ -283,8 +307,8 @@ eek_key_set_property (GObject *object,
eek_key_get_index (EEK_KEY(object), &column, &row); eek_key_get_index (EEK_KEY(object), &column, &row);
eek_key_set_index (EEK_KEY(object), column, g_value_get_int (value)); eek_key_set_index (EEK_KEY(object), column, g_value_get_int (value));
break; break;
case PROP_OUTLINE: case PROP_OREF:
eek_key_set_outline (EEK_KEY(object), g_value_get_pointer (value)); eek_key_set_oref (EEK_KEY(object), g_value_get_uint (value));
break; break;
default: default:
g_object_set_property (object, g_object_set_property (object,
@ -319,8 +343,8 @@ eek_key_get_property (GObject *object,
eek_key_get_index (EEK_KEY(object), &column, &row); eek_key_get_index (EEK_KEY(object), &column, &row);
g_value_set_int (value, row); g_value_set_int (value, row);
break; break;
case PROP_OUTLINE: case PROP_OREF:
g_value_set_pointer (value, eek_key_get_outline (EEK_KEY(object))); g_value_set_uint (value, eek_key_get_oref (EEK_KEY(object)));
break; break;
default: default:
g_object_get_property (object, g_object_get_property (object,
@ -345,8 +369,8 @@ eek_key_class_init (EekKeyClass *klass)
klass->get_symbol_matrix = eek_key_real_get_symbol_matrix; klass->get_symbol_matrix = eek_key_real_get_symbol_matrix;
klass->set_index = eek_key_real_set_index; klass->set_index = eek_key_real_set_index;
klass->get_index = eek_key_real_get_index; klass->get_index = eek_key_real_get_index;
klass->set_outline = eek_key_real_set_outline; klass->set_oref = eek_key_real_set_oref;
klass->get_outline = eek_key_real_get_outline; klass->get_oref = eek_key_real_get_oref;
klass->is_pressed = eek_key_real_is_pressed; klass->is_pressed = eek_key_real_is_pressed;
gobject_class->set_property = eek_key_set_property; gobject_class->set_property = eek_key_set_property;
@ -406,18 +430,16 @@ eek_key_class_init (EekKeyClass *klass)
g_object_class_install_property (gobject_class, PROP_ROW, pspec); g_object_class_install_property (gobject_class, PROP_ROW, pspec);
/** /**
* EekKey:outline: * EekKey:oref:
* *
* The pointer to the outline shape of #EekKey. * The outline id of #EekKey.
*/ */
/* Use pointer instead of boxed to avoid copy, since we can pspec = g_param_spec_ulong ("oref",
assume that only a few outline shapes are used in a whole "Oref",
keyboard (unlike symbol matrix and bounds). */ "Outline id of the key",
pspec = g_param_spec_pointer ("outline", 0, G_MAXULONG, 0,
"Outline", G_PARAM_READWRITE);
"Pointer to outline shape of the key", g_object_class_install_property (gobject_class, PROP_OREF, pspec);
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_OUTLINE, pspec);
/** /**
* EekKey::pressed: * EekKey::pressed:
@ -463,7 +485,7 @@ eek_key_init (EekKey *self)
priv->keycode = 0; priv->keycode = 0;
priv->symbol_matrix = eek_symbol_matrix_new (0, 0); priv->symbol_matrix = eek_symbol_matrix_new (0, 0);
priv->column = priv->row = 0; priv->column = priv->row = 0;
priv->outline = NULL; priv->oref = 0;
} }
/** /**
@ -639,8 +661,7 @@ eek_key_get_symbol_at_index (EekKey *key,
* @column: column index of @key in #EekSection * @column: column index of @key in #EekSection
* @row: row index of @key in #EekSection * @row: row index of @key in #EekSection
* *
* Set the index of @key (i.e. logical location of @key in * Set the location of @key in #EekSection with @column and @row.
* #EekSection) to @column and @row.
*/ */
void void
eek_key_set_index (EekKey *key, eek_key_set_index (EekKey *key,
@ -657,8 +678,7 @@ eek_key_set_index (EekKey *key,
* @column: pointer where the column index of @key in #EekSection will be stored * @column: pointer where the column index of @key in #EekSection will be stored
* @row: pointer where the row index of @key in #EekSection will be stored * @row: pointer where the row index of @key in #EekSection will be stored
* *
* Get the index of @key (i.e. logical location of @key in * Get the location of @key in #EekSection.
* #EekSection).
*/ */
void void
eek_key_get_index (EekKey *key, eek_key_get_index (EekKey *key,
@ -670,32 +690,32 @@ eek_key_get_index (EekKey *key,
} }
/** /**
* eek_key_set_outline: * eek_key_set_oref:
* @key: an #EekKey * @key: an #EekKey
* @outline: outline of @key * @oref: outline id of @key
* *
* Set the outline shape of @key to @outline. * Set the outline id of @key to @oref.
*/ */
void void
eek_key_set_outline (EekKey *key, eek_key_set_oref (EekKey *key,
EekOutline *outline) gulong oref)
{ {
g_return_if_fail (EEK_IS_KEY(key)); g_return_if_fail (EEK_IS_KEY(key));
EEK_KEY_GET_CLASS(key)->set_outline (key, outline); EEK_KEY_GET_CLASS(key)->set_oref (key, oref);
} }
/** /**
* eek_key_get_outline: * eek_key_get_oref:
* @key: an #EekKey * @key: an #EekKey
* *
* Get the outline shape of @key. * Get the outline id of @key.
* Returns: an #EekOutline pointer or NULL on failure * Returns: a non-zero unsigned integer on success, 0 if the id is not set
*/ */
EekOutline * gulong
eek_key_get_outline (EekKey *key) eek_key_get_oref (EekKey *key)
{ {
g_return_val_if_fail (EEK_IS_KEY (key), NULL); g_return_val_if_fail (EEK_IS_KEY (key), 0);
return EEK_KEY_GET_CLASS(key)->get_outline (key); return EEK_KEY_GET_CLASS(key)->get_oref (key);
} }
/** /**

View File

@ -54,8 +54,8 @@ struct _EekKey
* section * section
* @get_index: virtual function for getting position of the key in the * @get_index: virtual function for getting position of the key in the
* section * section
* @set_outline: virtual function for setting outline shape of the key * @set_oref: virtual function for setting outline id of the key
* @get_outline: virtual function for getting outline shape of the key * @get_oref: virtual function for getting outline id of the key
* @pressed: class handler for #EekKey::pressed signal * @pressed: class handler for #EekKey::pressed signal
* @released: class handler for #EekKey::released signal * @released: class handler for #EekKey::released signal
* @is_pressed: virtual function for getting whether the key is pressed * @is_pressed: virtual function for getting whether the key is pressed
@ -80,9 +80,9 @@ struct _EekKeyClass
gint *column, gint *column,
gint *row); gint *row);
void (* set_outline) (EekKey *self, void (* set_oref) (EekKey *self,
EekOutline *outline); gulong oref);
EekOutline *(* get_outline) (EekKey *self); gulong (* get_oref) (EekKey *self);
gboolean (* is_pressed) (EekKey *self); gboolean (* is_pressed) (EekKey *self);
@ -104,7 +104,7 @@ void eek_key_set_symbol_matrix (EekKey *key,
EekSymbolMatrix *matrix); EekSymbolMatrix *matrix);
EekSymbolMatrix *eek_key_get_symbol_matrix (EekKey *key); EekSymbolMatrix *eek_key_get_symbol_matrix (EekKey *key);
EekSymbol *eek_key_get_symbol (EekKey *key); EekSymbol *eek_key_get_symbol (EekKey *key);
EekSymbol * eek_key_get_symbol_with_fallback EekSymbol *eek_key_get_symbol_with_fallback
(EekKey *key, (EekKey *key,
gint fallback_group, gint fallback_group,
gint fallback_level); gint fallback_level);
@ -121,9 +121,9 @@ void eek_key_get_index (EekKey *key,
gint *column, gint *column,
gint *row); gint *row);
void eek_key_set_outline (EekKey *key, void eek_key_set_oref (EekKey *key,
EekOutline *outline); gulong oref);
EekOutline *eek_key_get_outline (EekKey *key); gulong eek_key_get_oref (EekKey *key);
gboolean eek_key_is_pressed (EekKey *key); gboolean eek_key_is_pressed (EekKey *key);

View File

@ -36,6 +36,7 @@
#include "eek-key.h" #include "eek-key.h"
#include "eek-symbol.h" #include "eek-symbol.h"
#include "eek-marshalers.h" #include "eek-marshalers.h"
#include "eek-serializable.h"
enum { enum {
PROP_0, PROP_0,
@ -55,7 +56,11 @@ enum {
static guint signals[LAST_SIGNAL] = { 0, }; static guint signals[LAST_SIGNAL] = { 0, };
G_DEFINE_TYPE (EekKeyboard, eek_keyboard, EEK_TYPE_CONTAINER); static void eek_serializable_iface_init (EekSerializableIface *iface);
G_DEFINE_TYPE_WITH_CODE (EekKeyboard, eek_keyboard, EEK_TYPE_CONTAINER,
G_IMPLEMENT_INTERFACE (EEK_TYPE_SERIALIZABLE,
eek_serializable_iface_init));
#define EEK_KEYBOARD_GET_PRIVATE(obj) \ #define EEK_KEYBOARD_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_KEYBOARD, EekKeyboardPrivate)) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_KEYBOARD, EekKeyboardPrivate))
@ -68,8 +73,117 @@ struct _EekKeyboardPrivate
EekLayout *layout; EekLayout *layout;
EekModifierBehavior modifier_behavior; EekModifierBehavior modifier_behavior;
EekModifierType modifiers; EekModifierType modifiers;
GArray *outline_array;
}; };
static EekSerializableIface *eek_keyboard_parent_serializable_iface;
static GVariant *_g_variant_new_outline (EekOutline *outline);
static EekOutline *_g_variant_get_outline (GVariant *variant);
static GVariant *
_g_variant_new_outline (EekOutline *outline)
{
GVariantBuilder builder, array;
gint i;
g_variant_builder_init (&builder, G_VARIANT_TYPE ("(div)"));
g_variant_builder_add (&builder, "d", outline->corner_radius);
g_variant_builder_add (&builder, "i", outline->num_points);
g_variant_builder_init (&array, G_VARIANT_TYPE ("a(dd)"));
for (i = 0; i < outline->num_points; i++)
g_variant_builder_add (&array,
"(dd)",
outline->points[i].x,
outline->points[i].y);
g_variant_builder_add (&builder, "v", g_variant_builder_end (&array));
return g_variant_builder_end (&builder);
}
static EekOutline *
_g_variant_get_outline (GVariant *variant)
{
EekOutline *outline;
GVariant *array;
GVariantIter iter;
gdouble x, y;
gint i;
outline = g_slice_new0 (EekOutline);
g_variant_get_child (variant, 0, "d", &outline->corner_radius);
g_variant_get_child (variant, 1, "i", &outline->num_points);
outline->points = g_slice_alloc0 (sizeof (EekPoint) * outline->num_points);
g_variant_get_child (variant, 2, "v", &array);
g_variant_iter_init (&iter, array);
for (i = 0; i < outline->num_points; i++) {
if (!g_variant_iter_next (&iter, "(dd)", &x, &y)) {
eek_outline_free (outline);
g_return_val_if_reached (NULL);
}
outline->points[i].x = x;
outline->points[i].y = y;
}
return outline;
}
static void
eek_keyboard_real_serialize (EekSerializable *self,
GVariantBuilder *builder)
{
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(self);
GVariantBuilder array;
guint i;
eek_keyboard_parent_serializable_iface->serialize (self, builder);
g_variant_builder_init (&array, G_VARIANT_TYPE ("av"));
for (i = 0; i < priv->outline_array->len; i++) {
EekOutline *outline =
eek_keyboard_get_outline (EEK_KEYBOARD(self), i + 1);
g_variant_builder_add (&array, "v",
_g_variant_new_outline (outline));
}
g_variant_builder_add (builder, "v", g_variant_builder_end (&array));
}
static gsize
eek_keyboard_real_deserialize (EekSerializable *self,
GVariant *variant,
gsize index)
{
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(self);
GVariant *array, *outline;
GVariantIter iter;
index = eek_keyboard_parent_serializable_iface->deserialize (self,
variant,
index);
g_variant_get_child (variant, index++, "v", &array);
g_variant_iter_init (&iter, array);
while (g_variant_iter_next (&iter, "v", &outline)) {
EekOutline *_outline = _g_variant_get_outline (outline);
g_array_append_val (priv->outline_array, *_outline);
}
return index;
}
static void
eek_serializable_iface_init (EekSerializableIface *iface)
{
eek_keyboard_parent_serializable_iface =
g_type_interface_peek_parent (iface);
iface->serialize = eek_keyboard_real_serialize;
iface->deserialize = eek_keyboard_real_deserialize;
}
static void static void
eek_keyboard_real_set_symbol_index (EekKeyboard *self, eek_keyboard_real_set_symbol_index (EekKeyboard *self,
gint group, gint group,
@ -123,11 +237,6 @@ eek_keyboard_real_create_section (EekKeyboard *self)
section = g_object_new (EEK_TYPE_SECTION, NULL); section = g_object_new (EEK_TYPE_SECTION, NULL);
g_return_val_if_fail (section, NULL); g_return_val_if_fail (section, NULL);
g_signal_connect (section, "key-pressed",
G_CALLBACK(on_key_pressed), self);
g_signal_connect (section, "key-released",
G_CALLBACK(on_key_released), self);
EEK_CONTAINER_GET_CLASS(self)->add_child (EEK_CONTAINER(self), EEK_CONTAINER_GET_CLASS(self)->add_child (EEK_CONTAINER(self),
EEK_ELEMENT(section)); EEK_ELEMENT(section));
return section; return section;
@ -318,9 +427,46 @@ eek_keyboard_dispose (GObject *object)
G_OBJECT_CLASS (eek_keyboard_parent_class)->dispose (object); G_OBJECT_CLASS (eek_keyboard_parent_class)->dispose (object);
} }
static void
eek_keyboard_finalize (GObject *object)
{
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(object);
gint i;
for (i = 0; i < priv->outline_array->len; i++) {
EekOutline *outline = &g_array_index (priv->outline_array,
EekOutline,
i);
g_slice_free1 (sizeof (EekPoint) * outline->num_points,
outline->points);
}
g_array_free (priv->outline_array, TRUE);
G_OBJECT_CLASS (eek_keyboard_parent_class)->finalize (object);
}
static void
eek_keyboard_real_child_added (EekContainer *self,
EekElement *element)
{
g_signal_connect (element, "key-pressed",
G_CALLBACK(on_key_pressed), self);
g_signal_connect (element, "key-released",
G_CALLBACK(on_key_released), self);
}
static void
eek_keyboard_real_child_removed (EekContainer *self,
EekElement *element)
{
g_signal_handlers_disconnect_by_func (element, on_key_pressed, self);
g_signal_handlers_disconnect_by_func (element, on_key_released, self);
}
static void static void
eek_keyboard_class_init (EekKeyboardClass *klass) eek_keyboard_class_init (EekKeyboardClass *klass)
{ {
EekContainerClass *container_class = EEK_CONTAINER_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec; GParamSpec *pspec;
@ -337,9 +483,13 @@ eek_keyboard_class_init (EekKeyboardClass *klass)
klass->key_released = eek_keyboard_real_key_released; klass->key_released = eek_keyboard_real_key_released;
klass->symbol_index_changed = eek_keyboard_real_symbol_index_changed; klass->symbol_index_changed = eek_keyboard_real_symbol_index_changed;
container_class->child_added = eek_keyboard_real_child_added;
container_class->child_removed = eek_keyboard_real_child_removed;
gobject_class->get_property = eek_keyboard_get_property; gobject_class->get_property = eek_keyboard_get_property;
gobject_class->set_property = eek_keyboard_set_property; gobject_class->set_property = eek_keyboard_set_property;
gobject_class->dispose = eek_keyboard_dispose; gobject_class->dispose = eek_keyboard_dispose;
gobject_class->finalize = eek_keyboard_finalize;
/** /**
* EekKeyboard:group: * EekKeyboard:group:
@ -470,6 +620,7 @@ eek_keyboard_init (EekKeyboard *self)
priv->layout = NULL; priv->layout = NULL;
priv->modifier_behavior = EEK_MODIFIER_BEHAVIOR_NONE; priv->modifier_behavior = EEK_MODIFIER_BEHAVIOR_NONE;
priv->modifiers = 0; priv->modifiers = 0;
priv->outline_array = g_array_new (FALSE, TRUE, sizeof (EekOutline));
} }
/** /**
@ -692,3 +843,49 @@ eek_keyboard_get_modifiers (EekKeyboard *keyboard)
return priv->modifiers; return priv->modifiers;
} }
/**
* eek_keyboard_add_outline:
* @keyboard: an #EekKeyboard
* @outline: an #EekOutline
*
* Register an outline of @keyboard.
* Returns: an unsigned long id of the registered outline, for later reference
*/
gulong
eek_keyboard_add_outline (EekKeyboard *keyboard,
EekOutline *outline)
{
EekKeyboardPrivate *priv;
EekOutline *_outline;
g_assert (EEK_IS_KEYBOARD(keyboard));
priv = EEK_KEYBOARD_GET_PRIVATE(keyboard);
_outline = eek_outline_copy (outline);
g_array_append_val (priv->outline_array, *_outline);
return priv->outline_array->len;
}
/**
* eek_keyboard_get_outline:
* @keyboard: an #EekKeyboard
* @oref: an unsigned long id
*
* Get an outline associated with @oref in @keyboard.
* Returns: an #EekOutline, which should not be released
*/
EekOutline *
eek_keyboard_get_outline (EekKeyboard *keyboard,
gulong oref)
{
EekKeyboardPrivate *priv;
g_assert (EEK_IS_KEYBOARD(keyboard));
priv = EEK_KEYBOARD_GET_PRIVATE(keyboard);
if (oref > priv->outline_array->len)
return NULL;
return &g_array_index (priv->outline_array, EekOutline, oref - 1);
}

View File

@ -102,6 +102,10 @@ void eek_keyboard_get_size
(EekKeyboard *keyboard, (EekKeyboard *keyboard,
gdouble *width, gdouble *width,
gdouble *height); gdouble *height);
void eek_keyboard_set_size
(EekKeyboard *keyboard,
gdouble width,
gdouble height);
void eek_keyboard_set_symbol_index void eek_keyboard_set_symbol_index
(EekKeyboard *keyboard, (EekKeyboard *keyboard,
gint group, gint group,
@ -137,5 +141,13 @@ EekKey *eek_keyboard_find_key_by_keycode
(EekKeyboard *keyboard, (EekKeyboard *keyboard,
guint keycode); guint keycode);
gulong eek_keyboard_add_outline
(EekKeyboard *keyboard,
EekOutline *outline);
EekOutline *eek_keyboard_get_outline
(EekKeyboard *keyboard,
gulong oref);
G_END_DECLS G_END_DECLS
#endif /* EEK_KEYBOARD_H */ #endif /* EEK_KEYBOARD_H */

View File

@ -31,6 +31,7 @@
#endif /* HAVE_CONFIG_H */ #endif /* HAVE_CONFIG_H */
#include "eek-keysym.h" #include "eek-keysym.h"
#include "eek-serializable.h"
/* modifier keys */ /* modifier keys */
#define EEK_KEYSYM_Shift_L 0xffe1 #define EEK_KEYSYM_Shift_L 0xffe1
@ -51,27 +52,68 @@
struct _EekKeysymPrivate { struct _EekKeysymPrivate {
guint xkeysym; guint xkeysym;
};
struct _EekKeysymEntry {
guint xkeysym;
const gchar *name; const gchar *name;
EekSymbolCategory category; EekSymbolCategory category;
}; };
typedef EekKeysymPrivate EekKeysymEntry; typedef struct _EekKeysymEntry EekKeysymEntry;
#include "eek-special-keysym-entries.h" #include "eek-special-keysym-entries.h"
#include "eek-unicode-keysym-entries.h" #include "eek-unicode-keysym-entries.h"
#include "eek-xkeysym-keysym-entries.h" #include "eek-xkeysym-keysym-entries.h"
static const EekKeysymEntry invalid_keysym_entry = { static void eek_serializable_iface_init (EekSerializableIface *iface);
EEK_INVALID_KEYSYM,
"\0",
EEK_SYMBOL_CATEGORY_UNKNOWN,
};
G_DEFINE_TYPE (EekKeysym, eek_keysym, EEK_TYPE_SYMBOL); G_DEFINE_TYPE_WITH_CODE (EekKeysym, eek_keysym, EEK_TYPE_SYMBOL,
G_IMPLEMENT_INTERFACE (EEK_TYPE_SERIALIZABLE,
eek_serializable_iface_init));
#define EEK_KEYSYM_GET_PRIVATE(obj) \ #define EEK_KEYSYM_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_KEYSYM, EekKeysymPrivate)) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_KEYSYM, EekKeysymPrivate))
static EekSerializableIface *eek_keysym_parent_serializable_iface;
static void
eek_keysym_real_serialize (EekSerializable *self,
GVariantBuilder *builder)
{
EekKeysymPrivate *priv = EEK_KEYSYM_GET_PRIVATE(self);
eek_keysym_parent_serializable_iface->serialize (self, builder);
g_variant_builder_add (builder, "u", priv->xkeysym);
}
static gsize
eek_keysym_real_deserialize (EekSerializable *self,
GVariant *variant,
gsize index)
{
EekKeysymPrivate *priv = EEK_KEYSYM_GET_PRIVATE(self);
index = eek_keysym_parent_serializable_iface->deserialize (self,
variant,
index);
g_variant_get_child (variant, index++, "u", &priv->xkeysym);
return index;
}
static void
eek_serializable_iface_init (EekSerializableIface *iface)
{
eek_keysym_parent_serializable_iface =
g_type_interface_peek_parent (iface);
iface->serialize = eek_keysym_real_serialize;
iface->deserialize = eek_keysym_real_deserialize;
}
static gchar * static gchar *
unichar_to_utf8 (gunichar uc) unichar_to_utf8 (gunichar uc)
{ {
@ -91,7 +133,7 @@ static int
keysym_entry_compare_by_xkeysym (const void *key0, const void *key1) keysym_entry_compare_by_xkeysym (const void *key0, const void *key1)
{ {
const EekKeysymEntry *entry0 = key0, *entry1 = key1; const EekKeysymEntry *entry0 = key0, *entry1 = key1;
return (gint)entry0->xkeysym - (gint)entry1->xkeysym; return (gint) (entry0->xkeysym - entry1->xkeysym);
} }
static EekKeysymEntry * static EekKeysymEntry *
@ -103,14 +145,7 @@ find_keysym_entry_by_xkeysym (guint xkeysym,
key.xkeysym = xkeysym; key.xkeysym = xkeysym;
return bsearch (&key, entries, num_entries, sizeof (EekKeysymEntry), return bsearch (&key, entries, num_entries, sizeof (EekKeysymEntry),
keysym_entry_compare_by_xkeysym); keysym_entry_compare_by_xkeysym);
}
static G_CONST_RETURN gchar *
eek_keysym_real_get_name (EekSymbol *self)
{
EekKeysymPrivate *priv = EEK_KEYSYM_GET_PRIVATE(self);
return priv->name;
} }
static gboolean static gboolean
@ -132,46 +167,10 @@ get_unichar (guint xkeysym, gunichar *uc) {
return FALSE; return FALSE;
} }
static gchar * G_INLINE_FUNC EekModifierType
eek_keysym_real_get_label (EekSymbol *self) get_modifier_mask (guint xkeysym)
{ {
EekKeysymPrivate *priv = EEK_KEYSYM_GET_PRIVATE(self); switch (xkeysym) {
EekKeysymEntry *entry;
gunichar uc;
/* First, search special keysyms. */
entry = find_keysym_entry_by_xkeysym (priv->xkeysym,
special_keysym_entries,
G_N_ELEMENTS(special_keysym_entries));
if (entry)
return g_strdup (entry->name);
if (get_unichar (priv->xkeysym, &uc))
return unichar_to_utf8 (uc);
/* Search known unicode keysyms. */
entry = find_keysym_entry_by_xkeysym (priv->xkeysym,
unicode_keysym_entries,
G_N_ELEMENTS(unicode_keysym_entries));
if (entry)
return g_strdup (entry->name);
return g_strdup (eek_symbol_get_name (self));
}
EekSymbolCategory
eek_keysym_real_get_category (EekSymbol *self)
{
EekKeysymPrivate *priv = EEK_KEYSYM_GET_PRIVATE(self);
return priv->category;
}
EekModifierType
eek_keysym_real_get_modifier_mask (EekSymbol *self)
{
EekKeysymPrivate *priv = EEK_KEYSYM_GET_PRIVATE(self);
switch (priv->xkeysym) {
case EEK_KEYSYM_Shift_L: case EEK_KEYSYM_Shift_L:
case EEK_KEYSYM_Shift_R: case EEK_KEYSYM_Shift_R:
case EEK_KEYSYM_Caps_Lock: case EEK_KEYSYM_Caps_Lock:
@ -201,15 +200,9 @@ eek_keysym_real_get_modifier_mask (EekSymbol *self)
static void static void
eek_keysym_class_init (EekKeysymClass *klass) eek_keysym_class_init (EekKeysymClass *klass)
{ {
EekSymbolClass *symbol_class = EEK_SYMBOL_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
g_type_class_add_private (gobject_class, sizeof (EekKeysymPrivate)); g_type_class_add_private (gobject_class, sizeof (EekKeysymPrivate));
symbol_class->get_name = eek_keysym_real_get_name;
symbol_class->get_label = eek_keysym_real_get_label;
symbol_class->get_category = eek_keysym_real_get_category;
symbol_class->get_modifier_mask = eek_keysym_real_get_modifier_mask;
} }
static void static void
@ -218,7 +211,7 @@ eek_keysym_init (EekKeysym *self)
EekKeysymPrivate *priv; EekKeysymPrivate *priv;
priv = self->priv = EEK_KEYSYM_GET_PRIVATE(self); priv = self->priv = EEK_KEYSYM_GET_PRIVATE(self);
memcpy (priv, &invalid_keysym_entry, sizeof (EekKeysymEntry)); priv->xkeysym = EEK_INVALID_KEYSYM;
} }
EekKeysym * EekKeysym *
@ -226,33 +219,77 @@ eek_keysym_new (guint xkeysym)
{ {
EekKeysym *keysym; EekKeysym *keysym;
EekKeysymPrivate *priv; EekKeysymPrivate *priv;
EekKeysymEntry *entry; EekKeysymEntry *special_entry, *xkeysym_entry, *unicode_entry,
*unichar_entry;
gchar *name, *label;
EekSymbolCategory category;
EekModifierType modifier_mask;
gunichar uc;
keysym = g_object_new (EEK_TYPE_KEYSYM, NULL); special_entry =
priv = EEK_KEYSYM_GET_PRIVATE(keysym); find_keysym_entry_by_xkeysym (xkeysym,
priv->xkeysym = xkeysym; special_keysym_entries,
G_N_ELEMENTS(special_keysym_entries));
/* First check the X standard keysyms */ xkeysym_entry =
entry = find_keysym_entry_by_xkeysym (xkeysym, find_keysym_entry_by_xkeysym (xkeysym,
xkeysym_keysym_entries, xkeysym_keysym_entries,
G_N_ELEMENTS(xkeysym_keysym_entries)); G_N_ELEMENTS(xkeysym_keysym_entries));
if (!entry) { unicode_entry =
gunichar uc; find_keysym_entry_by_xkeysym (xkeysym,
unicode_keysym_entries,
/* Check the special unicode mappings */ G_N_ELEMENTS(unicode_keysym_entries));
if (get_unichar (priv->xkeysym, &uc)) { unichar_entry = NULL;
priv->category = EEK_SYMBOL_CATEGORY_LETTER; if (get_unichar (xkeysym, &uc)) {
return keysym; unichar_entry = g_slice_new (EekKeysymEntry);
} unichar_entry->xkeysym = xkeysym;
unichar_entry->name = unichar_to_utf8 (uc);
entry = find_keysym_entry_by_xkeysym unichar_entry->category = EEK_SYMBOL_CATEGORY_LETTER;
(priv->xkeysym,
unicode_keysym_entries,
G_N_ELEMENTS(unicode_keysym_entries));
} }
if (entry) /* name and category */
memcpy (priv, entry, sizeof (EekKeysymEntry)); name = NULL;
if (xkeysym_entry) {
name = g_strdup (xkeysym_entry->name);
category = xkeysym_entry->category;
} else if (unichar_entry) {
name = g_strdup (unichar_entry->name);
category = unichar_entry->category;
} else if (unicode_entry) {
name = g_strdup (unicode_entry->name);
category = unicode_entry->category;
} else {
name = g_strdup ("");
category = EEK_SYMBOL_CATEGORY_UNKNOWN;
}
/* label */
if (special_entry)
label = g_strdup (special_entry->name);
else if (unichar_entry)
label = g_strdup (unichar_entry->name);
else if (unicode_entry)
label = g_strdup (unicode_entry->name);
else
label = g_strdup (name);
modifier_mask = get_modifier_mask (xkeysym);
keysym = g_object_new (EEK_TYPE_KEYSYM,
"name", name,
"label", label,
"category", category,
"modifier-mask", modifier_mask,
NULL);
g_free (name);
g_free (label);
if (unichar_entry) {
g_free ((gpointer) unichar_entry->name);
g_slice_free (EekKeysymEntry, unichar_entry);
}
priv = EEK_KEYSYM_GET_PRIVATE(keysym);
priv->xkeysym = xkeysym;
return keysym; return keysym;
} }
@ -260,25 +297,19 @@ eek_keysym_new (guint xkeysym)
EekKeysym * EekKeysym *
eek_keysym_new_from_name (const gchar *name) eek_keysym_new_from_name (const gchar *name)
{ {
EekKeysym *keysym;
EekKeysymPrivate *priv;
gint i; gint i;
for (i = 0; for (i = 0; i < G_N_ELEMENTS(xkeysym_keysym_entries); i++)
i < G_N_ELEMENTS(xkeysym_keysym_entries) && if (g_strcmp0 (xkeysym_keysym_entries[i].name, name) == 0)
g_strcmp0 (xkeysym_keysym_entries[i].name, name) != 0; i++) return eek_keysym_new (xkeysym_keysym_entries[i].xkeysym);
;
keysym = g_object_new (EEK_TYPE_KEYSYM, NULL); // g_warning ("can't find keysym entry for %s", name);
priv = EEK_KEYSYM_GET_PRIVATE(keysym); return g_object_new (EEK_TYPE_KEYSYM,
"name", name,
if (i < G_N_ELEMENTS(xkeysym_keysym_entries)) "label", name,
memcpy (priv, &xkeysym_keysym_entries[i], sizeof (EekKeysymEntry)); "category", EEK_SYMBOL_CATEGORY_UNKNOWN,
else { "modifier-mask", 0,
// g_warning ("can't find keysym entry for %s", name); NULL);
memcpy (priv, &invalid_keysym_entry, sizeof (EekKeysymEntry));
}
return keysym;
} }
guint guint

View File

@ -184,9 +184,9 @@ render_key_outline (EekRenderer *renderer,
EekOutline *outline; EekOutline *outline;
EekBounds bounds; EekBounds bounds;
cairo_pattern_t *pat; cairo_pattern_t *pat;
EekPoint *points;
gdouble scale; gdouble scale;
gint i; gint i;
gulong oref;
/* need to rescale so that the border fit inside the clipping /* need to rescale so that the border fit inside the clipping
region */ region */
@ -194,12 +194,15 @@ render_key_outline (EekRenderer *renderer,
scale = MIN((bounds.width - priv->border_width) / bounds.width, scale = MIN((bounds.width - priv->border_width) / bounds.width,
(bounds.height - priv->border_width) / bounds.height); (bounds.height - priv->border_width) / bounds.height);
outline = eek_key_get_outline (key); oref = eek_key_get_oref (key);
points = g_slice_copy (sizeof (EekPoint) * outline->num_points, if (oref == 0)
outline->points); return;
outline = eek_keyboard_get_outline (priv->keyboard, oref);
outline = eek_outline_copy (outline);
for (i = 0; i < outline->num_points; i++) { for (i = 0; i < outline->num_points; i++) {
points[i].x *= priv->scale * scale; outline->points[i].x *= priv->scale * scale;
points[i].y *= priv->scale * scale; outline->points[i].y *= priv->scale * scale;
} }
cairo_translate (cr, cairo_translate (cr,
@ -227,7 +230,7 @@ render_key_outline (EekRenderer *renderer,
cairo_set_source (cr, pat); cairo_set_source (cr, pat);
_eek_rounded_polygon (cr, _eek_rounded_polygon (cr,
outline->corner_radius, outline->corner_radius,
points, outline->points,
outline->num_points); outline->num_points);
cairo_fill (cr); cairo_fill (cr);
@ -246,11 +249,11 @@ render_key_outline (EekRenderer *renderer,
_eek_rounded_polygon (cr, _eek_rounded_polygon (cr,
outline->corner_radius, outline->corner_radius,
points, outline->points,
outline->num_points); outline->num_points);
cairo_stroke (cr); cairo_stroke (cr);
g_slice_free1 (sizeof (EekPoint) * outline->num_points, points); eek_outline_free (outline);
} }
struct _CalculateFontSizeCallbackData { struct _CalculateFontSizeCallbackData {
@ -338,6 +341,20 @@ calculate_font_size (EekRenderer *renderer)
return data.size > 0 ? data.size : data.em_size; return data.size > 0 ? data.size : data.em_size;
} }
static EekKeyboard *
get_keyboard (EekKey *key)
{
EekElement *parent;
parent = eek_element_get_parent (EEK_ELEMENT(key));
g_return_val_if_fail (EEK_IS_SECTION(parent), NULL);
parent = eek_element_get_parent (parent);
g_return_val_if_fail (EEK_IS_KEYBOARD(parent), NULL);
return EEK_KEYBOARD(parent);
}
static void static void
render_key (EekRenderer *self, render_key (EekRenderer *self,
cairo_t *cr, cairo_t *cr,
@ -349,10 +366,16 @@ render_key (EekRenderer *self,
EekBounds bounds; EekBounds bounds;
PangoLayout *layout; PangoLayout *layout;
PangoRectangle extents = { 0, }; PangoRectangle extents = { 0, };
gulong oref;
EekKeyboard *keyboard;
eek_element_get_bounds (EEK_ELEMENT(key), &bounds); eek_element_get_bounds (EEK_ELEMENT(key), &bounds);
outline = eek_key_get_outline (key); oref = eek_key_get_oref (key);
if (oref == 0)
return;
keyboard = get_keyboard (key);
outline = eek_keyboard_get_outline (keyboard, oref);
outline_surface = g_hash_table_lookup (priv->outline_surface_cache, outline_surface = g_hash_table_lookup (priv->outline_surface_cache,
outline); outline);
if (!outline_surface) { if (!outline_surface) {

View File

@ -34,6 +34,7 @@
#endif /* HAVE_CONFIG_H */ #endif /* HAVE_CONFIG_H */
#include "eek-section.h" #include "eek-section.h"
#include "eek-key.h" #include "eek-key.h"
#include "eek-serializable.h"
enum { enum {
PROP_0, PROP_0,
@ -49,7 +50,11 @@ enum {
static guint signals[LAST_SIGNAL] = { 0, }; static guint signals[LAST_SIGNAL] = { 0, };
G_DEFINE_TYPE (EekSection, eek_section, EEK_TYPE_CONTAINER); static void eek_serializable_iface_init (EekSerializableIface *iface);
G_DEFINE_TYPE_WITH_CODE (EekSection, eek_section, EEK_TYPE_CONTAINER,
G_IMPLEMENT_INTERFACE (EEK_TYPE_SERIALIZABLE,
eek_serializable_iface_init));
#define EEK_SECTION_GET_PRIVATE(obj) \ #define EEK_SECTION_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_SECTION, EekSectionPrivate)) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_SECTION, EekSectionPrivate))
@ -66,9 +71,82 @@ struct _EekSectionPrivate
{ {
gint angle; gint angle;
GSList *rows; GSList *rows;
GSList *keys;
}; };
static EekSerializableIface *eek_section_parent_serializable_iface;
static GVariant *
_g_variant_new_row (EekRow *row)
{
GVariantBuilder builder;
g_variant_builder_init (&builder, G_VARIANT_TYPE ("(iu)"));
g_variant_builder_add (&builder, "i", row->num_columns);
g_variant_builder_add (&builder, "u", row->orientation);
return g_variant_builder_end (&builder);
}
static EekRow *
_g_variant_get_row (GVariant *variant)
{
EekRow *row = g_slice_new (EekRow);
g_variant_get_child (variant, 0, "i", &row->num_columns);
g_variant_get_child (variant, 1, "u", &row->orientation);
return row;
}
static void
eek_section_real_serialize (EekSerializable *self,
GVariantBuilder *builder)
{
EekSectionPrivate *priv = EEK_SECTION_GET_PRIVATE(self);
GSList *head;
GVariantBuilder array;
eek_section_parent_serializable_iface->serialize (self, builder);
g_variant_builder_add (builder, "i", priv->angle);
g_variant_builder_init (&array, G_VARIANT_TYPE("av"));
for (head = priv->rows; head; head = g_slist_next (head))
g_variant_builder_add (&array, "v", _g_variant_new_row (head->data));
g_variant_builder_add (builder, "v", g_variant_builder_end (&array));
}
static gsize
eek_section_real_deserialize (EekSerializable *self,
GVariant *variant,
gsize index)
{
EekSectionPrivate *priv = EEK_SECTION_GET_PRIVATE(self);
GVariant *array, *child;
GVariantIter iter;
index = eek_section_parent_serializable_iface->deserialize (self,
variant,
index);
g_variant_get_child (variant, index++, "i", &priv->angle);
g_variant_get_child (variant, index++, "v", &array);
g_variant_iter_init (&iter, array);
while (g_variant_iter_next (&iter, "v", &child))
priv->rows = g_slist_prepend (priv->rows, _g_variant_get_row (child));
priv->rows = g_slist_reverse (priv->rows);
return index;
}
static void
eek_serializable_iface_init (EekSerializableIface *iface)
{
eek_section_parent_serializable_iface =
g_type_interface_peek_parent (iface);
iface->serialize = eek_section_real_serialize;
iface->deserialize = eek_section_real_deserialize;
}
static void static void
eek_section_real_set_angle (EekSection *self, eek_section_real_set_angle (EekSection *self,
gint angle) gint angle)
@ -161,9 +239,6 @@ eek_section_real_create_key (EekSection *self,
NULL); NULL);
g_return_val_if_fail (key, NULL); g_return_val_if_fail (key, NULL);
g_signal_connect (key, "pressed", G_CALLBACK(on_pressed), self);
g_signal_connect (key, "released", G_CALLBACK(on_released), self);
EEK_CONTAINER_GET_CLASS(self)->add_child (EEK_CONTAINER(self), EEK_CONTAINER_GET_CLASS(self)->add_child (EEK_CONTAINER(self),
EEK_ELEMENT(key)); EEK_ELEMENT(key));
@ -237,9 +312,26 @@ eek_section_get_property (GObject *object,
} }
} }
static void
eek_section_real_child_added (EekContainer *self,
EekElement *element)
{
g_signal_connect (element, "pressed", G_CALLBACK(on_pressed), self);
g_signal_connect (element, "released", G_CALLBACK(on_released), self);
}
static void
eek_section_real_child_removed (EekContainer *self,
EekElement *element)
{
g_signal_handlers_disconnect_by_func (element, on_pressed, self);
g_signal_handlers_disconnect_by_func (element, on_released, self);
}
static void static void
eek_section_class_init (EekSectionClass *klass) eek_section_class_init (EekSectionClass *klass)
{ {
EekContainerClass *container_class = EEK_CONTAINER_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec; GParamSpec *pspec;
@ -253,6 +345,10 @@ eek_section_class_init (EekSectionClass *klass)
klass->create_key = eek_section_real_create_key; klass->create_key = eek_section_real_create_key;
klass->find_key_by_keycode = eek_section_real_find_key_by_keycode; klass->find_key_by_keycode = eek_section_real_find_key_by_keycode;
/* signals */
container_class->child_added = eek_section_real_child_added;
container_class->child_removed = eek_section_real_child_removed;
gobject_class->set_property = eek_section_set_property; gobject_class->set_property = eek_section_set_property;
gobject_class->get_property = eek_section_get_property; gobject_class->get_property = eek_section_get_property;
gobject_class->finalize = eek_section_finalize; gobject_class->finalize = eek_section_finalize;

View File

@ -53,23 +53,27 @@ eek_serializable_serialize (EekSerializable *object)
EekSerializable * EekSerializable *
eek_serializable_deserialize (GVariant *variant) eek_serializable_deserialize (GVariant *variant)
{ {
GVariant *var = NULL;
gchar *type_name = NULL; gchar *type_name = NULL;
GType type; GType type;
EekSerializable *object; EekSerializable *object;
gsize index = 0;
g_return_val_if_fail (variant != NULL, NULL); g_return_val_if_fail (variant != NULL, NULL);
g_variant_get_child (var, 0, "&s", &type_name); g_variant_get_child (variant, index++, "&s", &type_name);
type = g_type_from_name (type_name); type = g_type_from_name (type_name);
g_return_val_if_fail (g_type_is_a (type, EEK_TYPE_SERIALIZABLE), NULL); g_return_val_if_fail (g_type_is_a (type, EEK_TYPE_SERIALIZABLE), NULL);
object = g_object_new (type, NULL); object = g_object_new (type, NULL);
EEK_SERIALIZABLE_GET_IFACE (object)->deserialize (object, var, 1); index = EEK_SERIALIZABLE_GET_IFACE (object)->deserialize (object,
g_variant_unref (var); variant,
index);
if (index < 0) {
g_object_unref (object);
g_return_val_if_reached (NULL);
}
g_object_unref (object); return object;
g_return_val_if_reached (NULL);
} }

View File

@ -23,6 +23,7 @@
#endif /* HAVE_CONFIG_H */ #endif /* HAVE_CONFIG_H */
#include "eek-symbol.h" #include "eek-symbol.h"
#include "eek-serializable.h"
enum { enum {
PROP_0, PROP_0,
@ -40,71 +41,47 @@ struct _EekSymbolPrivate {
EekModifierType modifier_mask; EekModifierType modifier_mask;
}; };
G_DEFINE_TYPE (EekSymbol, eek_symbol, G_TYPE_OBJECT); static void eek_serializable_iface_init (EekSerializableIface *iface);
G_DEFINE_TYPE_WITH_CODE (EekSymbol, eek_symbol, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (EEK_TYPE_SERIALIZABLE,
eek_serializable_iface_init));
#define EEK_SYMBOL_GET_PRIVATE(obj) \ #define EEK_SYMBOL_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_SYMBOL, EekSymbolPrivate)) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_SYMBOL, EekSymbolPrivate))
static void static void
eek_symbol_real_set_name (EekSymbol *self, eek_symbol_real_serialize (EekSerializable *self,
const gchar *name) GVariantBuilder *builder)
{ {
EekSymbolPrivate *priv = EEK_SYMBOL_GET_PRIVATE(self); EekSymbolPrivate *priv = EEK_SYMBOL_GET_PRIVATE(self);
g_free (priv->name);
priv->name = g_strdup (name); g_variant_builder_add (builder, "s", priv->name);
g_variant_builder_add (builder, "s", priv->label);
g_variant_builder_add (builder, "u", priv->category);
g_variant_builder_add (builder, "u", priv->modifier_mask);
} }
G_CONST_RETURN gchar * static gsize
eek_symbol_real_get_name (EekSymbol *self) eek_symbol_real_deserialize (EekSerializable *self,
GVariant *variant,
gsize index)
{ {
EekSymbolPrivate *priv = EEK_SYMBOL_GET_PRIVATE(self); EekSymbolPrivate *priv = EEK_SYMBOL_GET_PRIVATE(self);
return priv->name;
g_variant_get_child (variant, index++, "s", &priv->name);
g_variant_get_child (variant, index++, "s", &priv->label);
g_variant_get_child (variant, index++, "u", &priv->category);
g_variant_get_child (variant, index++, "u", &priv->modifier_mask);
return index;
} }
static void static void
eek_symbol_real_set_label (EekSymbol *self, eek_serializable_iface_init (EekSerializableIface *iface)
const gchar *label)
{ {
EekSymbolPrivate *priv = EEK_SYMBOL_GET_PRIVATE(self); iface->serialize = eek_symbol_real_serialize;
g_free (priv->label); iface->deserialize = eek_symbol_real_deserialize;
priv->label = g_strdup (label);
}
gchar *
eek_symbol_real_get_label (EekSymbol *self)
{
EekSymbolPrivate *priv = EEK_SYMBOL_GET_PRIVATE(self);
return priv->label;
}
static void
eek_symbol_real_set_category (EekSymbol *self,
EekSymbolCategory category)
{
EekSymbolPrivate *priv = EEK_SYMBOL_GET_PRIVATE(self);
priv->category = category;
}
EekSymbolCategory
eek_symbol_real_get_category (EekSymbol *self)
{
EekSymbolPrivate *priv = EEK_SYMBOL_GET_PRIVATE(self);
return priv->category;
}
static void
eek_symbol_real_set_modifier_mask (EekSymbol *self,
EekModifierType mask)
{
EekSymbolPrivate *priv = EEK_SYMBOL_GET_PRIVATE(self);
priv->modifier_mask = mask;
}
EekModifierType
eek_symbol_real_get_modifier_mask (EekSymbol *self)
{
EekSymbolPrivate *priv = EEK_SYMBOL_GET_PRIVATE(self);
return priv->modifier_mask;
} }
static void static void
@ -121,11 +98,11 @@ eek_symbol_set_property (GObject *object,
eek_symbol_set_label (EEK_SYMBOL(object), g_value_get_string (value)); eek_symbol_set_label (EEK_SYMBOL(object), g_value_get_string (value));
break; break;
case PROP_CATEGORY: case PROP_CATEGORY:
eek_symbol_set_category (EEK_SYMBOL(object), g_value_get_int (value)); eek_symbol_set_category (EEK_SYMBOL(object), g_value_get_uint (value));
break; break;
case PROP_MODIFIER_MASK: case PROP_MODIFIER_MASK:
eek_symbol_set_modifier_mask (EEK_SYMBOL(object), eek_symbol_set_modifier_mask (EEK_SYMBOL(object),
g_value_get_int (value)); g_value_get_uint (value));
break; break;
default: default:
g_object_set_property (object, g_object_set_property (object,
@ -149,11 +126,11 @@ eek_symbol_get_property (GObject *object,
g_value_set_string (value, eek_symbol_get_label (EEK_SYMBOL(object))); g_value_set_string (value, eek_symbol_get_label (EEK_SYMBOL(object)));
break; break;
case PROP_CATEGORY: case PROP_CATEGORY:
g_value_set_int (value, eek_symbol_get_category (EEK_SYMBOL(object))); g_value_set_uint (value, eek_symbol_get_category (EEK_SYMBOL(object)));
break; break;
case PROP_MODIFIER_MASK: case PROP_MODIFIER_MASK:
g_value_set_int (value, g_value_set_uint (value,
eek_symbol_get_modifier_mask (EEK_SYMBOL(object))); eek_symbol_get_modifier_mask (EEK_SYMBOL(object)));
break; break;
default: default:
g_object_get_property (object, g_object_get_property (object,
@ -180,32 +157,37 @@ eek_symbol_class_init (EekSymbolClass *klass)
g_type_class_add_private (gobject_class, sizeof (EekSymbolPrivate)); g_type_class_add_private (gobject_class, sizeof (EekSymbolPrivate));
klass->set_name = eek_symbol_real_set_name;
klass->get_name = eek_symbol_real_get_name;
klass->set_label = eek_symbol_real_set_label;
klass->get_label = eek_symbol_real_get_label;
klass->set_category = eek_symbol_real_set_category;
klass->get_category = eek_symbol_real_get_category;
klass->set_modifier_mask = eek_symbol_real_set_modifier_mask;
klass->get_modifier_mask = eek_symbol_real_get_modifier_mask;
gobject_class->set_property = eek_symbol_set_property; gobject_class->set_property = eek_symbol_set_property;
gobject_class->get_property = eek_symbol_get_property; gobject_class->get_property = eek_symbol_get_property;
gobject_class->finalize = eek_symbol_finalize; gobject_class->finalize = eek_symbol_finalize;
pspec = g_param_spec_string ("name", pspec = g_param_spec_string ("name",
"Name", "Name",
"Canonical name of the keysym", "Canonical name of the symbol",
NULL, NULL,
G_PARAM_READWRITE); G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_NAME, pspec); g_object_class_install_property (gobject_class, PROP_NAME, pspec);
pspec = g_param_spec_string ("label", pspec = g_param_spec_string ("label",
"Label", "Label",
"Text used to display the keysym", "Text used to display the symbol",
NULL, NULL,
G_PARAM_READWRITE); G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_LABEL, pspec); g_object_class_install_property (gobject_class, PROP_LABEL, pspec);
pspec = g_param_spec_uint ("category",
"Category",
"Category of the symbol",
0, G_MAXUINT, 0,
G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_CATEGORY, pspec);
pspec = g_param_spec_uint ("modifier-mask",
"Modifier mask",
"Modifier mask of the symbol",
0, G_MAXUINT, 0,
G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_MODIFIER_MASK, pspec);
} }
static void static void
@ -230,58 +212,92 @@ void
eek_symbol_set_name (EekSymbol *symbol, eek_symbol_set_name (EekSymbol *symbol,
const gchar *name) const gchar *name)
{ {
EekSymbolPrivate *priv;
g_return_if_fail (EEK_IS_SYMBOL(symbol)); g_return_if_fail (EEK_IS_SYMBOL(symbol));
EEK_SYMBOL_GET_CLASS(symbol)->set_name (symbol, name);
priv = EEK_SYMBOL_GET_PRIVATE(symbol);
g_free (priv->name);
priv->name = g_strdup (name);
} }
G_CONST_RETURN gchar * G_CONST_RETURN gchar *
eek_symbol_get_name (EekSymbol *symbol) eek_symbol_get_name (EekSymbol *symbol)
{ {
EekSymbolPrivate *priv;
g_return_val_if_fail (EEK_IS_SYMBOL(symbol), NULL); g_return_val_if_fail (EEK_IS_SYMBOL(symbol), NULL);
return EEK_SYMBOL_GET_CLASS(symbol)->get_name (symbol);
priv = EEK_SYMBOL_GET_PRIVATE(symbol);
return priv->name;
} }
void void
eek_symbol_set_label (EekSymbol *symbol, eek_symbol_set_label (EekSymbol *symbol,
const gchar *label) const gchar *label)
{ {
EekSymbolPrivate *priv;
g_return_if_fail (EEK_IS_SYMBOL(symbol)); g_return_if_fail (EEK_IS_SYMBOL(symbol));
return EEK_SYMBOL_GET_CLASS(symbol)->set_label (symbol, label);
priv = EEK_SYMBOL_GET_PRIVATE(symbol);
g_free (priv->label);
priv->label = g_strdup (label);
} }
gchar * gchar *
eek_symbol_get_label (EekSymbol *symbol) eek_symbol_get_label (EekSymbol *symbol)
{ {
EekSymbolPrivate *priv;
g_return_val_if_fail (EEK_IS_SYMBOL(symbol), NULL); g_return_val_if_fail (EEK_IS_SYMBOL(symbol), NULL);
return EEK_SYMBOL_GET_CLASS(symbol)->get_label (symbol);
priv = EEK_SYMBOL_GET_PRIVATE(symbol);
return g_strdup (priv->label);
} }
void void
eek_symbol_set_category (EekSymbol *symbol, eek_symbol_set_category (EekSymbol *symbol,
EekSymbolCategory category) EekSymbolCategory category)
{ {
EekSymbolPrivate *priv;
g_return_if_fail (EEK_IS_SYMBOL(symbol)); g_return_if_fail (EEK_IS_SYMBOL(symbol));
return EEK_SYMBOL_GET_CLASS(symbol)->set_category (symbol, category);
priv = EEK_SYMBOL_GET_PRIVATE(symbol);
priv->category = category;
} }
EekSymbolCategory EekSymbolCategory
eek_symbol_get_category (EekSymbol *symbol) eek_symbol_get_category (EekSymbol *symbol)
{ {
EekSymbolPrivate *priv;
g_return_val_if_fail (EEK_IS_SYMBOL(symbol), EEK_SYMBOL_CATEGORY_UNKNOWN); g_return_val_if_fail (EEK_IS_SYMBOL(symbol), EEK_SYMBOL_CATEGORY_UNKNOWN);
return EEK_SYMBOL_GET_CLASS(symbol)->get_category (symbol);
priv = EEK_SYMBOL_GET_PRIVATE(symbol);
return priv->category;
} }
void void
eek_symbol_set_modifier_mask (EekSymbol *symbol, eek_symbol_set_modifier_mask (EekSymbol *symbol,
EekModifierType mask) EekModifierType mask)
{ {
EekSymbolPrivate *priv;
g_return_if_fail (EEK_IS_SYMBOL(symbol)); g_return_if_fail (EEK_IS_SYMBOL(symbol));
return EEK_SYMBOL_GET_CLASS(symbol)->set_modifier_mask (symbol, mask);
priv = EEK_SYMBOL_GET_PRIVATE(symbol);
priv->modifier_mask = mask;
} }
EekModifierType EekModifierType
eek_symbol_get_modifier_mask (EekSymbol *symbol) eek_symbol_get_modifier_mask (EekSymbol *symbol)
{ {
EekSymbolPrivate *priv;
g_return_val_if_fail (EEK_IS_SYMBOL(symbol), 0); g_return_val_if_fail (EEK_IS_SYMBOL(symbol), 0);
return EEK_SYMBOL_GET_CLASS(symbol)->get_modifier_mask (symbol);
priv = EEK_SYMBOL_GET_PRIVATE(symbol);
return priv->modifier_mask;
} }

View File

@ -69,24 +69,6 @@ struct _EekSymbol {
struct _EekSymbolClass { struct _EekSymbolClass {
/*< private >*/ /*< private >*/
GObjectClass parent_class; GObjectClass parent_class;
/*< public >*/
void (* set_name) (EekSymbol *self,
const gchar *name);
G_CONST_RETURN gchar *(* get_name) (EekSymbol *self);
void (* set_label) (EekSymbol *self,
const gchar *label);
gchar *(* get_label) (EekSymbol *self);
void (* set_category) (EekSymbol *self,
EekSymbolCategory category);
EekSymbolCategory (* get_category) (EekSymbol *self);
void (* set_modifier_mask) (EekSymbol *self,
EekModifierType mask);
EekModifierType (* get_modifier_mask) (EekSymbol *self);
/*< private >*/
/* padding */
gpointer pdummy[24];
}; };
GType eek_symbol_get_type (void) G_GNUC_CONST; GType eek_symbol_get_type (void) G_GNUC_CONST;

View File

@ -27,9 +27,11 @@
#include "config.h" #include "config.h"
#endif /* HAVE_CONFIG_H */ #endif /* HAVE_CONFIG_H */
#include "eek-types.h" #include <string.h>
#include <math.h> #include <math.h>
#include "eek-types.h"
/* EekSymbolMatrix */ /* EekSymbolMatrix */
EekSymbolMatrix * EekSymbolMatrix *
eek_symbol_matrix_new (gint num_groups, gint num_levels) eek_symbol_matrix_new (gint num_groups, gint num_levels)
@ -147,15 +149,20 @@ eek_bounds_get_type (void)
} }
/* EekOutline */ /* EekOutline */
static EekOutline * EekOutline *
eek_outline_copy (const EekOutline *outline) eek_outline_copy (const EekOutline *outline)
{ {
return g_slice_dup (EekOutline, outline); EekOutline *_outline = g_slice_dup (EekOutline, outline);
_outline->num_points = outline->num_points;
_outline->points = g_slice_alloc0 (sizeof (EekPoint) * outline->num_points);
memcpy (_outline->points, outline->points, sizeof (EekPoint) * outline->num_points);
return _outline;
} }
static void void
eek_outline_free (EekOutline *outline) eek_outline_free (EekOutline *outline)
{ {
g_slice_free1 (sizeof (EekPoint) * outline->num_points, outline->points);
g_slice_free (EekOutline, outline); g_slice_free (EekOutline, outline);
} }

View File

@ -192,7 +192,9 @@ struct _EekOutline
gint num_points; gint num_points;
}; };
GType eek_outline_get_type (void) G_GNUC_CONST; GType eek_outline_get_type (void) G_GNUC_CONST;
EekOutline *eek_outline_copy (const EekOutline *outline);
void eek_outline_free (EekOutline *outline);
/** /**
* EekColor: * EekColor:

View File

@ -70,8 +70,8 @@ struct _EekXkbLayoutPrivate
/* Actual XKB configuration of DISPLAY. */ /* Actual XKB configuration of DISPLAY. */
XkbDescRec *xkb; XkbDescRec *xkb;
/* Hash table to cache outlines by shape address. */ /* Hash table to cache orefs by shape address. */
GHashTable *outline_hash; GHashTable *shape_oref_hash;
gint scale_numerator; gint scale_numerator;
gint scale_denominator; gint scale_denominator;
@ -109,6 +109,7 @@ xkb_to_pixmap_double (EekXkbLayout *layout,
static void static void
create_key (EekXkbLayout *layout, create_key (EekXkbLayout *layout,
EekKeyboard *keyboard,
EekSection *section, EekSection *section,
gint column, gint column,
gint row, gint row,
@ -125,14 +126,16 @@ create_key (EekXkbLayout *layout,
EekBounds bounds; EekBounds bounds;
EekSymbolMatrix *matrix = NULL; EekSymbolMatrix *matrix = NULL;
gchar name[XkbKeyNameLength + 1]; gchar name[XkbKeyNameLength + 1];
EekOutline *outline;
KeyCode keycode; KeyCode keycode;
gint num_groups, num_levels, num_symbols; gint num_groups, num_levels, num_symbols;
gulong oref;
xkbgeometry = priv->xkb->geom; xkbgeometry = priv->xkb->geom;
xkbshape = &xkbgeometry->shapes[xkbkey->shape_ndx]; xkbshape = &xkbgeometry->shapes[xkbkey->shape_ndx];
outline = g_hash_table_lookup (priv->outline_hash, xkbshape); oref = (gulong)g_hash_table_lookup (priv->shape_oref_hash, xkbshape);
if (outline == NULL) { if (oref == 0) {
EekOutline *outline;
xkboutline = xkbshape->primary == NULL ? &xkbshape->outlines[0] : xkboutline = xkbshape->primary == NULL ? &xkbshape->outlines[0] :
xkbshape->primary; xkbshape->primary;
@ -172,7 +175,8 @@ create_key (EekXkbLayout *layout,
xkb_to_pixmap_coord(layout, xkboutline->points[i].y); xkb_to_pixmap_coord(layout, xkboutline->points[i].y);
} }
} }
g_hash_table_insert (priv->outline_hash, xkbshape, outline); oref = eek_keyboard_add_outline (keyboard, outline);
g_hash_table_insert (priv->shape_oref_hash, xkbshape, (gpointer)oref);
} }
memset (name, 0, sizeof name); memset (name, 0, sizeof name);
@ -210,7 +214,7 @@ create_key (EekXkbLayout *layout,
eek_key_set_keycode (key, keycode); eek_key_set_keycode (key, keycode);
eek_key_set_symbol_matrix (key, matrix); eek_key_set_symbol_matrix (key, matrix);
eek_symbol_matrix_free (matrix); eek_symbol_matrix_free (matrix);
eek_key_set_outline (key, outline); eek_key_set_oref (key, oref);
} }
static void static void
@ -262,7 +266,7 @@ create_section (EekXkbLayout *layout,
top += xkbkey->gap; top += xkbkey->gap;
else else
left += xkbkey->gap; left += xkbkey->gap;
create_key (layout, section, j, i, left, top, xkbkey); create_key (layout, keyboard, section, j, i, left, top, xkbkey);
xkbbounds = &xkbgeometry->shapes[xkbkey->shape_ndx].bounds; xkbbounds = &xkbgeometry->shapes[xkbkey->shape_ndx].bounds;
if (xkbrow->vertical) if (xkbrow->vertical)
top += xkbbounds->y2 - xkbbounds->y1; top += xkbbounds->y2 - xkbbounds->y1;
@ -301,14 +305,6 @@ create_keyboard (EekXkbLayout *layout, EekKeyboard *keyboard)
eek_element_set_bounds (EEK_ELEMENT(keyboard), &bounds); eek_element_set_bounds (EEK_ELEMENT(keyboard), &bounds);
} }
static void
outline_free (gpointer data)
{
EekOutline *outline = data;
g_slice_free1 (sizeof (EekPoint) * outline->num_points, outline->points);
g_boxed_free (EEK_TYPE_OUTLINE, outline);
}
static EekKeyboard * static EekKeyboard *
eek_xkb_layout_real_create_keyboard (EekLayout *self, eek_xkb_layout_real_create_keyboard (EekLayout *self,
gdouble initial_width, gdouble initial_width,
@ -324,15 +320,12 @@ eek_xkb_layout_real_create_keyboard (EekLayout *self,
bounds.height = initial_height; bounds.height = initial_height;
eek_element_set_bounds (EEK_ELEMENT(keyboard), &bounds); eek_element_set_bounds (EEK_ELEMENT(keyboard), &bounds);
if (priv->outline_hash) if (priv->shape_oref_hash)
g_hash_table_unref (priv->outline_hash); g_hash_table_destroy (priv->shape_oref_hash);
priv->outline_hash = g_hash_table_new_full (g_direct_hash,
g_direct_equal,
NULL,
outline_free);
priv->shape_oref_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
create_keyboard (EEK_XKB_LAYOUT(self), keyboard); create_keyboard (EEK_XKB_LAYOUT(self), keyboard);
g_hash_table_destroy (priv->shape_oref_hash);
return keyboard; return keyboard;
} }
@ -345,8 +338,6 @@ eek_xkb_layout_finalize (GObject *object)
g_free (priv->names.keycodes); g_free (priv->names.keycodes);
g_free (priv->names.geometry); g_free (priv->names.geometry);
g_free (priv->names.symbols); g_free (priv->names.symbols);
if (priv->outline_hash)
g_hash_table_unref (priv->outline_hash);
XkbFreeKeyboard (priv->xkb, 0, TRUE); /* free_all = TRUE */ XkbFreeKeyboard (priv->xkb, 0, TRUE); /* free_all = TRUE */
G_OBJECT_CLASS (eek_xkb_layout_parent_class)->finalize (object); G_OBJECT_CLASS (eek_xkb_layout_parent_class)->finalize (object);
} }

View File

@ -48,7 +48,6 @@ G_DEFINE_TYPE (EekXmlLayout, eek_xml_layout, EEK_TYPE_LAYOUT);
struct _EekXmlLayoutPrivate struct _EekXmlLayoutPrivate
{ {
GInputStream *source; GInputStream *source;
GHashTable *outline_hash;
}; };
#define BUFSIZE 8192 #define BUFSIZE 8192
@ -86,7 +85,7 @@ static const gchar *valid_path_list[] = {
"orientation/row/section/keyboard", "orientation/row/section/keyboard",
"key/section/keyboard", "key/section/keyboard",
"bounds/key/section/keyboard", "bounds/key/section/keyboard",
"outline-ref/key/section/keyboard", "oref/key/section/keyboard",
"symbols/key/section/keyboard", "symbols/key/section/keyboard",
"groups/symbols/key/section/keyboard", "groups/symbols/key/section/keyboard",
"levels/symbols/key/section/keyboard", "levels/symbols/key/section/keyboard",
@ -293,7 +292,7 @@ end_element_callback (GMarkupParseContext *pcontext,
outline->points = g_slice_alloc0 (sizeof (EekPoint) * outline->points = g_slice_alloc0 (sizeof (EekPoint) *
outline->num_points); outline->num_points);
for (head = data->points = g_slist_reverse (data->points), i = 0; for (head = data->points = g_slist_reverse (data->points), i = 0;
head; head && i < outline->num_points;
head = g_slist_next (head), i++) { head = g_slist_next (head), i++) {
memcpy (&outline->points[i], head->data, sizeof (EekPoint)); memcpy (&outline->points[i], head->data, sizeof (EekPoint));
g_slice_free1 (sizeof (EekPoint), head->data); g_slice_free1 (sizeof (EekPoint), head->data);
@ -406,7 +405,7 @@ end_element_callback (GMarkupParseContext *pcontext,
goto out; goto out;
} }
if (g_strcmp0 (element_name, "outline-ref") == 0) { if (g_strcmp0 (element_name, "oref") == 0) {
g_hash_table_insert (data->key_oref_hash, data->key, g_strdup (text)); g_hash_table_insert (data->key_oref_hash, data->key, g_strdup (text));
goto out; goto out;
} }
@ -434,14 +433,6 @@ static const GMarkupParser parser = {
0 0
}; };
static void
outline_free (gpointer data)
{
EekOutline *outline = data;
g_slice_free1 (sizeof (EekPoint) * outline->num_points, outline->points);
g_boxed_free (EEK_TYPE_OUTLINE, outline);
}
static void scale_bounds_callback (EekElement *element, static void scale_bounds_callback (EekElement *element,
gpointer user_data); gpointer user_data);
@ -485,6 +476,7 @@ eek_xml_layout_real_create_keyboard (EekLayout *self,
gdouble scale; gdouble scale;
GHashTableIter iter; GHashTableIter iter;
gpointer k, v; gpointer k, v;
GHashTable *oref_hash;
g_return_val_if_fail (priv->source, NULL); g_return_val_if_fail (priv->source, NULL);
@ -495,10 +487,11 @@ eek_xml_layout_real_create_keyboard (EekLayout *self,
g_direct_equal, g_direct_equal,
NULL, NULL,
g_free); g_free);
data.oref_outline_hash = g_hash_table_new_full (g_str_hash, data.oref_outline_hash =
g_str_equal, g_hash_table_new_full (g_str_hash,
g_free, g_str_equal,
outline_free); g_free,
(GDestroyNotify)eek_outline_free);
pcontext = g_markup_parse_context_new (&parser, 0, &data, NULL); pcontext = g_markup_parse_context_new (&parser, 0, &data, NULL);
while (1) { while (1) {
@ -528,36 +521,44 @@ eek_xml_layout_real_create_keyboard (EekLayout *self,
if (!data.keyboard) if (!data.keyboard)
goto out; goto out;
g_hash_table_iter_init (&iter, data.key_oref_hash);
while (g_hash_table_iter_next (&iter, &k, &v)) {
EekOutline *outline = g_hash_table_lookup (data.oref_outline_hash, v);
g_assert (outline);
eek_key_set_outline (EEK_KEY(k), outline);
}
eek_element_get_bounds (EEK_ELEMENT(data.keyboard), &bounds); eek_element_get_bounds (EEK_ELEMENT(data.keyboard), &bounds);
scale = initial_width * bounds.height < initial_height * bounds.width ? scale = initial_width * bounds.height < initial_height * bounds.width ?
initial_width / bounds.width : initial_width / bounds.width :
initial_height / bounds.height; initial_height / bounds.height;
oref_hash = g_hash_table_new (g_str_hash, g_str_equal);
g_hash_table_iter_init (&iter, data.oref_outline_hash); g_hash_table_iter_init (&iter, data.oref_outline_hash);
while (g_hash_table_iter_next (&iter, &k, &v)) { while (g_hash_table_iter_next (&iter, &k, &v)) {
EekOutline *outline = v; EekOutline *outline = v;
gulong oref;
gint i; gint i;
for (i = 0; i < outline->num_points; i++) { for (i = 0; i < outline->num_points; i++) {
outline->points[i].x *= scale; outline->points[i].x *= scale;
outline->points[i].y *= scale; outline->points[i].y *= scale;
} }
oref = eek_keyboard_add_outline (data.keyboard, outline);
g_hash_table_insert (oref_hash, k, (gpointer) oref);
} }
g_hash_table_iter_init (&iter, data.key_oref_hash);
while (g_hash_table_iter_next (&iter, &k, &v)) {
gulong oref;
oref = (gulong) g_hash_table_lookup (oref_hash, v);
eek_key_set_oref (EEK_KEY(k), oref);
}
g_hash_table_destroy (oref_hash);
scale_bounds (EEK_ELEMENT(data.keyboard), scale); scale_bounds (EEK_ELEMENT(data.keyboard), scale);
out: out:
g_string_free (data.text, TRUE); g_string_free (data.text, TRUE);
if (data.key_oref_hash) if (data.key_oref_hash)
g_hash_table_destroy (data.key_oref_hash); g_hash_table_destroy (data.key_oref_hash);
priv->outline_hash = data.oref_outline_hash; if (data.oref_outline_hash)
g_hash_table_destroy (data.oref_outline_hash);
return data.keyboard; return data.keyboard;
} }
@ -612,17 +613,6 @@ eek_xml_layout_dispose (GObject *object)
G_OBJECT_CLASS (eek_xml_layout_parent_class)->dispose (object); G_OBJECT_CLASS (eek_xml_layout_parent_class)->dispose (object);
} }
static void
eek_xml_layout_finalize (GObject *object)
{
EekXmlLayoutPrivate *priv = EEK_XML_LAYOUT_GET_PRIVATE (object);
if (priv->outline_hash)
g_hash_table_unref (priv->outline_hash);
G_OBJECT_CLASS (eek_xml_layout_parent_class)->finalize (object);
}
static void static void
eek_xml_layout_class_init (EekXmlLayoutClass *klass) eek_xml_layout_class_init (EekXmlLayoutClass *klass)
{ {
@ -637,7 +627,6 @@ eek_xml_layout_class_init (EekXmlLayoutClass *klass)
gobject_class->set_property = eek_xml_layout_set_property; gobject_class->set_property = eek_xml_layout_set_property;
gobject_class->get_property = eek_xml_layout_get_property; gobject_class->get_property = eek_xml_layout_get_property;
gobject_class->dispose = eek_xml_layout_dispose; gobject_class->dispose = eek_xml_layout_dispose;
gobject_class->finalize = eek_xml_layout_finalize;
pspec = g_param_spec_object ("source", pspec = g_param_spec_object ("source",
"Source", "Source",

View File

@ -54,7 +54,7 @@ g_string_markup_printf (GString *output, const gchar *format, ...)
struct _OutputCallbackData { struct _OutputCallbackData {
GString *output; GString *output;
gint indent; gint indent;
GArray *outline_array; GHashTable *oref_hash;
gint key_serial; gint key_serial;
}; };
typedef struct _OutputCallbackData OutputCallbackData; typedef struct _OutputCallbackData OutputCallbackData;
@ -75,12 +75,12 @@ output_key_callback (EekElement *element, gpointer user_data)
{ {
OutputCallbackData *data = user_data; OutputCallbackData *data = user_data;
EekBounds bounds; EekBounds bounds;
EekOutline *outline;
gint i, num_symbols; gint i, num_symbols;
EekSymbolMatrix *matrix; EekSymbolMatrix *matrix;
gint column, row; gint column, row;
guint keycode; guint keycode;
gchar *id; gchar *id;
gulong oref;
keycode = eek_key_get_keycode (EEK_KEY(element)); keycode = eek_key_get_keycode (EEK_KEY(element));
if (keycode == EEK_INVALID_KEYCODE) if (keycode == EEK_INVALID_KEYCODE)
@ -112,19 +112,16 @@ output_key_callback (EekElement *element, gpointer user_data)
g_string_append_indent (data->output, data->indent + 1); g_string_append_indent (data->output, data->indent + 1);
output_bounds (data->output, &bounds); output_bounds (data->output, &bounds);
outline = eek_key_get_outline (EEK_KEY(element)); oref = eek_key_get_oref (EEK_KEY(element));
if (outline) { if (oref != 0) {
for (i = 0;
i < data->outline_array->len &&
g_array_index (data->outline_array, gpointer, i) != outline;
i++)
;
if (i == data->outline_array->len)
g_array_append_val (data->outline_array, outline);
g_string_append_indent (data->output, data->indent + 1); g_string_append_indent (data->output, data->indent + 1);
g_string_markup_printf (data->output, g_string_markup_printf (data->output,
"<outline-ref>outline%d</outline-ref>\n", "<oref>outline%u</oref>\n",
i); oref);
if (!g_hash_table_lookup (data->oref_hash, (gpointer)oref))
g_hash_table_insert (data->oref_hash,
(gpointer)oref,
(gpointer)TRUE);
} }
matrix = eek_key_get_symbol_matrix (EEK_KEY(element)); matrix = eek_key_get_symbol_matrix (EEK_KEY(element));
@ -224,7 +221,8 @@ eek_keyboard_output (EekKeyboard *keyboard, GString *output, gint indent)
{ {
OutputCallbackData data; OutputCallbackData data;
EekBounds bounds; EekBounds bounds;
gint i; gulong oref;
GHashTableIter iter;
g_assert (EEK_IS_KEYBOARD(keyboard)); g_assert (EEK_IS_KEYBOARD(keyboard));
@ -245,7 +243,7 @@ eek_keyboard_output (EekKeyboard *keyboard, GString *output, gint indent)
data.output = output; data.output = output;
data.indent = indent; data.indent = indent;
data.outline_array = g_array_new (FALSE, FALSE, sizeof (gpointer)); data.oref_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
data.key_serial = 0; data.key_serial = 0;
data.indent++; data.indent++;
@ -254,14 +252,14 @@ eek_keyboard_output (EekKeyboard *keyboard, GString *output, gint indent)
&data); &data);
data.indent--; data.indent--;
for (i = 0; i < data.outline_array->len; i++) { g_hash_table_iter_init (&iter, data.oref_hash);
while (g_hash_table_iter_next (&iter, (gpointer *)&oref, NULL)) {
EekOutline *outline; EekOutline *outline;
gint j; gint j;
outline = eek_keyboard_get_outline (keyboard, oref);
g_string_append_indent (output, indent + 1); g_string_append_indent (output, indent + 1);
g_string_markup_printf (output, "<outline id=\"outline%d\">\n", i); g_string_markup_printf (output, "<outline id=\"outline%u\">\n", oref);
outline = g_array_index (data.outline_array, gpointer, i);
for (j = 0; j < outline->num_points; j++) { for (j = 0; j < outline->num_points; j++) {
g_string_append_indent (output, indent + 2); g_string_append_indent (output, indent + 2);
g_string_markup_printf (output, "<point>%lf,%lf</point>\n", g_string_markup_printf (output, "<point>%lf,%lf</point>\n",
@ -272,7 +270,7 @@ eek_keyboard_output (EekKeyboard *keyboard, GString *output, gint indent)
g_string_append_indent (output, indent + 1); g_string_append_indent (output, indent + 1);
g_string_markup_printf (output, "</outline>\n"); g_string_markup_printf (output, "</outline>\n");
} }
g_array_free (data.outline_array, TRUE); g_hash_table_destroy (data.oref_hash);
g_string_append_indent (output, indent); g_string_append_indent (output, indent);
g_string_markup_printf (output, "</keyboard>\n"); g_string_markup_printf (output, "</keyboard>\n");

View File

@ -27,5 +27,6 @@
#include "eek-symbol.h" #include "eek-symbol.h"
#include "eek-keysym.h" #include "eek-keysym.h"
#include "eek-xml.h" #include "eek-xml.h"
#include "eek-serializable.h"
#endif /* EEK_H */ #endif /* EEK_H */

View File

@ -70,6 +70,7 @@ main (int argc, char **argv)
gint retval = 0; gint retval = 0;
g_type_init (); g_type_init ();
g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL);
context = g_option_context_new ("eekboard-client"); context = g_option_context_new ("eekboard-client");
g_option_context_add_main_entries (context, options, NULL); g_option_context_add_main_entries (context, options, NULL);

View File

@ -21,8 +21,6 @@
#include "proxy.h" #include "proxy.h"
#define BUFSIZE 8192
enum { enum {
KEY_PRESSED, KEY_PRESSED,
KEY_RELEASED, KEY_RELEASED,
@ -150,17 +148,9 @@ proxy_call_async_ready_cb (GObject *source_object,
void void
eekboard_proxy_set_keyboard (EekboardProxy *proxy, EekKeyboard *keyboard) eekboard_proxy_set_keyboard (EekboardProxy *proxy, EekKeyboard *keyboard)
{ {
GString *output;
GVariant *variant; GVariant *variant;
gchar *data;
output = g_string_sized_new (BUFSIZE);
eek_keyboard_output (keyboard, output, 0);
data = g_string_free (output, FALSE);
variant = g_variant_new ("(s)", data);
g_free (data);
variant = eek_serializable_serialize (EEK_SERIALIZABLE(keyboard));
g_dbus_proxy_call (G_DBUS_PROXY(proxy), g_dbus_proxy_call (G_DBUS_PROXY(proxy),
"SetKeyboard", "SetKeyboard",
g_variant_new ("(v)", variant), g_variant_new ("(v)", variant),

View File

@ -50,6 +50,14 @@ main (int argc, char **argv)
} }
#endif #endif
g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL);
g_type_class_ref (EEK_TYPE_KEYBOARD);
g_type_class_ref (EEK_TYPE_SECTION);
g_type_class_ref (EEK_TYPE_KEY);
g_type_class_ref (EEK_TYPE_SYMBOL);
g_type_class_ref (EEK_TYPE_KEYSYM);
error = NULL; error = NULL;
connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
if (error) { if (error) {

View File

@ -310,26 +310,21 @@ handle_method_call (GDBusConnection *connection,
// g_debug ("%s", method_name); // g_debug ("%s", method_name);
if (g_strcmp0 (method_name, "SetKeyboard") == 0) { if (g_strcmp0 (method_name, "SetKeyboard") == 0) {
EekSerializable *serializable;
GVariant *variant; GVariant *variant;
gchar *data; gchar *data;
GInputStream *input;
EekLayout *layout;
g_variant_get (parameters, "(v)", &variant); g_variant_get (parameters, "(v)", &variant);
g_variant_get (variant, "(&s)", &data); serializable = eek_serializable_deserialize (variant);
input = g_memory_input_stream_new_from_data (data, -1, NULL); if (!EEK_IS_KEYBOARD(serializable)) {
g_variant_unref (variant);
layout = eek_xml_layout_new (input);
if (!layout) {
g_dbus_method_invocation_return_error (invocation, g_dbus_method_invocation_return_error (invocation,
G_IO_ERROR, G_IO_ERROR,
G_IO_ERROR_FAILED_HANDLED, G_IO_ERROR_FAILED_HANDLED,
"can't create layout"); "not a keyboard");
return; return;
} }
server->keyboard = eek_keyboard_new (layout, CSW, CSH); server->keyboard = EEK_KEYBOARD(serializable);
disconnect_keyboard_signals (server); disconnect_keyboard_signals (server);
server->key_pressed_handler = server->key_pressed_handler =
g_signal_connect (server->keyboard, "key-pressed", g_signal_connect (server->keyboard, "key-pressed",