|
|
f92192 |
From a9c7fb96d9d03547d53c6fdd27a1cf6f4d00b17d Mon Sep 17 00:00:00 2001
|
|
|
f92192 |
From: Andrea Azzarone <azzaronea@gmail.com>
|
|
|
f92192 |
Date: Fri, 13 Jul 2018 14:49:38 +0200
|
|
|
f92192 |
Subject: [PATCH] clutter/x11: Implement keycode remap to keysyms on virtual
|
|
|
f92192 |
key devices
|
|
|
f92192 |
|
|
|
f92192 |
Keycode lookup can fail for serveral reasons, e.g. if there is no combination of
|
|
|
f92192 |
modifiers and keycodes that can produce the target keysym with the current
|
|
|
f92192 |
keyboard layout.
|
|
|
f92192 |
|
|
|
f92192 |
In case the keycode lookup fails, remap temporarily the keysym to an unused
|
|
|
f92192 |
keycodes.
|
|
|
f92192 |
|
|
|
f92192 |
Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/109
|
|
|
f92192 |
---
|
|
|
f92192 |
clutter/clutter/x11/clutter-keymap-x11.c | 154 ++++++++++++++++++
|
|
|
f92192 |
clutter/clutter/x11/clutter-keymap-x11.h | 6 +-
|
|
|
f92192 |
.../x11/clutter-virtual-input-device-x11.c | 19 ++-
|
|
|
f92192 |
3 files changed, 173 insertions(+), 6 deletions(-)
|
|
|
f92192 |
|
|
|
f92192 |
diff --git a/clutter/clutter/x11/clutter-keymap-x11.c b/clutter/clutter/x11/clutter-keymap-x11.c
|
|
|
f92192 |
index c34e676a4..744fab979 100644
|
|
|
f92192 |
--- a/clutter/clutter/x11/clutter-keymap-x11.c
|
|
|
f92192 |
+++ b/clutter/clutter/x11/clutter-keymap-x11.c
|
|
|
f92192 |
@@ -81,6 +81,9 @@ struct _ClutterKeymapX11
|
|
|
f92192 |
int current_group;
|
|
|
f92192 |
#endif
|
|
|
f92192 |
|
|
|
f92192 |
+ GHashTable *reserved_keycodes;
|
|
|
f92192 |
+ GQueue *available_keycodes;
|
|
|
f92192 |
+
|
|
|
f92192 |
guint caps_lock_state : 1;
|
|
|
f92192 |
guint num_lock_state : 1;
|
|
|
f92192 |
guint has_direction : 1;
|
|
|
f92192 |
@@ -441,15 +444,98 @@ clutter_keymap_x11_set_property (GObject *gobject,
|
|
|
f92192 |
}
|
|
|
f92192 |
}
|
|
|
f92192 |
|
|
|
f92192 |
+static void
|
|
|
f92192 |
+clutter_keymap_x11_refresh_reserved_keycodes (ClutterKeymapX11 *keymap_x11)
|
|
|
f92192 |
+{
|
|
|
f92192 |
+ Display *dpy = clutter_x11_get_default_display ();
|
|
|
f92192 |
+ GHashTableIter iter;
|
|
|
f92192 |
+ gpointer key, value;
|
|
|
f92192 |
+
|
|
|
f92192 |
+ g_hash_table_iter_init (&iter, keymap_x11->reserved_keycodes);
|
|
|
f92192 |
+ while (g_hash_table_iter_next (&iter, &key, &value))
|
|
|
f92192 |
+ {
|
|
|
f92192 |
+ guint reserved_keycode = GPOINTER_TO_UINT (key);
|
|
|
f92192 |
+ guint reserved_keysym = GPOINTER_TO_UINT (value);
|
|
|
f92192 |
+ guint actual_keysym = XkbKeycodeToKeysym (dpy, reserved_keycode, 0, 0);
|
|
|
f92192 |
+
|
|
|
f92192 |
+ /* If an available keycode is no longer mapped to the stored keysym, then
|
|
|
f92192 |
+ * the keycode should not be considered available anymore and should be
|
|
|
f92192 |
+ * removed both from the list of available and reserved keycodes.
|
|
|
f92192 |
+ */
|
|
|
f92192 |
+ if (reserved_keysym != actual_keysym)
|
|
|
f92192 |
+ {
|
|
|
f92192 |
+ g_hash_table_iter_remove (&iter);
|
|
|
f92192 |
+ g_queue_remove (keymap_x11->available_keycodes, key);
|
|
|
f92192 |
+ }
|
|
|
f92192 |
+ }
|
|
|
f92192 |
+}
|
|
|
f92192 |
+
|
|
|
f92192 |
+static gboolean
|
|
|
f92192 |
+clutter_keymap_x11_replace_keycode (ClutterKeymapX11 *keymap_x11,
|
|
|
f92192 |
+ KeyCode keycode,
|
|
|
f92192 |
+ KeySym keysym)
|
|
|
f92192 |
+{
|
|
|
f92192 |
+ if (CLUTTER_BACKEND_X11 (keymap_x11->backend)->use_xkb)
|
|
|
f92192 |
+ {
|
|
|
f92192 |
+ Display *dpy = clutter_x11_get_default_display ();
|
|
|
f92192 |
+ XkbDescPtr xkb = get_xkb (keymap_x11);
|
|
|
f92192 |
+ XkbMapChangesRec changes;
|
|
|
f92192 |
+
|
|
|
f92192 |
+ XFlush (dpy);
|
|
|
f92192 |
+
|
|
|
f92192 |
+ xkb->device_spec = XkbUseCoreKbd;
|
|
|
f92192 |
+ memset (&changes, 0, sizeof(changes));
|
|
|
f92192 |
+
|
|
|
f92192 |
+ if (keysym != NoSymbol)
|
|
|
f92192 |
+ {
|
|
|
f92192 |
+ int types[XkbNumKbdGroups] = { XkbOneLevelIndex };
|
|
|
f92192 |
+ XkbChangeTypesOfKey (xkb, keycode, 1, XkbGroup1Mask, types, &changes);
|
|
|
f92192 |
+ XkbKeySymEntry (xkb, keycode, 0, 0) = keysym;
|
|
|
f92192 |
+ }
|
|
|
f92192 |
+ else
|
|
|
f92192 |
+ {
|
|
|
f92192 |
+ /* Reset to NoSymbol */
|
|
|
f92192 |
+ XkbChangeTypesOfKey (xkb, keycode, 0, XkbGroup1Mask, NULL, &changes);
|
|
|
f92192 |
+ }
|
|
|
f92192 |
+
|
|
|
f92192 |
+ changes.changed = XkbKeySymsMask | XkbKeyTypesMask;
|
|
|
f92192 |
+ changes.first_key_sym = keycode;
|
|
|
f92192 |
+ changes.num_key_syms = 1;
|
|
|
f92192 |
+ changes.first_type = 0;
|
|
|
f92192 |
+ changes.num_types = xkb->map->num_types;
|
|
|
f92192 |
+ XkbChangeMap (dpy, xkb, &changes);
|
|
|
f92192 |
+
|
|
|
f92192 |
+ XFlush (dpy);
|
|
|
f92192 |
+
|
|
|
f92192 |
+ return TRUE;
|
|
|
f92192 |
+ }
|
|
|
f92192 |
+
|
|
|
f92192 |
+ return FALSE;
|
|
|
f92192 |
+}
|
|
|
f92192 |
+
|
|
|
f92192 |
static void
|
|
|
f92192 |
clutter_keymap_x11_finalize (GObject *gobject)
|
|
|
f92192 |
{
|
|
|
f92192 |
ClutterKeymapX11 *keymap;
|
|
|
f92192 |
ClutterEventTranslator *translator;
|
|
|
f92192 |
+ GHashTableIter iter;
|
|
|
f92192 |
+ gpointer key, value;
|
|
|
f92192 |
|
|
|
f92192 |
keymap = CLUTTER_KEYMAP_X11 (gobject);
|
|
|
f92192 |
translator = CLUTTER_EVENT_TRANSLATOR (keymap);
|
|
|
f92192 |
|
|
|
f92192 |
+ clutter_keymap_x11_refresh_reserved_keycodes (keymap);
|
|
|
f92192 |
+ g_hash_table_iter_init (&iter, keymap->reserved_keycodes);
|
|
|
f92192 |
+ while (g_hash_table_iter_next (&iter, &key, &value))
|
|
|
f92192 |
+ {
|
|
|
f92192 |
+ guint keycode = GPOINTER_TO_UINT (key);
|
|
|
f92192 |
+ clutter_keymap_x11_replace_keycode (keymap, keycode, NoSymbol);
|
|
|
f92192 |
+ }
|
|
|
f92192 |
+
|
|
|
f92192 |
+ g_hash_table_destroy (keymap->reserved_keycodes);
|
|
|
f92192 |
+ g_queue_free (keymap->available_keycodes);
|
|
|
f92192 |
+
|
|
|
f92192 |
+
|
|
|
f92192 |
#ifdef HAVE_XKB
|
|
|
f92192 |
_clutter_backend_remove_event_translator (keymap->backend, translator);
|
|
|
f92192 |
|
|
|
f92192 |
@@ -483,6 +569,8 @@ clutter_keymap_x11_init (ClutterKeymapX11 *keymap)
|
|
|
f92192 |
{
|
|
|
f92192 |
keymap->current_direction = PANGO_DIRECTION_NEUTRAL;
|
|
|
f92192 |
keymap->current_group = -1;
|
|
|
f92192 |
+ keymap->reserved_keycodes = g_hash_table_new (NULL, NULL);
|
|
|
f92192 |
+ keymap->available_keycodes = g_queue_new ();
|
|
|
f92192 |
}
|
|
|
f92192 |
|
|
|
f92192 |
static ClutterTranslateReturn
|
|
|
f92192 |
@@ -766,6 +854,72 @@ clutter_keymap_x11_get_entries_for_keyval (ClutterKeymapX11 *keymap_x11,
|
|
|
f92192 |
}
|
|
|
f92192 |
}
|
|
|
f92192 |
|
|
|
f92192 |
+static guint
|
|
|
f92192 |
+clutter_keymap_x11_get_available_keycode (ClutterKeymapX11 *keymap_x11)
|
|
|
f92192 |
+{
|
|
|
f92192 |
+ if (CLUTTER_BACKEND_X11 (keymap_x11->backend)->use_xkb)
|
|
|
f92192 |
+ {
|
|
|
f92192 |
+ clutter_keymap_x11_refresh_reserved_keycodes (keymap_x11);
|
|
|
f92192 |
+
|
|
|
f92192 |
+ if (g_hash_table_size (keymap_x11->reserved_keycodes) < 5)
|
|
|
f92192 |
+ {
|
|
|
f92192 |
+ Display *dpy = clutter_x11_get_default_display ();
|
|
|
f92192 |
+ XkbDescPtr xkb = get_xkb (keymap_x11);
|
|
|
f92192 |
+ guint i;
|
|
|
f92192 |
+
|
|
|
f92192 |
+ for (i = xkb->max_key_code; i >= xkb->min_key_code; --i)
|
|
|
f92192 |
+ {
|
|
|
f92192 |
+ if (XkbKeycodeToKeysym (dpy, i, 0, 0) == NoSymbol)
|
|
|
f92192 |
+ return i;
|
|
|
f92192 |
+ }
|
|
|
f92192 |
+ }
|
|
|
f92192 |
+
|
|
|
f92192 |
+ return GPOINTER_TO_UINT (g_queue_pop_head (keymap_x11->available_keycodes));
|
|
|
f92192 |
+ }
|
|
|
f92192 |
+
|
|
|
f92192 |
+ return 0;
|
|
|
f92192 |
+}
|
|
|
f92192 |
+
|
|
|
f92192 |
+gboolean clutter_keymap_x11_reserve_keycode (ClutterKeymapX11 *keymap_x11,
|
|
|
f92192 |
+ guint keyval,
|
|
|
f92192 |
+ guint *keycode_out)
|
|
|
f92192 |
+{
|
|
|
f92192 |
+ g_return_val_if_fail (CLUTTER_IS_KEYMAP_X11 (keymap_x11), FALSE);
|
|
|
f92192 |
+ g_return_val_if_fail (keyval != 0, FALSE);
|
|
|
f92192 |
+ g_return_val_if_fail (keycode_out != NULL, FALSE);
|
|
|
f92192 |
+
|
|
|
f92192 |
+ *keycode_out = clutter_keymap_x11_get_available_keycode (keymap_x11);
|
|
|
f92192 |
+
|
|
|
f92192 |
+ if (*keycode_out == NoSymbol)
|
|
|
f92192 |
+ {
|
|
|
f92192 |
+ g_warning ("Cannot reserve a keycode for keyval %d: no available keycode", keyval);
|
|
|
f92192 |
+ return FALSE;
|
|
|
f92192 |
+ }
|
|
|
f92192 |
+
|
|
|
f92192 |
+ if (!clutter_keymap_x11_replace_keycode (keymap_x11, *keycode_out, keyval))
|
|
|
f92192 |
+ {
|
|
|
f92192 |
+ g_warning ("Failed to remap keycode %d to keyval %d", *keycode_out, keyval);
|
|
|
f92192 |
+ return FALSE;
|
|
|
f92192 |
+ }
|
|
|
f92192 |
+
|
|
|
f92192 |
+ g_hash_table_insert (keymap_x11->reserved_keycodes, GUINT_TO_POINTER (*keycode_out), GUINT_TO_POINTER (keyval));
|
|
|
f92192 |
+ g_queue_remove (keymap_x11->available_keycodes, GUINT_TO_POINTER (*keycode_out));
|
|
|
f92192 |
+
|
|
|
f92192 |
+ return TRUE;
|
|
|
f92192 |
+}
|
|
|
f92192 |
+
|
|
|
f92192 |
+void clutter_keymap_x11_release_keycode_if_needed (ClutterKeymapX11 *keymap_x11,
|
|
|
f92192 |
+ guint keycode)
|
|
|
f92192 |
+{
|
|
|
f92192 |
+ g_return_if_fail (CLUTTER_IS_KEYMAP_X11 (keymap_x11));
|
|
|
f92192 |
+
|
|
|
f92192 |
+ if (!g_hash_table_contains (keymap_x11->reserved_keycodes, GUINT_TO_POINTER (keycode)) ||
|
|
|
f92192 |
+ g_queue_index (keymap_x11->available_keycodes, GUINT_TO_POINTER (keycode)) != -1)
|
|
|
f92192 |
+ return;
|
|
|
f92192 |
+
|
|
|
f92192 |
+ g_queue_push_tail (keymap_x11->available_keycodes, GUINT_TO_POINTER (keycode));
|
|
|
f92192 |
+}
|
|
|
f92192 |
+
|
|
|
f92192 |
void
|
|
|
f92192 |
clutter_keymap_x11_latch_modifiers (ClutterKeymapX11 *keymap_x11,
|
|
|
f92192 |
uint32_t level,
|
|
|
f92192 |
diff --git a/clutter/clutter/x11/clutter-keymap-x11.h b/clutter/clutter/x11/clutter-keymap-x11.h
|
|
|
f92192 |
index 4b5b403c8..4decb44ee 100644
|
|
|
f92192 |
--- a/clutter/clutter/x11/clutter-keymap-x11.h
|
|
|
f92192 |
+++ b/clutter/clutter/x11/clutter-keymap-x11.h
|
|
|
f92192 |
@@ -58,7 +58,11 @@ gboolean clutter_keymap_x11_keycode_for_keyval (ClutterKeymapX11 *keymap_x11,
|
|
|
f92192 |
void clutter_keymap_x11_latch_modifiers (ClutterKeymapX11 *keymap_x11,
|
|
|
f92192 |
uint32_t level,
|
|
|
f92192 |
gboolean enable);
|
|
|
f92192 |
-
|
|
|
f92192 |
+gboolean clutter_keymap_x11_reserve_keycode (ClutterKeymapX11 *keymap_x11,
|
|
|
f92192 |
+ guint keyval,
|
|
|
f92192 |
+ guint *keycode_out);
|
|
|
f92192 |
+void clutter_keymap_x11_release_keycode_if_needed (ClutterKeymapX11 *keymap_x11,
|
|
|
f92192 |
+ guint keycode);
|
|
|
f92192 |
G_END_DECLS
|
|
|
f92192 |
|
|
|
f92192 |
#endif /* __CLUTTER_KEYMAP_X11_H__ */
|
|
|
f92192 |
diff --git a/clutter/clutter/x11/clutter-virtual-input-device-x11.c b/clutter/clutter/x11/clutter-virtual-input-device-x11.c
|
|
|
f92192 |
index e16ba3fd0..cab26c38c 100644
|
|
|
f92192 |
--- a/clutter/clutter/x11/clutter-virtual-input-device-x11.c
|
|
|
f92192 |
+++ b/clutter/clutter/x11/clutter-virtual-input-device-x11.c
|
|
|
f92192 |
@@ -143,8 +143,13 @@ clutter_virtual_input_device_x11_notify_keyval (ClutterVirtualInputDevice *virtu
|
|
|
f92192 |
|
|
|
f92192 |
if (!clutter_keymap_x11_keycode_for_keyval (keymap, keyval, &keycode, &level))
|
|
|
f92192 |
{
|
|
|
f92192 |
- g_warning ("No keycode found for keyval %x in current group", keyval);
|
|
|
f92192 |
- return;
|
|
|
f92192 |
+ level = 0;
|
|
|
f92192 |
+
|
|
|
f92192 |
+ if (!clutter_keymap_x11_reserve_keycode (keymap, keyval, &keycode))
|
|
|
f92192 |
+ {
|
|
|
f92192 |
+ g_warning ("No keycode found for keyval %x in current group", keyval);
|
|
|
f92192 |
+ return;
|
|
|
f92192 |
+ }
|
|
|
f92192 |
}
|
|
|
f92192 |
|
|
|
f92192 |
if (!_clutter_keymap_x11_get_is_modifier (keymap, keycode) &&
|
|
|
f92192 |
@@ -155,9 +160,13 @@ clutter_virtual_input_device_x11_notify_keyval (ClutterVirtualInputDevice *virtu
|
|
|
f92192 |
(KeyCode) keycode,
|
|
|
f92192 |
key_state == CLUTTER_KEY_STATE_PRESSED, 0);
|
|
|
f92192 |
|
|
|
f92192 |
- if (!_clutter_keymap_x11_get_is_modifier (keymap, keycode) &&
|
|
|
f92192 |
- key_state == CLUTTER_KEY_STATE_RELEASED)
|
|
|
f92192 |
- clutter_keymap_x11_latch_modifiers (keymap, level, FALSE);
|
|
|
f92192 |
+
|
|
|
f92192 |
+ if (key_state == CLUTTER_KEY_STATE_RELEASED)
|
|
|
f92192 |
+ {
|
|
|
f92192 |
+ if (!_clutter_keymap_x11_get_is_modifier (keymap, keycode))
|
|
|
f92192 |
+ clutter_keymap_x11_latch_modifiers (keymap, level, FALSE);
|
|
|
f92192 |
+ clutter_keymap_x11_release_keycode_if_needed (keymap, keycode);
|
|
|
f92192 |
+ }
|
|
|
f92192 |
}
|
|
|
f92192 |
|
|
|
f92192 |
static void
|
|
|
f92192 |
--
|
|
|
f92192 |
2.26.2
|
|
|
f92192 |
|