[mutter] keybindings: Grab and emit a signal when XK_ISO_Next_Group is pressed
- From: Rui Matos <rtcm src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter] keybindings: Grab and emit a signal when XK_ISO_Next_Group is pressed
- Date: Mon, 27 May 2013 13:21:02 +0000 (UTC)
commit 2af49e503f1e5db3e9af867199c36e337d7d0fd2
Author: Rui Matos <tiagomatos gmail com>
Date: Wed Apr 10 13:34:26 2013 +0200
keybindings: Grab and emit a signal when XK_ISO_Next_Group is pressed
This will make it possible to implement input source switching in
gnome-shell using the popular modifiers-only keybinding that's
implemented on the X server through an XKB option.
https://bugzilla.gnome.org/show_bug.cgi?id=697002
src/core/display-private.h | 3 +
src/core/display.c | 30 ++++++
src/core/keybindings.c | 229 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 262 insertions(+), 0 deletions(-)
---
diff --git a/src/core/display-private.h b/src/core/display-private.h
index c9a7d23..a311317 100644
--- a/src/core/display-private.h
+++ b/src/core/display-private.h
@@ -237,6 +237,8 @@ struct _MetaDisplay
unsigned int meta_mask;
MetaKeyCombo overlay_key_combo;
gboolean overlay_key_only_pressed;
+ MetaKeyCombo *iso_next_group_combos;
+ int n_iso_next_group_combos;
/* Monitor cache */
unsigned int monitor_cache_invalidated : 1;
@@ -456,6 +458,7 @@ void meta_display_overlay_key_activate (MetaDisplay *display);
void meta_display_accelerator_activate (MetaDisplay *display,
guint action,
guint deviceid);
+gboolean meta_display_modifiers_accelerator_activate (MetaDisplay *display);
/* In above-tab-keycode.c */
guint meta_display_get_above_tab_keycode (MetaDisplay *display);
diff --git a/src/core/display.c b/src/core/display.c
index aa3338a..60cb00c 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -139,6 +139,7 @@ enum
{
OVERLAY_KEY,
ACCELERATOR_ACTIVATED,
+ MODIFIERS_ACCELERATOR_ACTIVATED,
FOCUS_WINDOW,
WINDOW_CREATED,
WINDOW_DEMANDS_ATTENTION,
@@ -255,6 +256,25 @@ meta_display_class_init (MetaDisplayClass *klass)
NULL, NULL, NULL,
G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
+ /**
+ * MetaDisplay::modifiers-accelerator-activated:
+ * @display: the #MetaDisplay instance
+ *
+ * The ::modifiers-accelerator-activated signal will be emitted when
+ * a special modifiers-only keybinding is activated.
+ *
+ * Returns: %TRUE means that the keyboard device should remain
+ * frozen and %FALSE for the default behavior of unfreezing the
+ * keyboard.
+ */
+ display_signals[MODIFIERS_ACCELERATOR_ACTIVATED] =
+ g_signal_new ("modifiers-accelerator-activated",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ g_signal_accumulator_first_wins, NULL, NULL,
+ G_TYPE_BOOLEAN, 0);
+
display_signals[WINDOW_CREATED] =
g_signal_new ("window-created",
G_TYPE_FROM_CLASS (klass),
@@ -5855,6 +5875,16 @@ meta_display_accelerator_activate (MetaDisplay *display,
0, action, deviceid);
}
+gboolean
+meta_display_modifiers_accelerator_activate (MetaDisplay *display)
+{
+ gboolean freeze;
+
+ g_signal_emit (display, display_signals[MODIFIERS_ACCELERATOR_ACTIVATED], 0, &freeze);
+
+ return freeze;
+}
+
void
meta_display_get_compositor_version (MetaDisplay *display,
int *major,
diff --git a/src/core/keybindings.c b/src/core/keybindings.c
index 94f86dc..baceb6d 100644
--- a/src/core/keybindings.c
+++ b/src/core/keybindings.c
@@ -302,6 +302,172 @@ reload_modmap (MetaDisplay *display)
display->meta_mask);
}
+/* Original code from gdk_x11_keymap_get_entries_for_keyval() in
+ * gdkkeys-x11.c */
+static int
+get_keycodes_for_keysym (MetaDisplay *display,
+ int keysym,
+ int **keycodes)
+{
+ GArray *retval;
+ int n_keycodes;
+ int keycode;
+
+ retval = g_array_new (FALSE, FALSE, sizeof (int));
+
+ keycode = display->min_keycode;
+ while (keycode <= display->max_keycode)
+ {
+ const KeySym *syms = display->keymap + (keycode - display->min_keycode) * display->keysyms_per_keycode;
+ int i = 0;
+
+ while (i < display->keysyms_per_keycode)
+ {
+ if (syms[i] == (unsigned int)keysym)
+ g_array_append_val (retval, keycode);
+
+ ++i;
+ }
+
+ ++keycode;
+ }
+
+ n_keycodes = retval->len;
+ *keycodes = (int*) g_array_free (retval, n_keycodes == 0 ? TRUE : FALSE);
+
+ return n_keycodes;
+}
+
+static void
+reload_iso_next_group_combos (MetaDisplay *display)
+{
+ const char *iso_next_group_option;
+ MetaKeyCombo *combos;
+ int *keycodes;
+ int n_keycodes;
+ int n_combos;
+ int i;
+
+ g_clear_pointer (&display->iso_next_group_combos, g_free);
+ display->n_iso_next_group_combos = 0;
+
+ iso_next_group_option = meta_prefs_get_iso_next_group_option ();
+ if (iso_next_group_option == NULL)
+ return;
+
+ n_keycodes = get_keycodes_for_keysym (display, XK_ISO_Next_Group, &keycodes);
+
+ if (g_str_equal (iso_next_group_option, "toggle") ||
+ g_str_equal (iso_next_group_option, "lalt_toggle") ||
+ g_str_equal (iso_next_group_option, "lwin_toggle") ||
+ g_str_equal (iso_next_group_option, "rwin_toggle") ||
+ g_str_equal (iso_next_group_option, "lshift_toggle") ||
+ g_str_equal (iso_next_group_option, "rshift_toggle") ||
+ g_str_equal (iso_next_group_option, "lctrl_toggle") ||
+ g_str_equal (iso_next_group_option, "rctrl_toggle") ||
+ g_str_equal (iso_next_group_option, "sclk_toggle") ||
+ g_str_equal (iso_next_group_option, "menu_toggle") ||
+ g_str_equal (iso_next_group_option, "caps_toggle"))
+ {
+ n_combos = n_keycodes;
+ combos = g_new (MetaKeyCombo, n_combos);
+
+ for (i = 0; i < n_keycodes; ++i)
+ {
+ combos[i].keysym = XK_ISO_Next_Group;
+ combos[i].keycode = keycodes[i];
+ combos[i].modifiers = 0;
+ }
+ }
+ else if (g_str_equal (iso_next_group_option, "shift_caps_toggle") ||
+ g_str_equal (iso_next_group_option, "shifts_toggle"))
+ {
+ n_combos = n_keycodes;
+ combos = g_new (MetaKeyCombo, n_combos);
+
+ for (i = 0; i < n_keycodes; ++i)
+ {
+ combos[i].keysym = XK_ISO_Next_Group;
+ combos[i].keycode = keycodes[i];
+ combos[i].modifiers = ShiftMask;
+ }
+ }
+ else if (g_str_equal (iso_next_group_option, "alt_caps_toggle") ||
+ g_str_equal (iso_next_group_option, "alt_space_toggle"))
+ {
+ n_combos = n_keycodes;
+ combos = g_new (MetaKeyCombo, n_combos);
+
+ for (i = 0; i < n_keycodes; ++i)
+ {
+ combos[i].keysym = XK_ISO_Next_Group;
+ combos[i].keycode = keycodes[i];
+ combos[i].modifiers = Mod1Mask;
+ }
+ }
+ else if (g_str_equal (iso_next_group_option, "ctrl_shift_toggle") ||
+ g_str_equal (iso_next_group_option, "lctrl_lshift_toggle") ||
+ g_str_equal (iso_next_group_option, "rctrl_rshift_toggle"))
+ {
+ n_combos = n_keycodes * 2;
+ combos = g_new (MetaKeyCombo, n_combos);
+
+ for (i = 0; i < n_keycodes; ++i)
+ {
+ combos[i].keysym = XK_ISO_Next_Group;
+ combos[i].keycode = keycodes[i];
+ combos[i].modifiers = ShiftMask;
+
+ combos[i + n_keycodes].keysym = XK_ISO_Next_Group;
+ combos[i + n_keycodes].keycode = keycodes[i];
+ combos[i + n_keycodes].modifiers = ControlMask;
+ }
+ }
+ else if (g_str_equal (iso_next_group_option, "ctrl_alt_toggle"))
+ {
+ n_combos = n_keycodes * 2;
+ combos = g_new (MetaKeyCombo, n_combos);
+
+ for (i = 0; i < n_keycodes; ++i)
+ {
+ combos[i].keysym = XK_ISO_Next_Group;
+ combos[i].keycode = keycodes[i];
+ combos[i].modifiers = Mod1Mask;
+
+ combos[i + n_keycodes].keysym = XK_ISO_Next_Group;
+ combos[i + n_keycodes].keycode = keycodes[i];
+ combos[i + n_keycodes].modifiers = ControlMask;
+ }
+ }
+ else if (g_str_equal (iso_next_group_option, "alt_shift_toggle") ||
+ g_str_equal (iso_next_group_option, "lalt_lshift_toggle"))
+ {
+ n_combos = n_keycodes * 2;
+ combos = g_new (MetaKeyCombo, n_combos);
+
+ for (i = 0; i < n_keycodes; ++i)
+ {
+ combos[i].keysym = XK_ISO_Next_Group;
+ combos[i].keycode = keycodes[i];
+ combos[i].modifiers = Mod1Mask;
+
+ combos[i + n_keycodes].keysym = XK_ISO_Next_Group;
+ combos[i + n_keycodes].keycode = keycodes[i];
+ combos[i + n_keycodes].modifiers = ShiftMask;
+ }
+ }
+ else
+ {
+ n_combos = 0;
+ combos = NULL;
+ }
+
+ g_free (keycodes);
+
+ display->n_iso_next_group_combos = n_combos;
+ display->iso_next_group_combos = combos;
+}
+
static guint
keysym_to_keycode (MetaDisplay *display,
guint keysym)
@@ -328,6 +494,8 @@ reload_keycodes (MetaDisplay *display)
display->overlay_key_combo.keycode = 0;
}
+ reload_iso_next_group_combos (display);
+
if (display->key_bindings)
{
int i;
@@ -1026,6 +1194,22 @@ meta_screen_change_keygrabs (MetaScreen *screen,
display->overlay_key_combo.keycode,
display->overlay_key_combo.modifiers);
+ if (display->iso_next_group_combos)
+ {
+ int i = 0;
+ while (i < display->n_iso_next_group_combos)
+ {
+ if (display->iso_next_group_combos[i].keycode != 0)
+ {
+ meta_change_keygrab (display, screen->xroot, grab,
+ display->iso_next_group_combos[i].keysym,
+ display->iso_next_group_combos[i].keycode,
+ display->iso_next_group_combos[i].modifiers);
+ }
+ ++i;
+ }
+ }
+
change_binding_keygrabs (screen->display->key_bindings,
screen->display->n_key_bindings,
screen->display, screen->xroot,
@@ -1801,6 +1985,41 @@ process_overlay_key (MetaDisplay *display,
return FALSE;
}
+static gboolean
+process_iso_next_group (MetaDisplay *display,
+ MetaScreen *screen,
+ XIDeviceEvent *event,
+ KeySym keysym)
+{
+ gboolean activate;
+ unsigned int mods;
+ int i;
+
+ if (event->evtype != XI_KeyPress)
+ return FALSE;
+
+ activate = FALSE;
+ mods = (event->mods.effective & 0xff & ~(display->ignored_modifier_mask));
+
+ for (i = 0; i < display->n_iso_next_group_combos; ++i)
+ {
+ if (event->detail == (int)display->iso_next_group_combos[i].keycode &&
+ mods == display->iso_next_group_combos[i].modifiers)
+ {
+ /* If the signal handler returns TRUE the keyboard will
+ remain frozen. It's the signal handler's responsibility
+ to unfreeze it. */
+ if (!meta_display_modifiers_accelerator_activate (display))
+ XIAllowEvents (display->xdisplay, event->deviceid,
+ XIAsyncDevice, event->time);
+ activate = TRUE;
+ break;
+ }
+ }
+
+ return activate;
+}
+
/* Handle a key event. May be called recursively: some key events cause
* grabs to be ended and then need to be processed again in their own
* right. This cannot cause infinite recursion because we never call
@@ -1875,6 +2094,10 @@ meta_display_process_key_event (MetaDisplay *display,
handled = process_overlay_key (display, screen, event, keysym);
if (handled)
return TRUE;
+
+ handled = process_iso_next_group (display, screen, event, keysym);
+ if (handled)
+ return TRUE;
}
XIAllowEvents (display->xdisplay, event->deviceid,
@@ -4569,6 +4792,12 @@ meta_display_init_keys (MetaDisplay *display)
g_hash_table_insert (key_handlers, g_strdup ("overlay-key"), handler);
handler = g_new0 (MetaKeyHandler, 1);
+ handler->name = g_strdup ("iso-next-group");
+ handler->flags = META_KEY_BINDING_BUILTIN;
+
+ g_hash_table_insert (key_handlers, g_strdup ("iso-next-group"), handler);
+
+ handler = g_new0 (MetaKeyHandler, 1);
handler->name = g_strdup ("external-grab");
handler->func = handle_external_grab;
handler->default_func = handle_external_grab;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]