[gtk+/gtk-2-24-quartz] Bug 663856 - Make option-foo accelerators use the right symbol



commit a7039c1564fdf889c2aaf1f1cd3e3f033a1b5e98
Author: Michael Natterer <mitch gimp org>
Date:   Fri Nov 18 12:25:03 2011 +0100

    Bug 663856 - Make option-foo accelerators use the right symbol
    
    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 |   16 ++++++++++----
 gtk/gtkcellrendereraccel.c  |   17 +++++++++------
 gtk/gtkkeyhash.c            |   35 +++++++++++++++++++++++++++------
 gtk/gtkmain.c               |   44 +++++++++++++++++++++++++++++++++++++++++++
 gtk/gtkmenu.c               |   21 ++++++++++++-------
 gtk/gtkprivate.h            |   17 ++++++++++++++++
 6 files changed, 123 insertions(+), 27 deletions(-)
---
diff --git a/gdk/quartz/gdkkeys-quartz.c b/gdk/quartz/gdkkeys-quartz.c
index 5b4a79a..19a20f5 100644
--- a/gdk/quartz/gdkkeys-quartz.c
+++ b/gdk/quartz/gdkkeys-quartz.c
@@ -688,12 +688,18 @@ gdk_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;
     }
 
diff --git a/gtk/gtkcellrendereraccel.c b/gtk/gtkcellrendereraccel.c
index 846b1ec..d25ec80 100644
--- a/gtk/gtkcellrendereraccel.c
+++ b/gtk/gtkcellrendereraccel.c
@@ -407,6 +407,7 @@ grab_key_callback (GtkWidget            *widget,
 {
   GdkModifierType accel_mods = 0;
   guint accel_key;
+  guint keyval;
   gchar *path;
   gboolean edited;
   gboolean cleared;
@@ -421,16 +422,18 @@ grab_key_callback (GtkWidget            *widget,
   edited = FALSE;
   cleared = FALSE;
 
-  gdk_keymap_translate_keyboard_state (gdk_keymap_get_for_display (display),
-				       event->hardware_keycode,
+  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_ISO_Left_Tab) 
     accel_key = GDK_Tab;
 
@@ -443,12 +446,12 @@ 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)
+      switch (keyval)
 	{
 	case GDK_Escape:
 	  goto out; /* cancel */
diff --git a/gtk/gtkkeyhash.c b/gtk/gtkkeyhash.c
index cbe0b77..bf7316e 100644
--- a/gtk/gtkkeyhash.c
+++ b/gtk/gtkkeyhash.c
@@ -18,9 +18,12 @@
  * 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"
 #include "gtkalias.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",
diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c
index bc19aed..a82ac51 100644
--- a/gtk/gtkmain.c
+++ b/gtk/gtkmain.c
@@ -2652,6 +2652,50 @@ _gtk_button_event_triggers_context_menu (GdkEventButton *event)
   return FALSE;
 }
 
+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;
+}
 
 #define __GTK_MAIN_C__
 #include "gtkaliasdef.c"
diff --git a/gtk/gtkmenu.c b/gtk/gtkmenu.c
index 69c8561..6415d58 100644
--- a/gtk/gtkmenu.c
+++ b/gtk/gtkmenu.c
@@ -3148,19 +3148,24 @@ 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),
-				       event->hardware_keycode, event->state, event->group,
-				       NULL, NULL, NULL, &consumed_modifiers);
-
-  accel_key = gdk_keyval_to_lower (event->keyval);
+  _gtk_translate_keyboard_accel_state (gdk_keymap_get_for_display (display),
+                                       event->hardware_keycode,
+                                       event->state,
+                                       gtk_accelerator_get_default_mod_mask (),
+                                       event->group,
+                                       &accel_key, NULL, NULL, &consumed_modifiers);
+
+  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-upper case when we match against the keyval, but display and save in caseless form.
+  /* If lowercasing affects the keysym, then we need to include SHIFT
+   * 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;
-  
+
+
   /* Modify the accelerators */
   if (can_change_accels &&
       menu_shell->active_menu_item &&
diff --git a/gtk/gtkprivate.h b/gtk/gtkprivate.h
index 53afe0e..6386c32 100644
--- a/gtk/gtkprivate.h
+++ b/gtk/gtkprivate.h
@@ -133,8 +133,25 @@ gboolean _gtk_fnmatch (const char *pattern,
 #define GTK_MODIFY_SELECTION_MOD_MASK GDK_MOD2_MASK
 #endif
 
+#ifndef GDK_WINDOWING_QUARTZ
+#define GTK_TOGGLE_GROUP_MOD_MASK 0
+#else
+#define GTK_TOGGLE_GROUP_MOD_MASK GDK_MOD1_MASK
+#endif
+
 gboolean _gtk_button_event_triggers_context_menu (GdkEventButton *event);
 
+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__ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]