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__ */
