summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2016-04-15 22:20:25 -0400
committerMatthias Clasen <mclasen@redhat.com>2016-04-19 10:36:14 -0400
commit4018a32e0b15047032e54d9a911bd9856b89ab34 (patch)
treed4ca97e121c35f972d2cbdf65c53a273f1860ba1
parente530a0ecd1de3577ee6c2eff649c9ee84bfcb501 (diff)
downloadgtk+-4018a32e0b15047032e54d9a911bd9856b89ab34.tar.gz
wayland: Implement virtual modifiers
Since Wayland is using libxkbcommon, it inherits X unfortunate real/virtual modifier distinction, so we have to do the same gymnastics we do for X to map between the two. This should fix matching of accelerators using virtual modifiers (modulo gnome-shell bugs regarding the handling of Super). https://bugzilla.gnome.org/show_bug.cgi?id=764424
-rw-r--r--gdk/wayland/gdkkeys-wayland.c52
1 files changed, 50 insertions, 2 deletions
diff --git a/gdk/wayland/gdkkeys-wayland.c b/gdk/wayland/gdkkeys-wayland.c
index 4819ab69d5..c8190c412f 100644
--- a/gdk/wayland/gdkkeys-wayland.c
+++ b/gdk/wayland/gdkkeys-wayland.c
@@ -370,14 +370,62 @@ static void
gdk_wayland_keymap_add_virtual_modifiers (GdkKeymap *keymap,
GdkModifierType *state)
{
- return;
+ struct xkb_keymap *xkb_keymap;
+ struct xkb_state *xkb_state;
+ xkb_mod_index_t idx;
+ uint32_t mods, real;
+ struct { const char *name; GdkModifierType mask; } vmods[] = {
+ { "Super", GDK_SUPER_MASK },
+ { "Hyper", GDK_HYPER_MASK },
+ { "Meta", GDK_META_MASK },
+ { NULL, 0 }
+ };
+ int i;
+
+ xkb_keymap = GDK_WAYLAND_KEYMAP (keymap)->xkb_keymap;
+ mods = get_xkb_modifiers (xkb_keymap, *state);
+
+ xkb_state = xkb_state_new (xkb_keymap);
+
+ for (i = 0; vmods[i].name; i++)
+ {
+ idx = xkb_keymap_mod_get_index (xkb_keymap, vmods[i].name);
+ if (idx == XKB_MOD_INVALID)
+ continue;
+
+ xkb_state_update_mask (xkb_state, 1 << idx, 0, 0, 0, 0, 0);
+ real = xkb_state_serialize_mods (xkb_state, XKB_STATE_MODS_EFFECTIVE);
+ real &= 0xff;
+ if (mods & real)
+ *state |= vmods[i].mask;
+ xkb_state_update_mask (xkb_state, 0, 0, 0, 0, 0, 0);
+ }
+
+ xkb_state_unref (xkb_state);
}
static gboolean
gdk_wayland_keymap_map_virtual_modifiers (GdkKeymap *keymap,
GdkModifierType *state)
{
- return TRUE;
+ struct xkb_keymap *xkb_keymap;
+ struct xkb_state *xkb_state;
+ uint32_t mods, mapped;
+ gboolean ret = TRUE;
+
+ xkb_keymap = GDK_WAYLAND_KEYMAP (keymap)->xkb_keymap;
+ mods = get_xkb_modifiers (xkb_keymap, *state);
+
+ xkb_state = xkb_state_new (xkb_keymap);
+ xkb_state_update_mask (xkb_state, mods, 0, 0, 0, 0, 0);
+ mapped = xkb_state_serialize_mods (xkb_state, XKB_STATE_MODS_EFFECTIVE);
+ if ((mapped & mods & 0xff) != 0)
+ ret = FALSE;
+ *state = get_gdk_modifiers (xkb_keymap, mapped);
+
+ xkb_state_unref (xkb_state);
+
+ return ret;
}
static void