mirror of
https://github.com/brl/mutter.git
synced 2024-11-22 08:00:42 -05:00
keybindings: handle multiple keycodes for keysym
A single keysym can resolve to multiple keycodes. Instead of only using the first one and ignoring the others, we store all codes in MetaResolvedKeyCombo and then handle all of them in keybinding resolution. If we already have bound a keycode for a keybinding with a specific keysym then this can get overwritten by a new keybinding with a different keysym that resolves to the same keycode. Now that we resolve and bind all keycodes for a keysym this might happen more often; in that case warn but still overwrite, but only for the first keycode for each keysym. If a secondary (i.e. all non-first keycodes) is already indexed we just ignore that; this should resemble the old behavior where we only took the first keycode for any keysym as close as possible. https://bugzilla.gnome.org/show_bug.cgi?id=781223
This commit is contained in:
parent
dd82f4afcd
commit
68dacb531b
@ -44,7 +44,8 @@ struct _MetaKeyHandler
|
||||
};
|
||||
|
||||
typedef struct _MetaResolvedKeyCombo {
|
||||
xkb_keycode_t keycode;
|
||||
xkb_keycode_t *keycodes;
|
||||
int len;
|
||||
xkb_mod_mask_t mask;
|
||||
} MetaResolvedKeyCombo;
|
||||
|
||||
@ -102,7 +103,7 @@ typedef struct
|
||||
MetaKeyCombo overlay_key_combo;
|
||||
MetaResolvedKeyCombo overlay_resolved_key_combo;
|
||||
gboolean overlay_key_only_pressed;
|
||||
MetaResolvedKeyCombo *iso_next_group_combos;
|
||||
MetaResolvedKeyCombo iso_next_group_combo[2];
|
||||
int n_iso_next_group_combos;
|
||||
|
||||
xkb_level_index_t keymap_num_levels;
|
||||
|
@ -64,16 +64,63 @@ static gboolean add_builtin_keybinding (MetaDisplay *display,
|
||||
MetaKeyHandlerFunc handler,
|
||||
int handler_arg);
|
||||
|
||||
static void
|
||||
resolved_key_combo_reset (MetaResolvedKeyCombo *resolved_combo)
|
||||
{
|
||||
g_free (resolved_combo->keycodes);
|
||||
resolved_combo->len = 0;
|
||||
resolved_combo->keycodes = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
resolved_key_combo_copy (MetaResolvedKeyCombo *from,
|
||||
MetaResolvedKeyCombo *to)
|
||||
{
|
||||
to->len = from->len;
|
||||
to->keycodes = g_memdup (from->keycodes,
|
||||
from->len * sizeof (xkb_keycode_t));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
resolved_key_combo_has_keycode (MetaResolvedKeyCombo *resolved_combo,
|
||||
int keycode)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < resolved_combo->len; i++)
|
||||
if ((int) resolved_combo->keycodes[i] == keycode)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
resolved_key_combo_intersect (MetaResolvedKeyCombo *a,
|
||||
MetaResolvedKeyCombo *b)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < a->len; i++)
|
||||
if (resolved_key_combo_has_keycode (b, a->keycodes[i]))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_key_binding_free (MetaKeyBinding *binding)
|
||||
{
|
||||
resolved_key_combo_reset (&binding->resolved_combo);
|
||||
g_slice_free (MetaKeyBinding, binding);
|
||||
}
|
||||
|
||||
static MetaKeyBinding *
|
||||
meta_key_binding_copy (MetaKeyBinding *binding)
|
||||
{
|
||||
return g_slice_dup (MetaKeyBinding, binding);
|
||||
MetaKeyBinding *clone = g_slice_dup (MetaKeyBinding, binding);
|
||||
resolved_key_combo_copy (&binding->resolved_combo,
|
||||
&clone->resolved_combo);
|
||||
return clone;
|
||||
}
|
||||
|
||||
G_DEFINE_BOXED_TYPE(MetaKeyBinding,
|
||||
@ -163,7 +210,8 @@ meta_key_grab_free (MetaKeyGrab *grab)
|
||||
}
|
||||
|
||||
static guint32
|
||||
key_combo_key (MetaResolvedKeyCombo *resolved_combo)
|
||||
key_combo_key (MetaResolvedKeyCombo *resolved_combo,
|
||||
int i)
|
||||
{
|
||||
/* On X, keycodes are only 8 bits while libxkbcommon supports 32 bit
|
||||
keycodes, but since we're using the same XKB keymaps that X uses,
|
||||
@ -173,7 +221,7 @@ key_combo_key (MetaResolvedKeyCombo *resolved_combo)
|
||||
can use a 32 bit integer to safely concatenate both keycode and
|
||||
mask and thus making it easy to use them as an index in a
|
||||
GHashTable. */
|
||||
guint32 key = resolved_combo->keycode & 0xffff;
|
||||
guint32 key = resolved_combo->keycodes[i] & 0xffff;
|
||||
return (key << 16) | (resolved_combo->mask & 0xffff);
|
||||
}
|
||||
|
||||
@ -274,21 +322,34 @@ get_keycodes_for_keysym_iter (struct xkb_keymap *keymap,
|
||||
xkb_level_index_t level = search_data->level;
|
||||
|
||||
if (is_keycode_for_keysym (keymap, layout, level, keycode, keysym))
|
||||
g_array_append_val (keycodes, keycode);
|
||||
{
|
||||
guint i;
|
||||
gboolean missing = TRUE;
|
||||
|
||||
/* duplicate keycode detection */
|
||||
for (i = 0; i < keycodes->len; i++)
|
||||
if (g_array_index (keycodes, xkb_keysym_t, i) == keycode)
|
||||
{
|
||||
missing = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (missing)
|
||||
g_array_append_val (keycodes, keycode);
|
||||
}
|
||||
}
|
||||
|
||||
/* Original code from gdk_x11_keymap_get_entries_for_keyval() in
|
||||
* gdkkeys-x11.c */
|
||||
static int
|
||||
static void
|
||||
get_keycodes_for_keysym (MetaKeyBindingManager *keys,
|
||||
int keysym,
|
||||
int **keycodes)
|
||||
MetaResolvedKeyCombo *resolved_combo)
|
||||
{
|
||||
GArray *retval;
|
||||
int n_keycodes;
|
||||
int keycode;
|
||||
|
||||
retval = g_array_new (FALSE, FALSE, sizeof (int));
|
||||
retval = g_array_new (FALSE, FALSE, sizeof (xkb_keysym_t));
|
||||
|
||||
/* Special-case: Fake mutter keysym */
|
||||
if (keysym == META_KEY_ABOVE_TAB)
|
||||
@ -313,28 +374,8 @@ get_keycodes_for_keysym (MetaKeyBindingManager *keys,
|
||||
}
|
||||
|
||||
out:
|
||||
n_keycodes = retval->len;
|
||||
*keycodes = (int*) g_array_free (retval, n_keycodes == 0 ? TRUE : FALSE);
|
||||
return n_keycodes;
|
||||
}
|
||||
|
||||
static guint
|
||||
get_first_keycode_for_keysym (MetaKeyBindingManager *keys,
|
||||
guint keysym)
|
||||
{
|
||||
int *keycodes;
|
||||
int n_keycodes;
|
||||
int keycode;
|
||||
|
||||
n_keycodes = get_keycodes_for_keysym (keys, keysym, &keycodes);
|
||||
|
||||
if (n_keycodes > 0)
|
||||
keycode = keycodes[0];
|
||||
else
|
||||
keycode = 0;
|
||||
|
||||
g_free (keycodes);
|
||||
return keycode;
|
||||
resolved_combo->len = retval->len;
|
||||
resolved_combo->keycodes = (xkb_keycode_t *) g_array_free (retval, retval->len == 0 ? TRUE : FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -367,20 +408,23 @@ static void
|
||||
reload_iso_next_group_combos (MetaKeyBindingManager *keys)
|
||||
{
|
||||
const char *iso_next_group_option;
|
||||
MetaResolvedKeyCombo *combos;
|
||||
int *keycodes;
|
||||
int n_keycodes;
|
||||
int n_combos;
|
||||
int i;
|
||||
|
||||
g_clear_pointer (&keys->iso_next_group_combos, g_free);
|
||||
for (i = 0; i < keys->n_iso_next_group_combos; i++)
|
||||
resolved_key_combo_reset (&keys->iso_next_group_combo[i]);
|
||||
|
||||
keys->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 (keys, XKB_KEY_ISO_Next_Group, &keycodes);
|
||||
get_keycodes_for_keysym (keys, XKB_KEY_ISO_Next_Group, keys->iso_next_group_combo);
|
||||
|
||||
if (keys->iso_next_group_combo[0].len == 0)
|
||||
return;
|
||||
|
||||
keys->n_iso_next_group_combos = 1;
|
||||
|
||||
if (g_str_equal (iso_next_group_option, "toggle") ||
|
||||
g_str_equal (iso_next_group_option, "lalt_toggle") ||
|
||||
@ -394,94 +438,53 @@ reload_iso_next_group_combos (MetaKeyBindingManager *keys)
|
||||
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 (MetaResolvedKeyCombo, n_combos);
|
||||
|
||||
for (i = 0; i < n_keycodes; ++i)
|
||||
{
|
||||
combos[i].keycode = keycodes[i];
|
||||
combos[i].mask = 0;
|
||||
}
|
||||
keys->iso_next_group_combo[0].mask = 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 (MetaResolvedKeyCombo, n_combos);
|
||||
|
||||
for (i = 0; i < n_keycodes; ++i)
|
||||
{
|
||||
combos[i].keycode = keycodes[i];
|
||||
combos[i].mask = ShiftMask;
|
||||
}
|
||||
keys->iso_next_group_combo[0].mask = 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 (MetaResolvedKeyCombo, n_combos);
|
||||
|
||||
for (i = 0; i < n_keycodes; ++i)
|
||||
{
|
||||
combos[i].keycode = keycodes[i];
|
||||
combos[i].mask = Mod1Mask;
|
||||
}
|
||||
keys->iso_next_group_combo[0].mask = 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 (MetaResolvedKeyCombo, n_combos);
|
||||
resolved_key_combo_copy (&keys->iso_next_group_combo[0],
|
||||
&keys->iso_next_group_combo[1]);
|
||||
|
||||
for (i = 0; i < n_keycodes; ++i)
|
||||
{
|
||||
combos[i].keycode = keycodes[i];
|
||||
combos[i].mask = ShiftMask;
|
||||
|
||||
combos[i + n_keycodes].keycode = keycodes[i];
|
||||
combos[i + n_keycodes].mask = ControlMask;
|
||||
}
|
||||
keys->iso_next_group_combo[0].mask = ShiftMask;
|
||||
keys->iso_next_group_combo[1].mask = ControlMask;
|
||||
keys->n_iso_next_group_combos = 2;
|
||||
}
|
||||
else if (g_str_equal (iso_next_group_option, "ctrl_alt_toggle"))
|
||||
{
|
||||
n_combos = n_keycodes * 2;
|
||||
combos = g_new (MetaResolvedKeyCombo, n_combos);
|
||||
resolved_key_combo_copy (&keys->iso_next_group_combo[0],
|
||||
&keys->iso_next_group_combo[1]);
|
||||
|
||||
for (i = 0; i < n_keycodes; ++i)
|
||||
{
|
||||
combos[i].keycode = keycodes[i];
|
||||
combos[i].mask = Mod1Mask;
|
||||
|
||||
combos[i + n_keycodes].keycode = keycodes[i];
|
||||
combos[i + n_keycodes].mask = ControlMask;
|
||||
}
|
||||
keys->iso_next_group_combo[0].mask = Mod1Mask;
|
||||
keys->iso_next_group_combo[1].mask = ControlMask;
|
||||
keys->n_iso_next_group_combos = 2;
|
||||
}
|
||||
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 (MetaResolvedKeyCombo, n_combos);
|
||||
resolved_key_combo_copy (&keys->iso_next_group_combo[0],
|
||||
&keys->iso_next_group_combo[1]);
|
||||
|
||||
for (i = 0; i < n_keycodes; ++i)
|
||||
{
|
||||
combos[i].keycode = keycodes[i];
|
||||
combos[i].mask = Mod1Mask;
|
||||
|
||||
combos[i + n_keycodes].keycode = keycodes[i];
|
||||
combos[i + n_keycodes].mask = ShiftMask;
|
||||
}
|
||||
keys->iso_next_group_combo[0].mask = Mod1Mask;
|
||||
keys->iso_next_group_combo[1].mask = ShiftMask;
|
||||
keys->n_iso_next_group_combos = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
n_combos = 0;
|
||||
combos = NULL;
|
||||
resolved_key_combo_reset (keys->iso_next_group_combo);
|
||||
keys->n_iso_next_group_combos = 0;
|
||||
}
|
||||
|
||||
g_free (keycodes);
|
||||
|
||||
keys->n_iso_next_group_combos = n_combos;
|
||||
keys->iso_next_group_combos = combos;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -517,11 +520,35 @@ static void
|
||||
index_binding (MetaKeyBindingManager *keys,
|
||||
MetaKeyBinding *binding)
|
||||
{
|
||||
guint32 index_key;
|
||||
int i;
|
||||
|
||||
index_key = key_combo_key (&binding->resolved_combo);
|
||||
g_hash_table_replace (keys->key_bindings_index,
|
||||
GINT_TO_POINTER (index_key), binding);
|
||||
for (i = 0; i < binding->resolved_combo.len; i++)
|
||||
{
|
||||
MetaKeyBinding *existing;
|
||||
guint32 index_key;
|
||||
|
||||
index_key = key_combo_key (&binding->resolved_combo, i);
|
||||
|
||||
existing = g_hash_table_lookup (keys->key_bindings_index,
|
||||
GINT_TO_POINTER (index_key));
|
||||
if (existing != NULL)
|
||||
{
|
||||
/* Overwrite already indexed keycodes only for the first
|
||||
* keycode, i.e. we give those primary keycodes precedence
|
||||
* over non-first ones. */
|
||||
if (i > 0)
|
||||
continue;
|
||||
|
||||
meta_warning ("Overwriting existing binding of keysym %x"
|
||||
" with keysym %x (keycode %x).\n",
|
||||
binding->combo.keysym,
|
||||
existing->combo.keysym,
|
||||
binding->resolved_combo.keycodes[i]);
|
||||
}
|
||||
|
||||
g_hash_table_replace (keys->key_bindings_index,
|
||||
GINT_TO_POINTER (index_key), binding);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -529,10 +556,19 @@ resolve_key_combo (MetaKeyBindingManager *keys,
|
||||
MetaKeyCombo *combo,
|
||||
MetaResolvedKeyCombo *resolved_combo)
|
||||
{
|
||||
|
||||
resolved_key_combo_reset (resolved_combo);
|
||||
|
||||
if (combo->keysym != 0)
|
||||
resolved_combo->keycode = get_first_keycode_for_keysym (keys, combo->keysym);
|
||||
else
|
||||
resolved_combo->keycode = combo->keycode;
|
||||
{
|
||||
get_keycodes_for_keysym (keys, combo->keysym, resolved_combo);
|
||||
}
|
||||
else if (combo->keycode != 0)
|
||||
{
|
||||
resolved_combo->keycodes = g_new0 (xkb_keycode_t, 1);
|
||||
resolved_combo->keycodes[0] = combo->keycode;
|
||||
resolved_combo->len = 1;
|
||||
}
|
||||
|
||||
devirtualize_modifiers (keys, combo->modifiers, &resolved_combo->mask);
|
||||
}
|
||||
@ -691,9 +727,22 @@ static MetaKeyBinding *
|
||||
get_keybinding (MetaKeyBindingManager *keys,
|
||||
MetaResolvedKeyCombo *resolved_combo)
|
||||
{
|
||||
guint32 key;
|
||||
key = key_combo_key (resolved_combo);
|
||||
return g_hash_table_lookup (keys->key_bindings_index, GINT_TO_POINTER (key));
|
||||
MetaKeyBinding *binding = NULL;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < resolved_combo->len; i++)
|
||||
{
|
||||
guint32 key;
|
||||
|
||||
key = key_combo_key (resolved_combo, i);
|
||||
binding = g_hash_table_lookup (keys->key_bindings_index,
|
||||
GINT_TO_POINTER (key));
|
||||
|
||||
if (binding != NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
return binding;
|
||||
}
|
||||
|
||||
static guint
|
||||
@ -823,7 +872,8 @@ get_keybinding_action (MetaKeyBindingManager *keys,
|
||||
* of mutter keybindings while holding a grab, the overlay-key-only-pressed
|
||||
* tracking is left to the plugin here.
|
||||
*/
|
||||
if (resolved_combo->keycode == (unsigned int)keys->overlay_resolved_key_combo.keycode)
|
||||
if (resolved_key_combo_intersect (resolved_combo,
|
||||
&keys->overlay_resolved_key_combo))
|
||||
return META_KEYBINDING_ACTION_OVERLAY_KEY;
|
||||
|
||||
binding = get_keybinding (keys, resolved_combo);
|
||||
@ -841,14 +891,11 @@ get_keybinding_action (MetaKeyBindingManager *keys,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
resolved_combo_from_event_params (MetaResolvedKeyCombo *resolved_combo,
|
||||
MetaKeyBindingManager *keys,
|
||||
unsigned int keycode,
|
||||
unsigned long mask)
|
||||
static xkb_mod_mask_t
|
||||
mask_from_event_params (MetaKeyBindingManager *keys,
|
||||
unsigned long mask)
|
||||
{
|
||||
resolved_combo->keycode = keycode;
|
||||
resolved_combo->mask = mask & 0xff & ~keys->ignored_modifier_mask;
|
||||
return mask & 0xff & ~keys->ignored_modifier_mask;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -871,8 +918,10 @@ meta_display_get_keybinding_action (MetaDisplay *display,
|
||||
unsigned long mask)
|
||||
{
|
||||
MetaKeyBindingManager *keys = &display->key_binding_manager;
|
||||
MetaResolvedKeyCombo resolved_combo;
|
||||
resolved_combo_from_event_params (&resolved_combo, keys, keycode, mask);
|
||||
xkb_keycode_t code = (xkb_keycode_t) keycode;
|
||||
MetaResolvedKeyCombo resolved_combo = { &code, 1 };
|
||||
|
||||
resolved_combo.mask = mask_from_event_params (keys, mask);
|
||||
return get_keybinding_action (keys, &resolved_combo);
|
||||
}
|
||||
|
||||
@ -1165,30 +1214,36 @@ meta_change_keygrab (MetaKeyBindingManager *keys,
|
||||
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
|
||||
Display *xdisplay = meta_backend_x11_get_xdisplay (backend);
|
||||
GArray *mods;
|
||||
int i;
|
||||
|
||||
/* Grab keycode/modmask, together with
|
||||
* all combinations of ignored modifiers.
|
||||
* X provides no better way to do this.
|
||||
*/
|
||||
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"%s keybinding keycode %d mask 0x%x on 0x%lx\n",
|
||||
grab ? "Grabbing" : "Ungrabbing",
|
||||
resolved_combo->keycode, resolved_combo->mask, xwindow);
|
||||
|
||||
mods = calc_grab_modifiers (keys, resolved_combo->mask);
|
||||
|
||||
if (grab)
|
||||
XIGrabKeycode (xdisplay,
|
||||
META_VIRTUAL_CORE_KEYBOARD_ID,
|
||||
resolved_combo->keycode, xwindow,
|
||||
XIGrabModeSync, XIGrabModeAsync,
|
||||
False, &mask, mods->len, (XIGrabModifiers *)mods->data);
|
||||
else
|
||||
XIUngrabKeycode (xdisplay,
|
||||
META_VIRTUAL_CORE_KEYBOARD_ID,
|
||||
resolved_combo->keycode, xwindow,
|
||||
mods->len, (XIGrabModifiers *)mods->data);
|
||||
for (i = 0; i < resolved_combo->len; i++)
|
||||
{
|
||||
xkb_keycode_t keycode = resolved_combo->keycodes[i];
|
||||
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"%s keybinding keycode %d mask 0x%x on 0x%lx\n",
|
||||
grab ? "Grabbing" : "Ungrabbing",
|
||||
keycode, resolved_combo->mask, xwindow);
|
||||
|
||||
if (grab)
|
||||
XIGrabKeycode (xdisplay,
|
||||
META_VIRTUAL_CORE_KEYBOARD_ID,
|
||||
keycode, xwindow,
|
||||
XIGrabModeSync, XIGrabModeAsync,
|
||||
False, &mask, mods->len, (XIGrabModifiers *)mods->data);
|
||||
else
|
||||
XIUngrabKeycode (xdisplay,
|
||||
META_VIRTUAL_CORE_KEYBOARD_ID,
|
||||
keycode, xwindow,
|
||||
mods->len, (XIGrabModifiers *)mods->data);
|
||||
}
|
||||
|
||||
g_array_free (mods, TRUE);
|
||||
}
|
||||
@ -1213,7 +1268,7 @@ change_keygrab_foreach (gpointer key,
|
||||
if (data->only_per_window != binding_is_per_window)
|
||||
return;
|
||||
|
||||
if (binding->resolved_combo.keycode == 0)
|
||||
if (binding->resolved_combo.len == 0)
|
||||
return;
|
||||
|
||||
meta_change_keygrab (data->keys, data->xwindow, data->grab, &binding->resolved_combo);
|
||||
@ -1241,21 +1296,13 @@ meta_screen_change_keygrabs (MetaScreen *screen,
|
||||
{
|
||||
MetaDisplay *display = screen->display;
|
||||
MetaKeyBindingManager *keys = &display->key_binding_manager;
|
||||
int i;
|
||||
|
||||
if (keys->overlay_resolved_key_combo.keycode != 0)
|
||||
if (keys->overlay_resolved_key_combo.len != 0)
|
||||
meta_change_keygrab (keys, screen->xroot, grab, &keys->overlay_resolved_key_combo);
|
||||
|
||||
if (keys->iso_next_group_combos)
|
||||
{
|
||||
int i = 0;
|
||||
while (i < keys->n_iso_next_group_combos)
|
||||
{
|
||||
if (keys->iso_next_group_combos[i].keycode != 0)
|
||||
meta_change_keygrab (keys, screen->xroot, grab, &keys->iso_next_group_combos[i]);
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < keys->n_iso_next_group_combos; i++)
|
||||
meta_change_keygrab (keys, screen->xroot, grab, &keys->iso_next_group_combo[i]);
|
||||
|
||||
change_binding_keygrabs (keys, screen->xroot, FALSE, grab);
|
||||
}
|
||||
@ -1367,7 +1414,7 @@ meta_display_grab_accelerator (MetaDisplay *display,
|
||||
MetaKeyBinding *binding;
|
||||
MetaKeyGrab *grab;
|
||||
MetaKeyCombo combo = { 0 };
|
||||
MetaResolvedKeyCombo resolved_combo = { 0 };
|
||||
MetaResolvedKeyCombo resolved_combo = { NULL, 0 };
|
||||
|
||||
if (!meta_parse_accelerator (accelerator, &combo))
|
||||
{
|
||||
@ -1380,11 +1427,14 @@ meta_display_grab_accelerator (MetaDisplay *display,
|
||||
|
||||
resolve_key_combo (keys, &combo, &resolved_combo);
|
||||
|
||||
if (resolved_combo.keycode == 0)
|
||||
if (resolved_combo.len == 0)
|
||||
return META_KEYBINDING_ACTION_NONE;
|
||||
|
||||
if (get_keybinding (keys, &resolved_combo))
|
||||
return META_KEYBINDING_ACTION_NONE;
|
||||
{
|
||||
resolved_key_combo_reset (&resolved_combo);
|
||||
return META_KEYBINDING_ACTION_NONE;
|
||||
}
|
||||
|
||||
meta_change_keygrab (keys, display->screen->xroot, TRUE, &resolved_combo);
|
||||
|
||||
@ -1415,7 +1465,7 @@ meta_display_ungrab_accelerator (MetaDisplay *display,
|
||||
MetaKeyBinding *binding;
|
||||
MetaKeyGrab *grab;
|
||||
char *key;
|
||||
MetaResolvedKeyCombo resolved_combo;
|
||||
MetaResolvedKeyCombo resolved_combo = { NULL, 0 };
|
||||
|
||||
g_return_val_if_fail (action != META_KEYBINDING_ACTION_NONE, FALSE);
|
||||
|
||||
@ -1428,18 +1478,22 @@ meta_display_ungrab_accelerator (MetaDisplay *display,
|
||||
binding = get_keybinding (keys, &resolved_combo);
|
||||
if (binding)
|
||||
{
|
||||
guint32 index_key;
|
||||
int i;
|
||||
|
||||
meta_change_keygrab (keys, display->screen->xroot, FALSE, &binding->resolved_combo);
|
||||
|
||||
index_key = key_combo_key (&binding->resolved_combo);
|
||||
g_hash_table_remove (keys->key_bindings_index, GINT_TO_POINTER (index_key));
|
||||
for (i = 0; i < binding->resolved_combo.len; i++)
|
||||
{
|
||||
guint32 index_key = key_combo_key (&binding->resolved_combo, i);
|
||||
g_hash_table_remove (keys->key_bindings_index, GINT_TO_POINTER (index_key));
|
||||
}
|
||||
|
||||
g_hash_table_remove (keys->key_bindings, binding);
|
||||
}
|
||||
|
||||
g_hash_table_remove (external_grabs, key);
|
||||
g_free (key);
|
||||
resolved_key_combo_reset (&resolved_combo);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -1645,16 +1699,15 @@ process_event (MetaDisplay *display,
|
||||
ClutterKeyEvent *event)
|
||||
{
|
||||
MetaKeyBindingManager *keys = &display->key_binding_manager;
|
||||
MetaResolvedKeyCombo resolved_combo;
|
||||
xkb_keycode_t keycode = (xkb_keycode_t) event->hardware_keycode;
|
||||
MetaResolvedKeyCombo resolved_combo = { &keycode, 1 };
|
||||
MetaKeyBinding *binding;
|
||||
|
||||
/* we used to have release-based bindings but no longer. */
|
||||
if (event->type == CLUTTER_KEY_RELEASE)
|
||||
return FALSE;
|
||||
|
||||
resolved_combo_from_event_params (&resolved_combo, keys,
|
||||
event->hardware_keycode,
|
||||
event->modifier_state);
|
||||
resolved_combo.mask = mask_from_event_params (keys, event->modifier_state);
|
||||
|
||||
binding = get_keybinding (keys, &resolved_combo);
|
||||
|
||||
@ -1708,7 +1761,8 @@ process_overlay_key (MetaDisplay *display,
|
||||
|
||||
if (keys->overlay_key_only_pressed)
|
||||
{
|
||||
if (event->hardware_keycode != (int)keys->overlay_resolved_key_combo.keycode)
|
||||
if (! resolved_key_combo_has_keycode (&keys->overlay_resolved_key_combo,
|
||||
event->hardware_keycode))
|
||||
{
|
||||
keys->overlay_key_only_pressed = FALSE;
|
||||
|
||||
@ -1790,7 +1844,8 @@ process_overlay_key (MetaDisplay *display,
|
||||
return TRUE;
|
||||
}
|
||||
else if (event->type == CLUTTER_KEY_PRESS &&
|
||||
event->hardware_keycode == (int)keys->overlay_resolved_key_combo.keycode)
|
||||
resolved_key_combo_has_keycode (&keys->overlay_resolved_key_combo,
|
||||
event->hardware_keycode))
|
||||
{
|
||||
keys->overlay_key_only_pressed = TRUE;
|
||||
/* We keep the keyboard frozen - this allows us to use ReplayKeyboard
|
||||
@ -1813,30 +1868,31 @@ process_iso_next_group (MetaDisplay *display,
|
||||
{
|
||||
MetaKeyBindingManager *keys = &display->key_binding_manager;
|
||||
gboolean activate;
|
||||
MetaResolvedKeyCombo resolved_combo;
|
||||
int i;
|
||||
xkb_keycode_t keycode = (xkb_keycode_t) event->hardware_keycode;
|
||||
xkb_mod_mask_t mask;
|
||||
int i, j;
|
||||
|
||||
if (event->type == CLUTTER_KEY_RELEASE)
|
||||
return FALSE;
|
||||
|
||||
activate = FALSE;
|
||||
|
||||
resolved_combo_from_event_params (&resolved_combo, keys,
|
||||
event->hardware_keycode,
|
||||
event->modifier_state);
|
||||
mask = mask_from_event_params (keys, event->modifier_state);
|
||||
|
||||
for (i = 0; i < keys->n_iso_next_group_combos; ++i)
|
||||
{
|
||||
if (resolved_combo.keycode == keys->iso_next_group_combos[i].keycode &&
|
||||
resolved_combo.mask == keys->iso_next_group_combos[i].mask)
|
||||
for (j = 0; j < keys->iso_next_group_combo[i].len; ++j)
|
||||
{
|
||||
/* 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))
|
||||
meta_display_unfreeze_keyboard (display, event->time);
|
||||
activate = TRUE;
|
||||
break;
|
||||
if (keycode == keys->iso_next_group_combo[i].keycodes[j] &&
|
||||
mask == keys->iso_next_group_combo[i].mask)
|
||||
{
|
||||
/* 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))
|
||||
meta_display_unfreeze_keyboard (display, event->time);
|
||||
activate = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user