[gnome-flashback] commit: redo keybindings when keymap changes
- From: Alberts Muktupāvels <muktupavels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-flashback] commit: redo keybindings when keymap changes
- Date: Mon, 28 Sep 2015 04:34:25 +0000 (UTC)
commit 762f1291886731ba9406383efe2fd27314e255ea
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date: Mon Sep 28 04:34:15 2015 +0300
commit: redo keybindings when keymap changes
gnome-flashback/libcommon/gf-keybindings.c | 384 ++++++++++++++++++---------
1 files changed, 256 insertions(+), 128 deletions(-)
---
diff --git a/gnome-flashback/libcommon/gf-keybindings.c b/gnome-flashback/libcommon/gf-keybindings.c
index 91db263..cf2ed9d 100644
--- a/gnome-flashback/libcommon/gf-keybindings.c
+++ b/gnome-flashback/libcommon/gf-keybindings.c
@@ -33,6 +33,9 @@ struct _GfKeybindings
Display *xdisplay;
Window xwindow;
+ gint xkb_event_base;
+ gint xkb_error_base;
+
guint meta_mask;
guint super_mask;
guint hyper_mask;
@@ -64,6 +67,111 @@ static guint signals[LAST_SIGNAL] = { 0 };
G_DEFINE_TYPE (GfKeybindings, gf_keybindings, G_TYPE_OBJECT)
+static gboolean
+devirtualize_modifier (GdkModifierType modifiers,
+ GdkModifierType gdk_mask,
+ unsigned int real_mask,
+ unsigned int *mask)
+{
+ if (modifiers & gdk_mask)
+ {
+ if (real_mask == 0)
+ return FALSE;
+
+ *mask |= real_mask;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+devirtualize_modifiers (GfKeybindings *keybindings,
+ GdkModifierType modifiers,
+ guint *mask)
+{
+ gboolean devirtualized;
+
+ devirtualized = TRUE;
+ *mask = 0;
+
+ devirtualized &= devirtualize_modifier (modifiers, GDK_SHIFT_MASK,
+ ShiftMask, mask);
+
+ devirtualized &= devirtualize_modifier (modifiers, GDK_CONTROL_MASK,
+ ControlMask, mask);
+
+ devirtualized &= devirtualize_modifier (modifiers, GDK_MOD1_MASK,
+ Mod1Mask, mask);
+
+ devirtualized &= devirtualize_modifier (modifiers, GDK_META_MASK,
+ keybindings->meta_mask, mask);
+
+ devirtualized &= devirtualize_modifier (modifiers, GDK_HYPER_MASK,
+ keybindings->hyper_mask, mask);
+
+ devirtualized &= devirtualize_modifier (modifiers, GDK_SUPER_MASK,
+ keybindings->super_mask, mask);
+
+ devirtualized &= devirtualize_modifier (modifiers, GDK_MOD2_MASK,
+ Mod2Mask, mask);
+
+ devirtualized &= devirtualize_modifier (modifiers, GDK_MOD3_MASK,
+ Mod3Mask, mask);
+
+ devirtualized &= devirtualize_modifier (modifiers, GDK_MOD4_MASK,
+ Mod4Mask, mask);
+
+ devirtualized &= devirtualize_modifier (modifiers, GDK_MOD5_MASK,
+ Mod5Mask, mask);
+
+ return devirtualized;
+}
+
+static void
+change_keygrab (GfKeybindings *keybindings,
+ gboolean grab,
+ Keybinding *keybinding)
+{
+ guint ignored_mask;
+ guint keycode;
+ guint mask;
+ gint error_code;
+
+ ignored_mask = 0;
+ keycode = keybinding->keycode;
+ mask = keybinding->mask;
+
+ while (ignored_mask <= keybindings->ignored_mask)
+ {
+ if (ignored_mask & ~(keybindings->ignored_mask))
+ {
+ ++ignored_mask;
+ continue;
+ }
+
+ gdk_error_trap_push ();
+
+ if (grab)
+ {
+ XGrabKey (keybindings->xdisplay, keycode, mask | ignored_mask,
+ keybindings->xwindow, True, GrabModeAsync, GrabModeSync);
+ }
+ else
+ {
+ XUngrabKey (keybindings->xdisplay, keycode, mask | ignored_mask,
+ keybindings->xwindow);
+ }
+
+ error_code = gdk_error_trap_pop ();
+ if (error_code != 0)
+ {
+ g_debug ("Failed to grab/ ungrab key. Error code - %d", error_code);
+ }
+
+ ++ignored_mask;
+ }
+}
+
static Keybinding *
keybinding_new (const gchar *name,
guint keyval,
@@ -116,6 +224,112 @@ get_keybinding (GfKeybindings *keybindings,
return keybinding;
}
+static void
+ungrab_keybindings (GfKeybindings *keybindings)
+{
+ GHashTableIter iter;
+ gpointer value;
+
+ g_hash_table_iter_init (&iter, keybindings->keybindings);
+ while (g_hash_table_iter_next (&iter, NULL, &value))
+ {
+ Keybinding *keybinding;
+
+ keybinding = (Keybinding *) value;
+
+ change_keygrab (keybindings, FALSE, keybinding);
+ }
+}
+
+static void
+reload_modmap (GfKeybindings *keybindings)
+{
+ guint meta_mask;
+ guint super_mask;
+ guint hyper_mask;
+ guint num_lock_mask;
+ guint scroll_lock_mask;
+
+ meta_mask = XkbKeysymToModifiers (keybindings->xdisplay, XK_Meta_L);
+ if (meta_mask == 0)
+ meta_mask = XkbKeysymToModifiers (keybindings->xdisplay, XK_Meta_R);
+
+ super_mask = XkbKeysymToModifiers (keybindings->xdisplay, XK_Super_L);
+ if (super_mask == 0)
+ super_mask = XkbKeysymToModifiers (keybindings->xdisplay, XK_Super_R);
+
+ hyper_mask = XkbKeysymToModifiers (keybindings->xdisplay, XK_Hyper_L);
+ if (hyper_mask == 0)
+ hyper_mask = XkbKeysymToModifiers (keybindings->xdisplay, XK_Hyper_R);
+
+ num_lock_mask = XkbKeysymToModifiers (keybindings->xdisplay, XK_Num_Lock);
+ scroll_lock_mask = XkbKeysymToModifiers (keybindings->xdisplay,
+ XK_Scroll_Lock);
+
+ keybindings->meta_mask = meta_mask;
+ keybindings->super_mask = super_mask;
+ keybindings->hyper_mask = hyper_mask;
+ keybindings->ignored_mask = num_lock_mask | scroll_lock_mask | LockMask;
+}
+
+static void
+reload_keybindings (GfKeybindings *keybindings)
+{
+ GHashTableIter iter;
+ gpointer value;
+
+ g_hash_table_iter_init (&iter, keybindings->keybindings);
+ while (g_hash_table_iter_next (&iter, NULL, &value))
+ {
+ Keybinding *keybinding;
+ guint keyval;
+ GdkModifierType modifiers;
+ guint keycode;
+ guint mask;
+
+ keybinding = (Keybinding *) value;
+
+ gtk_accelerator_parse (keybinding->name, &keyval, &modifiers);
+
+ if (gtk_accelerator_valid (keyval, modifiers) && keyval != 0)
+ {
+ keycode = XKeysymToKeycode (keybindings->xdisplay, keyval);
+
+ if (!devirtualize_modifiers (keybindings, modifiers, &mask))
+ mask = 0;
+ }
+ else
+ {
+ keyval = 0;
+ modifiers = 0;
+ keycode = 0;
+ mask = 0;
+ }
+
+ keybinding->keyval = keyval;
+ keybinding->modifiers = modifiers;
+ keybinding->keycode = keycode;
+ keybinding->mask = mask;
+ }
+}
+
+static void
+regrab_keybindings (GfKeybindings *keybindings)
+{
+ GHashTableIter iter;
+ gpointer value;
+
+ g_hash_table_iter_init (&iter, keybindings->keybindings);
+ while (g_hash_table_iter_next (&iter, NULL, &value))
+ {
+ Keybinding *keybinding;
+
+ keybinding = (Keybinding *) value;
+
+ change_keygrab (keybindings, TRUE, keybinding);
+ }
+}
+
static GdkFilterReturn
filter_func (GdkXEvent *xevent,
GdkEvent *event,
@@ -129,6 +343,26 @@ filter_func (GdkXEvent *xevent,
keybindings = GF_KEYBINDINGS (user_data);
ev = (XEvent *) xevent;
+ if (ev->type == keybindings->xkb_event_base)
+ {
+ XkbEvent *xkb_ev;
+
+ xkb_ev = (XkbEvent *) ev;
+
+ switch (xkb_ev->any.xkb_type)
+ {
+ case XkbNewKeyboardNotify:
+ case XkbMapNotify:
+ ungrab_keybindings (keybindings);
+ reload_modmap (keybindings);
+ reload_keybindings (keybindings);
+ regrab_keybindings (keybindings);
+ break;
+ default:
+ break;
+ }
+ }
+
XAllowEvents (keybindings->xdisplay, AsyncKeyboard, ev->xkey.time);
if (ev->type != KeyPress)
@@ -160,51 +394,6 @@ filter_func (GdkXEvent *xevent,
return GDK_FILTER_CONTINUE;
}
-static void
-change_keygrab (GfKeybindings *keybindings,
- gboolean grab,
- Keybinding *keybinding)
-{
- guint ignored_mask;
- guint keycode;
- guint mask;
- gint error_code;
-
- ignored_mask = 0;
- keycode = keybinding->keycode;
- mask = keybinding->mask;
-
- while (ignored_mask <= keybindings->ignored_mask)
- {
- if (ignored_mask & ~(keybindings->ignored_mask))
- {
- ++ignored_mask;
- continue;
- }
-
- gdk_error_trap_push ();
-
- if (grab)
- {
- XGrabKey (keybindings->xdisplay, keycode, mask | ignored_mask,
- keybindings->xwindow, True, GrabModeAsync, GrabModeSync);
- }
- else
- {
- XUngrabKey (keybindings->xdisplay, keycode, mask | ignored_mask,
- keybindings->xwindow);
- }
-
- error_code = gdk_error_trap_pop ();
- if (error_code != 0)
- {
- g_debug ("Failed to grab/ ungrab key. Error code - %d", error_code);
- }
-
- ++ignored_mask;
- }
-}
-
static guint
get_next_action (void)
{
@@ -213,66 +402,6 @@ get_next_action (void)
return ++action;
}
-static gboolean
-devirtualize_modifier (GdkModifierType modifiers,
- GdkModifierType gdk_mask,
- unsigned int real_mask,
- unsigned int *mask)
-{
- if (modifiers & gdk_mask)
- {
- if (real_mask == 0)
- return FALSE;
-
- *mask |= real_mask;
- }
-
- return TRUE;
-}
-
-static gboolean
-devirtualize_modifiers (GfKeybindings *keybindings,
- GdkModifierType modifiers,
- guint *mask)
-{
- gboolean devirtualized;
-
- devirtualized = TRUE;
- *mask = 0;
-
- devirtualized &= devirtualize_modifier (modifiers, GDK_SHIFT_MASK,
- ShiftMask, mask);
-
- devirtualized &= devirtualize_modifier (modifiers, GDK_CONTROL_MASK,
- ControlMask, mask);
-
- devirtualized &= devirtualize_modifier (modifiers, GDK_MOD1_MASK,
- Mod1Mask, mask);
-
- devirtualized &= devirtualize_modifier (modifiers, GDK_META_MASK,
- keybindings->meta_mask, mask);
-
- devirtualized &= devirtualize_modifier (modifiers, GDK_HYPER_MASK,
- keybindings->hyper_mask, mask);
-
- devirtualized &= devirtualize_modifier (modifiers, GDK_SUPER_MASK,
- keybindings->super_mask, mask);
-
- devirtualized &= devirtualize_modifier (modifiers, GDK_MOD2_MASK,
- Mod2Mask, mask);
-
- devirtualized &= devirtualize_modifier (modifiers, GDK_MOD3_MASK,
- Mod3Mask, mask);
-
- devirtualized &= devirtualize_modifier (modifiers, GDK_MOD4_MASK,
- Mod4Mask, mask);
-
- devirtualized &= devirtualize_modifier (modifiers, GDK_MOD5_MASK,
- Mod5Mask, mask);
-
- return devirtualized;
-}
-
static void
gf_keybindings_dispose (GObject *object)
{
@@ -329,39 +458,38 @@ static void
gf_keybindings_init (GfKeybindings *keybindings)
{
GdkDisplay *display;
- guint meta_mask;
- guint super_mask;
- guint hyper_mask;
- guint num_lock_mask;
- guint scroll_lock_mask;
+ gint xkb_opcode;
+ gint xkb_major;
+ gint xkb_minor;
keybindings->keybindings = g_hash_table_new_full (NULL, NULL, NULL,
keybinding_free);
display = gdk_display_get_default ();
+ xkb_major = XkbMajorVersion;
+ xkb_minor = XkbMinorVersion;
+
keybindings->xdisplay = gdk_x11_display_get_xdisplay (display);
keybindings->xwindow = XDefaultRootWindow (keybindings->xdisplay);
- meta_mask = XkbKeysymToModifiers (keybindings->xdisplay, XK_Meta_L);
- if (meta_mask == 0)
- meta_mask = XkbKeysymToModifiers (keybindings->xdisplay, XK_Meta_R);
-
- super_mask = XkbKeysymToModifiers (keybindings->xdisplay, XK_Super_L);
- if (super_mask == 0)
- super_mask = XkbKeysymToModifiers (keybindings->xdisplay, XK_Super_R);
-
- hyper_mask = XkbKeysymToModifiers (keybindings->xdisplay, XK_Hyper_L);
- if (hyper_mask == 0)
- hyper_mask = XkbKeysymToModifiers (keybindings->xdisplay, XK_Hyper_R);
+ if (!XkbQueryExtension (keybindings->xdisplay, &xkb_opcode,
+ &keybindings->xkb_event_base,
+ &keybindings->xkb_error_base,
+ &xkb_major, &xkb_minor))
+ {
+ keybindings->xkb_event_base = -1;
- num_lock_mask = XkbKeysymToModifiers (keybindings->xdisplay, XK_Num_Lock);
- scroll_lock_mask = XkbKeysymToModifiers (keybindings->xdisplay,
- XK_Scroll_Lock);
+ g_warning ("X server doesn't have the XKB extension, version %d.%d or "
+ "newer", XkbMajorVersion, XkbMinorVersion);
+ }
+ else
+ {
+ XkbSelectEvents (keybindings->xdisplay, XkbUseCoreKbd,
+ XkbNewKeyboardNotifyMask | XkbMapNotifyMask,
+ XkbNewKeyboardNotifyMask | XkbMapNotifyMask);
+ }
- keybindings->meta_mask = meta_mask;
- keybindings->super_mask = super_mask;
- keybindings->hyper_mask = hyper_mask;
- keybindings->ignored_mask = num_lock_mask | scroll_lock_mask | LockMask;
+ reload_modmap (keybindings);
gdk_window_add_filter (NULL, filter_func, keybindings);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]