Index: gnome-settings-daemon/eggaccelerators.c
===================================================================
RCS file: /cvs/gnome/gnome-control-center/gnome-settings-daemon/eggaccelerators.c,v
retrieving revision 1.3
diff -u -p -r1.3 eggaccelerators.c
--- gnome-settings-daemon/eggaccelerators.c	1 Apr 2004 05:59:55 -0000	1.3
+++ gnome-settings-daemon/eggaccelerators.c	8 Nov 2004 20:27:30 -0000
@@ -185,20 +185,27 @@ is_keycode (const gchar *string)
 
 /**
  * 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
@@ -210,27 +217,29 @@ is_keycode (const gchar *string)
  */
 gboolean
 egg_accelerator_parse_virtual (const gchar            *accelerator,
-                               guint                  *accelerator_key,
-			       guint                  *keycode,
+                               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;
-  if (keycode)
-    *keycode = 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)
@@ -325,66 +334,121 @@ egg_accelerator_parse_virtual (const gch
       else
 	{
           keyval = gdk_keyval_from_name (accelerator);
-
+          
           if (keyval == 0)
-	    {
-	      /* If keyval is 0, than maybe it's a keycode.  Check for 0x## */
-	      if (len >= 4 && is_keycode (accelerator))
-		{
-		  char keystring[5];
-		  gchar *endptr;
-		  gint tmp_keycode;
-
-		  memcpy (keystring, accelerator, 4);
-		  keystring [4] = '\000';
-
-		  tmp_keycode = strtol (keystring, &endptr, 16);
-
-		  if (endptr == NULL || *endptr != '\000')
-		    {
-		      bad_keyval = TRUE;
-		    }
-		  else if (keycode != NULL)
-		    {
-		      *keycode = tmp_keycode;
-		      /* 0x00 is an invalid keycode too. */
-		      if (*keycode == 0)
-			bad_keyval = TRUE;
-		    }
-		}
-	    } else if (keycode != NULL)
-		*keycode = XKeysymToKeycode (GDK_DISPLAY(), keyval);
-
+            {
+              /* 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;
+          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,
-			      guint		     keycode,
+egg_virtual_accelerator_name (guint                  accelerator_keyval,
+                              guint                  accelerator_keycode,
                               EggVirtualModifierType accelerator_mods)
 {
   static const gchar text_release[] = "<Release>";
@@ -400,20 +464,24 @@ 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;
 
-  if (!accelerator_key)
+  keyval_name = NULL;
+  if (accelerator_keyval != 0)
     {
-      keyval_name = g_strdup_printf ("0x%02x", keycode);
+      keyval_name = gdk_keyval_name (gdk_keyval_to_lower (accelerator_keyval));
     }
-  else
+  else if (accelerator_keycode != 0)
     {
-      keyval_name = gdk_keyval_name (gdk_keyval_to_lower (accelerator_key));
-      if (!keyval_name)
-        keyval_name = "";
+      g_snprintf (keycode_buf, sizeof(keycode_buf), 
+                  "0x%02x", accelerator_keycode);
+      keyval_name = keycode_buf;
     }
+  if (!keyval_name)
+    keyval_name = "";
 
   l = 0;
   if (accelerator_mods & EGG_VIRTUAL_RELEASE_MASK)
Index: gnome-settings-daemon/eggaccelerators.h
===================================================================
RCS file: /cvs/gnome/gnome-control-center/gnome-settings-daemon/eggaccelerators.h,v
retrieving revision 1.1
diff -u -p -r1.1 eggaccelerators.h
--- gnome-settings-daemon/eggaccelerators.h	13 Jan 2004 15:57:35 -0000	1.1
+++ gnome-settings-daemon/eggaccelerators.h	8 Nov 2004 20:27:30 -0000
@@ -68,10 +68,14 @@ typedef enum
 
 } EggVirtualModifierType;
 
-gboolean egg_accelerator_parse_virtual        (const gchar            *accelerator,
-                                               guint                  *accelerator_key,
-					       guint                  *keycode,
-                                               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);
@@ -80,7 +84,7 @@ void     egg_keymap_virtualize_modifiers
                                                EggVirtualModifierType *virtual_mods);
 
 gchar* egg_virtual_accelerator_name (guint                  accelerator_key,
-				     guint		    keycode,
+                                     guint                  accelerator_keycode,
                                      EggVirtualModifierType accelerator_mods);
 
 G_END_DECLS
Index: gnome-settings-daemon/gnome-settings-keybindings.c
===================================================================
RCS file: /cvs/gnome/gnome-control-center/gnome-settings-daemon/gnome-settings-keybindings.c,v
retrieving revision 1.8
diff -u -p -r1.8 gnome-settings-keybindings.c
--- gnome-settings-daemon/gnome-settings-keybindings.c	7 Apr 2004 14:33:18 -0000	1.8
+++ gnome-settings-daemon/gnome-settings-keybindings.c	8 Nov 2004 20:27:30 -0000
@@ -22,7 +22,6 @@
 #define GCONF_BINDING_DIR "/desktop/gnome/keybindings"
 
 typedef struct {
-  guint keysym;
   guint state;
   guint keycode;
 } Key;
@@ -155,7 +154,6 @@ parse_binding (Binding *binding)
 {
   g_return_val_if_fail (binding != NULL, FALSE);
 
-  binding->key.keysym = 0;
   binding->key.state = 0;
 
   if (binding->binding_str == NULL ||
@@ -163,7 +161,7 @@ parse_binding (Binding *binding)
       strcmp (binding->binding_str, "Disabled") == 0)
           return FALSE;
 
-  if (egg_accelerator_parse_virtual (binding->binding_str, &binding->key.keysym, &binding->key.keycode, &binding->key.state) == FALSE)
+  if (egg_accelerator_parse_virtual_to_keycode (binding->binding_str, &binding->key.keycode, &binding->key.state, gdk_keymap_get_default ()) == FALSE)
           return FALSE;
 
   return TRUE;
@@ -243,7 +241,6 @@ bindings_get_entry (char *subdir)
   new_binding->action = action;
   new_binding->gconf_key = gconf_key;
 
-  new_binding->previous_key.keysym = new_binding->key.keysym;
   new_binding->previous_key.state = new_binding->key.state;
   new_binding->previous_key.keycode = new_binding->key.keycode;
 
@@ -351,7 +348,6 @@ binding_register_keys ()
 		do_grab (FALSE, &binding->previous_key);
 	      do_grab (TRUE, &binding->key);
 
-	      binding->previous_key.keysym = binding->key.keysym;
 	      binding->previous_key.state = binding->key.state;
 	      binding->previous_key.keycode = binding->key.keycode;
             }
Index: gnome-settings-daemon/gnome-settings-multimedia-keys.c
===================================================================
RCS file: /cvs/gnome/gnome-control-center/gnome-settings-daemon/gnome-settings-multimedia-keys.c,v
retrieving revision 1.9
diff -u -p -r1.9 gnome-settings-multimedia-keys.c
--- gnome-settings-daemon/gnome-settings-multimedia-keys.c	21 Oct 2004 19:41:26 -0000	1.9
+++ gnome-settings-daemon/gnome-settings-multimedia-keys.c	8 Nov 2004 20:27:30 -0000
@@ -318,7 +318,7 @@ update_kbd_cb (GConfClient *client, guin
 				break;
 
 			key = g_new0 (Key, 1);
-			if (egg_accelerator_parse_virtual (tmp, &key->keysym, &key->keycode, &key->state) == FALSE)
+			if (egg_accelerator_parse_virtual_to_keycode (tmp, &key->keycode, &key->state, gdk_keymap_get_default ()) == FALSE)
 			{
 				g_free (key);
 				break;
@@ -354,7 +354,7 @@ update_kbd_cb (GConfClient *client, guin
 				break;
 
 			key = g_new0 (Key, 1);
-			if (egg_accelerator_parse_virtual (tmp, &key->keysym, &key->keycode, &key->state) == FALSE)
+			if (egg_accelerator_parse_virtual_to_keycode (tmp, &key->keycode, &key->state, gdk_keymap_get_default ()) == FALSE)
 			{
 				g_free (key);
 				break;
@@ -431,7 +431,7 @@ init_kbd (Acme *acme)
 		}
 
 		key = g_new0 (Key, 1);
-		if (!egg_accelerator_parse_virtual (tmp, &key->keysym, &key->keycode, &key->state))
+		if (!egg_accelerator_parse_virtual_to_keycode (tmp, &key->keycode, &key->state, gdk_keymap_get_default ()))
 		{
 		        g_free (tmp);
 			g_free (key);
@@ -461,7 +461,7 @@ init_kbd (Acme *acme)
 		}
 
 		key = g_new0 (Key, 1);
-		if (egg_accelerator_parse_virtual (tmp, &key->keysym, &key->keycode, &key->state) == FALSE)
+		if (egg_accelerator_parse_virtual_to_keycode (tmp, &key->keycode, &key->state, gdk_keymap_get_default ()) == FALSE)
 		{
 		        g_free (tmp);
 			g_free (key);
Index: gnome-settings-daemon/actions/acme.h
===================================================================
RCS file: /cvs/gnome/gnome-control-center/gnome-settings-daemon/actions/acme.h,v
retrieving revision 1.3
diff -u -p -r1.3 acme.h
--- gnome-settings-daemon/actions/acme.h	24 Mar 2004 02:54:33 -0000	1.3
+++ gnome-settings-daemon/actions/acme.h	8 Nov 2004 20:27:30 -0000
@@ -51,7 +51,6 @@ enum {
 };
 
 typedef struct {
-  guint keysym;
   guint state;
   guint keycode;
 } Key;
