Commit ee0505c1 authored by Daiki Ueno's avatar Daiki Ueno
Browse files

Add keyboard selection dialog to preferences.

parent 1943749c
......@@ -256,7 +256,6 @@ Build options:
Build shared libs $enable_shared
Build static libs $enable_static
CFLAGS $CFLAGS
GTK version $with_gtk
Build Vala binding $enable_vala
Sound support $enable_libcanberra
Build document $enable_gtk_doc
......
......@@ -119,7 +119,7 @@ eek_gtk_keyboard_real_draw (GtkWidget *self,
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(self);
GtkAllocation allocation;
EekColor background;
GList *head;
GList *list, *head;
gtk_widget_get_allocation (self, &allocation);
......@@ -164,16 +164,18 @@ eek_gtk_keyboard_real_draw (GtkWidget *self,
eek_renderer_render_keyboard (priv->renderer, cr);
/* redraw pressed key */
head = eek_keyboard_get_pressed_keys (priv->keyboard);
for (; head; head = g_list_next (head)) {
list = eek_keyboard_get_pressed_keys (priv->keyboard);
for (head = list; head; head = g_list_next (head)) {
render_pressed_key (self, head->data);
}
g_list_free (list);
/* redraw locked key */
head = eek_keyboard_get_locked_keys (priv->keyboard);
for (; head; head = g_list_next (head)) {
list = eek_keyboard_get_locked_keys (priv->keyboard);
for (head = list; head; head = g_list_next (head)) {
render_locked_key (self, ((EekModifierKey *)head->data)->key);
}
g_list_free (list);
return FALSE;
}
......@@ -213,16 +215,12 @@ eek_gtk_keyboard_real_button_release_event (GtkWidget *self,
GdkEventButton *event)
{
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(self);
GList *head = eek_keyboard_get_pressed_keys (priv->keyboard);
/* Make a copy of HEAD before sending "released" signal on
elements, so that the default handler of
EekKeyboard::key-released signal can remove elements from its
internal copy */
head = g_list_copy (head);
for (; head; head = g_list_next (head))
GList *list, *head;
list = eek_keyboard_get_pressed_keys (priv->keyboard);
for (head = list; head; head = g_list_next (head))
g_signal_emit_by_name (head->data, "released", priv->keyboard);
g_list_free (head);
g_list_free (list);
return TRUE;
}
......@@ -238,21 +236,17 @@ eek_gtk_keyboard_real_motion_notify_event (GtkWidget *self,
(gdouble)event->x,
(gdouble)event->y);
if (key) {
GList *head = eek_keyboard_get_pressed_keys (priv->keyboard);
GList *list, *head;
gboolean found = FALSE;
/* Make a copy of HEAD before sending "cancelled" signal on
elements, so that the default handler of
EekKeyboard::key-cancelled signal can remove elements from its
internal copy */
head = g_list_copy (head);
for (; head; head = g_list_next (head)) {
list = eek_keyboard_get_pressed_keys (priv->keyboard);
for (head = list; head; head = g_list_next (head)) {
if (head->data == key)
found = TRUE;
else
g_signal_emit_by_name (head->data, "cancelled", priv->keyboard);
}
g_list_free (head);
g_list_free (list);
if (!found)
g_signal_emit_by_name (key, "pressed", priv->keyboard);
......@@ -266,16 +260,16 @@ eek_gtk_keyboard_real_unmap (GtkWidget *self)
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(self);
if (priv->keyboard) {
GList *head = eek_keyboard_get_pressed_keys (priv->keyboard);
GList *list, *head;
/* Make a copy of HEAD before sending "released" signal on
elements, so that the default handler of
EekKeyboard::key-released signal can remove elements from its
internal copy */
head = g_list_copy (head);
for (; head; head = g_list_next (head))
list = eek_keyboard_get_pressed_keys (priv->keyboard);
for (head = list; head; head = g_list_next (head))
g_signal_emit_by_name (head->data, "released", priv->keyboard);
g_list_free (head);
g_list_free (list);
}
GTK_WIDGET_CLASS (eek_gtk_keyboard_parent_class)->unmap (self);
......@@ -363,12 +357,13 @@ eek_gtk_keyboard_dispose (GObject *object)
g_signal_handler_disconnect (priv->keyboard,
priv->symbol_index_changed_handler);
GList *head;
GList *list, *head;
head = eek_keyboard_get_pressed_keys (priv->keyboard);
for (; head; head = g_list_next (head)) {
list = eek_keyboard_get_pressed_keys (priv->keyboard);
for (head = list; head; head = g_list_next (head)) {
g_signal_emit_by_name (head->data, "released", priv->keyboard);
}
g_list_free (list);
g_object_unref (priv->keyboard);
priv->keyboard = NULL;
......
......@@ -74,6 +74,22 @@ struct _EekKeyboardPrivate
EekModifierType alt_gr_mask;
};
G_DEFINE_BOXED_TYPE(EekModifierKey, eek_modifier_key,
eek_modifier_key_copy, eek_modifier_key_free);
EekModifierKey *
eek_modifier_key_copy (EekModifierKey *modkey)
{
return g_slice_dup (EekModifierKey, modkey);
}
void
eek_modifier_key_free (EekModifierKey *modkey)
{
g_object_unref (modkey->key);
g_slice_free (EekModifierKey, modkey);
}
static void
on_key_pressed (EekSection *section,
EekKey *key,
......@@ -240,7 +256,7 @@ set_modifiers_with_key (EekKeyboard *self,
if (priv->modifier_behavior != EEK_MODIFIER_BEHAVIOR_NONE) {
EekModifierKey *modifier_key = g_slice_new (EekModifierKey);
modifier_key->modifiers = enabled;
modifier_key->key = key;
modifier_key->key = g_object_ref (key);
priv->locked_keys =
g_list_prepend (priv->locked_keys, modifier_key);
g_signal_emit_by_name (modifier_key->key, "locked");
......@@ -356,7 +372,8 @@ eek_keyboard_finalize (GObject *object)
gint i;
g_list_free (priv->pressed_keys);
g_list_free (priv->locked_keys);
g_list_free_full (priv->locked_keys,
(GDestroyNotify) eek_modifier_key_free);
for (i = 0; i < priv->outline_array->len; i++) {
EekOutline *outline = &g_array_index (priv->outline_array,
......@@ -810,7 +827,7 @@ GList *
eek_keyboard_get_pressed_keys (EekKeyboard *keyboard)
{
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), NULL);
return keyboard->priv->pressed_keys;
return g_list_copy (keyboard->priv->pressed_keys);
}
/**
......@@ -825,5 +842,5 @@ GList *
eek_keyboard_get_locked_keys (EekKeyboard *keyboard)
{
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), NULL);
return keyboard->priv->locked_keys;
return g_list_copy (keyboard->priv->locked_keys);
}
......@@ -183,5 +183,10 @@ GList *eek_keyboard_get_pressed_keys
GList *eek_keyboard_get_locked_keys
(EekKeyboard *keyboard);
EekModifierKey *eek_modifier_key_copy
(EekModifierKey *modkey);
void eek_modifier_key_free
(EekModifierKey *modkey);
G_END_DECLS
#endif /* EEK_KEYBOARD_H */
......@@ -56,11 +56,13 @@ struct _EekXmlLayoutPrivate
EekXmlKeyboardDesc *desc;
};
G_DEFINE_BOXED_TYPE(EekXmlKeyboardDesc, eek_xml_keyboard_desc, eek_xml_keyboard_desc_copy, eek_xml_keyboard_desc_free);
#define BUFSIZE 8192
static GSList *parse_keyboards (const gchar *path,
static GList *parse_keyboards (const gchar *path,
GError **error);
static GSList *parse_prerequisites
static GList *parse_prerequisites
(const gchar *path,
GError **error);
static gboolean parse_geometry (const gchar *path,
......@@ -69,7 +71,7 @@ static gboolean parse_geometry (const gchar *path,
static gboolean parse_symbols_with_prerequisites
(const gchar *name,
EekKeyboard *keyboard,
GSList **loaded,
GList **loaded,
GError **error);
static gboolean parse_symbols (const gchar *path,
EekKeyboard *keyboard,
......@@ -107,7 +109,7 @@ keyboard_desc_free (EekXmlKeyboardDesc *desc)
struct _KeyboardsParseData {
GSList *element_stack;
GSList *keyboards;
GList *keyboards;
};
typedef struct _KeyboardsParseData KeyboardsParseData;
......@@ -120,7 +122,7 @@ keyboards_parse_data_new (void)
static void
keyboards_parse_data_free (KeyboardsParseData *data)
{
g_slist_free_full (data->keyboards, (GDestroyNotify) keyboard_desc_free);
g_list_free_full (data->keyboards, (GDestroyNotify) keyboard_desc_free);
g_slice_free (KeyboardsParseData, data);
}
......@@ -150,7 +152,7 @@ keyboards_start_element_callback (GMarkupParseContext *pcontext,
EekXmlKeyboardDesc *desc = g_slice_new0 (EekXmlKeyboardDesc);
const gchar *attribute;
data->keyboards = g_slist_prepend (data->keyboards, desc);
data->keyboards = g_list_prepend (data->keyboards, desc);
attribute = get_attribute (attribute_names, attribute_values,
"id");
......@@ -821,7 +823,7 @@ struct _PrerequisitesParseData {
GSList *element_stack;
GString *text;
GSList *prerequisites;
GList *prerequisites;
};
typedef struct _PrerequisitesParseData PrerequisitesParseData;
......@@ -836,7 +838,7 @@ prerequisites_parse_data_new (void)
static void
prerequisites_parse_data_free (PrerequisitesParseData *data)
{
g_slist_free_full (data->prerequisites, g_free);
g_list_free_full (data->prerequisites, g_free);
g_string_free (data->text, TRUE);
g_slice_free (PrerequisitesParseData, data);
}
......@@ -877,7 +879,7 @@ prerequisites_end_element_callback (GMarkupParseContext *pcontext,
g_slist_free1 (head);
if (g_strcmp0 (element_name, "include") == 0) {
data->prerequisites = g_slist_append (data->prerequisites,
data->prerequisites = g_list_append (data->prerequisites,
g_strndup (data->text->str,
data->text->len));
}
......@@ -910,7 +912,7 @@ eek_xml_layout_real_create_keyboard (EekLayout *self,
EekXmlLayout *layout = EEK_XML_LAYOUT (self);
EekKeyboard *keyboard;
gchar *filename, *path;
GSList *loaded;
GList *loaded;
GError *error;
gboolean retval;
......@@ -935,15 +937,13 @@ eek_xml_layout_real_create_keyboard (EekLayout *self,
return NULL;
}
EekKey *key = eek_keyboard_find_key_by_keycode (keyboard,
149);
/* Read symbols information. */
loaded = NULL;
retval = parse_symbols_with_prerequisites (layout->priv->desc->symbols,
keyboard,
&loaded,
&error);
g_slist_free_full (loaded, g_free);
g_list_free_full (loaded, g_free);
if (!retval) {
g_object_unref (keyboard);
g_warning ("can't parse symbols file %s: %s",
......@@ -1057,7 +1057,7 @@ initable_init (GInitable *initable,
GError **error)
{
EekXmlLayout *layout = EEK_XML_LAYOUT (initable);
GSList *keyboards, *p;
GList *keyboards, *p;
gchar *path;
EekXmlKeyboardDesc *desc;
......@@ -1081,10 +1081,10 @@ initable_init (GInitable *initable,
return FALSE;
}
keyboards = g_slist_remove_link (keyboards, p);
keyboards = g_list_remove_link (keyboards, p);
layout->priv->desc = p->data;
g_slist_free_1 (p);
g_slist_free_full (keyboards, (GDestroyNotify) keyboard_desc_free);
g_list_free_1 (p);
g_list_free_full (keyboards, (GDestroyNotify) keyboard_desc_free);
return TRUE;
}
......@@ -1095,14 +1095,34 @@ initable_iface_init (GInitableIface *initable_iface)
initable_iface->init = initable_init;
}
GSList *
eek_xml_layout_list_keyboards (void)
GList *
eek_xml_list_keyboards (void)
{
gchar *path;
GSList *keyboards;
GList *keyboards;
path = g_build_filename (KEYBOARDSDIR, "keyboards.xml", NULL);
return parse_keyboards (path, NULL);
keyboards = parse_keyboards (path, NULL);
g_free (path);
return keyboards;
}
EekXmlKeyboardDesc *
eek_xml_keyboard_desc_copy (EekXmlKeyboardDesc *desc)
{
return g_slice_dup (EekXmlKeyboardDesc, desc);
}
void
eek_xml_keyboard_desc_free (EekXmlKeyboardDesc *desc)
{
g_free (desc->id);
g_free (desc->name);
g_free (desc->geometry);
g_free (desc->symbols);
g_free (desc->language);
g_free (desc->longname);
g_slice_free (EekXmlKeyboardDesc, desc);
}
static gboolean
......@@ -1164,11 +1184,11 @@ parse_geometry (const gchar *path, EekKeyboard *keyboard, GError **error)
static gboolean
parse_symbols_with_prerequisites (const gchar *name,
EekKeyboard *keyboard,
GSList **loaded,
GList **loaded,
GError **error)
{
gchar *filename, *path;
GSList *prerequisites, *p;
GList *prerequisites, *p;
GError *prerequisites_error;
gboolean retval;
......@@ -1182,7 +1202,7 @@ parse_symbols_with_prerequisites (const gchar *name,
return FALSE;
}
}
*loaded = g_slist_prepend (*loaded, g_strdup (name));
*loaded = g_list_prepend (*loaded, g_strdup (name));
filename = g_strdup_printf ("%s.xml", name);
path = g_build_filename (KEYBOARDSDIR, "symbols", filename, NULL);
......@@ -1203,7 +1223,7 @@ parse_symbols_with_prerequisites (const gchar *name,
if (!retval)
return FALSE;
}
g_slist_free_full (prerequisites, (GDestroyNotify)g_free);
g_list_free_full (prerequisites, (GDestroyNotify)g_free);
retval = parse_symbols (path, keyboard, error);
g_free (path);
......@@ -1243,14 +1263,14 @@ parse_symbols (const gchar *path, EekKeyboard *keyboard, GError **error)
return TRUE;
}
static GSList *
static GList *
parse_prerequisites (const gchar *path, GError **error)
{
PrerequisitesParseData *data;
GMarkupParseContext *pcontext;
GFile *file;
GFileInputStream *input;
GSList *prerequisites;
GList *prerequisites;
gboolean retval;
file = g_file_new_for_path (path);
......@@ -1278,14 +1298,14 @@ parse_prerequisites (const gchar *path, GError **error)
return prerequisites;
}
static GSList *
static GList *
parse_keyboards (const gchar *path, GError **error)
{
KeyboardsParseData *data;
GMarkupParseContext *pcontext;
GFile *file;
GFileInputStream *input;
GSList *keyboards;
GList *keyboards;
gboolean retval;
file = g_file_new_for_path (path);
......
......@@ -76,10 +76,13 @@ struct _EekXmlKeyboardDesc
};
typedef struct _EekXmlKeyboardDesc EekXmlKeyboardDesc;
GType eek_xml_layout_get_type (void) G_GNUC_CONST;
EekLayout *eek_xml_layout_new (const gchar *id,
GError **error);
GSList *eek_xml_layout_list_keyboards (void);
GType eek_xml_layout_get_type (void) G_GNUC_CONST;
EekLayout *eek_xml_layout_new (const gchar *id,
GError **error);
GList *eek_xml_list_keyboards (void);
EekXmlKeyboardDesc *eek_xml_keyboard_desc_copy (EekXmlKeyboardDesc *desc);
void eek_xml_keyboard_desc_free (EekXmlKeyboardDesc *desc);
G_END_DECLS
#endif /* EEK_XML_LAYOUT_H */
......@@ -50,6 +50,7 @@ enum {
enum {
ENABLED,
DISABLED,
DESTROYED,
LAST_SIGNAL
};
......@@ -114,8 +115,9 @@ static const gchar introspection_xml[] =
/* signals */
" <signal name='Enabled'/>"
" <signal name='Disabled'/>"
" <signal name='Destroyed'/>"
" <signal name='KeyActivated'>"
" <arg type='s' name='keyname'/>"
" <arg type='u' name='keycode'/>"
" <arg type='v' name='symbol'/>"
" <arg type='u' name='modifiers'/>"
" </signal>"
......@@ -399,6 +401,23 @@ eekboard_context_service_class_init (EekboardContextServiceClass *klass)
G_TYPE_NONE,
0);
/**
* EekboardContextService::destroyed:
* @context: an #EekboardContextService
*
* Emitted when @context is destroyed.
*/
signals[DESTROYED] =
g_signal_new (I_("destroyed"),
G_TYPE_FROM_CLASS(gobject_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(EekboardContextServiceClass, destroyed),
NULL,
NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0);
/**
* EekboardContextService:object-path:
*
......@@ -574,7 +593,7 @@ emit_key_activated_dbus_signal (EekboardContextService *context,
EekKey *key)
{
if (context->priv->connection && context->priv->enabled) {
const gchar *keyname = eek_element_get_name (EEK_ELEMENT(key));
guint keycode = eek_key_get_keycode (key);
EekSymbol *symbol = eek_key_get_symbol_with_fallback (key, 0, 0);
guint modifiers = eek_keyboard_get_modifiers (context->priv->keyboard);
GVariant *variant;
......@@ -589,8 +608,8 @@ emit_key_activated_dbus_signal (EekboardContextService *context,
context->priv->object_path,
EEKBOARD_CONTEXT_SERVICE_INTERFACE,
"KeyActivated",
g_variant_new ("(svu)",
keyname,
g_variant_new ("(uvu)",
keycode,
variant,
modifiers),
&error);
......@@ -748,13 +767,15 @@ handle_method_call (GDBusConnection *connection,
g_variant_get (parameters, "(u)", &keyboard_id);
current_keyboard_id =
GPOINTER_TO_UINT (g_object_get_data (G_OBJECT(context->priv->keyboard),
"keyboard-id"));
if (keyboard_id == current_keyboard_id) {
disconnect_keyboard_signals (context);
context->priv->keyboard = NULL;
g_object_notify (G_OBJECT(context), "keyboard");
if (context->priv->keyboard != NULL) {
current_keyboard_id =
GPOINTER_TO_UINT (g_object_get_data (G_OBJECT(context->priv->keyboard),
"keyboard-id"));
if (keyboard_id == current_keyboard_id) {
disconnect_keyboard_signals (context);
context->priv->keyboard = NULL;
g_object_notify (G_OBJECT(context), "keyboard");
}
}
g_hash_table_remove (context->priv->keyboard_hash,
......@@ -978,6 +999,42 @@ eekboard_context_service_disable (EekboardContextService *context)
}
}
/**
* eekboard_context_service_destroy:
* @context: an #EekboardContextService
*
* Destroy @context.
*/
void
eekboard_context_service_destroy (EekboardContextService *context)
{
gboolean retval;
GError *error;
g_return_if_fail (EEKBOARD_IS_CONTEXT_SERVICE(context));
g_return_if_fail (context->priv->connection);
if (context->priv->enabled) {
eekboard_context_service_disable (context);
}
error = NULL;
retval = g_dbus_connection_emit_signal (context->priv->connection,
NULL,
context->priv->object_path,
EEKBOARD_CONTEXT_SERVICE_INTERFACE,
"Destroyed",
NULL,
&error);
if (!retval) {
g_warning ("failed to emit Destroyed signal: %s",
error->message);
g_error_free (error);
g_assert_not_reached ();
}
g_signal_emit (context, signals[DESTROYED], 0);
}
/**
* eekboard_context_service_get_keyboard:
* @context: an #EekboardContextService
......
......@@ -73,6 +73,7 @@ struct _EekboardContextServiceClass {
/* signals */
void (*enabled) (EekboardContextService *self);
void (*disabled) (EekboardContextService *self);
void (*destroyed) (EekboardContextService *self);
/*< private >*/
/* padding */
......@@ -83,6 +84,7 @@ GType eekboard_context_service_get_type
(void) G_GNUC_CONST;
void eekboard_context_service_enable (EekboardContextService *context);
void eekboard_context_service_disable (EekboardContextService *context);
void eekboard_context_service_destroy (EekboardContextService *context);
EekKeyboard *eekboard_context_service_get_keyboard
(EekboardContextService *context);
gboolean eekboard_context_service_get_fullscreen
......
......@@ -36,8 +36,8 @@
enum {
ENABLED,
DISABLED,
KEY_PRESSED,
DESTROYED,
KEY_ACTIVATED,
LAST_SIGNAL
};
......@@ -80,14 +80,19 @@ eekboard_context_real_g_signal (GDBusProxy *self,
return;
}
if (g_strcmp0 (signal_name, "Destroyed") == 0) {
g_signal_emit (context, signals[DESTROYED], 0);
return;
}
if (g_strcmp0 (signal_name, "KeyActivated") == 0) {
const gchar *keyname;
guint keycode;
GVariant *variant = NULL;
guint modifiers = 0;
EekSerializable *serializable;
g_variant_get (parameters, "(&svu)",
&keyname, &variant, &modifiers);
g_variant_get (parameters, "(uvu)",
&keycode, &variant, &modifiers);
g_return_if_fail (variant != NULL);
serializable = eek_serializable_deserialize (variant);
......@@ -95,8 +100,8 @@ eekboard_context_real_g_signal (GDBusProxy *self,
g_return_if_fail (EEK_IS_SYMBOL(serializable));
g_signal_emit (context, signals[KEY_PRESSED], 0,
keyname, EEK_SYMBOL(serializable), modifiers);
g_signal_emit (context, signals[KEY_ACTIVATED], 0,
keycode, EEK_SYMBOL(serializable), modifiers);