Author: jannis Date: 2008-08-31 23:48:13 +0000 (Sun, 31 Aug 2008) New Revision: 27632
Modified: xfce4-settings/trunk/ChangeLog xfce4-settings/trunk/dialogs/keyboard-settings/shortcut-dialog.c xfce4-settings/trunk/xfce4-settings-helper/keyboard-shortcuts.c Log: * dialogs/keyboard-settings/shortcuts-dialog.c, xfce4-settings-helper/keyboard-shortcuts.c: Add two new functions called get_modifier_masks() and get_ignore_mask(). The first determines to which of the Mod2-Mod5 modifiers CapsLock, NumLock and ScrollLock are mapped and generates a modifier mask for them. The latter combines this mask with the IGNORED_MODIFIERS mask which we already used before and which includes GDK_HYPER_MASK etc.. This mask is then used in several places to avoid these modifiers to appear in the result of gtk_accelerator_name() and to properly grab the shortcuts. This should fix bug #4304. Modified: xfce4-settings/trunk/ChangeLog =================================================================== --- xfce4-settings/trunk/ChangeLog 2008-08-31 19:02:51 UTC (rev 27631) +++ xfce4-settings/trunk/ChangeLog 2008-08-31 23:48:13 UTC (rev 27632) @@ -1,3 +1,16 @@ +2008-09-01 Jannis Pohlmann <[EMAIL PROTECTED]> + + * dialogs/keyboard-settings/shortcuts-dialog.c, + xfce4-settings-helper/keyboard-shortcuts.c: Add two new functions + called get_modifier_masks() and get_ignore_mask(). The first + determines to which of the Mod2-Mod5 modifiers CapsLock, NumLock and + ScrollLock are mapped and generates a modifier mask for them. The + latter combines this mask with the IGNORED_MODIFIERS mask which we + already used before and which includes GDK_HYPER_MASK etc.. This + mask is then used in several places to avoid these modifiers to + appear in the result of gtk_accelerator_name() and to properly grab + the shortcuts. This should fix bug #4304. +. 2008-08-31 Jannis Pohlmann <[EMAIL PROTECTED]> * dialogs/keyboard-settings/shortcut-dialog.c: Ignore Modified: xfce4-settings/trunk/dialogs/keyboard-settings/shortcut-dialog.c =================================================================== --- xfce4-settings/trunk/dialogs/keyboard-settings/shortcut-dialog.c 2008-08-31 19:02:51 UTC (rev 27631) +++ xfce4-settings/trunk/dialogs/keyboard-settings/shortcut-dialog.c 2008-08-31 23:48:13 UTC (rev 27632) @@ -23,6 +23,8 @@ #include <config.h> #endif +#include <gdk/gdkkeysyms.h> + #include <gtk/gtk.h> #include <libxfce4util/libxfce4util.h> @@ -32,15 +34,6 @@ -/* Modifiers to be ignored (0x2000 is an Xkb modifier) */ -#define IGNORED_MODIFIERS (0x2000 | GDK_LOCK_MASK | GDK_HYPER_MASK | GDK_SUPER_MASK | GDK_META_MASK) - -/* Modifiers to be used */ -#define USED_MODIFIERS (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK | GDK_MOD2_MASK | \ - GDK_MOD3_MASK | GDK_MOD4_MASK | GDK_MOD5_MASK) - - - static void shortcut_dialog_class_init (ShortcutDialogClass *klass); static void shortcut_dialog_init (ShortcutDialog *dialog); static void shortcut_dialog_dispose (GObject *object); @@ -49,6 +42,11 @@ const gchar *action); static gboolean shortcut_dialog_key_released (ShortcutDialog *dialog, GdkEventKey *event); +static gboolean get_modmap_masks (Display *display, + gint *caps_lock_mask, + gint *num_lock_mask, + gint *scroll_lock_mask); +static gint get_ignore_mask (Display *display); @@ -308,13 +306,18 @@ shortcut_dialog_key_released (ShortcutDialog *dialog, GdkEventKey *event) { + Display *display; gboolean event_handled = FALSE; gboolean shortcut_accepted = FALSE; gchar *shortcut; gint modifiers; + gint ignore_mask; + /* Determine mask of ignored modifiers */ + ignore_mask = get_ignore_mask (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ())); + /* Strip ignored modifiers from the event mask */ - modifiers = event->state & ~IGNORED_MODIFIERS & GDK_MODIFIER_MASK; + modifiers = event->state & ~ignore_mask; /* Get GTK+ accelerator string */ shortcut = gtk_accelerator_name (event->keyval, modifiers); @@ -352,3 +355,117 @@ g_return_val_if_fail (IS_SHORTCUT_DIALOG (dialog), NULL); return dialog->shortcut; } + + + +/* The following code appears again in xfce4-settings-helper/keyboard-shortcuts-helper.c: */ + +/* Modifiers to be ignored (0x2000 is an Xkb modifier) */ +#define IGNORED_MODIFIERS (0x2000 | GDK_LOCK_MASK | GDK_HYPER_MASK | GDK_SUPER_MASK | GDK_META_MASK) + +/* Modifiers to be used */ +#define USED_MODIFIERS (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK | GDK_MOD2_MASK | \ + GDK_MOD3_MASK | GDK_MOD4_MASK | GDK_MOD5_MASK) + + + +static gboolean +get_modmap_masks (Display *display, + gint *caps_lock_mask, + gint *num_lock_mask, + gint *scroll_lock_mask) +{ + XModifierKeymap *modmap; + 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; + + /* Clear the masks */ + *caps_lock_mask = 0; + *num_lock_mask = 0; + *scroll_lock_mask = 0; + + gdk_error_trap_push (); + + /* Determine minimum and maximum number of keycodes */ + XDisplayKeycodes (display, &min_keycode, &max_keycode); + + /* Determine symbols for all keycodes */ + keymap = XGetKeyboardMapping (display, min_keycode, max_keycode - min_keycode + 1, &keysyms_per_keycode); + + if (G_UNLIKELY (keymap == NULL)) + return FALSE; + + /* Determine modifier mappign */ + modmap = XGetModifierMapping (display); + + if (G_UNLIKELY (modmap == NULL)) + { + XFree (keymap); + return FALSE; + } + + /* Iterate over all modifier keycodes */ + for (i = 0; i < 8 * modmap->max_keypermod; ++i) + { + /* Get the current keycode */ + keycode = modmap->modifiermap[i]; + + /* Ignore invalid codes */ + if (keycode == 0 || keycode < min_keycode || keycode > max_keycode) + continue; + + /* Determine all keysyms for the current keycode */ + keysyms = keymap + (keycode - min_keycode) * keysyms_per_keycode; + + /* Create modifier mask for the current modifier */ + mask = 1 << (i / modmap->max_keypermod); + + /* Iterate over all keysyms of the current keycode and modify the resulting + * masks according to which keysyms belong to which X modifiers */ + for (j = 0; j < keysyms_per_keycode; ++j) + { + if (keysyms[j] == GDK_Caps_Lock) + *caps_lock_mask |= mask; + else if (keysyms[j] == GDK_Num_Lock) + *num_lock_mask |= mask; + else if (keysyms[j] == GDK_Scroll_Lock) + *scroll_lock_mask |= mask; + } + } + + /* Free mappings */ + XFreeModifiermap (modmap); + XFree (keymap); + + gdk_flush (); + gdk_error_trap_pop (); + + return TRUE; +} + + + +static gint +get_ignore_mask (Display *display) +{ + gint caps_lock_mask; + gint num_lock_mask; + gint scroll_lock_mask; + gint ignore_mask; + + ignore_mask = IGNORED_MODIFIERS & GDK_MODIFIER_MASK; + + if (G_LIKELY (get_modmap_masks (display, &caps_lock_mask, &num_lock_mask, &scroll_lock_mask))) + ignore_mask |= caps_lock_mask | num_lock_mask | scroll_lock_mask; + + return ignore_mask; +} + +/* End of the duplicated code */ Modified: xfce4-settings/trunk/xfce4-settings-helper/keyboard-shortcuts.c =================================================================== --- xfce4-settings/trunk/xfce4-settings-helper/keyboard-shortcuts.c 2008-08-31 19:02:51 UTC (rev 27631) +++ xfce4-settings/trunk/xfce4-settings-helper/keyboard-shortcuts.c 2008-08-31 23:48:13 UTC (rev 27632) @@ -31,6 +31,7 @@ #include <gtk/gtk.h> #include <gdk/gdk.h> #include <gdk/gdkx.h> +#include <gdk/gdkkeysyms.h> #include <xfconf/xfconf.h> #include <libxfcegui4/libxfcegui4.h> @@ -40,16 +41,6 @@ -/* Modifiers to be ignored (0x2000 is an Xkb modifier) */ -#define IGNORED_MODIFIERS (0x2000 | GDK_LOCK_MASK | GDK_HYPER_MASK) - -/* Modifiers to be used */ -#define USED_MODIFIERS (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_SUPER_MASK | GDK_META_MASK | \ - GDK_MOD1_MASK | GDK_MOD2_MASK | GDK_MOD3_MASK | GDK_MOD4_MASK | GDK_MOD5_MASK) - - - - /* Property identifiers */ enum { @@ -103,10 +94,14 @@ const GValue *value, gchar **shortcut, gchar **action); +static gboolean get_modmap_masks (Display *display, + gint *caps_lock_mask, + gint *num_lock_mask, + gint *scroll_lock_mask); +static gint get_ignore_mask (Display *display); - struct _XfceKeyboardShortcutsHelperClass { GObjectClass __parent__; @@ -389,11 +384,11 @@ return FALSE ; } - /* Create mask containing ignored modifier bits set which are not set in the grab_mask already */ - ignore_mask = IGNORED_MODIFIERS & ~grab_mask & GDK_MODIFIER_MASK; + /* Determine mask containing ignored modifier bits */ + ignore_mask = get_ignore_mask (xdisplay); /* Store indices of all set bits of the ignore mask in an array */ - for (i = 0, n_bits = 0; ignore_mask != 0; ++i, ignore_mask >>= 1) + for (i = 0, n_bits = 0; i < 32; ++i, ignore_mask >>= 1) if ((ignore_mask & 0x1) != 0) bits[n_bits++] = i; @@ -496,6 +491,7 @@ const gchar *value; gint monitor; gint modifiers; + gint ignore_mask; g_return_if_fail (XFCE_IS_KEYBOARD_SHORTCUTS_HELPER (helper)); @@ -509,12 +505,17 @@ /* Convert event keycode to keysym */ keysym = XKeycodeToKeysym (GDK_DISPLAY_XDISPLAY (display), xevent->keycode, 0); + /* Determine ignored modifiers mask */ + ignore_mask = get_ignore_mask (GDK_DISPLAY_XDISPLAY (display)); + /* Remove ignored modifiers and non-modifier keys from the event state mask */ - modifiers = xevent->state & ~IGNORED_MODIFIERS & GDK_MODIFIER_MASK; + modifiers = xevent->state & ~ignore_mask & GDK_MODIFIER_MASK; /* Get accelerator string for the pressed keys */ accelerator_name = gtk_accelerator_name (keysym, modifiers); + g_message ("accelerator_name = %s", accelerator_name); + /* Perform accelerator lookup */ if (G_LIKELY (g_hash_table_lookup_extended (helper->shortcuts, accelerator_name, (gpointer) &key, (gpointer) &value))) { @@ -641,3 +642,117 @@ return result; } + + + +/* The following code appears again in dialogs/keyboard-settings/shortcut-dialog.c: */ + +/* Modifiers to be ignored (0x2000 is an Xkb modifier) */ +#define IGNORED_MODIFIERS (0x2000 | GDK_LOCK_MASK | GDK_HYPER_MASK | GDK_SUPER_MASK | GDK_META_MASK) + +/* Modifiers to be used */ +#define USED_MODIFIERS (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK | GDK_MOD2_MASK | \ + GDK_MOD3_MASK | GDK_MOD4_MASK | GDK_MOD5_MASK) + + + +static gboolean +get_modmap_masks (Display *display, + gint *caps_lock_mask, + gint *num_lock_mask, + gint *scroll_lock_mask) +{ + XModifierKeymap *modmap; + 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; + + /* Clear the masks */ + *caps_lock_mask = 0; + *num_lock_mask = 0; + *scroll_lock_mask = 0; + + gdk_error_trap_push (); + + /* Determine minimum and maximum number of keycodes */ + XDisplayKeycodes (display, &min_keycode, &max_keycode); + + /* Determine symbols for all keycodes */ + keymap = XGetKeyboardMapping (display, min_keycode, max_keycode - min_keycode + 1, &keysyms_per_keycode); + + if (G_UNLIKELY (keymap == NULL)) + return FALSE; + + /* Determine modifier mappign */ + modmap = XGetModifierMapping (display); + + if (G_UNLIKELY (modmap == NULL)) + { + XFree (keymap); + return FALSE; + } + + /* Iterate over all modifier keycodes */ + for (i = 0; i < 8 * modmap->max_keypermod; ++i) + { + /* Get the current keycode */ + keycode = modmap->modifiermap[i]; + + /* Ignore invalid codes */ + if (keycode == 0 || keycode < min_keycode || keycode > max_keycode) + continue; + + /* Determine all keysyms for the current keycode */ + keysyms = keymap + (keycode - min_keycode) * keysyms_per_keycode; + + /* Create modifier mask for the current modifier */ + mask = 1 << (i / modmap->max_keypermod); + + /* Iterate over all keysyms of the current keycode and modify the resulting + * masks according to which keysyms belong to which X modifiers */ + for (j = 0; j < keysyms_per_keycode; ++j) + { + if (keysyms[j] == GDK_Caps_Lock) + *caps_lock_mask |= mask; + else if (keysyms[j] == GDK_Num_Lock) + *num_lock_mask |= mask; + else if (keysyms[j] == GDK_Scroll_Lock) + *scroll_lock_mask |= mask; + } + } + + /* Free mappings */ + XFreeModifiermap (modmap); + XFree (keymap); + + gdk_flush (); + gdk_error_trap_pop (); + + return TRUE; +} + + + +static gint +get_ignore_mask (Display *display) +{ + gint caps_lock_mask; + gint num_lock_mask; + gint scroll_lock_mask; + gint ignore_mask; + + ignore_mask = IGNORED_MODIFIERS & GDK_MODIFIER_MASK; + + if (G_LIKELY (get_modmap_masks (display, &caps_lock_mask, &num_lock_mask, &scroll_lock_mask))) + ignore_mask |= caps_lock_mask | num_lock_mask | scroll_lock_mask; + + return ignore_mask; +} + +/* End of the duplicated code */ _______________________________________________ Xfce4-commits mailing list Xfce4-commits@xfce.org http://foo-projects.org/mailman/listinfo/xfce4-commits