diff --git a/gdk/wayland/gdkkeys-wayland.c b/gdk/wayland/gdkkeys-wayland.c index 46d2631046..d73199f42c 100644 --- a/gdk/wayland/gdkkeys-wayland.c +++ b/gdk/wayland/gdkkeys-wayland.c @@ -373,14 +373,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