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");
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user