diff --git a/eek/eek-key.c b/eek/eek-key.c index 9abe6b81..7256b5bc 100644 --- a/eek/eek-key.c +++ b/eek/eek-key.c @@ -451,7 +451,7 @@ eek_key_class_init (EekKeyClass *klass) signals[PRESSED] = g_signal_new (I_("pressed"), G_TYPE_FROM_CLASS(gobject_class), - G_SIGNAL_RUN_FIRST, + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(EekKeyClass, pressed), NULL, NULL, @@ -468,7 +468,7 @@ eek_key_class_init (EekKeyClass *klass) signals[RELEASED] = g_signal_new (I_("released"), G_TYPE_FROM_CLASS(gobject_class), - G_SIGNAL_RUN_FIRST, + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(EekKeyClass, released), NULL, NULL, diff --git a/eek/eek-keyboard.c b/eek/eek-keyboard.c index a7d453f6..4305446a 100644 --- a/eek/eek-keyboard.c +++ b/eek/eek-keyboard.c @@ -68,6 +68,7 @@ struct _EekKeyboardPrivate EekModifierBehavior modifier_behavior; EekModifierType modifiers; GArray *outline_array; + EekModifierType num_lock_mask; }; static EekSerializableIface *eek_keyboard_parent_serializable_iface; @@ -142,6 +143,7 @@ eek_keyboard_real_serialize (EekSerializable *self, _g_variant_new_outline (outline)); } g_variant_builder_add (builder, "v", g_variant_builder_end (&array)); + g_variant_builder_add (builder, "u", priv->num_lock_mask); } static gsize @@ -164,6 +166,7 @@ eek_keyboard_real_deserialize (EekSerializable *self, EekOutline *_outline = _g_variant_get_outline (outline); g_array_append_val (priv->outline_array, *_outline); } + g_variant_get_child (variant, index++, "u", &priv->num_lock_mask); return index; } @@ -194,6 +197,15 @@ on_key_released (EekSection *section, g_signal_emit_by_name (keyboard, "key-released", key); } +static void +on_symbol_index_changed (EekSection *section, + gint group, + gint level, + EekKeyboard *keyboard) +{ + g_signal_emit_by_name (keyboard, "symbol-index-changed", group, level); +} + static EekSection * eek_keyboard_real_create_section (EekKeyboard *self) { @@ -309,10 +321,8 @@ eek_keyboard_real_key_pressed (EekKeyboard *self, EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(self); EekSymbol *symbol; EekModifierType modifier; - gint group, level; - eek_element_get_symbol_index (EEK_ELEMENT(self), &group, &level); - symbol = eek_key_get_symbol_at_index (key, group, level, 0, 0); + symbol = eek_key_get_symbol_with_fallback (key, 0, 0); if (!symbol) return; @@ -338,10 +348,8 @@ eek_keyboard_real_key_released (EekKeyboard *self, EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(self); EekSymbol *symbol; EekModifierType modifier; - gint group, level; - eek_element_get_symbol_index (EEK_ELEMENT(self), &group, &level); - symbol = eek_key_get_symbol_at_index (key, group, level, 0, 0); + symbol = eek_key_get_symbol_with_fallback (key, 0, 0); if (!symbol) return; @@ -392,6 +400,8 @@ eek_keyboard_real_child_added (EekContainer *self, G_CALLBACK(on_key_pressed), self); g_signal_connect (element, "key-released", G_CALLBACK(on_key_released), self); + g_signal_connect (element, "symbol-index-changed", + G_CALLBACK(on_symbol_index_changed), self); } static void @@ -506,6 +516,7 @@ eek_keyboard_init (EekKeyboard *self) priv->modifier_behavior = EEK_MODIFIER_BEHAVIOR_NONE; priv->modifiers = 0; priv->outline_array = g_array_new (FALSE, TRUE, sizeof (EekOutline)); + priv->num_lock_mask = 0; eek_element_set_symbol_index (EEK_ELEMENT(self), 0, 0); } @@ -789,3 +800,26 @@ eek_keyboard_get_outline (EekKeyboard *keyboard, return &g_array_index (priv->outline_array, EekOutline, oref - 1); } + +void +eek_keyboard_set_num_lock_mask (EekKeyboard *keyboard, + EekModifierType num_lock_mask) +{ + EekKeyboardPrivate *priv; + + g_assert (EEK_IS_KEYBOARD(keyboard)); + priv = EEK_KEYBOARD_GET_PRIVATE(keyboard); + + priv->num_lock_mask = num_lock_mask; +} + +EekModifierType +eek_keyboard_get_num_lock_mask (EekKeyboard *keyboard) +{ + EekKeyboardPrivate *priv; + + g_assert (EEK_IS_KEYBOARD(keyboard)); + priv = EEK_KEYBOARD_GET_PRIVATE(keyboard); + + return priv->num_lock_mask; +} diff --git a/eek/eek-keyboard.h b/eek/eek-keyboard.h index e8397c57..d8f9c873 100644 --- a/eek/eek-keyboard.h +++ b/eek/eek-keyboard.h @@ -147,5 +147,11 @@ EekOutline *eek_keyboard_get_outline (EekKeyboard *keyboard, gulong oref); +void eek_keyboard_set_num_lock_mask + (EekKeyboard *keyboard, + EekModifierType num_lock_mask); +EekModifierType eek_keyboard_get_num_lock_mask + (EekKeyboard *keyboard); + G_END_DECLS #endif /* EEK_KEYBOARD_H */ diff --git a/eek/eek-keysym.c b/eek/eek-keysym.c index fd808128..8c9d4925 100644 --- a/eek/eek-keysym.c +++ b/eek/eek-keysym.c @@ -215,7 +215,7 @@ eek_keysym_init (EekKeysym *self) } EekKeysym * -eek_keysym_new (guint xkeysym) +eek_keysym_new_with_modifier (guint xkeysym, EekModifierType modifier_mask) { EekKeysym *keysym; EekKeysymPrivate *priv; @@ -223,7 +223,6 @@ eek_keysym_new (guint xkeysym) *unichar_entry; gchar *name, *label; EekSymbolCategory category; - EekModifierType modifier_mask; gunichar uc; special_entry = @@ -272,8 +271,6 @@ eek_keysym_new (guint xkeysym) else label = g_strdup (name); - modifier_mask = get_modifier_mask (xkeysym); - keysym = g_object_new (EEK_TYPE_KEYSYM, "name", name, "label", label, @@ -294,6 +291,12 @@ eek_keysym_new (guint xkeysym) return keysym; } +EekKeysym * +eek_keysym_new (guint xkeysym) +{ + return eek_keysym_new_with_modifier (xkeysym, get_modifier_mask (xkeysym)); +} + EekKeysym * eek_keysym_new_from_name (const gchar *name) { diff --git a/eek/eek-keysym.h b/eek/eek-keysym.h index 759b57d0..795afbca 100644 --- a/eek/eek-keysym.h +++ b/eek/eek-keysym.h @@ -20,6 +20,7 @@ #ifndef EEK_KEYSYM_H #define EEK_KEYSYM_H 1 +#include #include "eek-symbol.h" G_BEGIN_DECLS @@ -53,11 +54,13 @@ struct _EekKeysymClass { EekSymbolClass parent_class; }; -GType eek_keysym_get_type (void) G_GNUC_CONST; -EekKeysym *eek_keysym_new (guint xkeysym); -guint eek_keysym_get_xkeysym (EekKeysym *keysym); +GType eek_keysym_get_type (void) G_GNUC_CONST; +EekKeysym *eek_keysym_new (guint xkeysym); +guint eek_keysym_get_xkeysym (EekKeysym *keysym); -EekKeysym *eek_keysym_new_from_name (const gchar *name); +EekKeysym *eek_keysym_new_from_name (const gchar *name); +EekKeysym *eek_keysym_new_with_modifier (guint xkeysym, + EekModifierType modifier); G_END_DECLS diff --git a/eek/eek-section.c b/eek/eek-section.c index d657290c..f3801edc 100644 --- a/eek/eek-section.c +++ b/eek/eek-section.c @@ -32,8 +32,10 @@ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* HAVE_CONFIG_H */ +#include "eek-keyboard.h" #include "eek-section.h" #include "eek-key.h" +#include "eek-symbol.h" #include "eek-serializable.h" enum { @@ -71,6 +73,7 @@ struct _EekSectionPrivate { gint angle; GSList *rows; + EekModifierType modifiers; }; static EekSerializableIface *eek_section_parent_serializable_iface; @@ -262,6 +265,71 @@ eek_section_real_find_key_by_keycode (EekSection *self, (gpointer)(long)keycode); } +static void +eek_section_real_key_pressed (EekSection *self, EekKey *key) +{ + EekSectionPrivate *priv = EEK_SECTION_GET_PRIVATE(self); + EekSymbol *symbol; + EekKeyboard *keyboard; + EekModifierBehavior behavior; + EekModifierType modifier; + EekModifierType num_lock_mask; + gint level = -1; + + symbol = eek_key_get_symbol_with_fallback (key, 0, 0); + if (!symbol) + return; + + keyboard = EEK_KEYBOARD(eek_element_get_parent (EEK_ELEMENT(self))); + behavior = eek_keyboard_get_modifier_behavior (keyboard); + modifier = eek_symbol_get_modifier_mask (symbol); + switch (behavior) { + case EEK_MODIFIER_BEHAVIOR_NONE: + priv->modifiers |= modifier; + break; + case EEK_MODIFIER_BEHAVIOR_LOCK: + priv->modifiers ^= modifier; + break; + case EEK_MODIFIER_BEHAVIOR_LATCH: + priv->modifiers = (priv->modifiers ^ modifier) & modifier; + break; + } + + num_lock_mask = eek_keyboard_get_num_lock_mask (keyboard); + if (priv->modifiers & num_lock_mask) + level = 1; + eek_element_set_level (EEK_ELEMENT(self), level); +} + +static void +eek_section_real_key_released (EekSection *self, EekKey *key) +{ + EekSectionPrivate *priv = EEK_SECTION_GET_PRIVATE(self); + EekSymbol *symbol; + EekKeyboard *keyboard; + EekModifierBehavior behavior; + EekModifierType modifier; + EekModifierType num_lock_mask; + gint level = -1; + + symbol = eek_key_get_symbol_with_fallback (key, 0, 0); + if (!symbol) + return; + + keyboard = EEK_KEYBOARD(eek_element_get_parent (EEK_ELEMENT(self))); + behavior = eek_keyboard_get_modifier_behavior (keyboard); + modifier = eek_symbol_get_modifier_mask (symbol); + if (modifier != 0) { + if (behavior == EEK_MODIFIER_BEHAVIOR_NONE) + priv->modifiers &= ~modifier; + } + + num_lock_mask = eek_keyboard_get_num_lock_mask (keyboard); + if (priv->modifiers & num_lock_mask) + level = 1; + eek_element_set_level (EEK_ELEMENT(self), level); +} + static void eek_section_finalize (GObject *object) { @@ -346,6 +414,9 @@ eek_section_class_init (EekSectionClass *klass) klass->find_key_by_keycode = eek_section_real_find_key_by_keycode; /* signals */ + klass->key_pressed = eek_section_real_key_pressed; + klass->key_released = eek_section_real_key_released; + container_class->child_added = eek_section_real_child_added; container_class->child_removed = eek_section_real_child_removed; @@ -378,8 +449,8 @@ eek_section_class_init (EekSectionClass *klass) signals[KEY_PRESSED] = g_signal_new (I_("key-pressed"), G_TYPE_FROM_CLASS(gobject_class), - G_SIGNAL_RUN_FIRST, - 0, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(EekSectionClass, key_pressed), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, @@ -398,8 +469,8 @@ eek_section_class_init (EekSectionClass *klass) signals[KEY_RELEASED] = g_signal_new (I_("key-released"), G_TYPE_FROM_CLASS(gobject_class), - G_SIGNAL_RUN_FIRST, - 0, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(EekSectionClass, key_released), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, @@ -416,6 +487,7 @@ eek_section_init (EekSection *self) priv = self->priv = EEK_SECTION_GET_PRIVATE (self); priv->angle = 0; priv->rows = NULL; + priv->modifiers = 0; } /** diff --git a/eek/eek-section.h b/eek/eek-section.h index e65a03a4..958addf6 100644 --- a/eek/eek-section.h +++ b/eek/eek-section.h @@ -81,9 +81,15 @@ struct _EekSectionClass EekKey *(* find_key_by_keycode) (EekSection *self, guint keycode); + /* signals */ + void (* key_pressed) (EekSection *self, + EekKey *key); + void (* key_released) (EekSection *self, + EekKey *key); + /*< private >*/ /* padding */ - gpointer pdummy[24]; + gpointer pdummy[22]; }; GType eek_section_get_type (void) G_GNUC_CONST; diff --git a/eek/eek-xkb-layout.c b/eek/eek-xkb-layout.c index a76e69a5..b6d417c8 100644 --- a/eek/eek-xkb-layout.c +++ b/eek/eek-xkb-layout.c @@ -202,9 +202,13 @@ create_key (EekXkbLayout *layout, matrix = eek_symbol_matrix_new (num_groups, num_levels); for (i = 0; i < num_groups; i++) for (j = 0; j < num_levels; j++) { + EekModifierType modifier; + keysym = XkbKeySymEntry (priv->xkb, keycode, j, i); + modifier = XkbKeysymToModifiers (priv->display, keysym); matrix->data[i * num_levels + j] = - EEK_SYMBOL(eek_keysym_new (keysym)); + EEK_SYMBOL(eek_keysym_new_with_modifier (keysym, + modifier)); } } @@ -320,6 +324,10 @@ eek_xkb_layout_real_create_keyboard (EekLayout *self, bounds.height = initial_height; eek_element_set_bounds (EEK_ELEMENT(keyboard), &bounds); + eek_keyboard_set_num_lock_mask (keyboard, + XkbKeysymToModifiers (priv->display, + XK_Num_Lock)); + if (priv->shape_oref_hash) g_hash_table_destroy (priv->shape_oref_hash); diff --git a/src/desktop-client.c b/src/desktop-client.c index c89301a2..4f33d0cf 100644 --- a/src/desktop-client.c +++ b/src/desktop-client.c @@ -512,23 +512,6 @@ on_xkl_state_changed (XklEngine *xklengine, } #ifdef HAVE_FAKEKEY -G_INLINE_FUNC FakeKeyModifier -get_fakekey_modifiers (EekModifierType modifiers) -{ - FakeKeyModifier retval = 0; - - if (modifiers & EEK_SHIFT_MASK) - retval |= FAKEKEYMOD_SHIFT; - if (modifiers & EEK_CONTROL_MASK) - retval |= FAKEKEYMOD_CONTROL; - if (modifiers & EEK_MOD1_MASK) - retval |= FAKEKEYMOD_ALT; - if (modifiers & EEK_META_MASK) - retval |= FAKEKEYMOD_META; - - return retval; -} - static void on_key_pressed (EekKeyboard *keyboard, EekKey *key, @@ -536,19 +519,15 @@ on_key_pressed (EekKeyboard *keyboard, { EekboardDesktopClient *client = user_data; EekSymbol *symbol; - EekModifierType modifiers; - FakeKeyModifier fakekey_modifiers; - guint keycode; g_assert (client->fakekey); - modifiers = eek_keyboard_get_modifiers (client->keyboard); - fakekey_modifiers = get_fakekey_modifiers (modifiers); symbol = eek_key_get_symbol_with_fallback (key, 0, 0); - keycode = eek_key_get_keycode (key); if (EEK_IS_KEYSYM(symbol) && !eek_symbol_is_modifier (symbol)) { - fakekey_send_keyevent (client->fakekey, keycode, True, fakekey_modifiers); - fakekey_send_keyevent (client->fakekey, keycode, False, fakekey_modifiers); + fakekey_press_keysym (client->fakekey, + eek_keysym_get_xkeysym (EEK_KEYSYM(symbol)), + 0); + fakekey_release (client->fakekey); } }