[Xfce4-commits] <libxfce4ui:master> Merge branch 'jeromeg/keyboard-shortcuts-rework'
Jérôme Guelfucci
noreply at xfce.org
Thu Jun 2 23:46:13 CEST 2011
Updating branch refs/heads/master
to 1b78f177b7b604b8fb846fab600bff712d7f5578 (commit)
from f04158b0edbaece61b0397ebfa7b28db85377600 (commit)
commit 1b78f177b7b604b8fb846fab600bff712d7f5578
Merge: f04158b 6bd3a41
Author: Jérôme Guelfucci <jeromeg at xfce.org>
Date: Thu Jun 2 23:44:01 2011 +0200
Merge branch 'jeromeg/keyboard-shortcuts-rework'
commit 6bd3a4156da0f4a334a3887451f984ff507e78bf
Author: Jérôme Guelfucci <jeromeg at xfce.org>
Date: Thu Jun 2 15:00:04 2011 +0200
Improve indentation.
commit a3d141ec2665de548da5073366fcbc873468d0f1
Author: Jérôme Guelfucci <jeromeg at xfce.org>
Date: Thu Jun 2 14:56:34 2011 +0200
Also grab with MOD5 modifier.
commit 56f8e3858e6d84850f51c1772f8f4617bae4dd9b
Author: Jérôme Guelfucci <jeromeg at xfce.org>
Date: Thu Jun 2 14:54:07 2011 +0200
Add more debbuging information.
commit 5e50a7d5f6f868c12b1d439ff54600b984b2d5bd
Author: Jérôme Guelfucci <jeromeg at xfce.org>
Date: Sun May 29 18:09:45 2011 +0200
Use the current group when translating the keyboard state
commit 83770eec38278dd1e05577b48908d4b0b0d68dfc
Author: Jérôme Guelfucci <jeromeg at xfce.org>
Date: Sun May 29 18:09:19 2011 +0200
Improve code comments and error handling.
commit 13251f7a7ab201dd20186d81ca11e21922d35628
Author: Jérôme Guelfucci <jeromeg at xfce.org>
Date: Sun May 29 17:41:53 2011 +0200
Rework grabbing/ungrabbing code.
The code has been reworked to grab all keycodes generating the keyval
needed for the shortcut which should fix a number of issues where the
shortcut was not grabbed.
Error handling needs to be improved.
commit 310a4d7d9d3834e7ee074359973f52cc1e186502
Author: Jérôme Guelfucci <jeromeg at xfce.org>
Date: Sun May 29 16:40:39 2011 +0200
Remove gobject boilerplate.
commit a0fb8ffefa37d61e7f4724b5b422276902f4445b
Author: Jérôme Guelfucci <jeromeg at xfce.org>
Date: Sun May 22 16:18:32 2011 +0200
Fix shortcut comparing.
Because GDK functions do very useful stuff like echoing <Mod4><Super>
when Windows key is pressed or <Alt><Meta> is pressed we need to ignore
some modifiers in those cases...
This needs testing to ensure that it works in all cases.
commit 4868a7bac5234af48748bce09e2a848dfb37a628
Author: Jérôme Guelfucci <jeromeg at xfce.org>
Date: Sun May 22 16:17:53 2011 +0200
Rework shortcut parsing using gdk functions.
commit 5a4cbdd01c7712934c26a068af8b027b7ac3e1cc
Author: Jérôme Guelfucci <jeromeg at xfce.org>
Date: Fri Apr 22 17:09:46 2011 +0200
Simplify code monitoring key press events.
commit 899aaa97827f263c877faab3f8d0686fd9784b66
Author: Jérôme Guelfucci <jeromeg at xfce.org>
Date: Fri Apr 22 09:16:51 2011 +0200
Simplify computing of shortcut name in the dialog.
Instead of handling the key-pressed event with XKB code, we now use
gdk/gtk functions directly which simplifies things a lot.
This needs testing to ensure that there is no regression and that
shortcuts with Numlock work.
libxfce4kbd-private/xfce-shortcut-dialog.c | 108 +-----
libxfce4kbd-private/xfce-shortcuts-grabber.c | 541 +++++++++++---------------
2 files changed, 252 insertions(+), 397 deletions(-)
diff --git a/libxfce4kbd-private/xfce-shortcut-dialog.c b/libxfce4kbd-private/xfce-shortcut-dialog.c
index 8049467..5f1b058 100644
--- a/libxfce4kbd-private/xfce-shortcut-dialog.c
+++ b/libxfce4kbd-private/xfce-shortcut-dialog.c
@@ -43,9 +43,6 @@ static gboolean xfce_shortcut_dialog_key_pressed (XfceShortcutDialog *
GdkEventKey *event);
static gboolean xfce_shortcut_dialog_key_released (XfceShortcutDialog *dialog,
GdkEventKey *event);
-static gchar *xfce_shortcut_dialog_shortcut_name (XfceShortcutDialog *dialog,
- guint keyval,
- guint modifiers);
@@ -312,13 +309,29 @@ static gboolean
xfce_shortcut_dialog_key_pressed (XfceShortcutDialog *dialog,
GdkEventKey *event)
{
- gchar *text;
- gchar *shortcut;
+ GdkKeymap *keymap;
+ GdkModifierType consumed, modifiers;
+ guint keyval, mod_mask;
+ gchar *text;
+ gchar *shortcut;
g_free (dialog->shortcut);
- /* Determine and remember the current shortcut */
- dialog->shortcut = xfce_shortcut_dialog_shortcut_name (dialog, event->keyval, event->state);
+ /* Get the keyboard state */
+ mod_mask = gtk_accelerator_get_default_mod_mask ();
+ keymap = gdk_keymap_get_default ();
+ modifiers = event->state;
+
+ gdk_keymap_translate_keyboard_state (keymap, event->hardware_keycode,
+ modifiers, 0,
+ &keyval, NULL, NULL, &consumed);
+
+ /* Get the modifiers */
+ modifiers &= ~consumed;
+ modifiers &= mod_mask;
+
+ /* Get and store the pressed shortcut */
+ dialog->shortcut = gtk_accelerator_name (keyval, modifiers);
shortcut = g_markup_escape_text (dialog->shortcut, -1);
text = g_strdup_printf ("<span size='large'><b>%s</b></span>", shortcut);
@@ -362,87 +375,6 @@ xfce_shortcut_dialog_key_released (XfceShortcutDialog *dialog,
-static gchar *
-xfce_shortcut_dialog_shortcut_name (XfceShortcutDialog *dialog,
- guint keyval,
- guint modifiers)
-{
- XModifierKeymap *modmap;
- Display *display;
- const KeySym *keysyms;
- KeyCode keycode;
- KeySym *keymap;
- gint keysyms_per_keycode = 0;
- gint min_keycode = 0;
- gint max_keycode = 0;
- gint mask;
- gint i;
- gint j;
-
- g_return_val_if_fail (XFCE_IS_SHORTCUT_DIALOG (dialog), NULL);
-
- display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
-
- gdk_error_trap_push ();
-
- XDisplayKeycodes (display, &min_keycode, &max_keycode);
-
- keymap = XGetKeyboardMapping (display, min_keycode, max_keycode - min_keycode + 1, &keysyms_per_keycode);
-
- if (G_LIKELY (keymap != NULL))
- {
- modmap = XGetModifierMapping (display);
-
- if (G_LIKELY (modmap != NULL))
- {
- for (i = 0; i < 8 * modmap->max_keypermod; ++i)
- {
- keycode = modmap->modifiermap[i];
-
- if (keycode == 0 || keycode < min_keycode || keycode > max_keycode)
- continue;
-
- keysyms = keymap + (keycode - min_keycode) * keysyms_per_keycode;
- mask = 1 << (i / modmap->max_keypermod);
-
- for (j = 0; j < keysyms_per_keycode; ++j)
- {
- if (keysyms[j] == GDK_Super_L || keysyms[j] == GDK_Super_R)
- modifiers &= ~mask;
-
-#if 0
- if (keysyms[j] == GDK_Meta_L || keysyms[j] == GDK_Meta_R)
- modifiers &= ~mask;
-#endif
-
- if (keysyms[j] == GDK_Hyper_L || keysyms[j] == GDK_Hyper_R)
- modifiers &= ~mask;
-
- if (keysyms[j] == GDK_Scroll_Lock)
- modifiers &= ~mask;
-
- if (keysyms[j] == GDK_Num_Lock)
- modifiers &= ~mask;
-
- if (keysyms[j] == GDK_Caps_Lock)
- modifiers &= ~mask;
- }
- }
-
- XFreeModifiermap (modmap);
- }
-
- XFree (keymap);
- }
-
- gdk_flush ();
- gdk_error_trap_pop ();
-
- return gtk_accelerator_name (keyval, modifiers);
-}
-
-
-
const gchar*
xfce_shortcut_dialog_get_shortcut (XfceShortcutDialog *dialog)
{
diff --git a/libxfce4kbd-private/xfce-shortcuts-grabber.c b/libxfce4kbd-private/xfce-shortcuts-grabber.c
index e1a4f97..9faec07 100644
--- a/libxfce4kbd-private/xfce-shortcuts-grabber.c
+++ b/libxfce4kbd-private/xfce-shortcuts-grabber.c
@@ -26,6 +26,7 @@
#include <glib-object.h>
#include <X11/Xlib.h>
+#include <X11/XKBlib.h>
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
@@ -41,45 +42,8 @@
#define XFCE_SHORTCUTS_GRABBER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), XFCE_TYPE_SHORTCUTS_GRABBER, XfceShortcutsGrabberPrivate))
-
-
-
-#define MODIFIER_MASK (GDK_SHIFT_MASK | \
- GDK_CONTROL_MASK | \
- GDK_MOD1_MASK | \
- GDK_MOD2_MASK | \
- GDK_MOD3_MASK | \
- GDK_MOD4_MASK | \
- GDK_MOD5_MASK)
-
-#define IGNORE_MASK (0x2000 | \
- GDK_LOCK_MASK | \
- GDK_HYPER_MASK | \
- GDK_SUPER_MASK | \
- GDK_META_MASK)
-
-
-
-/* Property identifiers */
-enum
-{
- PROP_0,
-};
-
-
-
-/* Cache indices for modifiers */
-enum
-{
- CACHE_SUPER,
- CACHE_HYPER,
- CACHE_META,
- CACHE_CAPS_LOCK,
- CACHE_NUM_LOCK,
- CACHE_SCROLL_LOCK,
- CACHE_LAST,
-};
-
+#define MODIFIERS_ERROR ((GdkModifierType)(-1))
+#define MODIFIERS_NONE 0
typedef struct _XfceKey XfceKey;
@@ -88,27 +52,13 @@ typedef struct _XfceKey XfceKey;
static void xfce_shortcuts_grabber_constructed (GObject *object);
static void xfce_shortcuts_grabber_finalize (GObject *object);
-static void xfce_shortcuts_grabber_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec);
-static void xfce_shortcuts_grabber_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec);
static void xfce_shortcuts_grabber_keys_changed (GdkKeymap *keymap,
XfceShortcutsGrabber *grabber);
static void xfce_shortcuts_grabber_grab_all (XfceShortcutsGrabber *grabber);
static void xfce_shortcuts_grabber_ungrab_all (XfceShortcutsGrabber *grabber);
-static void xfce_shortcuts_grabber_reload_modifiers (XfceShortcutsGrabber *grabber);
-static void xfce_shortcuts_grabber_parse_shortcut (XfceShortcutsGrabber *grabber,
- const gchar *shortcut,
- guint *keycode,
- guint *modifiers);
static void xfce_shortcuts_grabber_grab (XfceShortcutsGrabber *grabber,
XfceKey *key,
gboolean grab);
-static guint xfce_shortcuts_grabber_get_ignore_mask (XfceShortcutsGrabber *grabber);
static GdkFilterReturn xfce_shortcuts_grabber_event_filter (GdkXEvent *gdk_xevent,
GdkEvent *event,
XfceShortcutsGrabber *grabber);
@@ -118,12 +68,11 @@ static GdkFilterReturn xfce_shortcuts_grabber_event_filter (GdkXEvent
struct _XfceShortcutsGrabberPrivate
{
GHashTable *keys;
- guint modifiers[CACHE_LAST];
};
struct _XfceKey
{
- guint keycode;
+ guint keyval;
guint modifiers;
};
@@ -143,8 +92,6 @@ xfce_shortcuts_grabber_class_init (XfceShortcutsGrabberClass *klass)
gobject_class = G_OBJECT_CLASS (klass);
gobject_class->constructed = xfce_shortcuts_grabber_constructed;
gobject_class->finalize = xfce_shortcuts_grabber_finalize;
- gobject_class->get_property = xfce_shortcuts_grabber_get_property;
- gobject_class->set_property = xfce_shortcuts_grabber_set_property;
g_signal_new ("shortcut-activated",
XFCE_TYPE_SHORTCUTS_GRABBER,
@@ -166,7 +113,12 @@ xfce_shortcuts_grabber_init (XfceShortcutsGrabber *grabber)
grabber->priv = XFCE_SHORTCUTS_GRABBER_GET_PRIVATE (grabber);
grabber->priv->keys = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
- xfce_shortcuts_grabber_reload_modifiers (grabber);
+ /* Workaround: Make sure modmap is up to date
+ * There is possibly a bug in GTK+ where virtual modifiers are not
+ * mapped because the modmap is not updated. The following function
+ * updates it.
+ */
+ (void) gdk_keymap_have_bidi_layouts (gdk_keymap_get_default ());
}
@@ -208,53 +160,14 @@ xfce_shortcuts_grabber_finalize (GObject *object)
static void
-xfce_shortcuts_grabber_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
-#if 0
- XfceShortcutsGrabber *grabber = XFCE_SHORTCUTS_GRABBER (object);
-#endif
-
- switch (prop_id)
- {
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-
-
-static void
-xfce_shortcuts_grabber_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
-#if 0
- XfceShortcutsGrabber *grabber = XFCE_SHORTCUTS_GRABBER (object);
-#endif
-
- switch (prop_id)
- {
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-
-
-static void
xfce_shortcuts_grabber_keys_changed (GdkKeymap *keymap,
XfceShortcutsGrabber *grabber)
{
g_return_if_fail (XFCE_IS_SHORTCUTS_GRABBER (grabber));
+ TRACE ("Keys changed, regrabbing");
+
xfce_shortcuts_grabber_ungrab_all (grabber);
- xfce_shortcuts_grabber_reload_modifiers (grabber);
xfce_shortcuts_grabber_grab_all (grabber);
}
@@ -300,246 +213,214 @@ xfce_shortcuts_grabber_ungrab_all (XfceShortcutsGrabber *grabber)
-static void
-xfce_shortcuts_grabber_reload_modifiers (XfceShortcutsGrabber *grabber)
+/* Return the modifier mask that needs to be pressed to produce key in the
+ * given group (keyboard layout) and level ("shift level").
+ *
+ * Taken from libkeybinder
+ * Copyright (C) 2010 Ulrik Sverdrup <ulrik.sverdrup at gmail.com>
+ */
+static GdkModifierType
+FinallyGetModifiersForKeycode (XkbDescPtr xkb,
+ KeyCode key,
+ uint group,
+ uint level)
{
- XModifierKeymap *modmap;
- const KeySym *keysyms;
- Display *display;
- KeyCode keycode;
- KeySym *keymap;
- gint keysyms_per_keycode = 0;
- gint min_keycode = 0;
- gint max_keycode = 0;
- gint mask;
- gint i;
- gint j;
-
- g_return_if_fail (XFCE_IS_SHORTCUTS_GRABBER (grabber));
-
- for (i = 0; i < CACHE_LAST; ++i)
- grabber->priv->modifiers[i] = 0;
-
- display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+ XkbKeyTypeRec *type;
+ int nKeyGroups;
+ int effectiveGroup;
+ int k;
- gdk_error_trap_push ();
-
- XDisplayKeycodes (display, &min_keycode, &max_keycode);
-
- keymap = XGetKeyboardMapping (display, min_keycode, max_keycode - min_keycode + 1,
- &keysyms_per_keycode);
+ nKeyGroups = XkbKeyNumGroups (xkb, key);
- if (G_UNLIKELY (keymap == NULL))
- return;
+ if ((!XkbKeycodeInRange (xkb, key)) || (nKeyGroups == 0))
+ return MODIFIERS_ERROR;
- modmap = XGetModifierMapping (display);
+ /* Taken from GDK's MyEnhancedXkbTranslateKeyCode */
+ /* find the offset of the effective group */
+ effectiveGroup = group;
- if (G_UNLIKELY (modmap == NULL))
+ if (effectiveGroup >= nKeyGroups)
{
- XFree (keymap);
- return;
- }
-
- for (i = 0; i < 8 * modmap->max_keypermod; ++i)
- {
- keycode = modmap->modifiermap[i];
-
- if (keycode == 0 || keycode < min_keycode || keycode > max_keycode)
- continue;
-
- keysyms = keymap + (keycode - min_keycode) * keysyms_per_keycode;
- mask = 1 << (i / modmap->max_keypermod);
+ unsigned groupInfo = XkbKeyGroupInfo (xkb,key);
- for (j = 0; j < keysyms_per_keycode; ++j)
+ switch (XkbOutOfRangeGroupAction(groupInfo))
{
- if (keysyms[j] == GDK_Super_L || keysyms[j] == GDK_Super_R)
- grabber->priv->modifiers[CACHE_SUPER] = mask;
-
- if (keysyms[j] == GDK_Meta_L || keysyms[j] == GDK_Meta_R)
- grabber->priv->modifiers[CACHE_META] = mask;
-
- if (keysyms[j] == GDK_Hyper_L || keysyms[j] == GDK_Hyper_R)
- grabber->priv->modifiers[CACHE_HYPER] = mask;
-
- if (keysyms[j] == GDK_Scroll_Lock)
- grabber->priv->modifiers[CACHE_SCROLL_LOCK] = mask;
+ default:
+ effectiveGroup %= nKeyGroups;
+ break;
+ case XkbClampIntoRange:
+ effectiveGroup = nKeyGroups-1;
+ break;
+ case XkbRedirectIntoRange:
+ effectiveGroup = XkbOutOfRangeGroupNumber (groupInfo);
+ if (effectiveGroup >= nKeyGroups)
+ effectiveGroup = 0;
+ break;
+ }
+ }
- if (keysyms[j] == GDK_Num_Lock)
- grabber->priv->modifiers[CACHE_NUM_LOCK] = mask;
+ type = XkbKeyKeyType (xkb, key, effectiveGroup);
- if (keysyms[j] == GDK_Caps_Lock)
- grabber->priv->modifiers[CACHE_CAPS_LOCK] = mask;
+ for (k = 0; k < type->map_count; k++)
+ {
+ if (type->map[k].active && type->map[k].level == level)
+ {
+ if (type->preserve)
+ return (type->map[k].mods.mask & ~type->preserve[k].mask);
+ else
+ return type->map[k].mods.mask;
}
}
- XFreeModifiermap (modmap);
- XFree (keymap);
-
- gdk_flush ();
- gdk_error_trap_pop ();
+ return MODIFIERS_NONE;
}
static void
-xfce_shortcuts_grabber_parse_shortcut (XfceShortcutsGrabber *grabber,
- const gchar *shortcut,
- guint *keycode,
- guint *modifiers)
+xfce_shortcuts_grabber_grab (XfceShortcutsGrabber *grabber,
+ XfceKey *key,
+ gboolean grab)
{
- guint keyval;
+ GdkKeymapKey *keys;
+ XkbDescPtr xmap;
+ GdkDisplay *display;
+ GdkKeymap *keymap;
+ gchar *shortcut_name;
+ guint modifiers;
+ guint k;
+ gint i, j;
+ gint n_keys;
+ gint screens;
g_return_if_fail (XFCE_IS_SHORTCUTS_GRABBER (grabber));
+ g_return_if_fail (key != NULL);
- gtk_accelerator_parse (shortcut, &keyval, modifiers);
-
- *keycode = XKeysymToKeycode (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), keyval);
-
- if ((*modifiers & GDK_SUPER_MASK) == GDK_SUPER_MASK)
- {
- *modifiers |= grabber->priv->modifiers[CACHE_SUPER];
- *modifiers ^= GDK_SUPER_MASK;
- }
-
- if ((*modifiers & GDK_HYPER_MASK) == GDK_HYPER_MASK)
- {
- *modifiers |= grabber->priv->modifiers[CACHE_HYPER];
- *modifiers ^= GDK_HYPER_MASK;
- }
-
- if ((*modifiers & GDK_META_MASK) == GDK_META_MASK)
- {
- *modifiers |= grabber->priv->modifiers[CACHE_META];
- *modifiers ^= GDK_META_MASK;
- }
-
- *modifiers &= MODIFIER_MASK;
- *modifiers &= ~xfce_shortcuts_grabber_get_ignore_mask (grabber);
-}
-
+ display = gdk_display_get_default ();
+ screens = gdk_display_get_n_screens (display);
+ keymap = gdk_keymap_get_default ();
+ /* Map virtual modifiers to non-virtual modifiers */
+ modifiers = key->modifiers;
+ gdk_keymap_map_virtual_modifiers (keymap, &modifiers);
-gchar *
-xfce_shortcuts_grabber_shortcut_name (XfceShortcutsGrabber *grabber,
- guint keycode,
- guint modifiers)
-{
- Display *display;
- KeySym keysym;
+ /* Debugging information */
+ shortcut_name = gtk_accelerator_name (key->keyval, modifiers);
- g_return_val_if_fail (XFCE_IS_SHORTCUTS_GRABBER (grabber), NULL);
+ if (grab)
+ TRACE ("Grabbing %s", shortcut_name);
+ else
+ TRACE ("Ungrabbing %s", shortcut_name);
- display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
- keysym = XKeycodeToKeysym (display, keycode, 0);
+ TRACE ("Keyval: %d", key->keyval);
+ TRACE ("Modifiers: 0x%x", key->modifiers);
- modifiers &= MODIFIER_MASK;
- modifiers &= ~xfce_shortcuts_grabber_get_ignore_mask (grabber);
+ g_free (shortcut_name);
- if ((modifiers & grabber->priv->modifiers[CACHE_SUPER]) != 0)
+ if (modifiers == key->modifiers &&
+ (GDK_SUPER_MASK | GDK_HYPER_MASK | GDK_META_MASK) & modifiers)
{
- modifiers |= GDK_SUPER_MASK;
- modifiers ^= grabber->priv->modifiers[CACHE_SUPER];
+ TRACE ("Failed to map virtual modifiers");
+ return;
}
- if ((modifiers & grabber->priv->modifiers[CACHE_HYPER]) != 0)
- {
- modifiers |= GDK_HYPER_MASK;
- modifiers ^= grabber->priv->modifiers[CACHE_HYPER];
- }
+ xmap = XkbGetMap (GDK_DISPLAY_XDISPLAY (display),
+ XkbAllClientInfoMask,
+ XkbUseCoreKbd);
-#if 0
- if ((modifiers & grabber->priv->modifiers[CACHE_META]) != 0)
+ /* Get all keys generating keyval */
+ if (!gdk_keymap_get_entries_for_keyval (keymap,key->keyval,
+ &keys, &n_keys))
{
- modifiers |= GDK_META_MASK;
- modifiers ^= grabber->priv->modifiers[CACHE_META];
+ XkbFreeClientMap (xmap, 0, TRUE);
+ TRACE ("Got no keys for keyval");
+ return;
}
-#endif
-
- return gtk_accelerator_name (keysym, modifiers);
-}
-
+ if (n_keys == 0)
+ {
+ XkbFreeClientMap (xmap, 0, TRUE);
+ g_free (keys);
-static void
-xfce_shortcuts_grabber_grab (XfceShortcutsGrabber *grabber,
- XfceKey *key,
- gboolean grab)
-{
- GdkDisplay *display;
- GdkScreen *screen;
- Window window;
- guint bits[32];
- guint current_mask;
- guint n_bits;
- guint screens;
- guint modifiers;
- guint ignored_modifiers = 0;
- gint i;
- guint j;
- guint k;
+ TRACE ("Got 0 keys for keyval");
+ return;
+ }
- g_return_if_fail (XFCE_IS_SHORTCUTS_GRABBER (grabber));
- g_return_if_fail (key != NULL);
+ for (i = 0; i < n_keys; i ++)
+ {
+ /* Grab all hardware keys generating keyval */
- display = gdk_display_get_default ();
- screens = gdk_display_get_n_screens (display);
+ GdkModifierType add_modifiers;
- ignored_modifiers = xfce_shortcuts_grabber_get_ignore_mask (grabber);
+ TRACE ("Keycode: %d", keys[i].keycode);
- modifiers = key->modifiers & MODIFIER_MASK & ~ignored_modifiers;
+ add_modifiers = FinallyGetModifiersForKeycode (xmap,
+ keys[i].keycode,
+ keys[i].group,
+ keys[i].level);
- /* Store indices of all the set bits of the ignore mask in an array */
- for (i = 0, n_bits = 0; i < 32; ++i, ignored_modifiers >>= 1)
- if ((ignored_modifiers & 0x1) == 0x1)
- bits[n_bits++] = i;
+ if (add_modifiers == MODIFIERS_ERROR)
+ {
+ TRACE ("Error when getting modifiers for keycode");
+ continue;
+ }
- for (i = 0; i < (1 << n_bits); ++i)
- {
- /* Map bits in the counter to those in the mask and thereby retrieve all ignored bit
- * mask combinations */
- for (current_mask = 0, j = 0; j < n_bits; ++j)
- if ((i & (1 << j)) != 0)
- current_mask |= (1 << bits[j]);
-
- /* Grab key on all screens */
- for (k = 0; k < screens; ++k)
+ for (j = 0; j < screens; j++)
{
- /* Get current screen and X root window */
- screen = gdk_display_get_screen (display, k);
- window = GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen));
+ /* Do the grab on all screens */
+ GdkScreen *screen;
+ Window root_window;
+
+ /* Ignorable modifiers */
+ guint mod_masks [] = {
+ 0,
+ GDK_MOD2_MASK,
+ GDK_LOCK_MASK,
+ GDK_MOD5_MASK,
+ GDK_MOD2_MASK | GDK_LOCK_MASK,
+ GDK_MOD2_MASK | GDK_MOD5_MASK,
+ GDK_LOCK_MASK | GDK_MOD5_MASK,
+ GDK_MOD2_MASK | GDK_LOCK_MASK | GDK_MOD5_MASK,
+ };
+
+ /* Retrieve the root window of the screen */
+ screen = gdk_display_get_screen (display, j);
+ root_window = GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen));
gdk_error_trap_push ();
- if (grab)
+ for (k = 0; k < G_N_ELEMENTS (mod_masks); k++)
{
- XGrabKey (GDK_DISPLAY_XDISPLAY (display), key->keycode, current_mask | modifiers,
- window, FALSE, GrabModeAsync, GrabModeAsync);
+ /* Take ignorable modifiers into account when grabbing */
+ if (grab)
+ XGrabKey (GDK_DISPLAY_XDISPLAY (display),
+ keys[i].keycode,
+ add_modifiers | modifiers | mod_masks [k],
+ root_window,
+ False,
+ GrabModeAsync,
+ GrabModeAsync);
+ else
+ XUngrabKey (GDK_DISPLAY_XDISPLAY (display),
+ keys[i].keycode,
+ add_modifiers | modifiers | mod_masks [k],
+ root_window);
}
- else
- XUngrabKey (GDK_DISPLAY_XDISPLAY (display), key->keycode, current_mask | modifiers,
- window);
gdk_flush ();
- gdk_error_trap_pop ();
+
+ if (gdk_error_trap_pop ())
+ {
+ if (grab)
+ TRACE ("Failed to grab");
+ else
+ TRACE ("Failed to ungrab");
+ }
}
}
-}
-
-
-static guint
-xfce_shortcuts_grabber_get_ignore_mask (XfceShortcutsGrabber *grabber)
-{
- guint mask = 0;
-
- g_return_val_if_fail (XFCE_IS_SHORTCUTS_GRABBER (grabber), 0);
-
- mask |= 0x200 | GDK_LOCK_MASK | GDK_HYPER_MASK | GDK_SUPER_MASK | GDK_META_MASK;
- mask |= grabber->priv->modifiers[CACHE_CAPS_LOCK];
- mask |= grabber->priv->modifiers[CACHE_NUM_LOCK];
- mask |= grabber->priv->modifiers[CACHE_SCROLL_LOCK];
-
- return mask;
+ g_free (keys);
+ XkbFreeClientMap (xmap, 0, TRUE);
}
@@ -547,7 +428,8 @@ xfce_shortcuts_grabber_get_ignore_mask (XfceShortcutsGrabber *grabber)
struct EventKeyFindContext
{
XfceShortcutsGrabber *grabber;
- XKeyEvent *xevent;
+ GdkModifierType modifiers;
+ guint keyval;
const gchar *result;
};
@@ -558,29 +440,38 @@ find_event_key (const gchar *shortcut,
XfceKey *key,
struct EventKeyFindContext *context)
{
- gchar *name;
- gboolean result = FALSE;
+ GdkModifierType ignored;
- g_return_val_if_fail (context != NULL, TRUE);
- g_return_val_if_fail (context->xevent != NULL, TRUE);
+ g_return_val_if_fail (context != NULL, FALSE);
- gdk_error_trap_push ();
+ TRACE ("Comparing to %s", shortcut);
- name = xfce_shortcuts_grabber_shortcut_name (context->grabber, context->xevent->keycode,
- context->xevent->state);
+ ignored = 0;
- if (G_UNLIKELY (g_str_equal (shortcut, name)))
+ /* Accept MOD1 + META as MOD1 */
+ if (key->modifiers & context->modifiers & GDK_MOD1_MASK)
{
- context->result = shortcut;
- result = TRUE;
+ TRACE ("Ignoring Meta Mask");
+ ignored |= GDK_META_MASK;
+ }
+
+ /* Accept SUPER + HYPER as SUPER */
+ if (key->modifiers & context->modifiers & GDK_SUPER_MASK)
+ {
+ TRACE ("Ignoring Hyper Mask");
+ ignored |= GDK_HYPER_MASK;
}
- g_free (name);
+ if ((key->modifiers & ~ignored) == (context->modifiers & ~ignored)
+ && key->keyval == context->keyval)
+ {
+ context->result = shortcut;
- gdk_flush ();
- gdk_error_trap_pop ();
+ TRACE ("Positive match for %s", context->result);
+ return TRUE;
+ }
- return result;
+ return FALSE;
}
@@ -590,9 +481,13 @@ xfce_shortcuts_grabber_event_filter (GdkXEvent *gdk_xevent,
GdkEvent *event,
XfceShortcutsGrabber *grabber)
{
- struct EventKeyFindContext context;
- XEvent *xevent;
- gint timestamp;
+ struct EventKeyFindContext context;
+ GdkKeymap *keymap;
+ GdkModifierType consumed, modifiers;
+ XEvent *xevent;
+ guint keyval, mod_mask;
+ gchar *raw_shortcut_name;
+ gint timestamp;
g_return_val_if_fail (XFCE_IS_SHORTCUTS_GRABBER (grabber), GDK_FILTER_CONTINUE);
@@ -602,14 +497,40 @@ xfce_shortcuts_grabber_event_filter (GdkXEvent *gdk_xevent,
return GDK_FILTER_CONTINUE;
context.grabber = grabber;
- context.xevent = (XKeyEvent *) xevent;
context.result = NULL;
- timestamp = context.xevent->time;
+ timestamp = xevent->xkey.time;
+
+ /* Get the keyboard state */
+ gdk_error_trap_push ();
+ keymap = gdk_keymap_get_default ();
+ mod_mask = gtk_accelerator_get_default_mod_mask ();
+ modifiers = xevent->xkey.state;
+
+ gdk_keymap_translate_keyboard_state (keymap, xevent->xkey.keycode,
+ modifiers,
+ XkbGroupForCoreState (xevent->xkey.state),
+ &keyval, NULL, NULL, &consumed);
+
+ /* Get the modifiers */
+ modifiers &= ~consumed;
+ gdk_keymap_add_virtual_modifiers (keymap, &modifiers);
+ modifiers &= mod_mask;
+
+ context.keyval = keyval;
+ context.modifiers = modifiers;
+
+ raw_shortcut_name = gtk_accelerator_name (keyval, modifiers);
+ TRACE ("Looking for %s", raw_shortcut_name);
+ g_free (raw_shortcut_name);
g_hash_table_foreach (grabber->priv->keys, (GHFunc) find_event_key, &context);
if (G_LIKELY (context.result != NULL))
- g_signal_emit_by_name (grabber, "shortcut-activated", context.result, timestamp);
+ g_signal_emit_by_name (grabber, "shortcut-activated",
+ context.result, timestamp);
+
+ gdk_flush ();
+ gdk_error_trap_pop ();
return GDK_FILTER_CONTINUE;
}
@@ -635,13 +556,15 @@ xfce_shortcuts_grabber_add (XfceShortcutsGrabber *grabber,
key = g_new0 (XfceKey, 1);
- xfce_shortcuts_grabber_parse_shortcut (grabber, shortcut, &key->keycode, &key->modifiers);
+ gtk_accelerator_parse (shortcut, &key->keyval, &key->modifiers);
- if (G_LIKELY (key->keycode != 0))
+ if (G_LIKELY (key->keyval != 0))
{
xfce_shortcuts_grabber_grab (grabber, key, TRUE);
g_hash_table_insert (grabber->priv->keys, g_strdup (shortcut), key);
}
+ else
+ g_free (key);
}
More information about the Xfce4-commits
mailing list