Index: src/eggaccelerators.c
===================================================================
RCS file: /cvs/gnome/metacity/src/eggaccelerators.c,v
retrieving revision 1.3
diff -u -p -r1.3 eggaccelerators.c
--- src/eggaccelerators.c	30 Sep 2002 03:58:41 -0000	1.3
+++ src/eggaccelerators.c	8 Nov 2004 20:26:36 -0000
@@ -20,6 +20,7 @@
 
 #include "eggaccelerators.h"
 
+#include <stdlib.h>
 #include <string.h>
 #include <gdk/gdkx.h>
 #include <gdk/gdkkeysyms.h>
@@ -175,22 +176,36 @@ is_hyper (const gchar *string)
 	  (string[6] == '>'));
 }
 
+static inline gboolean
+is_keycode (const gchar *string)
+{
+  return ((string[0] == '0') &&
+	  (string[1] == 'x'));
+}
+
 /**
  * egg_accelerator_parse_virtual:
- * @accelerator:      string representing an accelerator
- * @accelerator_key:  return location for accelerator keyval
- * @accelerator_mods: return location for accelerator modifier mask
+ * @accelerator:         string representing an accelerator
+ * @accelerator_keyval:  return location for accelerator key value
+ * @accelerator_keycode: return location for accelerator hardware keycode
+ * @accelerator_mods:    return location for accelerator modifier mask
  *
- * Parses a string representing a virtual accelerator. The format
- * looks like "&lt;Control&gt;a" or "&lt;Shift&gt;&lt;Alt&gt;F1" or
- * "&lt;Release&gt;z" (the last one is for key release).  The parser
- * is fairly liberal and allows lower or upper case, and also
- * abbreviations such as "&lt;Ctl&gt;" and "&lt;Ctrl&gt;".
+ * Parses a string representing a virtual accelerator. The format looks like 
+ * "&lt;Control&gt;a" or "&lt;Shift&gt;&lt;Alt&gt;F1" or "&lt;Alt&gt;0xeb" or
+ * "&lt;Release&gt;z" (the last one is for key release). The parser is fairly 
+ * liberal and allows lower or upper case, and also abbreviations such as 
+ * "&lt;Ctl&gt;" and "&lt;Ctrl&gt;". If the key is expressed in the form "0x##"
+ * @accelerator_keycode will be set to the hardware keycode, otherwise 
+ * @accelerator_keyval will be set to the key value of the key. In both cases 
+ * the other argument will be set to 0. Note that the mapping between key 
+ * values and hardware keycodes is display-dependent and not 1-1: the key 
+ * values "4" and "$" often have the same hardware keycode, and "multimedia 
+ * keys" often have a hardware keycode e.g. 0xeb but no key value.
  *
- * If the parse fails, @accelerator_key and @accelerator_mods will
- * be set to 0 (zero) and %FALSE will be returned. If the string contains
- * only modifiers, @accelerator_key will be set to 0 but %TRUE will be
- * returned.
+ * If the parse fails, @accelerator_keyval, @accelerator_keycode and 
+ * @accelerator_mods will be set to 0 (zero) and %FALSE will be returned. If 
+ * the string contains only modifiers, @accelerator_keyval and 
+ * @accelerator_keycode will be set to 0 but %TRUE will be returned.
  *
  * The virtual vs. concrete accelerator distinction is a relic of
  * how the X Window System works; there are modifiers Mod2-Mod5 that
@@ -202,24 +217,29 @@ is_hyper (const gchar *string)
  */
 gboolean
 egg_accelerator_parse_virtual (const gchar            *accelerator,
-                               guint                  *accelerator_key,
+                               guint                  *accelerator_keyval,
+                               guint                  *accelerator_keycode,
                                EggVirtualModifierType *accelerator_mods)
 {
   guint keyval;
+  guint keycode;
   GdkModifierType mods;
   gint len;
-  gboolean bad_keyval;
+  gboolean bad_keyname;
   
-  if (accelerator_key)
-    *accelerator_key = 0;
+  if (accelerator_keyval)
+    *accelerator_keyval = 0;
+  if (accelerator_keycode)
+    *accelerator_keycode = 0;
   if (accelerator_mods)
     *accelerator_mods = 0;
 
   g_return_val_if_fail (accelerator != NULL, FALSE);
 
-  bad_keyval = FALSE;
+  bad_keyname = FALSE;
   
   keyval = 0;
+  keycode = 0;
   mods = 0;
   len = strlen (accelerator);
   while (len)
@@ -316,37 +336,119 @@ egg_accelerator_parse_virtual (const gch
           keyval = gdk_keyval_from_name (accelerator);
           
           if (keyval == 0)
-            bad_keyval = TRUE;
+            {
+              /* If keyval is 0, than maybe it's a keycode.  Check for 0x## */
+              if (len >= 4 && is_keycode (accelerator))
+                {
+                  char keystring[5];
+                  gchar *endptr;
+
+                  memcpy (keystring, accelerator, 4);
+                  keystring [4] = '\000';
+
+                  keycode = strtoul (keystring, &endptr, 16);
+
+                  if (endptr == NULL || *endptr != '\000' || keycode == 0)
+                    {
+                      bad_keyname = TRUE;
+                    }
+                }
+              else
+                {
+                  bad_keyname = TRUE;
+                }
+            }
           
           accelerator += len;
           len -= len;              
 	}
     }
   
-  if (accelerator_key)
-    *accelerator_key = gdk_keyval_to_lower (keyval);
+  if (bad_keyname)
+    return FALSE;
+  
+  if (keyval != 0)
+    {
+      if (accelerator_keyval)
+        *accelerator_keyval = gdk_keyval_to_lower (keyval);
+    }
+  else if (keycode != 0)
+    {
+      if (accelerator_keycode)
+        *accelerator_keycode = keycode;
+    }
   if (accelerator_mods)
     *accelerator_mods = mods;
 
-  return !bad_keyval;
+  return TRUE;
 }
 
+/**
+ * egg_accelerator_parse_virtual_to_keycode:
+ * @accelerator:         string representing an accelerator
+ * @accelerator_keycode: return location for accelerator hardware keycode
+ * @accelerator_mods:    return location for accelerator modifier mask
+ * @keymap               the GdkKeymap to convert key values to keycodes
+ *
+ * Parses a string representing a virtual accelerator. Similar to 
+ * egg_accelerator_parse_virtual(), but converting key values to the 
+ * associated hardware keycode.
+ * 
+ * Returns: %TRUE on success.
+ */
+gboolean
+egg_accelerator_parse_virtual_to_keycode (const gchar            *accelerator,
+                                          guint                  *accelerator_keycode,
+                                          EggVirtualModifierType *accelerator_mods,
+                                          GdkKeymap              *keymap)
+{
+  guint keyval;
+  guint keycode;
+
+  if (accelerator_keycode)
+    *accelerator_keycode = 0;
+  
+  if (!egg_accelerator_parse_virtual (accelerator, &keyval, &keycode,
+                                      accelerator_mods))
+    return FALSE;
+
+  if (keycode == 0 && keyval != 0)
+    {
+      GdkKeymapKey *keys;
+      gint n_keys;
+      
+      if (!gdk_keymap_get_entries_for_keyval (keymap, keyval, &keys, &n_keys))
+        return FALSE;
+
+      keycode = keys[0].keycode;
+
+      g_free (keys);
+    }
+
+  if (keycode != 0 && accelerator_keycode)
+    *accelerator_keycode = keycode;
+  
+  return TRUE;
+}
 
 /**
  * egg_virtual_accelerator_name:
- * @accelerator_key:  accelerator keyval
- * @accelerator_mods: accelerator modifier mask
- * @returns:          a newly-allocated accelerator name
+ * @accelerator_keyval:  accelerator keyval
+ * @accelerator_keycode: accelerator hardware keycode
+ * @accelerator_mods:    accelerator modifier mask
+ * @returns:             a newly-allocated accelerator name
  * 
- * Converts an accelerator keyval and modifier mask
+ * Converts an accelerator keyval (or hardware keycode) and modifier mask
  * into a string parseable by egg_accelerator_parse_virtual().
- * For example, if you pass in #GDK_q and #EGG_VIRTUAL_CONTROL_MASK,
- * this function returns "&lt;Control&gt;q".
+ * For example, if you pass in (#GDK_q, 0, #EGG_VIRTUAL_CONTROL_MASK)
+ * this function returns "&lt;Control&gt;q"; if you pass in (0, 0xeb,
+ * #EGG_VIRTUAL_META_MASK) this function returns "&lt;Meta&gt;0xeb".
  *
  * The caller of this function must free the returned string.
  */
 gchar*
-egg_virtual_accelerator_name (guint                  accelerator_key,
+egg_virtual_accelerator_name (guint                  accelerator_keyval,
+                              guint                  accelerator_keycode,
                               EggVirtualModifierType accelerator_mods)
 {
   static const gchar text_release[] = "<Release>";
@@ -362,11 +464,22 @@ egg_virtual_accelerator_name (guint     
   static const gchar text_hyper[] = "<Hyper>";
   guint l;
   gchar *keyval_name;
+  gchar keycode_buf[5]; /* "0x##" - keycodes are in range [8,255] */
   gchar *accelerator;
 
   accelerator_mods &= EGG_VIRTUAL_MODIFIER_MASK;
 
-  keyval_name = gdk_keyval_name (gdk_keyval_to_lower (accelerator_key));
+  keyval_name = NULL;
+  if (accelerator_keyval != 0)
+    {
+      keyval_name = gdk_keyval_name (gdk_keyval_to_lower (accelerator_keyval));
+    }
+  else if (accelerator_keycode != 0)
+    {
+      g_snprintf (keycode_buf, sizeof(keycode_buf), 
+                  "0x%02x", accelerator_keycode);
+      keyval_name = keycode_buf;
+    }
   if (!keyval_name)
     keyval_name = "";
 
Index: src/eggaccelerators.h
===================================================================
RCS file: /cvs/gnome/metacity/src/eggaccelerators.h,v
retrieving revision 1.1
diff -u -p -r1.1 eggaccelerators.h
--- src/eggaccelerators.h	14 Jul 2002 03:16:40 -0000	1.1
+++ src/eggaccelerators.h	8 Nov 2004 20:26:36 -0000
@@ -68,9 +68,14 @@ typedef enum
 
 } EggVirtualModifierType;
 
-gboolean egg_accelerator_parse_virtual        (const gchar            *accelerator,
-                                               guint                  *accelerator_key,
-                                               EggVirtualModifierType *accelerator_mods);
+gboolean egg_accelerator_parse_virtual            (const gchar            *accelerator,
+                                                   guint                  *accelerator_keyval,
+                                                   guint                  *accelerator_keycode,
+                                                   EggVirtualModifierType *accelerator_mods);
+gboolean egg_accelerator_parse_virtual_to_keycode (const gchar            *accelerator,
+                                                   guint                  *accelerator_keycode,
+                                                   EggVirtualModifierType *accelerator_mods,
+                                                   GdkKeymap              *keymap);
 void     egg_keymap_resolve_virtual_modifiers (GdkKeymap              *keymap,
                                                EggVirtualModifierType  virtual_mods,
                                                GdkModifierType        *concrete_mods);
@@ -79,6 +84,7 @@ void     egg_keymap_virtualize_modifiers
                                                EggVirtualModifierType *virtual_mods);
 
 gchar* egg_virtual_accelerator_name (guint                  accelerator_key,
+                                     guint                  accelerator_keycode,
                                      EggVirtualModifierType accelerator_mods);
 
 G_END_DECLS
Index: src/keybindings.c
===================================================================
RCS file: /cvs/gnome/metacity/src/keybindings.c,v
retrieving revision 1.107
diff -u -p -r1.107 keybindings.c
--- src/keybindings.c	20 Oct 2004 23:16:08 -0000	1.107
+++ src/keybindings.c	8 Nov 2004 20:26:37 -0000
@@ -231,8 +231,8 @@ struct _MetaKeyBinding
 {
   const char *name;
   KeySym keysym;
+  KeyCode keycode;
   unsigned int mask;
-  unsigned int keycode;
   MetaVirtualModifier modifiers;
   const MetaKeyHandler *handler;
 };
@@ -548,8 +548,9 @@ reload_keycodes (MetaDisplay *display)
       i = 0;
       while (i < display->n_screen_bindings)
         {
-          display->screen_bindings[i].keycode = XKeysymToKeycode (display->xdisplay,
-                                                                  display->screen_bindings[i].keysym);
+          if (display->screen_bindings[i].keycode == 0)
+              display->screen_bindings[i].keycode = XKeysymToKeycode (
+                      display->xdisplay, display->screen_bindings[i].keysym);
           
           ++i;
         }
@@ -562,8 +563,9 @@ reload_keycodes (MetaDisplay *display)
       i = 0;
       while (i < display->n_window_bindings)
         {
-          display->window_bindings[i].keycode = XKeysymToKeycode (display->xdisplay,
-                                                                  display->window_bindings[i].keysym);
+          if (display->window_bindings[i].keycode == 0)
+              display->window_bindings[i].keycode = XKeysymToKeycode (
+                      display->xdisplay, display->window_bindings[i].keysym);
           
           ++i;
         }
@@ -630,7 +632,7 @@ count_bindings (const MetaKeyPref *prefs
   i = 0;
   while (i < n_prefs)
     {
-      if (prefs[i].keysym != None)
+      if (prefs[i].keysym != None || prefs[i].keycode != 0)
         {
           count += 1;
 
@@ -663,13 +665,13 @@ rebuild_binding_table (MetaDisplay      
   dest = 0;
   while (src < n_prefs)
     {
-      if (prefs[src].keysym != None)
+      if (prefs[src].keysym != None || prefs[src].keycode != 0)
         {
           (*bindings_p)[dest].name = prefs[src].name;
           (*bindings_p)[dest].keysym = prefs[src].keysym;
+          (*bindings_p)[dest].keycode = prefs[src].keycode;
           (*bindings_p)[dest].modifiers = prefs[src].modifiers;
           (*bindings_p)[dest].mask = 0;
-          (*bindings_p)[dest].keycode = 0;          
           
           ++dest;
 
@@ -682,10 +684,10 @@ rebuild_binding_table (MetaDisplay      
               
               (*bindings_p)[dest].name = prefs[src].name;
               (*bindings_p)[dest].keysym = prefs[src].keysym;
+              (*bindings_p)[dest].keycode = prefs[src].keycode;
               (*bindings_p)[dest].modifiers = prefs[src].modifiers |
                 META_VIRTUAL_SHIFT_MASK;
               (*bindings_p)[dest].mask = 0;
-              (*bindings_p)[dest].keycode = 0;          
               
               ++dest;
             }
@@ -783,6 +785,7 @@ regrab_window_bindings (MetaDisplay *dis
 static MetaKeyBindingAction
 display_get_keybinding_action (MetaDisplay  *display,
                                unsigned int  keysym,
+                               unsigned int  keycode,
                                unsigned long mask)
 {
   int i;
@@ -791,6 +794,7 @@ display_get_keybinding_action (MetaDispl
   while (i >= 0)
     {
       if (display->screen_bindings[i].keysym == keysym &&
+          display->screen_bindings[i].keycode == keycode &&
           display->screen_bindings[i].mask == mask)
         {
           return meta_prefs_get_keybinding_action (display->screen_bindings[i].name);
@@ -949,9 +953,9 @@ meta_change_keygrab (MetaDisplay *displa
    */
 
   meta_topic (META_DEBUG_KEYBINDINGS,
-              "%s keybinding %s mask 0x%x on 0x%lx\n",
+              "%s keybinding %s keycode %d mask 0x%x on 0x%lx\n",
               grab ? "Grabbing" : "Ungrabbing",
-              keysym_name (keysym),
+              keysym_name (keysym), keycode,
               modmask, xwindow);
 
   /* efficiency, avoid so many XSync() */
@@ -2402,6 +2406,7 @@ process_tab_grab (MetaDisplay *display,
 
   action = display_get_keybinding_action (display,
                                           keysym,
+                                          event->xkey.keycode,
                                           display->grab_mask);
 
   /* FIXME weird side effect here is that you can use the Escape
@@ -2768,6 +2773,7 @@ process_workspace_switch_grab (MetaDispl
 
       action = display_get_keybinding_action (display,
                                               keysym,
+                                              event->xkey.keycode,
                                               display->grab_mask);
 
       switch (action)
Index: src/prefs.c
===================================================================
RCS file: /cvs/gnome/metacity/src/prefs.c,v
retrieving revision 1.48
diff -u -p -r1.48 prefs.c
--- src/prefs.c	13 Oct 2004 08:32:10 -0000	1.48
+++ src/prefs.c	8 Nov 2004 20:26:37 -0000
@@ -1432,106 +1432,106 @@ meta_prefs_set_num_workspaces (int n_wor
 
 /* Indexes must correspond to MetaKeybindingAction */
 static MetaKeyPref screen_bindings[] = {
-  { META_KEYBINDING_WORKSPACE_1, 0, 0, FALSE },
-  { META_KEYBINDING_WORKSPACE_2, 0, 0, FALSE },
-  { META_KEYBINDING_WORKSPACE_3, 0, 0, FALSE },
-  { META_KEYBINDING_WORKSPACE_4, 0, 0, FALSE },
-  { META_KEYBINDING_WORKSPACE_5, 0, 0, FALSE },
-  { META_KEYBINDING_WORKSPACE_6, 0, 0, FALSE },
-  { META_KEYBINDING_WORKSPACE_7, 0, 0, FALSE },
-  { META_KEYBINDING_WORKSPACE_8, 0, 0, FALSE }, 
-  { META_KEYBINDING_WORKSPACE_9, 0, 0, FALSE },
-  { META_KEYBINDING_WORKSPACE_10, 0, 0, FALSE },
-  { META_KEYBINDING_WORKSPACE_11, 0, 0, FALSE },
-  { META_KEYBINDING_WORKSPACE_12, 0, 0, FALSE },
-  { META_KEYBINDING_WORKSPACE_LEFT, 0, 0, FALSE },
-  { META_KEYBINDING_WORKSPACE_RIGHT, 0, 0, FALSE },
-  { META_KEYBINDING_WORKSPACE_UP, 0, 0, FALSE },
-  { META_KEYBINDING_WORKSPACE_DOWN, 0, 0, FALSE },
-  { META_KEYBINDING_SWITCH_WINDOWS, 0, 0, TRUE },
-  { META_KEYBINDING_SWITCH_WINDOWS_BACKWARD, 0, 0, TRUE },
-  { META_KEYBINDING_SWITCH_PANELS, 0, 0, TRUE },
-  { META_KEYBINDING_SWITCH_PANELS_BACKWARD, 0, 0, TRUE },
-  { META_KEYBINDING_CYCLE_WINDOWS, 0, 0, TRUE },
-  { META_KEYBINDING_CYCLE_WINDOWS_BACKWARD, 0, 0, TRUE },
-  { META_KEYBINDING_CYCLE_PANELS, 0, 0, TRUE },
-  { META_KEYBINDING_CYCLE_PANELS_BACKWARD, 0, 0, TRUE },
-  { META_KEYBINDING_SHOW_DESKTOP, 0, 0, FALSE },
-  { META_KEYBINDING_PANEL_MAIN_MENU, 0, 0, FALSE },
-  { META_KEYBINDING_PANEL_RUN_DIALOG, 0, 0, FALSE },
-  { META_KEYBINDING_COMMAND_1, 0, 0, FALSE },
-  { META_KEYBINDING_COMMAND_2, 0, 0, FALSE },
-  { META_KEYBINDING_COMMAND_3, 0, 0, FALSE },
-  { META_KEYBINDING_COMMAND_4, 0, 0, FALSE },
-  { META_KEYBINDING_COMMAND_5, 0, 0, FALSE },
-  { META_KEYBINDING_COMMAND_6, 0, 0, FALSE },
-  { META_KEYBINDING_COMMAND_7, 0, 0, FALSE },
-  { META_KEYBINDING_COMMAND_8, 0, 0, FALSE }, 
-  { META_KEYBINDING_COMMAND_9, 0, 0, FALSE },
-  { META_KEYBINDING_COMMAND_10, 0, 0, FALSE },
-  { META_KEYBINDING_COMMAND_11, 0, 0, FALSE },
-  { META_KEYBINDING_COMMAND_12, 0, 0, FALSE },
-  { META_KEYBINDING_COMMAND_13, 0, 0, FALSE },
-  { META_KEYBINDING_COMMAND_14, 0, 0, FALSE },
-  { META_KEYBINDING_COMMAND_15, 0, 0, FALSE },
-  { META_KEYBINDING_COMMAND_16, 0, 0, FALSE },
-  { META_KEYBINDING_COMMAND_17, 0, 0, FALSE },
-  { META_KEYBINDING_COMMAND_18, 0, 0, FALSE },
-  { META_KEYBINDING_COMMAND_19, 0, 0, FALSE },
-  { META_KEYBINDING_COMMAND_20, 0, 0, FALSE },
-  { META_KEYBINDING_COMMAND_21, 0, 0, FALSE },
-  { META_KEYBINDING_COMMAND_22, 0, 0, FALSE },
-  { META_KEYBINDING_COMMAND_23, 0, 0, FALSE },
-  { META_KEYBINDING_COMMAND_24, 0, 0, FALSE },
-  { META_KEYBINDING_COMMAND_25, 0, 0, FALSE },
-  { META_KEYBINDING_COMMAND_26, 0, 0, FALSE },
-  { META_KEYBINDING_COMMAND_27, 0, 0, FALSE },
-  { META_KEYBINDING_COMMAND_28, 0, 0, FALSE },
-  { META_KEYBINDING_COMMAND_29, 0, 0, FALSE },
-  { META_KEYBINDING_COMMAND_30, 0, 0, FALSE },
-  { META_KEYBINDING_COMMAND_31, 0, 0, FALSE },
-  { META_KEYBINDING_COMMAND_32, 0, 0, FALSE },
-  { META_KEYBINDING_COMMAND_SCREENSHOT, 0, 0, FALSE },
-  { META_KEYBINDING_COMMAND_WIN_SCREENSHOT, 0, 0, FALSE },
-  { META_KEYBINDING_RUN_COMMAND_TERMINAL, 0, 0, FALSE },
-  { NULL, 0, 0, FALSE}
+  { META_KEYBINDING_WORKSPACE_1, 0, 0, 0, FALSE },
+  { META_KEYBINDING_WORKSPACE_2, 0, 0, 0, FALSE },
+  { META_KEYBINDING_WORKSPACE_3, 0, 0, 0, FALSE },
+  { META_KEYBINDING_WORKSPACE_4, 0, 0, 0, FALSE },
+  { META_KEYBINDING_WORKSPACE_5, 0, 0, 0, FALSE },
+  { META_KEYBINDING_WORKSPACE_6, 0, 0, 0, FALSE },
+  { META_KEYBINDING_WORKSPACE_7, 0, 0, 0, FALSE },
+  { META_KEYBINDING_WORKSPACE_8, 0, 0, 0, FALSE }, 
+  { META_KEYBINDING_WORKSPACE_9, 0, 0, 0, FALSE },
+  { META_KEYBINDING_WORKSPACE_10, 0, 0, 0, FALSE },
+  { META_KEYBINDING_WORKSPACE_11, 0, 0, 0, FALSE },
+  { META_KEYBINDING_WORKSPACE_12, 0, 0, 0, FALSE },
+  { META_KEYBINDING_WORKSPACE_LEFT, 0, 0, 0, FALSE },
+  { META_KEYBINDING_WORKSPACE_RIGHT, 0, 0, 0, FALSE },
+  { META_KEYBINDING_WORKSPACE_UP, 0, 0, 0, FALSE },
+  { META_KEYBINDING_WORKSPACE_DOWN, 0, 0, 0, FALSE },
+  { META_KEYBINDING_SWITCH_WINDOWS, 0, 0, 0, TRUE },
+  { META_KEYBINDING_SWITCH_WINDOWS_BACKWARD, 0, 0, 0, TRUE },
+  { META_KEYBINDING_SWITCH_PANELS, 0, 0, 0, TRUE },
+  { META_KEYBINDING_SWITCH_PANELS_BACKWARD, 0, 0, 0, TRUE },
+  { META_KEYBINDING_CYCLE_WINDOWS, 0, 0, 0, TRUE },
+  { META_KEYBINDING_CYCLE_WINDOWS_BACKWARD, 0, 0, 0, TRUE },
+  { META_KEYBINDING_CYCLE_PANELS, 0, 0, 0, TRUE },
+  { META_KEYBINDING_CYCLE_PANELS_BACKWARD, 0, 0, 0, TRUE },
+  { META_KEYBINDING_SHOW_DESKTOP, 0, 0, 0, FALSE },
+  { META_KEYBINDING_PANEL_MAIN_MENU, 0, 0, 0, FALSE },
+  { META_KEYBINDING_PANEL_RUN_DIALOG, 0, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_1, 0, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_2, 0, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_3, 0, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_4, 0, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_5, 0, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_6, 0, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_7, 0, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_8, 0, 0, 0, FALSE }, 
+  { META_KEYBINDING_COMMAND_9, 0, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_10, 0, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_11, 0, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_12, 0, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_13, 0, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_14, 0, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_15, 0, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_16, 0, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_17, 0, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_18, 0, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_19, 0, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_20, 0, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_21, 0, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_22, 0, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_23, 0, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_24, 0, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_25, 0, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_26, 0, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_27, 0, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_28, 0, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_29, 0, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_30, 0, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_31, 0, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_32, 0, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_SCREENSHOT, 0, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_WIN_SCREENSHOT, 0, 0, 0, FALSE },
+  { META_KEYBINDING_RUN_COMMAND_TERMINAL, 0, 0, 0, FALSE },
+  { NULL, 0, 0, 0, FALSE}
 };
 
 static MetaKeyPref window_bindings[] = {
-  { META_KEYBINDING_WINDOW_MENU, 0, 0, FALSE },
-  { META_KEYBINDING_TOGGLE_FULLSCREEN, 0, 0, FALSE },
-  { META_KEYBINDING_TOGGLE_MAXIMIZE, 0, 0, FALSE },
-  { META_KEYBINDING_TOGGLE_ABOVE, 0, 0, FALSE },
-  { META_KEYBINDING_MAXIMIZE, 0, 0, FALSE },
-  { META_KEYBINDING_UNMAXIMIZE, 0, 0, FALSE },
-  { META_KEYBINDING_TOGGLE_SHADE, 0, 0, FALSE },
-  { META_KEYBINDING_MINIMIZE, 0, 0, FALSE },
-  { META_KEYBINDING_CLOSE, 0, 0, FALSE },
-  { META_KEYBINDING_BEGIN_MOVE, 0, 0, FALSE },
-  { META_KEYBINDING_BEGIN_RESIZE, 0, 0, FALSE },
-  { META_KEYBINDING_TOGGLE_STICKY, 0, 0, FALSE },
-  { META_KEYBINDING_MOVE_WORKSPACE_1, 0, 0, FALSE },
-  { META_KEYBINDING_MOVE_WORKSPACE_2, 0, 0, FALSE },
-  { META_KEYBINDING_MOVE_WORKSPACE_3, 0, 0, FALSE },
-  { META_KEYBINDING_MOVE_WORKSPACE_4, 0, 0, FALSE },
-  { META_KEYBINDING_MOVE_WORKSPACE_5, 0, 0, FALSE },
-  { META_KEYBINDING_MOVE_WORKSPACE_6, 0, 0, FALSE },
-  { META_KEYBINDING_MOVE_WORKSPACE_7, 0, 0, FALSE },
-  { META_KEYBINDING_MOVE_WORKSPACE_8, 0, 0, FALSE },
-  { META_KEYBINDING_MOVE_WORKSPACE_9, 0, 0, FALSE },
-  { META_KEYBINDING_MOVE_WORKSPACE_10, 0, 0, FALSE },
-  { META_KEYBINDING_MOVE_WORKSPACE_11, 0, 0, FALSE },
-  { META_KEYBINDING_MOVE_WORKSPACE_12, 0, 0, FALSE },
-  { META_KEYBINDING_MOVE_WORKSPACE_LEFT, 0, 0, FALSE },
-  { META_KEYBINDING_MOVE_WORKSPACE_RIGHT, 0, 0, FALSE },
-  { META_KEYBINDING_MOVE_WORKSPACE_UP, 0, 0, FALSE },
-  { META_KEYBINDING_MOVE_WORKSPACE_DOWN, 0, 0, FALSE },
-  { META_KEYBINDING_RAISE_OR_LOWER, 0, 0, FALSE },
-  { META_KEYBINDING_RAISE, 0, 0, FALSE },
-  { META_KEYBINDING_LOWER, 0, 0, FALSE },
-  { META_KEYBINDING_MAXIMIZE_VERTICALLY, 0, 0, FALSE },
-  { META_KEYBINDING_MAXIMIZE_HORIZONTALLY, 0, 0, FALSE },
-  { NULL, 0, 0, FALSE }
+  { META_KEYBINDING_WINDOW_MENU, 0, 0, 0, FALSE },
+  { META_KEYBINDING_TOGGLE_FULLSCREEN, 0, 0, 0, FALSE },
+  { META_KEYBINDING_TOGGLE_MAXIMIZE, 0, 0, 0, FALSE },
+  { META_KEYBINDING_TOGGLE_ABOVE, 0, 0, 0, FALSE },
+  { META_KEYBINDING_MAXIMIZE, 0, 0, 0, FALSE },
+  { META_KEYBINDING_UNMAXIMIZE, 0, 0, 0, FALSE },
+  { META_KEYBINDING_TOGGLE_SHADE, 0, 0, 0, FALSE },
+  { META_KEYBINDING_MINIMIZE, 0, 0, 0, FALSE },
+  { META_KEYBINDING_CLOSE, 0, 0, 0, FALSE },
+  { META_KEYBINDING_BEGIN_MOVE, 0, 0, 0, FALSE },
+  { META_KEYBINDING_BEGIN_RESIZE, 0, 0, 0, FALSE },
+  { META_KEYBINDING_TOGGLE_STICKY, 0, 0, 0, FALSE },
+  { META_KEYBINDING_MOVE_WORKSPACE_1, 0, 0, 0, FALSE },
+  { META_KEYBINDING_MOVE_WORKSPACE_2, 0, 0, 0, FALSE },
+  { META_KEYBINDING_MOVE_WORKSPACE_3, 0, 0, 0, FALSE },
+  { META_KEYBINDING_MOVE_WORKSPACE_4, 0, 0, 0, FALSE },
+  { META_KEYBINDING_MOVE_WORKSPACE_5, 0, 0, 0, FALSE },
+  { META_KEYBINDING_MOVE_WORKSPACE_6, 0, 0, 0, FALSE },
+  { META_KEYBINDING_MOVE_WORKSPACE_7, 0, 0, 0, FALSE },
+  { META_KEYBINDING_MOVE_WORKSPACE_8, 0, 0, 0, FALSE },
+  { META_KEYBINDING_MOVE_WORKSPACE_9, 0, 0, 0, FALSE },
+  { META_KEYBINDING_MOVE_WORKSPACE_10, 0, 0, 0, FALSE },
+  { META_KEYBINDING_MOVE_WORKSPACE_11, 0, 0, 0, FALSE },
+  { META_KEYBINDING_MOVE_WORKSPACE_12, 0, 0, 0, FALSE },
+  { META_KEYBINDING_MOVE_WORKSPACE_LEFT, 0, 0, 0, FALSE },
+  { META_KEYBINDING_MOVE_WORKSPACE_RIGHT, 0, 0, 0, FALSE },
+  { META_KEYBINDING_MOVE_WORKSPACE_UP, 0, 0, 0, FALSE },
+  { META_KEYBINDING_MOVE_WORKSPACE_DOWN, 0, 0, 0, FALSE },
+  { META_KEYBINDING_RAISE_OR_LOWER, 0, 0, 0, FALSE },
+  { META_KEYBINDING_RAISE, 0, 0, 0, FALSE },
+  { META_KEYBINDING_LOWER, 0, 0, 0, FALSE },
+  { META_KEYBINDING_MAXIMIZE_VERTICALLY, 0, 0, 0, FALSE },
+  { META_KEYBINDING_MAXIMIZE_HORIZONTALLY, 0, 0, 0, FALSE },
+  { NULL, 0, 0, 0, FALSE }
 };
 
 static void
@@ -1651,6 +1651,7 @@ update_binding (MetaKeyPref *binding,
                 const char  *value)
 {
   unsigned int keysym;
+  unsigned int keycode;
   MetaVirtualModifier mods;
   gboolean changed;
   
@@ -1659,10 +1660,11 @@ update_binding (MetaKeyPref *binding,
               binding->name, value ? value : "none");
   
   keysym = 0;
+  keycode = 0;
   mods = 0;
   if (value)
     {
-      if (!meta_ui_parse_accelerator (value, &keysym, &mods))
+      if (!meta_ui_parse_accelerator (value, &keysym, &keycode, &mods))
         {
           meta_topic (META_DEBUG_KEYBINDINGS,
                       "Failed to parse new gconf value\n");
@@ -1673,16 +1675,19 @@ update_binding (MetaKeyPref *binding,
   
   changed = FALSE;
   if (keysym != binding->keysym ||
+      keycode != binding->keycode ||
       mods != binding->modifiers)
     {
       changed = TRUE;
       
       binding->keysym = keysym;
+      binding->keycode = keycode;
       binding->modifiers = mods;
       
       meta_topic (META_DEBUG_KEYBINDINGS,
-                  "New keybinding for \"%s\" is keysym = 0x%x mods = 0x%x\n",
-                  binding->name, binding->keysym, binding->modifiers);
+                  "New keybinding for \"%s\" is keysym = 0x%x keycode = 0x%x mods = 0x%x\n",
+                  binding->name, binding->keysym, binding->keycode, 
+                  binding->modifiers);
     }
   else
     {
Index: src/prefs.h
===================================================================
RCS file: /cvs/gnome/metacity/src/prefs.h,v
retrieving revision 1.35
diff -u -p -r1.35 prefs.h
--- src/prefs.h	13 Oct 2004 08:32:10 -0000	1.35
+++ src/prefs.h	8 Nov 2004 20:26:37 -0000
@@ -236,6 +236,7 @@ typedef struct
 {
   const char   *name;
   unsigned int  keysym;
+  unsigned int  keycode;
   MetaVirtualModifier modifiers;
   /* for keybindings that can have shift or not like Alt+Tab */
   gboolean      add_shift;
Index: src/ui.c
===================================================================
RCS file: /cvs/gnome/metacity/src/ui.c,v
retrieving revision 1.57
diff -u -p -r1.57 ui.c
--- src/ui.c	22 Sep 2004 18:57:36 -0000	1.57
+++ src/ui.c	8 Nov 2004 20:26:37 -0000
@@ -742,27 +742,31 @@ meta_ui_have_a_theme (void)
 gboolean
 meta_ui_parse_accelerator (const char          *accel,
                            unsigned int        *keysym,
+                           unsigned int        *keycode,
                            MetaVirtualModifier *mask)
 {
   EggVirtualModifierType gdk_mask = 0;
   guint gdk_sym = 0;
+  guint gdk_code = 0;
   
   *keysym = 0;
+  *keycode = 0;
   *mask = 0;
 
   if (strcmp (accel, "disabled") == 0)
     return TRUE;
   
-  if (!egg_accelerator_parse_virtual (accel, &gdk_sym, &gdk_mask))
+  if (!egg_accelerator_parse_virtual (accel, &gdk_sym, &gdk_code, &gdk_mask))
     return FALSE;
 
-  if (gdk_sym == None)
+  if (gdk_sym == None && gdk_code == 0)
     return FALSE;
   
   if (gdk_mask & EGG_VIRTUAL_RELEASE_MASK) /* we don't allow this */
     return FALSE;
   
   *keysym = gdk_sym;
+  *keycode = gdk_code;
 
   if (gdk_mask & EGG_VIRTUAL_SHIFT_MASK)
     *mask |= META_VIRTUAL_SHIFT_MASK;
@@ -794,16 +798,17 @@ meta_ui_parse_modifier (const char      
 {
   EggVirtualModifierType gdk_mask = 0;
   guint gdk_sym = 0;
+  guint gdk_code = 0;
   
   *mask = 0;
 
   if (strcmp (accel, "disabled") == 0)
     return TRUE;
   
-  if (!egg_accelerator_parse_virtual (accel, &gdk_sym, &gdk_mask))
+  if (!egg_accelerator_parse_virtual (accel, &gdk_sym, &gdk_code, &gdk_mask))
     return FALSE;
 
-  if (gdk_sym != None)
+  if (gdk_sym != None || gdk_code != 0)
     return FALSE;
   
   if (gdk_mask & EGG_VIRTUAL_RELEASE_MASK) /* we don't allow this */
Index: src/ui.h
===================================================================
RCS file: /cvs/gnome/metacity/src/ui.h,v
retrieving revision 1.34
diff -u -p -r1.34 ui.h
--- src/ui.h	10 Jan 2004 17:16:07 -0000	1.34
+++ src/ui.h	8 Nov 2004 20:26:37 -0000
@@ -181,6 +181,7 @@ gboolean meta_ui_have_a_theme      (void
 
 gboolean meta_ui_parse_accelerator (const char          *accel,
                                     unsigned int        *keysym,
+                                    unsigned int        *keycode,
                                     MetaVirtualModifier *mask);
 gboolean meta_ui_parse_modifier    (const char          *accel,
                                     MetaVirtualModifier *mask);
