--- src/keybindings.c	2006/08/08 16:52:43	1.1
+++ src/keybindings.c	2006/08/08 16:53:21
@@ -232,8 +232,8 @@ struct _MetaKeyBinding
 {
   const char *name;
   KeySym keysym;
+  KeyCode keycode;
   unsigned int mask;
-  unsigned int keycode;
   MetaVirtualModifier modifiers;
   const MetaKeyHandler *handler;
 };
@@ -557,8 +557,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;
         }
@@ -571,8 +572,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;
         }
@@ -645,7 +647,7 @@ count_bindings (const MetaKeyPref *prefs
         {
           MetaKeyCombo *combo = tmp->data;
 
-          if (combo && combo->keysym != None)
+          if (combo && (combo->keysym != None || combo->keycode != 0))
             {
               count += 1;
 
@@ -687,13 +689,13 @@ rebuild_binding_table (MetaDisplay      
         {
           MetaKeyCombo *combo = tmp->data;
 
-          if (combo && combo->keysym != None)
+          if (combo && (combo->keysym != None || combo->keycode != 0))
             {
               (*bindings_p)[dest].name = prefs[src].name;
               (*bindings_p)[dest].keysym = combo->keysym;
+              (*bindings_p)[dest].keycode = combo->keycode;
               (*bindings_p)[dest].modifiers = combo->modifiers;
               (*bindings_p)[dest].mask = 0;
-              (*bindings_p)[dest].keycode = 0;          
           
               ++dest;
 
@@ -706,10 +708,10 @@ rebuild_binding_table (MetaDisplay      
               
                   (*bindings_p)[dest].name = prefs[src].name;
                   (*bindings_p)[dest].keysym = combo->keysym;
+                  (*bindings_p)[dest].keycode = combo->keycode;
                   (*bindings_p)[dest].modifiers = combo->modifiers |
                     META_VIRTUAL_SHIFT_MASK;
                   (*bindings_p)[dest].mask = 0;
-                  (*bindings_p)[dest].keycode = 0;          
               
                   ++dest;
                 }
@@ -810,6 +812,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;
@@ -818,6 +821,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);
@@ -976,9 +980,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() */
@@ -2346,6 +2350,7 @@ process_tab_grab (MetaDisplay *display,
   prev_window  = meta_display_lookup_x_window (display, prev_xwindow);
   action = display_get_keybinding_action (display,
                                           keysym,
+                                          event->xkey.keycode,
                                           display->grab_mask);
 
   /* Cancel when alt-Escape is pressed during using alt-Tab, and vice
@@ -2806,6 +2811,7 @@ process_workspace_switch_grab (MetaDispl
 
       action = display_get_keybinding_action (display,
                                               keysym,
+                                              event->xkey.keycode,
                                               display->grab_mask);
 
       switch (action)
--- src/prefs.c	2006/08/08 16:52:49	1.1
+++ src/prefs.c	2006/08/08 17:39:00
@@ -2151,6 +2151,7 @@ update_binding (MetaKeyPref *binding,
                 const char  *value)
 {
   unsigned int keysym;
+  unsigned int keycode;
   MetaVirtualModifier mods;
   MetaKeyCombo *combo;
   gboolean changed;
@@ -2160,10 +2161,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");
@@ -2246,16 +2248,19 @@ update_binding (MetaKeyPref *binding,
   
   changed = FALSE;
   if (keysym != combo->keysym ||
+      keycode != combo->keycode ||
       mods != combo->modifiers)
     {
       changed = TRUE;
       
       combo->keysym = keysym;
+      combo->keycode = keycode;
       combo->modifiers = mods;
       
       meta_topic (META_DEBUG_KEYBINDINGS,
-                  "New keybinding for \"%s\" is keysym = 0x%x mods = 0x%x\n",
-                  binding->name, combo->keysym, combo->modifiers);
+                  "New keybinding for \"%s\" is keysym = 0x%x keycode = 0x%x mods = 0x%x\n",
+                  binding->name, combo->keysym, combo->keycode,
+                  combo->modifiers);
     }
   else
     {
@@ -2272,6 +2277,7 @@ update_list_binding (MetaKeyPref *bindin
                      MetaStringListType type_of_value)
 {
   unsigned int keysym;
+  unsigned int keycode;
   MetaVirtualModifier mods;
   gboolean changed = FALSE;
   const gchar *pref_string;
@@ -2308,6 +2314,7 @@ update_list_binding (MetaKeyPref *bindin
   while (pref_iterator)
     {
       keysym = 0;
+      keycode = 0;
       mods = 0;
 
       if (!pref_iterator->data)
@@ -2328,7 +2335,7 @@ update_list_binding (MetaKeyPref *bindin
           g_assert_not_reached ();
         }
       
-      if (!meta_ui_parse_accelerator (pref_string, &keysym, &mods))
+      if (!meta_ui_parse_accelerator (pref_string, &keysym, &keycode, &mods))
         {
           meta_topic (META_DEBUG_KEYBINDINGS,
                       "Failed to parse new gconf value\n");
@@ -2363,12 +2370,13 @@ update_list_binding (MetaKeyPref *bindin
 
       combo = g_malloc0 (sizeof (MetaKeyCombo));
       combo->keysym = keysym;
+      combo->keycode = keycode;
       combo->modifiers = mods;
       binding->bindings->next = g_slist_prepend (binding->bindings->next, combo);
 
       meta_topic (META_DEBUG_KEYBINDINGS,
-                      "New keybinding for \"%s\" is keysym = 0x%x mods = 0x%x\n",
-                      binding->name, keysym, mods);
+                      "New keybinding for \"%s\" is keysym = 0x%x keycode = 0x%x mods = 0x%x\n",
+                      binding->name, keysym, keycode, mods);
 
       pref_iterator = pref_iterator->next;
     }  
--- src/prefs.h	2006/08/08 16:52:49	1.1
+++ src/prefs.h	2006/08/08 16:53:21
@@ -257,6 +257,7 @@ typedef enum _MetaKeyBindingAction
 typedef struct
 {
   unsigned int keysym;
+  unsigned int keycode;
   MetaVirtualModifier modifiers;
 } MetaKeyCombo;
 
--- src/ui.c	2006/08/08 16:52:49	1.1
+++ src/ui.c	2006/08/08 17:36:08
@@ -34,8 +34,13 @@
 #include <pango/pangox.h>
 
 #include <string.h>
+#include <stdlib.h>
 
 static void meta_stock_icons_init (void);
+static void meta_ui_accelerator_parse (const char      *accel,
+                                       guint           *keysym,
+                                       guint           *keycode,
+                                       GdkModifierType *keymask);
 
 struct _MetaUI
 {
@@ -737,31 +742,51 @@ meta_ui_have_a_theme (void)
   return meta_theme_get_current () != NULL;
 }
 
+static void
+meta_ui_accelerator_parse (const char      *accel,
+                           guint           *keysym,
+                           guint           *keycode,
+                           GdkModifierType *keymask)
+{
+  if (accel[0] == '0' && accel[1] == 'x')
+    {
+      *keysym = 0;
+      *keycode = (guint) strtoul (accel, NULL, 16);
+      *keymask = 0;
+    }
+  else
+    gtk_accelerator_parse (accel, keysym, keymask);
+}
+
 gboolean
 meta_ui_parse_accelerator (const char          *accel,
                            unsigned int        *keysym,
+                           unsigned int        *keycode,
                            MetaVirtualModifier *mask)
 {
   GdkModifierType gdk_mask = 0;
   guint gdk_sym = 0;
+  guint gdk_code = 0;
   
   *keysym = 0;
+  *keycode = 0;
   *mask = 0;
 
   if (strcmp (accel, "disabled") == 0)
     return TRUE;
   
-  gtk_accelerator_parse (accel, &gdk_sym, &gdk_mask);
-  if (gdk_mask == 0 && gdk_sym == 0)
+  meta_ui_accelerator_parse (accel, &gdk_sym, &gdk_code, &gdk_mask);
+  if (gdk_mask == 0 && gdk_sym == 0 && gdk_code == 0)
     return FALSE;
 
-  if (gdk_sym == None)
+  if (gdk_sym == None && gdk_code == 0)
     return FALSE;
   
   if (gdk_mask & GDK_RELEASE_MASK) /* we don't allow this */
     return FALSE;
   
   *keysym = gdk_sym;
+  *keycode = gdk_code;
 
   if (gdk_mask & GDK_SHIFT_MASK)
     *mask |= META_VIRTUAL_SHIFT_MASK;
@@ -830,17 +855,18 @@ meta_ui_parse_modifier (const char      
 {
   GdkModifierType gdk_mask = 0;
   guint gdk_sym = 0;
+  guint gdk_code = 0;
   
   *mask = 0;
 
   if (strcmp (accel, "disabled") == 0)
     return TRUE;
   
-  gtk_accelerator_parse (accel, &gdk_sym, &gdk_mask);
-  if (gdk_mask == 0 && gdk_sym == 0)
+  meta_ui_accelerator_parse (accel, &gdk_sym, &gdk_code, &gdk_mask);
+  if (gdk_mask == 0 && gdk_sym == 0 && gdk_code == 0)
     return FALSE;
 
-  if (gdk_sym != None)
+  if (gdk_sym != None || gdk_code != 0)
     return FALSE;
   
   if (gdk_mask & GDK_RELEASE_MASK) /* we don't allow this */
--- src/ui.h	2006/08/08 16:52:49	1.1
+++ src/ui.h	2006/08/08 16:53:21
@@ -179,6 +179,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);
