Index: gtk/gtkaccelgroup.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkaccelgroup.c,v
retrieving revision 1.61
diff -u -p -r1.61 gtkaccelgroup.c
--- gtk/gtkaccelgroup.c	1 Sep 2005 05:11:38 -0000	1.61
+++ gtk/gtkaccelgroup.c	5 Sep 2005 05:46:31 -0000
@@ -963,6 +963,41 @@ is_release (const gchar *string)
 	  (string[8] == '>'));
 }
 
+static inline gboolean
+is_meta (const gchar *string)
+{
+  return ((string[0] == '<') &&
+	  (string[1] == 'm' || string[1] == 'M') &&
+	  (string[2] == 'e' || string[2] == 'E') &&
+	  (string[3] == 't' || string[3] == 'T') &&
+	  (string[4] == 'a' || string[4] == 'A') &&
+	  (string[5] == '>'));
+}
+
+static inline gboolean
+is_super (const gchar *string)
+{
+  return ((string[0] == '<') &&
+	  (string[1] == 's' || string[1] == 'S') &&
+	  (string[2] == 'u' || string[2] == 'U') &&
+	  (string[3] == 'p' || string[3] == 'P') &&
+	  (string[4] == 'e' || string[4] == 'E') &&
+	  (string[5] == 'r' || string[5] == 'R') &&
+	  (string[6] == '>'));
+}
+
+static inline gboolean
+is_hyper (const gchar *string)
+{
+  return ((string[0] == '<') &&
+	  (string[1] == 'h' || string[1] == 'H') &&
+	  (string[2] == 'y' || string[2] == 'Y') &&
+	  (string[3] == 'p' || string[3] == 'P') &&
+	  (string[4] == 'e' || string[4] == 'E') &&
+	  (string[5] == 'r' || string[5] == 'R') &&
+	  (string[6] == '>'));
+}
+
 /**
  * gtk_accelerator_parse:
  * @accelerator:      string representing an accelerator
@@ -1052,7 +1087,25 @@ gtk_accelerator_parse (const gchar     *
 	    {
 	      accelerator += 5;
 	      len -= 5;
-	      mods |= GDK_MOD1_MASK;
+	      mods |= GDK_ALT_MASK;
+	    }
+          else if (len >= 6 && is_meta (accelerator))
+	    {
+	      accelerator += 6;
+	      len -= 6;
+	      mods |= GDK_META_MASK;
+	    }
+          else if (len >= 7 && is_hyper (accelerator))
+	    {
+	      accelerator += 7;
+	      len -= 7;
+	      mods |= GDK_HYPER_MASK;
+	    }
+          else if (len >= 7 && is_super (accelerator))
+	    {
+	      accelerator += 7;
+	      len -= 7;
+	      mods |= GDK_SUPER_MASK;
 	    }
 	  else
 	    {
@@ -1108,6 +1161,9 @@ gtk_accelerator_name (guint           ac
   static const gchar text_mod3[] = "<Mod3>";
   static const gchar text_mod4[] = "<Mod4>";
   static const gchar text_mod5[] = "<Mod5>";
+  static const gchar text_meta[] = "<Meta>";
+  static const gchar text_super[] = "<Super>";
+  static const gchar text_hyper[] = "<Hyper>";
   guint l;
   gchar *keyval_name;
   gchar *accelerator;
@@ -1136,6 +1192,12 @@ gtk_accelerator_name (guint           ac
   if (accelerator_mods & GDK_MOD5_MASK)
     l += sizeof (text_mod5) - 1;
   l += strlen (keyval_name);
+  if (accelerator_mods & GDK_META_MASK)
+    l += sizeof (text_meta) - 1;
+  if (accelerator_mods & GDK_HYPER_MASK)
+    l += sizeof (text_hyper) - 1;
+  if (accelerator_mods & GDK_SUPER_MASK)
+    l += sizeof (text_super) - 1;
 
   accelerator = g_new (gchar, l + 1);
 
@@ -1180,6 +1242,21 @@ gtk_accelerator_name (guint           ac
     {
       strcpy (accelerator + l, text_mod5);
       l += sizeof (text_mod5) - 1;
+    }
+  if (accelerator_mods & GDK_META_MASK)
+    {
+      strcpy (accelerator + l, text_meta);
+      l += sizeof (text_meta) - 1;
+    }
+  if (accelerator_mods & GDK_HYPER_MASK)
+    {
+      strcpy (accelerator + l, text_hyper);
+      l += sizeof (text_hyper) - 1;
+    }
+  if (accelerator_mods & GDK_SUPER_MASK)
+    {
+      strcpy (accelerator + l, text_super);
+      l += sizeof (text_super) - 1;
     }
   strcpy (accelerator + l, keyval_name);
 
Index: gtk/gtkstock.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkstock.c,v
retrieving revision 1.26
diff -u -p -r1.26 gtkstock.c
--- gtk/gtkstock.c	29 Aug 2005 20:01:26 -0000	1.26
+++ gtk/gtkstock.c	5 Sep 2005 05:46:31 -0000
@@ -40,7 +40,7 @@ static void init_stock_hash (void);
 /* We use an unused modifier bit to mark stock items which
  * must be freed when they are removed from the hash table.
  */
-#define NON_STATIC_MASK (1 << 29)
+#define NON_STATIC_MASK (1 << 31)
 
 typedef struct _GtkStockTranslateFunc GtkStockTranslateFunc;
 struct _GtkStockTranslateFunc
@@ -70,7 +70,7 @@ real_add (const GtkStockItem *items,
 
       if (item->modifier & NON_STATIC_MASK)
 	{
-	  g_warning ("Bit 29 set in stock accelerator.\n");
+	  g_warning ("Bit 31 set in stock accelerator.\n");
 	  copy = TRUE;
 	}
 
Index: gdk/gdk.symbols
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/gdk.symbols,v
retrieving revision 1.28
diff -u -p -r1.28 gdk.symbols
--- gdk/gdk.symbols	26 Aug 2005 18:49:50 -0000	1.28
+++ gdk/gdk.symbols	5 Sep 2005 05:46:31 -0000
@@ -806,6 +806,8 @@ gdk_keymap_get_entries_for_keyval
 gdk_keymap_get_for_display
 gdk_keymap_lookup_key
 gdk_keymap_translate_keyboard_state
+gdk_keymap_resolve_virtual_modifiers
+gdk_keymap_virtualize_modifiers
 gdk_keyval_convert_case
 gdk_keyval_from_name
 gdk_keyval_name G_GNUC_CONST
Index: gdk/gdktypes.h
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/gdktypes.h,v
retrieving revision 1.65
diff -u -p -r1.65 gdktypes.h
--- gdk/gdktypes.h	12 Jun 2005 05:32:24 -0000	1.65
+++ gdk/gdktypes.h	5 Sep 2005 05:46:31 -0000
@@ -119,6 +119,7 @@ typedef enum
   GDK_LOCK_MASK	    = 1 << 1,
   GDK_CONTROL_MASK  = 1 << 2,
   GDK_MOD1_MASK	    = 1 << 3,
+  GDK_ALT_MASK      = GDK_MOD1_MASK,
   GDK_MOD2_MASK	    = 1 << 4,
   GDK_MOD3_MASK	    = 1 << 5,
   GDK_MOD4_MASK	    = 1 << 6,
@@ -128,12 +129,20 @@ typedef enum
   GDK_BUTTON3_MASK  = 1 << 10,
   GDK_BUTTON4_MASK  = 1 << 11,
   GDK_BUTTON5_MASK  = 1 << 12,
+
   /* The next few modifiers are used by XKB, so we skip to the end.
-   * Bits 16 - 28 are currently unused, but will eventually
-   * be used for "virtual modifiers". Bit 29 is used internally.
+   * Bits 16 - 23 are currently unused. Bit 31 is used internally.
    */
+  
+  GDK_META_MASK        = 1 << 24,
+  GDK_SUPER_MASK       = 1 << 25,
+  GDK_HYPER_MASK       = 1 << 26,
+  GDK_MODE_SWITCH_MASK = 1 << 27, 
+  GDK_NUM_LOCK_MASK    = 1 << 28,
+  GDK_SCROLL_LOCK_MASK = 1 << 29,
+  
   GDK_RELEASE_MASK  = 1 << 30,
-  GDK_MODIFIER_MASK = GDK_RELEASE_MASK | 0x1fff
+  GDK_MODIFIER_MASK = 0x7f001fff
 } GdkModifierType;
 
 typedef enum
Index: gdk/gdkkeys.h
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/gdkkeys.h,v
retrieving revision 1.7
diff -u -p -r1.7 gdkkeys.h
--- gdk/gdkkeys.h	12 Jun 2005 05:32:24 -0000	1.7
+++ gdk/gdkkeys.h	5 Sep 2005 05:46:31 -0000
@@ -59,6 +59,7 @@ typedef struct _GdkKeymapClass GdkKeymap
 #define GDK_IS_KEYMAP_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_KEYMAP))
 #define GDK_KEYMAP_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_KEYMAP, GdkKeymapClass))
 
+
 struct _GdkKeymap
 {
   GObject     parent_instance;
@@ -101,6 +102,11 @@ gboolean       gdk_keymap_get_entries_fo
 						    guint              **keyvals,
 						    gint                *n_entries);
 PangoDirection gdk_keymap_get_direction            (GdkKeymap           *keymap);
+
+GdkModifierType gdk_keymap_resolve_virtual_modifiers (GdkKeymap          *keymap,
+						      GdkModifierType     modifiers);
+GdkModifierType gdk_keymap_virtualize_modifiers      (GdkKeymap          *keymap,
+						      GdkModifierType     modifiers);
 
 /* Key values
  */
Index: gdk/x11/gdkkeys-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkkeys-x11.c,v
retrieving revision 1.47
diff -u -p -r1.47 gdkkeys-x11.c
--- gdk/x11/gdkkeys-x11.c	31 Aug 2005 15:14:26 -0000	1.47
+++ gdk/x11/gdkkeys-x11.c	5 Sep 2005 05:46:31 -0000
@@ -80,6 +80,7 @@ struct _GdkKeymapX11
   guint lock_keysym;
   GdkModifierType group_switch_mask;
   GdkModifierType num_lock_mask;
+  GdkModifierType modmap[8];
   gboolean sun_keypad;
   PangoDirection current_direction;
   gboolean have_direction;
@@ -324,6 +325,16 @@ update_keymaps (GdkKeymapX11 *keymap_x11
       keymap_x11->lock_keysym = GDK_VoidSymbol;
       keymap_x11->group_switch_mask = 0;
       keymap_x11->num_lock_mask = 0;
+      
+      /* Add in the not-really-virtual fixed entries */
+      keymap_x11->modmap[0] |= GDK_SHIFT_MASK;
+      keymap_x11->modmap[1] |= GDK_CONTROL_MASK;
+      keymap_x11->modmap[2] |= GDK_LOCK_MASK;
+      keymap_x11->modmap[3] |= GDK_ALT_MASK;
+      keymap_x11->modmap[4] |= GDK_MOD2_MASK;
+      keymap_x11->modmap[5] |= GDK_MOD3_MASK;
+      keymap_x11->modmap[6] |= GDK_MOD4_MASK;
+      keymap_x11->modmap[7] |= GDK_MOD5_MASK;
 
       /* There are 8 sets of modifiers, with each set containing
        * max_keypermod keycodes.
@@ -344,6 +355,28 @@ update_keymaps (GdkKeymapX11 *keymap_x11
 
           syms = keymap_x11->keymap + (keycode - keymap_x11->min_keycode) * keymap_x11->keysyms_per_keycode;
 
+	  mask = 0;
+	  for (j = 0; j < keymap_x11->keysyms_per_keycode; j++)
+	    {
+	      if (syms[j] == GDK_Num_Lock)
+		mask |= GDK_NUM_LOCK_MASK;
+	      else if (syms[j] == GDK_Scroll_Lock)
+		mask |= GDK_SCROLL_LOCK_MASK;
+	      else if (syms[j] == GDK_Meta_L ||
+		       syms[j] == GDK_Meta_R)
+		mask |= GDK_META_MASK;
+	      else if (syms[j] == GDK_Hyper_L ||
+		       syms[j] == GDK_Hyper_R)
+		mask |= GDK_HYPER_MASK;
+	      else if (syms[j] == GDK_Super_L ||
+		       syms[j] == GDK_Super_R)
+		mask |= GDK_SUPER_MASK;
+	      else if (syms[j] == GDK_Mode_switch)
+		mask |= GDK_MODE_SWITCH_MASK;
+	    }
+
+	  keymap_x11->modmap[i/keymap_x11->mod_keymap->max_keypermod] |= mask;
+
           /* The fourth modifier, GDK_MOD1_MASK is 1 << 3.
 	   * Each group of max_keypermod entries refers to the same modifier.
            */
@@ -1446,6 +1479,72 @@ _gdk_x11_get_group_for_state (GdkDisplay
       return (state & keymap_impl->group_switch_mask) ? 1 : 0;
     }
 }
+
+GdkModifierType 
+gdk_keymap_resolve_virtual_modifiers (GdkKeymap       *keymap,
+				      GdkModifierType  modifiers)
+{
+  GdkKeymapX11 *keymap_x11;
+  GdkModifierType concrete;
+  int i;
+  
+  keymap = GET_EFFECTIVE_KEYMAP (keymap);
+  keymap_x11 = GDK_KEYMAP_X11 (keymap);
+
+  /* Not so sure about this algorithm. */
+  
+  concrete = 0;
+  for (i = 0; i < 8; i++)
+    {
+      if (keymap_x11->modmap[i] & modifiers)
+        concrete |= (1 << i);
+    }
+
+  return concrete;
+}
+
+GdkModifierType 
+gdk_keymap_virtualize_modifiers (GdkKeymap       *keymap,
+				 GdkModifierType  modifiers)
+{
+  GdkKeymapX11 *keymap_x11;
+  GdkModifierType virtual;
+  int i;
+  
+  keymap = GET_EFFECTIVE_KEYMAP (keymap);
+  keymap_x11 = GDK_KEYMAP_X11 (keymap);
+
+  /* Not so sure about this algorithm. */
+  
+  virtual = 0;
+  for (i = 0; i < 8; i++)
+    {
+      if ((1 << i) & modifiers)
+        {
+          GdkModifierType cleaned;
+          
+          cleaned = keymap_x11->modmap[i] & ~(GDK_MOD2_MASK |
+					      GDK_MOD3_MASK |
+					      GDK_MOD4_MASK |
+					      GDK_MOD5_MASK);
+          
+          if (cleaned != 0)
+            {
+              virtual |= cleaned;
+            }
+          else
+            {
+              /* Rather than dropping mod2->mod5 if not bound,
+               * go ahead and use the concrete names
+               */
+              virtual |= keymap_x11->modmap[i];
+            }
+        }
+    }
+  
+  return virtual;
+}
+
 
 #define __GDK_KEYS_X11_C__
 #include "gdkaliasdef.c"
