]> Pileus Git - ~andy/gtk/commitdiff
Bug 663856 - Make option-foo accelerators use the right symbol
authorMichael Natterer <mitch@lanedo.com>
Fri, 18 Nov 2011 11:25:03 +0000 (12:25 +0100)
committerMichael Natterer <mitch@gimp.org>
Fri, 18 Nov 2011 12:06:27 +0000 (13:06 +0100)
If the keyboard group shifting modifier is *also* a normal
accelerator modifier, we need to special case it when calling
gdk_keymap_translate_keyboard_state(), so we get the right
key symbol for accelerators (for example we want Option-O,
not Option-Ø displayed in menu items). This patch should only
affect quartz where the Alt key both shifts the group and can
be used as accel modifier, and not X11 or Win32 where AltGr
is not used for accelerators.

- fix quartz' gdk_keymap_translate_keyboard_state() to return
  the right consumed_modifiers
- add _gtk_translate_keyboard_accel_state() which does the
  special casing
- use it everywhere instead of gdk_keymap_translate_keyboard_state()

gdk/quartz/gdkkeys-quartz.c
gtk/gtkcellrendereraccel.c
gtk/gtkkeyhash.c
gtk/gtkmenu.c
gtk/gtkprivate.c
gtk/gtkprivate.h

index bb877361c3a573ed6971da64751d8e2d1a93a744..07d8489740fab0be19a352e5e4162ecd4deea79c 100644 (file)
@@ -692,12 +692,18 @@ gdk_quartz_keymap_translate_keyboard_state (GdkKeymap       *keymap,
 
   if (hardware_keycode < 0 || hardware_keycode >= NUM_KEYCODES)
     return FALSE;
-  
-  /* Check if shift or capslock modify the keyval */
-  for (bit = GDK_SHIFT_MASK; bit < GDK_CONTROL_MASK; bit <<= 1)
+
+  /* Check if modifiers modify the keyval */
+  for (bit = GDK_SHIFT_MASK; bit < GDK_BUTTON1_MASK; bit <<= 1)
     {
-      if (translate_keysym (hardware_keycode, group, state & ~bit, NULL, NULL) !=
-         translate_keysym (hardware_keycode, group, state | bit, NULL, NULL))
+      if (translate_keysym (hardware_keycode,
+                            (bit == GDK_MOD1_MASK) ? 0 : group,
+                            state & ~bit,
+                            NULL, NULL) !=
+         translate_keysym (hardware_keycode,
+                            (bit == GDK_MOD1_MASK) ? 1 : group,
+                            state | bit,
+                            NULL, NULL))
        tmp_modifiers |= bit;
     }
 
index 037aaa10c58a62bbba2e0f0ffb802691e960d01c..56be7f4463683458184372f69f7b8f519d8361e8 100644 (file)
@@ -442,6 +442,7 @@ grab_key_callback (GtkWidget            *widget,
   GtkCellRendererAccelPrivate *priv = accel->priv;
   GdkModifierType accel_mods = 0;
   guint accel_key;
+  guint keyval;
   gchar *path;
   gboolean edited;
   gboolean cleared;
@@ -456,16 +457,18 @@ grab_key_callback (GtkWidget            *widget,
   edited = FALSE;
   cleared = FALSE;
 
-  gdk_keymap_translate_keyboard_state (gdk_keymap_get_for_display (display),
+  accel_mods = event->state;
+
+  _gtk_translate_keyboard_accel_state (gdk_keymap_get_for_display (display),
                                        event->hardware_keycode,
                                        event->state,
+                                       gtk_accelerator_get_default_mod_mask (),
                                        event->group,
-                                       NULL, NULL, NULL, &consumed_modifiers);
+                                       &keyval, NULL, NULL, &consumed_modifiers);
 
-  accel_mods = event->state;
   gdk_keymap_add_virtual_modifiers (gdk_keymap_get_for_display (display), &accel_mods);
 
-  accel_key = gdk_keyval_to_lower (event->keyval);
+  accel_key = gdk_keyval_to_lower (keyval);
   if (accel_key == GDK_KEY_ISO_Left_Tab) 
     accel_key = GDK_KEY_Tab;
 
@@ -478,22 +481,22 @@ grab_key_callback (GtkWidget            *widget,
   
   /* Put shift back if it changed the case of the key, not otherwise.
    */
-  if (accel_key != event->keyval)
+  if (accel_key != keyval)
     accel_mods |= GDK_SHIFT_MASK;
     
   if (accel_mods == 0)
     {
-      switch (event->keyval)
-        {
-        case GDK_KEY_Escape:
-          goto out; /* cancel */
-        case GDK_KEY_BackSpace:
-          /* clear the accelerator on Backspace */
-          cleared = TRUE;
-          goto out;
-        default:
-          break;
-        }
+      switch (keyval)
+       {
+       case GDK_KEY_Escape:
+         goto out; /* cancel */
+       case GDK_KEY_BackSpace:
+         /* clear the accelerator on Backspace */
+         cleared = TRUE;
+         goto out;
+       default:
+         break;
+       }
     }
 
   if (priv->accel_mode == GTK_CELL_RENDERER_ACCEL_MODE_GTK)
index f5063f7322d35c615a2d616ad9b51b7e3fbfe4d7..954b9a100353bbc56c7573dd8369699174565da9 100644 (file)
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
+
 #include "config.h"
+
 #include "gtkdebug.h"
 #include "gtkkeyhash.h"
+#include "gtkprivate.h"
 
 typedef struct _GtkKeyHashEntry GtkKeyHashEntry;
 
@@ -392,6 +395,7 @@ _gtk_key_hash_lookup (GtkKeyHash      *key_hash,
   gint level;
   GdkModifierType modifiers;
   GdkModifierType consumed_modifiers;
+  gboolean group_mod_is_accel_mod = FALSE;
   const GdkModifierType xmods = GDK_MOD2_MASK|GDK_MOD3_MASK|GDK_MOD4_MASK|GDK_MOD5_MASK;
   const GdkModifierType vmods = GDK_SUPER_MASK|GDK_HYPER_MASK|GDK_META_MASK;
 
@@ -399,11 +403,18 @@ _gtk_key_hash_lookup (GtkKeyHash      *key_hash,
    */
   state &= ~GDK_LOCK_MASK;
 
-  gdk_keymap_map_virtual_modifiers (key_hash->keymap, &mask);
+  _gtk_translate_keyboard_accel_state (key_hash->keymap,
+                                       hardware_keycode, state, mask, group,
+                                       &keyval,
+                                       &effective_group, &level, &consumed_modifiers);
 
-  gdk_keymap_translate_keyboard_state (key_hash->keymap,
-                                      hardware_keycode, state, group,
-                                      &keyval, &effective_group, &level, &consumed_modifiers);
+  /* if the group-toggling modifier is part of the default accel mod
+   * mask, and it is active, disable it for matching
+   */
+  if (mask & GTK_TOGGLE_GROUP_MOD_MASK)
+    group_mod_is_accel_mod = TRUE;
+
+  gdk_keymap_map_virtual_modifiers (key_hash->keymap, &mask);
   gdk_keymap_add_virtual_modifiers (key_hash->keymap, &state);
 
   GTK_NOTE (KEYBINDINGS,
@@ -433,7 +444,14 @@ _gtk_key_hash_lookup (GtkKeyHash      *key_hash,
            {
              gint i;
 
-             if (keyval == entry->keyval) /* Exact match */
+             if (keyval == entry->keyval && /* Exact match */
+                  /* but also match for group if it is an accel mod, because
+                   * otherwise we can get multiple exact matches, some being
+                   * bogus */
+                  (!group_mod_is_accel_mod ||
+                   (state & GTK_TOGGLE_GROUP_MOD_MASK) ==
+                   (entry->modifiers & GTK_TOGGLE_GROUP_MOD_MASK)))
+
                {
                  GTK_NOTE (KEYBINDINGS,
                            g_message ("  found exact match, keyval = %u, modifiers = 0x%04x",
@@ -453,8 +471,11 @@ _gtk_key_hash_lookup (GtkKeyHash      *key_hash,
                {
                  for (i = 0; i < entry->n_keys; i++)
                    {
-                     if (entry->keys[i].keycode == hardware_keycode &&
-                         entry->keys[i].level == level) /* Match for all but group */
+                      if (entry->keys[i].keycode == hardware_keycode &&
+                          entry->keys[i].level == level &&
+                           /* Only match for group if it's an accel mod */
+                          (!group_mod_is_accel_mod ||
+                           entry->keys[i].group == effective_group))
                        {
                          GTK_NOTE (KEYBINDINGS,
                                    g_message ("  found group = %d, level = %d",
index bb52807b53e739f36e4b4fa0b3a756f0df2c06a3..ecb4038de46daf4208793addeab71fcbe79dab06 100644 (file)
@@ -3584,17 +3584,19 @@ gtk_menu_key_press (GtkWidget   *widget,
     }
 
   /* Figure out what modifiers went into determining the key symbol */
-  gdk_keymap_translate_keyboard_state (gdk_keymap_get_for_display (display),
+  _gtk_translate_keyboard_accel_state (gdk_keymap_get_for_display (display),
                                        event->hardware_keycode,
-                                       event->state, event->group,
-                                       NULL, NULL, NULL, &consumed_modifiers);
+                                       event->state,
+                                       gtk_accelerator_get_default_mod_mask (),
+                                       event->group,
+                                       &accel_key, NULL, NULL, &consumed_modifiers);
 
-  accel_key = gdk_keyval_to_lower (event->keyval);
+  accel_key = gdk_keyval_to_lower (accel_key);
   accel_mods = event->state & gtk_accelerator_get_default_mod_mask () & ~consumed_modifiers;
 
   /* If lowercasing affects the keysym, then we need to include SHIFT
-   * in the modifiers, we re-uppercase when we match against the keyval,
-   * but display and save in caseless form.
+   * in the modifiers, We re-upper case when we match against the
+   * keyval, but display and save in caseless form.
    */
   if (accel_key != event->keyval)
     accel_mods |= GDK_SHIFT_MASK;
index 73275fc13b6b592e9513743c31714ba4364cf512..1ec08147fb00d38c8ee843be7490029f5838b5bc 100644 (file)
@@ -204,3 +204,48 @@ _gtk_get_primary_accel_mod (void)
 
   return primary;
 }
+
+gboolean
+_gtk_translate_keyboard_accel_state (GdkKeymap       *keymap,
+                                     guint            hardware_keycode,
+                                     GdkModifierType  state,
+                                     GdkModifierType  accel_mask,
+                                     gint             group,
+                                     guint           *keyval,
+                                     gint            *effective_group,
+                                     gint            *level,
+                                     GdkModifierType *consumed_modifiers)
+{
+  gboolean group_mask_disabled = FALSE;
+  gboolean retval;
+
+  /* if the group-toggling modifier is part of the accel mod mask, and
+   * it is active, disable it for matching
+   */
+  if (accel_mask & state & GTK_TOGGLE_GROUP_MOD_MASK)
+    {
+      state &= ~GTK_TOGGLE_GROUP_MOD_MASK;
+      group = 0;
+      group_mask_disabled = TRUE;
+    }
+
+  retval = gdk_keymap_translate_keyboard_state (keymap,
+                                                hardware_keycode, state, group,
+                                                keyval,
+                                                effective_group, level,
+                                                consumed_modifiers);
+
+  /* add back the group mask, we want to match against the modifier,
+   * but not against the keyval from its group
+   */
+  if (group_mask_disabled)
+    {
+      if (effective_group)
+        *effective_group = 1;
+
+      if (consumed_modifiers)
+        *consumed_modifiers &= ~GTK_TOGGLE_GROUP_MOD_MASK;
+    }
+
+  return retval;
+}
index 53290ffc4d5fd1e582e429adb3de6a0659f6cc5e..e243199bc34efac8be8b25489172be7e7d5d6f98 100644 (file)
@@ -62,6 +62,23 @@ GdkModifierType _gtk_replace_virtual_modifiers (GdkKeymap       *keymap,
                                                 GdkModifierType  modifiers);
 GdkModifierType _gtk_get_primary_accel_mod     (void);
 
+/* temp hack, will go away soon --mitch */
+#ifndef GDK_WINDOWING_QUARTZ
+#define GTK_TOGGLE_GROUP_MOD_MASK 0
+#else
+#define GTK_TOGGLE_GROUP_MOD_MASK GDK_MOD1_MASK
+#endif
+
+gboolean _gtk_translate_keyboard_accel_state   (GdkKeymap       *keymap,
+                                                guint            hardware_keycode,
+                                                GdkModifierType  state,
+                                                GdkModifierType  accel_mask,
+                                                gint             group,
+                                                guint           *keyval,
+                                                gint            *effective_group,
+                                                gint            *level,
+                                                GdkModifierType *consumed_modifiers);
+
 G_END_DECLS
 
 #endif /* __GTK_PRIVATE_H__ */