From 543ce67477599e8b519a66fec1fc34d2e7157066 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 6 Sep 2005 17:56:01 +0000 Subject: [PATCH] Add support for extra virtual modifiers: (#85780, Owen Taylor) 2005-09-06 Matthias Clasen Add support for extra virtual modifiers: (#85780, Owen Taylor) * gdk/x11/gdkkeys-x11.c (struct _GdkKeymapX11): Add a modmap to maintain the information which X modifiers map to virtual modifiers. (get_xkb): Set up the modmap from the XKB tables. (update_keymaps): Set up the modmap from the information returned by XGetModifierMapping in the non-XKB case. * gdk/x11/gdkprivate-x11.h: * gdk/x11/gdkkeys-x11.c (_gdk_keymap_add_virtual_modifiers): New function to set the virtual modifiers in the state. * gdk/x11/gdkevents-x11.c (translate_key_event): Call _gdk_keymap_add_virtual_modifiers here. * gdk/gdktypes.h (GdkModifierType): Add bits for virtual Super, Hyper and Meta modifiers. Also add GDK_ALT_MASK as an alias for GDK_MOD1_MASK. --- ChangeLog | 22 ++++++++++ ChangeLog.pre-2-10 | 22 ++++++++++ gdk/gdktypes.h | 13 ++++-- gdk/x11/gdkevents-x11.c | 2 + gdk/x11/gdkkeys-x11.c | 95 +++++++++++++++++++++++++++++++++++++--- gdk/x11/gdkprivate-x11.h | 2 + 6 files changed, 147 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index b7feeca281..cdbca2bd1e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2005-09-06 Matthias Clasen + + Add support for extra virtual modifiers: (#85780, Owen Taylor) + + * gdk/x11/gdkkeys-x11.c (struct _GdkKeymapX11): Add a + modmap to maintain the information which X modifiers map to + virtual modifiers. + (get_xkb): Set up the modmap from the XKB tables. + (update_keymaps): Set up the modmap from the information returned + by XGetModifierMapping in the non-XKB case. + + * gdk/x11/gdkprivate-x11.h: + * gdk/x11/gdkkeys-x11.c (_gdk_keymap_add_virtual_modifiers): New + function to set the virtual modifiers in the state. + + * gdk/x11/gdkevents-x11.c (translate_key_event): Call + _gdk_keymap_add_virtual_modifiers here. + + * gdk/gdktypes.h (GdkModifierType): Add bits for virtual Super, + Hyper and Meta modifiers. Also add GDK_ALT_MASK as an alias + for GDK_MOD1_MASK. + 2005-09-05 Matthias Clasen * gtk/gtkaction.c (connect_proxy): Set the label of a button diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index b7feeca281..cdbca2bd1e 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,25 @@ +2005-09-06 Matthias Clasen + + Add support for extra virtual modifiers: (#85780, Owen Taylor) + + * gdk/x11/gdkkeys-x11.c (struct _GdkKeymapX11): Add a + modmap to maintain the information which X modifiers map to + virtual modifiers. + (get_xkb): Set up the modmap from the XKB tables. + (update_keymaps): Set up the modmap from the information returned + by XGetModifierMapping in the non-XKB case. + + * gdk/x11/gdkprivate-x11.h: + * gdk/x11/gdkkeys-x11.c (_gdk_keymap_add_virtual_modifiers): New + function to set the virtual modifiers in the state. + + * gdk/x11/gdkevents-x11.c (translate_key_event): Call + _gdk_keymap_add_virtual_modifiers here. + + * gdk/gdktypes.h (GdkModifierType): Add bits for virtual Super, + Hyper and Meta modifiers. Also add GDK_ALT_MASK as an alias + for GDK_MOD1_MASK. + 2005-09-05 Matthias Clasen * gtk/gtkaction.c (connect_proxy): Set the label of a button diff --git a/gdk/gdktypes.h b/gdk/gdktypes.h index 5472ca9d1a..3998e5586c 100644 --- a/gdk/gdktypes.h +++ b/gdk/gdktypes.h @@ -119,6 +119,7 @@ typedef enum GDK_LOCK_MASK = 1 << 1, GDK_CONTROL_MASK = 1 << 2, GDK_MOD1_MASK = 1 << 3, + GDK_ALT_MASK = GDK_MOD1_MASK, GDK_MOD2_MASK = 1 << 4, GDK_MOD3_MASK = 1 << 5, GDK_MOD4_MASK = 1 << 6, @@ -128,12 +129,18 @@ typedef enum GDK_BUTTON3_MASK = 1 << 10, GDK_BUTTON4_MASK = 1 << 11, GDK_BUTTON5_MASK = 1 << 12, + /* The next few modifiers are used by XKB, so we skip to the end. - * Bits 16 - 28 are currently unused, but will eventually - * be used for "virtual modifiers". Bit 29 is used internally. + * Bits 15 - 25 are currently unused. Bit 29 is used internally. */ + + GDK_SUPER_MASK = 1 << 26, + GDK_HYPER_MASK = 1 << 27, + GDK_META_MASK = 1 << 28, + GDK_RELEASE_MASK = 1 << 30, - GDK_MODIFIER_MASK = GDK_RELEASE_MASK | 0x1fff + + GDK_MODIFIER_MASK = 0x5c001fff } GdkModifierType; typedef enum diff --git a/gdk/x11/gdkevents-x11.c b/gdk/x11/gdkevents-x11.c index 0a273a4b6b..d1505b2ae1 100644 --- a/gdk/x11/gdkevents-x11.c +++ b/gdk/x11/gdkevents-x11.c @@ -610,6 +610,8 @@ translate_key_event (GdkDisplay *display, &event->key.keyval, NULL, NULL, NULL); + _gdk_keymap_add_virtual_modifiers (keymap, &event->key.state); + /* Fill in event->string crudely, since various programs * depend on it. */ diff --git a/gdk/x11/gdkkeys-x11.c b/gdk/x11/gdkkeys-x11.c index 6539e79fff..531aa17383 100644 --- a/gdk/x11/gdkkeys-x11.c +++ b/gdk/x11/gdkkeys-x11.c @@ -80,6 +80,7 @@ struct _GdkKeymapX11 guint lock_keysym; GdkModifierType group_switch_mask; GdkModifierType num_lock_mask; + GdkModifierType modmap[8]; gboolean sun_keypad; PangoDirection current_direction; gboolean have_direction; @@ -168,6 +169,43 @@ update_keyrange (GdkKeymapX11 *keymap_x11) #ifdef HAVE_XKB +static void +update_modmap (Display *display, + GdkKeymapX11 *keymap_x11) +{ + static struct { + const gchar *name; + Atom atom; + GdkModifierType mask; + } vmods[] = { + { "Meta", 0, GDK_META_MASK }, + { "Super", 0, GDK_SUPER_MASK }, + { "Hyper", 0, GDK_HYPER_MASK }, + { NULL, 0, 0 } + }; + + gint i, j, k; + + if (!vmods[0].atom) + for (i = 0; vmods[i].name; i++) + vmods[i].atom = XInternAtom (display, vmods[i].name, FALSE); + + for (i = 0; i < XkbNumVirtualMods; i++) + { + for (j = 0; vmods[j].atom; j++) + { + if (keymap_x11->xkb_desc->names->vmods[i] == vmods[j].atom) + { + for (k = 0; k < 8; k++) + { + if (keymap_x11->xkb_desc->server->vmods[i] & (1 << k)) + keymap_x11->modmap[k] |= vmods[j].mask; + } + } + } + } +} + static XkbDescPtr get_xkb (GdkKeymapX11 *keymap_x11) { @@ -178,17 +216,21 @@ get_xkb (GdkKeymapX11 *keymap_x11) if (keymap_x11->xkb_desc == NULL) { - keymap_x11->xkb_desc = XkbGetMap (xdisplay, XkbKeySymsMask | XkbKeyTypesMask, XkbUseCoreKbd); + keymap_x11->xkb_desc = XkbGetMap (xdisplay, XkbKeySymsMask | XkbKeyTypesMask | XkbVirtualModsMask, XkbUseCoreKbd); if (keymap_x11->xkb_desc == NULL) g_error ("Failed to get keymap"); - XkbGetNames (xdisplay, XkbGroupNamesMask, keymap_x11->xkb_desc); + XkbGetNames (xdisplay, XkbGroupNamesMask | XkbVirtualModNamesMask, keymap_x11->xkb_desc); + + update_modmap (xdisplay, keymap_x11); } else if (keymap_x11->current_serial != display_x11->keymap_serial) { - XkbGetUpdatedMap (xdisplay, XkbKeySymsMask | XkbKeyTypesMask, + XkbGetUpdatedMap (xdisplay, XkbKeySymsMask | XkbKeyTypesMask | XkbVirtualModsMask, keymap_x11->xkb_desc); - XkbGetNames (xdisplay, XkbGroupNamesMask, keymap_x11->xkb_desc); + XkbGetNames (xdisplay, XkbGroupNamesMask | XkbVirtualModNamesMask, keymap_x11->xkb_desc); + + update_modmap (xdisplay, keymap_x11); } keymap_x11->current_serial = display_x11->keymap_serial; @@ -324,7 +366,7 @@ update_keymaps (GdkKeymapX11 *keymap_x11) keymap_x11->lock_keysym = GDK_VoidSymbol; keymap_x11->group_switch_mask = 0; keymap_x11->num_lock_mask = 0; - + /* There are 8 sets of modifiers, with each set containing * max_keypermod keycodes. */ @@ -344,6 +386,22 @@ update_keymaps (GdkKeymapX11 *keymap_x11) syms = keymap_x11->keymap + (keycode - keymap_x11->min_keycode) * keymap_x11->keysyms_per_keycode; + mask = 0; + for (j = 0; j < keymap_x11->keysyms_per_keycode; j++) + { + if (syms[j] == GDK_Meta_L || + syms[j] == GDK_Meta_R) + mask |= GDK_META_MASK; + else if (syms[j] == GDK_Hyper_L || + syms[j] == GDK_Hyper_R) + mask |= GDK_HYPER_MASK; + else if (syms[j] == GDK_Super_L || + syms[j] == GDK_Super_R) + mask |= GDK_SUPER_MASK; + } + + keymap_x11->modmap[i/keymap_x11->mod_keymap->max_keypermod] |= mask; + /* The fourth modifier, GDK_MOD1_MASK is 1 << 3. * Each group of max_keypermod entries refers to the same modifier. */ @@ -1299,7 +1357,7 @@ gdk_keymap_translate_keyboard_state (GdkKeymap *keymap, if (hardware_keycode < keymap_x11->min_keycode || hardware_keycode > keymap_x11->max_keycode) return FALSE; - + #ifdef HAVE_XKB if (KEYMAP_USE_XKB (keymap)) { @@ -1447,5 +1505,30 @@ _gdk_x11_get_group_for_state (GdkDisplay *display, } } +void +_gdk_keymap_add_virtual_modifiers (GdkKeymap *keymap, + GdkModifierType *modifiers) +{ + GdkKeymapX11 *keymap_x11; + int i; + + keymap = GET_EFFECTIVE_KEYMAP (keymap); + keymap_x11 = GDK_KEYMAP_X11 (keymap); + + for (i = 3; i < 8; i++) + { + if ((1 << i) & *modifiers) + { + if (keymap_x11->modmap[i] & GDK_SUPER_MASK) + *modifiers |= GDK_SUPER_MASK; + else if (keymap_x11->modmap[i] & GDK_HYPER_MASK) + *modifiers |= GDK_HYPER_MASK; + else if (keymap_x11->modmap[i] & GDK_META_MASK) + *modifiers |= GDK_META_MASK; + } + } +} + + #define __GDK_KEYS_X11_C__ #include "gdkaliasdef.c" diff --git a/gdk/x11/gdkprivate-x11.h b/gdk/x11/gdkprivate-x11.h index 5e9e2cba61..cc310cf820 100644 --- a/gdk/x11/gdkprivate-x11.h +++ b/gdk/x11/gdkprivate-x11.h @@ -143,6 +143,8 @@ void _gdk_keymap_state_changed (GdkDisplay *display); void _gdk_keymap_keys_changed (GdkDisplay *display); gint _gdk_x11_get_group_for_state (GdkDisplay *display, GdkModifierType state); +void _gdk_keymap_add_virtual_modifiers (GdkKeymap *keymap, + GdkModifierType *modifiers); GC _gdk_x11_gc_flush (GdkGC *gc);