Implement serialization to GVariant.
This commit is contained in:
@ -82,7 +82,6 @@ eek_container_real_deserialize (EekSerializable *self,
|
||||
GVariant *variant,
|
||||
gsize index)
|
||||
{
|
||||
EekContainerPrivate *priv = EEK_CONTAINER_GET_PRIVATE(self);
|
||||
GVariant *array, *child;
|
||||
GVariantIter iter;
|
||||
|
||||
@ -94,9 +93,9 @@ eek_container_real_deserialize (EekSerializable *self,
|
||||
g_variant_iter_init (&iter, array);
|
||||
while (g_variant_iter_next (&iter, "v", &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;
|
||||
}
|
||||
@ -122,6 +121,7 @@ eek_container_real_add_child (EekContainer *self,
|
||||
|
||||
priv->children = g_slist_prepend (priv->children, child);
|
||||
eek_element_set_parent (child, EEK_ELEMENT(self));
|
||||
g_signal_emit_by_name (self, "child-added", child);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -137,6 +137,7 @@ eek_container_real_remove_child (EekContainer *self,
|
||||
g_object_unref (child);
|
||||
priv->children = g_slist_remove_link (priv->children, head);
|
||||
eek_element_set_parent (child, NULL);
|
||||
g_signal_emit_by_name (self, "child-removed", child);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -202,6 +203,10 @@ eek_container_class_init (EekContainerClass *klass)
|
||||
klass->foreach_child = eek_container_real_foreach_child;
|
||||
klass->find = eek_container_real_find;
|
||||
|
||||
/* signals */
|
||||
klass->child_added = NULL;
|
||||
klass->child_removed = NULL;
|
||||
|
||||
gobject_class->finalize = eek_container_finalize;
|
||||
gobject_class->dispose = eek_container_dispose;
|
||||
|
||||
@ -290,3 +295,11 @@ eek_container_find (EekContainer *container,
|
||||
func,
|
||||
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);
|
||||
}
|
||||
|
||||
@ -81,14 +81,16 @@ struct _EekContainerClass
|
||||
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,
|
||||
EekCallback callback,
|
||||
gpointer user_data);
|
||||
EekElement *eek_container_find (EekContainer *container,
|
||||
EekCompareFunc func,
|
||||
gpointer user_data);
|
||||
void eek_container_foreach_child (EekContainer *container,
|
||||
EekCallback callback,
|
||||
gpointer user_data);
|
||||
EekElement *eek_container_find (EekContainer *container,
|
||||
EekCompareFunc func,
|
||||
gpointer user_data);
|
||||
void eek_container_add_child (EekContainer *container,
|
||||
EekElement *element);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* EEK_CONTAINER_H */
|
||||
|
||||
@ -89,7 +89,7 @@ eek_element_real_serialize (EekSerializable *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));
|
||||
}
|
||||
|
||||
|
||||
110
eek/eek-key.c
110
eek/eek-key.c
@ -46,7 +46,7 @@ enum {
|
||||
PROP_SYMBOL_MATRIX,
|
||||
PROP_COLUMN,
|
||||
PROP_ROW,
|
||||
PROP_OUTLINE,
|
||||
PROP_OREF,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
@ -74,7 +74,7 @@ struct _EekKeyPrivate
|
||||
EekSymbolMatrix *symbol_matrix;
|
||||
gint column;
|
||||
gint row;
|
||||
EekOutline *outline;
|
||||
gulong oref;
|
||||
gboolean is_pressed;
|
||||
};
|
||||
|
||||
@ -86,23 +86,45 @@ _g_variant_new_symbol_matrix (EekSymbolMatrix *symbol_matrix)
|
||||
GVariantBuilder builder, array;
|
||||
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_levels);
|
||||
g_variant_builder_init (&array, G_VARIANT_TYPE ("av"));
|
||||
for (i = 0; i < num_symbols; i++) {
|
||||
GVariant *symbol = eek_serializable_serialize
|
||||
(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);
|
||||
}
|
||||
|
||||
static EekSymbolMatrix *
|
||||
_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
|
||||
@ -118,6 +140,7 @@ eek_key_real_serialize (EekSerializable *self,
|
||||
_g_variant_new_symbol_matrix (priv->symbol_matrix));
|
||||
g_variant_builder_add (builder, "i", priv->column);
|
||||
g_variant_builder_add (builder, "i", priv->row);
|
||||
g_variant_builder_add (builder, "u", priv->oref);
|
||||
}
|
||||
|
||||
static gsize
|
||||
@ -137,6 +160,7 @@ eek_key_real_deserialize (EekSerializable *self,
|
||||
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->row);
|
||||
g_variant_get_child (variant, index++, "u", &priv->oref);
|
||||
|
||||
return index;
|
||||
}
|
||||
@ -208,17 +232,17 @@ eek_key_real_get_index (EekKey *self,
|
||||
}
|
||||
|
||||
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);
|
||||
priv->outline = outline;
|
||||
priv->oref = oref;
|
||||
}
|
||||
|
||||
static EekOutline *
|
||||
eek_key_real_get_outline (EekKey *self)
|
||||
static gulong
|
||||
eek_key_real_get_oref (EekKey *self)
|
||||
{
|
||||
EekKeyPrivate *priv = EEK_KEY_GET_PRIVATE(self);
|
||||
return priv->outline;
|
||||
return priv->oref;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -283,8 +307,8 @@ eek_key_set_property (GObject *object,
|
||||
eek_key_get_index (EEK_KEY(object), &column, &row);
|
||||
eek_key_set_index (EEK_KEY(object), column, g_value_get_int (value));
|
||||
break;
|
||||
case PROP_OUTLINE:
|
||||
eek_key_set_outline (EEK_KEY(object), g_value_get_pointer (value));
|
||||
case PROP_OREF:
|
||||
eek_key_set_oref (EEK_KEY(object), g_value_get_uint (value));
|
||||
break;
|
||||
default:
|
||||
g_object_set_property (object,
|
||||
@ -319,8 +343,8 @@ eek_key_get_property (GObject *object,
|
||||
eek_key_get_index (EEK_KEY(object), &column, &row);
|
||||
g_value_set_int (value, row);
|
||||
break;
|
||||
case PROP_OUTLINE:
|
||||
g_value_set_pointer (value, eek_key_get_outline (EEK_KEY(object)));
|
||||
case PROP_OREF:
|
||||
g_value_set_uint (value, eek_key_get_oref (EEK_KEY(object)));
|
||||
break;
|
||||
default:
|
||||
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->set_index = eek_key_real_set_index;
|
||||
klass->get_index = eek_key_real_get_index;
|
||||
klass->set_outline = eek_key_real_set_outline;
|
||||
klass->get_outline = eek_key_real_get_outline;
|
||||
klass->set_oref = eek_key_real_set_oref;
|
||||
klass->get_oref = eek_key_real_get_oref;
|
||||
klass->is_pressed = eek_key_real_is_pressed;
|
||||
|
||||
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);
|
||||
|
||||
/**
|
||||
* 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
|
||||
assume that only a few outline shapes are used in a whole
|
||||
keyboard (unlike symbol matrix and bounds). */
|
||||
pspec = g_param_spec_pointer ("outline",
|
||||
"Outline",
|
||||
"Pointer to outline shape of the key",
|
||||
G_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class, PROP_OUTLINE, pspec);
|
||||
pspec = g_param_spec_ulong ("oref",
|
||||
"Oref",
|
||||
"Outline id of the key",
|
||||
0, G_MAXULONG, 0,
|
||||
G_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class, PROP_OREF, pspec);
|
||||
|
||||
/**
|
||||
* EekKey::pressed:
|
||||
@ -463,7 +485,7 @@ eek_key_init (EekKey *self)
|
||||
priv->keycode = 0;
|
||||
priv->symbol_matrix = eek_symbol_matrix_new (0, 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
|
||||
* @row: row index of @key in #EekSection
|
||||
*
|
||||
* Set the index of @key (i.e. logical location of @key in
|
||||
* #EekSection) to @column and @row.
|
||||
* Set the location of @key in #EekSection with @column and @row.
|
||||
*/
|
||||
void
|
||||
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
|
||||
* @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
|
||||
* #EekSection).
|
||||
* Get the location of @key in #EekSection.
|
||||
*/
|
||||
void
|
||||
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
|
||||
* @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
|
||||
eek_key_set_outline (EekKey *key,
|
||||
EekOutline *outline)
|
||||
eek_key_set_oref (EekKey *key,
|
||||
gulong oref)
|
||||
{
|
||||
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
|
||||
*
|
||||
* Get the outline shape of @key.
|
||||
* Returns: an #EekOutline pointer or NULL on failure
|
||||
* Get the outline id of @key.
|
||||
* Returns: a non-zero unsigned integer on success, 0 if the id is not set
|
||||
*/
|
||||
EekOutline *
|
||||
eek_key_get_outline (EekKey *key)
|
||||
gulong
|
||||
eek_key_get_oref (EekKey *key)
|
||||
{
|
||||
g_return_val_if_fail (EEK_IS_KEY (key), NULL);
|
||||
return EEK_KEY_GET_CLASS(key)->get_outline (key);
|
||||
g_return_val_if_fail (EEK_IS_KEY (key), 0);
|
||||
return EEK_KEY_GET_CLASS(key)->get_oref (key);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -54,8 +54,8 @@ struct _EekKey
|
||||
* section
|
||||
* @get_index: virtual function for getting position of the key in the
|
||||
* section
|
||||
* @set_outline: virtual function for setting outline shape of the key
|
||||
* @get_outline: virtual function for getting outline shape of the key
|
||||
* @set_oref: virtual function for setting outline id of the key
|
||||
* @get_oref: virtual function for getting outline id of the key
|
||||
* @pressed: class handler for #EekKey::pressed signal
|
||||
* @released: class handler for #EekKey::released signal
|
||||
* @is_pressed: virtual function for getting whether the key is pressed
|
||||
@ -80,9 +80,9 @@ struct _EekKeyClass
|
||||
gint *column,
|
||||
gint *row);
|
||||
|
||||
void (* set_outline) (EekKey *self,
|
||||
EekOutline *outline);
|
||||
EekOutline *(* get_outline) (EekKey *self);
|
||||
void (* set_oref) (EekKey *self,
|
||||
gulong oref);
|
||||
gulong (* get_oref) (EekKey *self);
|
||||
|
||||
gboolean (* is_pressed) (EekKey *self);
|
||||
|
||||
@ -104,7 +104,7 @@ void eek_key_set_symbol_matrix (EekKey *key,
|
||||
EekSymbolMatrix *matrix);
|
||||
EekSymbolMatrix *eek_key_get_symbol_matrix (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,
|
||||
gint fallback_group,
|
||||
gint fallback_level);
|
||||
@ -121,9 +121,9 @@ void eek_key_get_index (EekKey *key,
|
||||
gint *column,
|
||||
gint *row);
|
||||
|
||||
void eek_key_set_outline (EekKey *key,
|
||||
EekOutline *outline);
|
||||
EekOutline *eek_key_get_outline (EekKey *key);
|
||||
void eek_key_set_oref (EekKey *key,
|
||||
gulong oref);
|
||||
gulong eek_key_get_oref (EekKey *key);
|
||||
|
||||
gboolean eek_key_is_pressed (EekKey *key);
|
||||
|
||||
|
||||
@ -36,6 +36,7 @@
|
||||
#include "eek-key.h"
|
||||
#include "eek-symbol.h"
|
||||
#include "eek-marshalers.h"
|
||||
#include "eek-serializable.h"
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
@ -55,7 +56,11 @@ enum {
|
||||
|
||||
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) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_KEYBOARD, EekKeyboardPrivate))
|
||||
@ -68,8 +73,117 @@ struct _EekKeyboardPrivate
|
||||
EekLayout *layout;
|
||||
EekModifierBehavior modifier_behavior;
|
||||
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
|
||||
eek_keyboard_real_set_symbol_index (EekKeyboard *self,
|
||||
gint group,
|
||||
@ -123,11 +237,6 @@ eek_keyboard_real_create_section (EekKeyboard *self)
|
||||
section = g_object_new (EEK_TYPE_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_ELEMENT(section));
|
||||
return section;
|
||||
@ -318,9 +427,46 @@ eek_keyboard_dispose (GObject *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
|
||||
eek_keyboard_class_init (EekKeyboardClass *klass)
|
||||
{
|
||||
EekContainerClass *container_class = EEK_CONTAINER_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GParamSpec *pspec;
|
||||
|
||||
@ -337,9 +483,13 @@ eek_keyboard_class_init (EekKeyboardClass *klass)
|
||||
klass->key_released = eek_keyboard_real_key_released;
|
||||
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->set_property = eek_keyboard_set_property;
|
||||
gobject_class->dispose = eek_keyboard_dispose;
|
||||
gobject_class->finalize = eek_keyboard_finalize;
|
||||
|
||||
/**
|
||||
* EekKeyboard:group:
|
||||
@ -470,6 +620,7 @@ eek_keyboard_init (EekKeyboard *self)
|
||||
priv->layout = NULL;
|
||||
priv->modifier_behavior = EEK_MODIFIER_BEHAVIOR_NONE;
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
@ -102,6 +102,10 @@ void eek_keyboard_get_size
|
||||
(EekKeyboard *keyboard,
|
||||
gdouble *width,
|
||||
gdouble *height);
|
||||
void eek_keyboard_set_size
|
||||
(EekKeyboard *keyboard,
|
||||
gdouble width,
|
||||
gdouble height);
|
||||
void eek_keyboard_set_symbol_index
|
||||
(EekKeyboard *keyboard,
|
||||
gint group,
|
||||
@ -137,5 +141,13 @@ EekKey *eek_keyboard_find_key_by_keycode
|
||||
(EekKeyboard *keyboard,
|
||||
guint keycode);
|
||||
|
||||
gulong eek_keyboard_add_outline
|
||||
(EekKeyboard *keyboard,
|
||||
EekOutline *outline);
|
||||
|
||||
EekOutline *eek_keyboard_get_outline
|
||||
(EekKeyboard *keyboard,
|
||||
gulong oref);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* EEK_KEYBOARD_H */
|
||||
|
||||
235
eek/eek-keysym.c
235
eek/eek-keysym.c
@ -31,6 +31,7 @@
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include "eek-keysym.h"
|
||||
#include "eek-serializable.h"
|
||||
|
||||
/* modifier keys */
|
||||
#define EEK_KEYSYM_Shift_L 0xffe1
|
||||
@ -51,27 +52,68 @@
|
||||
|
||||
struct _EekKeysymPrivate {
|
||||
guint xkeysym;
|
||||
};
|
||||
|
||||
struct _EekKeysymEntry {
|
||||
guint xkeysym;
|
||||
const gchar *name;
|
||||
EekSymbolCategory category;
|
||||
};
|
||||
|
||||
typedef EekKeysymPrivate EekKeysymEntry;
|
||||
typedef struct _EekKeysymEntry EekKeysymEntry;
|
||||
|
||||
#include "eek-special-keysym-entries.h"
|
||||
#include "eek-unicode-keysym-entries.h"
|
||||
#include "eek-xkeysym-keysym-entries.h"
|
||||
|
||||
static const EekKeysymEntry invalid_keysym_entry = {
|
||||
EEK_INVALID_KEYSYM,
|
||||
"\0",
|
||||
EEK_SYMBOL_CATEGORY_UNKNOWN,
|
||||
};
|
||||
static void eek_serializable_iface_init (EekSerializableIface *iface);
|
||||
|
||||
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) \
|
||||
(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 *
|
||||
unichar_to_utf8 (gunichar uc)
|
||||
{
|
||||
@ -91,7 +133,7 @@ static int
|
||||
keysym_entry_compare_by_xkeysym (const void *key0, const void *key1)
|
||||
{
|
||||
const EekKeysymEntry *entry0 = key0, *entry1 = key1;
|
||||
return (gint)entry0->xkeysym - (gint)entry1->xkeysym;
|
||||
return (gint) (entry0->xkeysym - entry1->xkeysym);
|
||||
}
|
||||
|
||||
static EekKeysymEntry *
|
||||
@ -103,14 +145,7 @@ find_keysym_entry_by_xkeysym (guint xkeysym,
|
||||
|
||||
key.xkeysym = xkeysym;
|
||||
return bsearch (&key, entries, num_entries, sizeof (EekKeysymEntry),
|
||||
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;
|
||||
keysym_entry_compare_by_xkeysym);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -132,46 +167,10 @@ get_unichar (guint xkeysym, gunichar *uc) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gchar *
|
||||
eek_keysym_real_get_label (EekSymbol *self)
|
||||
G_INLINE_FUNC EekModifierType
|
||||
get_modifier_mask (guint xkeysym)
|
||||
{
|
||||
EekKeysymPrivate *priv = EEK_KEYSYM_GET_PRIVATE(self);
|
||||
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) {
|
||||
switch (xkeysym) {
|
||||
case EEK_KEYSYM_Shift_L:
|
||||
case EEK_KEYSYM_Shift_R:
|
||||
case EEK_KEYSYM_Caps_Lock:
|
||||
@ -201,15 +200,9 @@ eek_keysym_real_get_modifier_mask (EekSymbol *self)
|
||||
static void
|
||||
eek_keysym_class_init (EekKeysymClass *klass)
|
||||
{
|
||||
EekSymbolClass *symbol_class = EEK_SYMBOL_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
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
|
||||
@ -218,7 +211,7 @@ eek_keysym_init (EekKeysym *self)
|
||||
EekKeysymPrivate *priv;
|
||||
|
||||
priv = self->priv = EEK_KEYSYM_GET_PRIVATE(self);
|
||||
memcpy (priv, &invalid_keysym_entry, sizeof (EekKeysymEntry));
|
||||
priv->xkeysym = EEK_INVALID_KEYSYM;
|
||||
}
|
||||
|
||||
EekKeysym *
|
||||
@ -226,33 +219,77 @@ eek_keysym_new (guint xkeysym)
|
||||
{
|
||||
EekKeysym *keysym;
|
||||
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);
|
||||
priv = EEK_KEYSYM_GET_PRIVATE(keysym);
|
||||
priv->xkeysym = xkeysym;
|
||||
|
||||
/* First check the X standard keysyms */
|
||||
entry = find_keysym_entry_by_xkeysym (xkeysym,
|
||||
xkeysym_keysym_entries,
|
||||
G_N_ELEMENTS(xkeysym_keysym_entries));
|
||||
if (!entry) {
|
||||
gunichar uc;
|
||||
|
||||
/* Check the special unicode mappings */
|
||||
if (get_unichar (priv->xkeysym, &uc)) {
|
||||
priv->category = EEK_SYMBOL_CATEGORY_LETTER;
|
||||
return keysym;
|
||||
}
|
||||
|
||||
entry = find_keysym_entry_by_xkeysym
|
||||
(priv->xkeysym,
|
||||
unicode_keysym_entries,
|
||||
G_N_ELEMENTS(unicode_keysym_entries));
|
||||
special_entry =
|
||||
find_keysym_entry_by_xkeysym (xkeysym,
|
||||
special_keysym_entries,
|
||||
G_N_ELEMENTS(special_keysym_entries));
|
||||
xkeysym_entry =
|
||||
find_keysym_entry_by_xkeysym (xkeysym,
|
||||
xkeysym_keysym_entries,
|
||||
G_N_ELEMENTS(xkeysym_keysym_entries));
|
||||
unicode_entry =
|
||||
find_keysym_entry_by_xkeysym (xkeysym,
|
||||
unicode_keysym_entries,
|
||||
G_N_ELEMENTS(unicode_keysym_entries));
|
||||
unichar_entry = NULL;
|
||||
if (get_unichar (xkeysym, &uc)) {
|
||||
unichar_entry = g_slice_new (EekKeysymEntry);
|
||||
unichar_entry->xkeysym = xkeysym;
|
||||
unichar_entry->name = unichar_to_utf8 (uc);
|
||||
unichar_entry->category = EEK_SYMBOL_CATEGORY_LETTER;
|
||||
}
|
||||
|
||||
if (entry)
|
||||
memcpy (priv, entry, sizeof (EekKeysymEntry));
|
||||
/* name and category */
|
||||
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;
|
||||
}
|
||||
@ -260,25 +297,19 @@ eek_keysym_new (guint xkeysym)
|
||||
EekKeysym *
|
||||
eek_keysym_new_from_name (const gchar *name)
|
||||
{
|
||||
EekKeysym *keysym;
|
||||
EekKeysymPrivate *priv;
|
||||
gint i;
|
||||
|
||||
for (i = 0;
|
||||
i < G_N_ELEMENTS(xkeysym_keysym_entries) &&
|
||||
g_strcmp0 (xkeysym_keysym_entries[i].name, name) != 0; i++)
|
||||
;
|
||||
for (i = 0; i < G_N_ELEMENTS(xkeysym_keysym_entries); i++)
|
||||
if (g_strcmp0 (xkeysym_keysym_entries[i].name, name) == 0)
|
||||
return eek_keysym_new (xkeysym_keysym_entries[i].xkeysym);
|
||||
|
||||
keysym = g_object_new (EEK_TYPE_KEYSYM, NULL);
|
||||
priv = EEK_KEYSYM_GET_PRIVATE(keysym);
|
||||
|
||||
if (i < G_N_ELEMENTS(xkeysym_keysym_entries))
|
||||
memcpy (priv, &xkeysym_keysym_entries[i], sizeof (EekKeysymEntry));
|
||||
else {
|
||||
// g_warning ("can't find keysym entry for %s", name);
|
||||
memcpy (priv, &invalid_keysym_entry, sizeof (EekKeysymEntry));
|
||||
}
|
||||
return keysym;
|
||||
// g_warning ("can't find keysym entry for %s", name);
|
||||
return g_object_new (EEK_TYPE_KEYSYM,
|
||||
"name", name,
|
||||
"label", name,
|
||||
"category", EEK_SYMBOL_CATEGORY_UNKNOWN,
|
||||
"modifier-mask", 0,
|
||||
NULL);
|
||||
}
|
||||
|
||||
guint
|
||||
|
||||
@ -184,9 +184,9 @@ render_key_outline (EekRenderer *renderer,
|
||||
EekOutline *outline;
|
||||
EekBounds bounds;
|
||||
cairo_pattern_t *pat;
|
||||
EekPoint *points;
|
||||
gdouble scale;
|
||||
gint i;
|
||||
gulong oref;
|
||||
|
||||
/* need to rescale so that the border fit inside the clipping
|
||||
region */
|
||||
@ -194,12 +194,15 @@ render_key_outline (EekRenderer *renderer,
|
||||
scale = MIN((bounds.width - priv->border_width) / bounds.width,
|
||||
(bounds.height - priv->border_width) / bounds.height);
|
||||
|
||||
outline = eek_key_get_outline (key);
|
||||
points = g_slice_copy (sizeof (EekPoint) * outline->num_points,
|
||||
outline->points);
|
||||
oref = eek_key_get_oref (key);
|
||||
if (oref == 0)
|
||||
return;
|
||||
|
||||
outline = eek_keyboard_get_outline (priv->keyboard, oref);
|
||||
outline = eek_outline_copy (outline);
|
||||
for (i = 0; i < outline->num_points; i++) {
|
||||
points[i].x *= priv->scale * scale;
|
||||
points[i].y *= priv->scale * scale;
|
||||
outline->points[i].x *= priv->scale * scale;
|
||||
outline->points[i].y *= priv->scale * scale;
|
||||
}
|
||||
|
||||
cairo_translate (cr,
|
||||
@ -227,7 +230,7 @@ render_key_outline (EekRenderer *renderer,
|
||||
cairo_set_source (cr, pat);
|
||||
_eek_rounded_polygon (cr,
|
||||
outline->corner_radius,
|
||||
points,
|
||||
outline->points,
|
||||
outline->num_points);
|
||||
cairo_fill (cr);
|
||||
|
||||
@ -246,11 +249,11 @@ render_key_outline (EekRenderer *renderer,
|
||||
|
||||
_eek_rounded_polygon (cr,
|
||||
outline->corner_radius,
|
||||
points,
|
||||
outline->points,
|
||||
outline->num_points);
|
||||
cairo_stroke (cr);
|
||||
|
||||
g_slice_free1 (sizeof (EekPoint) * outline->num_points, points);
|
||||
eek_outline_free (outline);
|
||||
}
|
||||
|
||||
struct _CalculateFontSizeCallbackData {
|
||||
@ -338,6 +341,20 @@ calculate_font_size (EekRenderer *renderer)
|
||||
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
|
||||
render_key (EekRenderer *self,
|
||||
cairo_t *cr,
|
||||
@ -349,10 +366,16 @@ render_key (EekRenderer *self,
|
||||
EekBounds bounds;
|
||||
PangoLayout *layout;
|
||||
PangoRectangle extents = { 0, };
|
||||
gulong oref;
|
||||
EekKeyboard *keyboard;
|
||||
|
||||
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);
|
||||
if (!outline_surface) {
|
||||
|
||||
@ -34,6 +34,7 @@
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#include "eek-section.h"
|
||||
#include "eek-key.h"
|
||||
#include "eek-serializable.h"
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
@ -49,7 +50,11 @@ enum {
|
||||
|
||||
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) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_SECTION, EekSectionPrivate))
|
||||
@ -66,9 +71,82 @@ struct _EekSectionPrivate
|
||||
{
|
||||
gint angle;
|
||||
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
|
||||
eek_section_real_set_angle (EekSection *self,
|
||||
gint angle)
|
||||
@ -161,9 +239,6 @@ eek_section_real_create_key (EekSection *self,
|
||||
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_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
|
||||
eek_section_class_init (EekSectionClass *klass)
|
||||
{
|
||||
EekContainerClass *container_class = EEK_CONTAINER_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GParamSpec *pspec;
|
||||
|
||||
@ -253,6 +345,10 @@ eek_section_class_init (EekSectionClass *klass)
|
||||
klass->create_key = eek_section_real_create_key;
|
||||
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->get_property = eek_section_get_property;
|
||||
gobject_class->finalize = eek_section_finalize;
|
||||
|
||||
@ -53,23 +53,27 @@ eek_serializable_serialize (EekSerializable *object)
|
||||
EekSerializable *
|
||||
eek_serializable_deserialize (GVariant *variant)
|
||||
{
|
||||
GVariant *var = NULL;
|
||||
gchar *type_name = NULL;
|
||||
GType type;
|
||||
EekSerializable *object;
|
||||
gsize index = 0;
|
||||
|
||||
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);
|
||||
|
||||
g_return_val_if_fail (g_type_is_a (type, EEK_TYPE_SERIALIZABLE), NULL);
|
||||
|
||||
object = g_object_new (type, NULL);
|
||||
|
||||
EEK_SERIALIZABLE_GET_IFACE (object)->deserialize (object, var, 1);
|
||||
g_variant_unref (var);
|
||||
index = EEK_SERIALIZABLE_GET_IFACE (object)->deserialize (object,
|
||||
variant,
|
||||
index);
|
||||
if (index < 0) {
|
||||
g_object_unref (object);
|
||||
g_return_val_if_reached (NULL);
|
||||
}
|
||||
|
||||
g_object_unref (object);
|
||||
g_return_val_if_reached (NULL);
|
||||
return object;
|
||||
}
|
||||
|
||||
168
eek/eek-symbol.c
168
eek/eek-symbol.c
@ -23,6 +23,7 @@
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include "eek-symbol.h"
|
||||
#include "eek-serializable.h"
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
@ -40,71 +41,47 @@ struct _EekSymbolPrivate {
|
||||
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) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_SYMBOL, EekSymbolPrivate))
|
||||
|
||||
static void
|
||||
eek_symbol_real_set_name (EekSymbol *self,
|
||||
const gchar *name)
|
||||
eek_symbol_real_serialize (EekSerializable *self,
|
||||
GVariantBuilder *builder)
|
||||
{
|
||||
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 *
|
||||
eek_symbol_real_get_name (EekSymbol *self)
|
||||
static gsize
|
||||
eek_symbol_real_deserialize (EekSerializable *self,
|
||||
GVariant *variant,
|
||||
gsize index)
|
||||
{
|
||||
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
|
||||
eek_symbol_real_set_label (EekSymbol *self,
|
||||
const gchar *label)
|
||||
eek_serializable_iface_init (EekSerializableIface *iface)
|
||||
{
|
||||
EekSymbolPrivate *priv = EEK_SYMBOL_GET_PRIVATE(self);
|
||||
g_free (priv->label);
|
||||
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;
|
||||
iface->serialize = eek_symbol_real_serialize;
|
||||
iface->deserialize = eek_symbol_real_deserialize;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -121,11 +98,11 @@ eek_symbol_set_property (GObject *object,
|
||||
eek_symbol_set_label (EEK_SYMBOL(object), g_value_get_string (value));
|
||||
break;
|
||||
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;
|
||||
case PROP_MODIFIER_MASK:
|
||||
eek_symbol_set_modifier_mask (EEK_SYMBOL(object),
|
||||
g_value_get_int (value));
|
||||
g_value_get_uint (value));
|
||||
break;
|
||||
default:
|
||||
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)));
|
||||
break;
|
||||
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;
|
||||
case PROP_MODIFIER_MASK:
|
||||
g_value_set_int (value,
|
||||
eek_symbol_get_modifier_mask (EEK_SYMBOL(object)));
|
||||
g_value_set_uint (value,
|
||||
eek_symbol_get_modifier_mask (EEK_SYMBOL(object)));
|
||||
break;
|
||||
default:
|
||||
g_object_get_property (object,
|
||||
@ -180,32 +157,37 @@ eek_symbol_class_init (EekSymbolClass *klass)
|
||||
|
||||
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->get_property = eek_symbol_get_property;
|
||||
gobject_class->finalize = eek_symbol_finalize;
|
||||
|
||||
pspec = g_param_spec_string ("name",
|
||||
"Name",
|
||||
"Canonical name of the keysym",
|
||||
"Canonical name of the symbol",
|
||||
NULL,
|
||||
G_PARAM_READWRITE);
|
||||
G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class, PROP_NAME, pspec);
|
||||
|
||||
pspec = g_param_spec_string ("label",
|
||||
"Label",
|
||||
"Text used to display the keysym",
|
||||
"Text used to display the symbol",
|
||||
NULL,
|
||||
G_PARAM_READWRITE);
|
||||
G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
|
||||
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
|
||||
@ -230,58 +212,92 @@ void
|
||||
eek_symbol_set_name (EekSymbol *symbol,
|
||||
const gchar *name)
|
||||
{
|
||||
EekSymbolPrivate *priv;
|
||||
|
||||
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 *
|
||||
eek_symbol_get_name (EekSymbol *symbol)
|
||||
{
|
||||
EekSymbolPrivate *priv;
|
||||
|
||||
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
|
||||
eek_symbol_set_label (EekSymbol *symbol,
|
||||
const gchar *label)
|
||||
{
|
||||
EekSymbolPrivate *priv;
|
||||
|
||||
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 *
|
||||
eek_symbol_get_label (EekSymbol *symbol)
|
||||
{
|
||||
EekSymbolPrivate *priv;
|
||||
|
||||
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
|
||||
eek_symbol_set_category (EekSymbol *symbol,
|
||||
EekSymbolCategory category)
|
||||
{
|
||||
EekSymbolPrivate *priv;
|
||||
|
||||
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
|
||||
eek_symbol_get_category (EekSymbol *symbol)
|
||||
{
|
||||
EekSymbolPrivate *priv;
|
||||
|
||||
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
|
||||
eek_symbol_set_modifier_mask (EekSymbol *symbol,
|
||||
EekModifierType mask)
|
||||
{
|
||||
EekSymbolPrivate *priv;
|
||||
|
||||
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
|
||||
eek_symbol_get_modifier_mask (EekSymbol *symbol)
|
||||
{
|
||||
EekSymbolPrivate *priv;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -69,24 +69,6 @@ struct _EekSymbol {
|
||||
struct _EekSymbolClass {
|
||||
/*< private >*/
|
||||
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;
|
||||
|
||||
@ -27,9 +27,11 @@
|
||||
#include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include "eek-types.h"
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "eek-types.h"
|
||||
|
||||
/* EekSymbolMatrix */
|
||||
EekSymbolMatrix *
|
||||
eek_symbol_matrix_new (gint num_groups, gint num_levels)
|
||||
@ -147,15 +149,20 @@ eek_bounds_get_type (void)
|
||||
}
|
||||
|
||||
/* EekOutline */
|
||||
static EekOutline *
|
||||
EekOutline *
|
||||
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)
|
||||
{
|
||||
g_slice_free1 (sizeof (EekPoint) * outline->num_points, outline->points);
|
||||
g_slice_free (EekOutline, outline);
|
||||
}
|
||||
|
||||
|
||||
@ -192,7 +192,9 @@ struct _EekOutline
|
||||
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:
|
||||
|
||||
@ -70,8 +70,8 @@ struct _EekXkbLayoutPrivate
|
||||
/* Actual XKB configuration of DISPLAY. */
|
||||
XkbDescRec *xkb;
|
||||
|
||||
/* Hash table to cache outlines by shape address. */
|
||||
GHashTable *outline_hash;
|
||||
/* Hash table to cache orefs by shape address. */
|
||||
GHashTable *shape_oref_hash;
|
||||
|
||||
gint scale_numerator;
|
||||
gint scale_denominator;
|
||||
@ -109,6 +109,7 @@ xkb_to_pixmap_double (EekXkbLayout *layout,
|
||||
|
||||
static void
|
||||
create_key (EekXkbLayout *layout,
|
||||
EekKeyboard *keyboard,
|
||||
EekSection *section,
|
||||
gint column,
|
||||
gint row,
|
||||
@ -125,14 +126,16 @@ create_key (EekXkbLayout *layout,
|
||||
EekBounds bounds;
|
||||
EekSymbolMatrix *matrix = NULL;
|
||||
gchar name[XkbKeyNameLength + 1];
|
||||
EekOutline *outline;
|
||||
KeyCode keycode;
|
||||
gint num_groups, num_levels, num_symbols;
|
||||
gulong oref;
|
||||
|
||||
xkbgeometry = priv->xkb->geom;
|
||||
xkbshape = &xkbgeometry->shapes[xkbkey->shape_ndx];
|
||||
outline = g_hash_table_lookup (priv->outline_hash, xkbshape);
|
||||
if (outline == NULL) {
|
||||
oref = (gulong)g_hash_table_lookup (priv->shape_oref_hash, xkbshape);
|
||||
if (oref == 0) {
|
||||
EekOutline *outline;
|
||||
|
||||
xkboutline = xkbshape->primary == NULL ? &xkbshape->outlines[0] :
|
||||
xkbshape->primary;
|
||||
|
||||
@ -172,7 +175,8 @@ create_key (EekXkbLayout *layout,
|
||||
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);
|
||||
@ -210,7 +214,7 @@ create_key (EekXkbLayout *layout,
|
||||
eek_key_set_keycode (key, keycode);
|
||||
eek_key_set_symbol_matrix (key, matrix);
|
||||
eek_symbol_matrix_free (matrix);
|
||||
eek_key_set_outline (key, outline);
|
||||
eek_key_set_oref (key, oref);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -262,7 +266,7 @@ create_section (EekXkbLayout *layout,
|
||||
top += xkbkey->gap;
|
||||
else
|
||||
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;
|
||||
if (xkbrow->vertical)
|
||||
top += xkbbounds->y2 - xkbbounds->y1;
|
||||
@ -301,14 +305,6 @@ create_keyboard (EekXkbLayout *layout, EekKeyboard *keyboard)
|
||||
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 *
|
||||
eek_xkb_layout_real_create_keyboard (EekLayout *self,
|
||||
gdouble initial_width,
|
||||
@ -324,15 +320,12 @@ eek_xkb_layout_real_create_keyboard (EekLayout *self,
|
||||
bounds.height = initial_height;
|
||||
eek_element_set_bounds (EEK_ELEMENT(keyboard), &bounds);
|
||||
|
||||
if (priv->outline_hash)
|
||||
g_hash_table_unref (priv->outline_hash);
|
||||
|
||||
priv->outline_hash = g_hash_table_new_full (g_direct_hash,
|
||||
g_direct_equal,
|
||||
NULL,
|
||||
outline_free);
|
||||
if (priv->shape_oref_hash)
|
||||
g_hash_table_destroy (priv->shape_oref_hash);
|
||||
|
||||
priv->shape_oref_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
create_keyboard (EEK_XKB_LAYOUT(self), keyboard);
|
||||
g_hash_table_destroy (priv->shape_oref_hash);
|
||||
|
||||
return keyboard;
|
||||
}
|
||||
@ -345,8 +338,6 @@ eek_xkb_layout_finalize (GObject *object)
|
||||
g_free (priv->names.keycodes);
|
||||
g_free (priv->names.geometry);
|
||||
g_free (priv->names.symbols);
|
||||
if (priv->outline_hash)
|
||||
g_hash_table_unref (priv->outline_hash);
|
||||
XkbFreeKeyboard (priv->xkb, 0, TRUE); /* free_all = TRUE */
|
||||
G_OBJECT_CLASS (eek_xkb_layout_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
@ -48,7 +48,6 @@ G_DEFINE_TYPE (EekXmlLayout, eek_xml_layout, EEK_TYPE_LAYOUT);
|
||||
struct _EekXmlLayoutPrivate
|
||||
{
|
||||
GInputStream *source;
|
||||
GHashTable *outline_hash;
|
||||
};
|
||||
|
||||
#define BUFSIZE 8192
|
||||
@ -86,7 +85,7 @@ static const gchar *valid_path_list[] = {
|
||||
"orientation/row/section/keyboard",
|
||||
"key/section/keyboard",
|
||||
"bounds/key/section/keyboard",
|
||||
"outline-ref/key/section/keyboard",
|
||||
"oref/key/section/keyboard",
|
||||
"symbols/key/section/keyboard",
|
||||
"groups/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->num_points);
|
||||
for (head = data->points = g_slist_reverse (data->points), i = 0;
|
||||
head;
|
||||
head && i < outline->num_points;
|
||||
head = g_slist_next (head), i++) {
|
||||
memcpy (&outline->points[i], head->data, sizeof (EekPoint));
|
||||
g_slice_free1 (sizeof (EekPoint), head->data);
|
||||
@ -406,7 +405,7 @@ end_element_callback (GMarkupParseContext *pcontext,
|
||||
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));
|
||||
goto out;
|
||||
}
|
||||
@ -434,14 +433,6 @@ static const GMarkupParser parser = {
|
||||
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,
|
||||
gpointer user_data);
|
||||
|
||||
@ -485,6 +476,7 @@ eek_xml_layout_real_create_keyboard (EekLayout *self,
|
||||
gdouble scale;
|
||||
GHashTableIter iter;
|
||||
gpointer k, v;
|
||||
GHashTable *oref_hash;
|
||||
|
||||
g_return_val_if_fail (priv->source, NULL);
|
||||
|
||||
@ -495,10 +487,11 @@ eek_xml_layout_real_create_keyboard (EekLayout *self,
|
||||
g_direct_equal,
|
||||
NULL,
|
||||
g_free);
|
||||
data.oref_outline_hash = g_hash_table_new_full (g_str_hash,
|
||||
g_str_equal,
|
||||
g_free,
|
||||
outline_free);
|
||||
data.oref_outline_hash =
|
||||
g_hash_table_new_full (g_str_hash,
|
||||
g_str_equal,
|
||||
g_free,
|
||||
(GDestroyNotify)eek_outline_free);
|
||||
|
||||
pcontext = g_markup_parse_context_new (&parser, 0, &data, NULL);
|
||||
while (1) {
|
||||
@ -528,36 +521,44 @@ eek_xml_layout_real_create_keyboard (EekLayout *self,
|
||||
if (!data.keyboard)
|
||||
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);
|
||||
scale = initial_width * bounds.height < initial_height * bounds.width ?
|
||||
initial_width / bounds.width :
|
||||
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);
|
||||
while (g_hash_table_iter_next (&iter, &k, &v)) {
|
||||
EekOutline *outline = v;
|
||||
gulong oref;
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < outline->num_points; i++) {
|
||||
outline->points[i].x *= 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);
|
||||
|
||||
out:
|
||||
g_string_free (data.text, TRUE);
|
||||
if (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;
|
||||
}
|
||||
@ -612,17 +613,6 @@ eek_xml_layout_dispose (GObject *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
|
||||
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->get_property = eek_xml_layout_get_property;
|
||||
gobject_class->dispose = eek_xml_layout_dispose;
|
||||
gobject_class->finalize = eek_xml_layout_finalize;
|
||||
|
||||
pspec = g_param_spec_object ("source",
|
||||
"Source",
|
||||
|
||||
@ -54,7 +54,7 @@ g_string_markup_printf (GString *output, const gchar *format, ...)
|
||||
struct _OutputCallbackData {
|
||||
GString *output;
|
||||
gint indent;
|
||||
GArray *outline_array;
|
||||
GHashTable *oref_hash;
|
||||
gint key_serial;
|
||||
};
|
||||
typedef struct _OutputCallbackData OutputCallbackData;
|
||||
@ -75,12 +75,12 @@ output_key_callback (EekElement *element, gpointer user_data)
|
||||
{
|
||||
OutputCallbackData *data = user_data;
|
||||
EekBounds bounds;
|
||||
EekOutline *outline;
|
||||
gint i, num_symbols;
|
||||
EekSymbolMatrix *matrix;
|
||||
gint column, row;
|
||||
guint keycode;
|
||||
gchar *id;
|
||||
gulong oref;
|
||||
|
||||
keycode = eek_key_get_keycode (EEK_KEY(element));
|
||||
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);
|
||||
output_bounds (data->output, &bounds);
|
||||
|
||||
outline = eek_key_get_outline (EEK_KEY(element));
|
||||
if (outline) {
|
||||
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);
|
||||
oref = eek_key_get_oref (EEK_KEY(element));
|
||||
if (oref != 0) {
|
||||
g_string_append_indent (data->output, data->indent + 1);
|
||||
g_string_markup_printf (data->output,
|
||||
"<outline-ref>outline%d</outline-ref>\n",
|
||||
i);
|
||||
"<oref>outline%u</oref>\n",
|
||||
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));
|
||||
@ -224,7 +221,8 @@ eek_keyboard_output (EekKeyboard *keyboard, GString *output, gint indent)
|
||||
{
|
||||
OutputCallbackData data;
|
||||
EekBounds bounds;
|
||||
gint i;
|
||||
gulong oref;
|
||||
GHashTableIter iter;
|
||||
|
||||
g_assert (EEK_IS_KEYBOARD(keyboard));
|
||||
|
||||
@ -245,7 +243,7 @@ eek_keyboard_output (EekKeyboard *keyboard, GString *output, gint indent)
|
||||
|
||||
data.output = output;
|
||||
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.indent++;
|
||||
@ -254,14 +252,14 @@ eek_keyboard_output (EekKeyboard *keyboard, GString *output, gint indent)
|
||||
&data);
|
||||
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;
|
||||
gint j;
|
||||
|
||||
outline = eek_keyboard_get_outline (keyboard, oref);
|
||||
g_string_append_indent (output, indent + 1);
|
||||
g_string_markup_printf (output, "<outline id=\"outline%d\">\n", i);
|
||||
|
||||
outline = g_array_index (data.outline_array, gpointer, i);
|
||||
g_string_markup_printf (output, "<outline id=\"outline%u\">\n", oref);
|
||||
for (j = 0; j < outline->num_points; j++) {
|
||||
g_string_append_indent (output, indent + 2);
|
||||
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_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_markup_printf (output, "</keyboard>\n");
|
||||
|
||||
@ -27,5 +27,6 @@
|
||||
#include "eek-symbol.h"
|
||||
#include "eek-keysym.h"
|
||||
#include "eek-xml.h"
|
||||
#include "eek-serializable.h"
|
||||
|
||||
#endif /* EEK_H */
|
||||
|
||||
@ -70,6 +70,7 @@ main (int argc, char **argv)
|
||||
gint retval = 0;
|
||||
|
||||
g_type_init ();
|
||||
g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL);
|
||||
|
||||
context = g_option_context_new ("eekboard-client");
|
||||
g_option_context_add_main_entries (context, options, NULL);
|
||||
|
||||
12
src/proxy.c
12
src/proxy.c
@ -21,8 +21,6 @@
|
||||
|
||||
#include "proxy.h"
|
||||
|
||||
#define BUFSIZE 8192
|
||||
|
||||
enum {
|
||||
KEY_PRESSED,
|
||||
KEY_RELEASED,
|
||||
@ -150,17 +148,9 @@ proxy_call_async_ready_cb (GObject *source_object,
|
||||
void
|
||||
eekboard_proxy_set_keyboard (EekboardProxy *proxy, EekKeyboard *keyboard)
|
||||
{
|
||||
GString *output;
|
||||
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),
|
||||
"SetKeyboard",
|
||||
g_variant_new ("(v)", variant),
|
||||
|
||||
@ -50,6 +50,14 @@ main (int argc, char **argv)
|
||||
}
|
||||
#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;
|
||||
connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
|
||||
if (error) {
|
||||
|
||||
15
src/server.c
15
src/server.c
@ -310,26 +310,21 @@ handle_method_call (GDBusConnection *connection,
|
||||
|
||||
// g_debug ("%s", method_name);
|
||||
if (g_strcmp0 (method_name, "SetKeyboard") == 0) {
|
||||
EekSerializable *serializable;
|
||||
GVariant *variant;
|
||||
gchar *data;
|
||||
GInputStream *input;
|
||||
EekLayout *layout;
|
||||
|
||||
g_variant_get (parameters, "(v)", &variant);
|
||||
g_variant_get (variant, "(&s)", &data);
|
||||
input = g_memory_input_stream_new_from_data (data, -1, NULL);
|
||||
g_variant_unref (variant);
|
||||
|
||||
layout = eek_xml_layout_new (input);
|
||||
if (!layout) {
|
||||
serializable = eek_serializable_deserialize (variant);
|
||||
if (!EEK_IS_KEYBOARD(serializable)) {
|
||||
g_dbus_method_invocation_return_error (invocation,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_FAILED_HANDLED,
|
||||
"can't create layout");
|
||||
"not a keyboard");
|
||||
return;
|
||||
}
|
||||
|
||||
server->keyboard = eek_keyboard_new (layout, CSW, CSH);
|
||||
server->keyboard = EEK_KEYBOARD(serializable);
|
||||
disconnect_keyboard_signals (server);
|
||||
server->key_pressed_handler =
|
||||
g_signal_connect (server->keyboard, "key-pressed",
|
||||
|
||||
Reference in New Issue
Block a user