Index: capplets/keybindings/gnome-keybinding-properties.c
===================================================================
--- capplets/keybindings/gnome-keybinding-properties.c	(revision 7350)
+++ capplets/keybindings/gnome-keybinding-properties.c	(working copy)
@@ -19,28 +19,37 @@
 #define LABEL_DATA "gnome-keybinding-properties-label"
 #define MAX_ELEMENTS_BEFORE_SCROLLING 10
 
+typedef struct {
+  char *name;
+  /* Name of the window manager the keys would apply to */
+  char *wm_name;
+  /* an array of KeyListEntry */
+  GArray *entries;
+} KeyList;
+
 typedef enum {
   ALWAYS_VISIBLE,
   N_WORKSPACES_GT
 } KeyListEntryVisibility;
 
+typedef enum {
+  COMPARISON_NONE = 0,
+  COMPARISON_GT,
+  COMPARISON_LT,
+  COMPARISON_EQ
+} Comparison;
+
 typedef struct
 {
-  const char *name;
-  KeyListEntryVisibility visibility;
-  gint data;
+  char *name;
+  int value;
+  char *key;
+  Comparison comparison;
 } KeyListEntry;
 
+#if 0
 static const KeyListEntry desktop_key_list[] =
 {
-  { "/apps/gnome_settings_daemon/keybindings/help", ALWAYS_VISIBLE, 0 },
-  { "/apps/gnome_settings_daemon/keybindings/power", ALWAYS_VISIBLE, 0 },
-  { "/apps/gnome_settings_daemon/keybindings/sleep", ALWAYS_VISIBLE, 0 },
-  { "/apps/gnome_settings_daemon/keybindings/screensaver", ALWAYS_VISIBLE, 0 },
-  { "/apps/gnome_settings_daemon/keybindings/home", ALWAYS_VISIBLE, 0 },
-  { "/apps/gnome_settings_daemon/keybindings/search", ALWAYS_VISIBLE, 0 },
-  { "/apps/gnome_settings_daemon/keybindings/email", ALWAYS_VISIBLE, 0 },
-  { "/apps/gnome_settings_daemon/keybindings/www", ALWAYS_VISIBLE, 0 },
   { "/apps/metacity/global_keybindings/panel_run_dialog", ALWAYS_VISIBLE, 0 },
   { "/apps/metacity/global_keybindings/panel_main_menu", ALWAYS_VISIBLE, 0 },
   { "/apps/metacity/global_keybindings/run_command_screenshot", ALWAYS_VISIBLE, 0 },
@@ -48,21 +57,8 @@
   { "/apps/metacity/global_keybindings/run_command_terminal", ALWAYS_VISIBLE, 0 },
   { NULL }
 };
-static const KeyListEntry sounds_key_list[] =
-{
-  { "/apps/gnome_settings_daemon/keybindings/volume_mute", ALWAYS_VISIBLE, 0 },
-  { "/apps/gnome_settings_daemon/keybindings/volume_down", ALWAYS_VISIBLE, 0 },
-  { "/apps/gnome_settings_daemon/keybindings/volume_up", ALWAYS_VISIBLE, 0 },
-  /* Other ones that need keysyms bindings */
-  { "/apps/gnome_settings_daemon/keybindings/play", ALWAYS_VISIBLE, 0 },        
-  { "/apps/gnome_settings_daemon/keybindings/pause", ALWAYS_VISIBLE, 0 },       
-  { "/apps/gnome_settings_daemon/keybindings/stop", ALWAYS_VISIBLE, 0 },        
-  { "/apps/gnome_settings_daemon/keybindings/previous", ALWAYS_VISIBLE, 0 },    
-  { "/apps/gnome_settings_daemon/keybindings/next", ALWAYS_VISIBLE, 0 },        
-  { "/apps/gnome_settings_daemon/keybindings/eject", ALWAYS_VISIBLE, 0 },
-  { NULL }
-};
-
+#endif
+#if 0
 static const KeyListEntry metacity_key_list[] =
 {
   { "/apps/metacity/window_keybindings/activate_window_menu",      ALWAYS_VISIBLE,  0 },
@@ -122,7 +118,7 @@
   { "/apps/metacity/global_keybindings/switch_to_workspace_down",  N_WORKSPACES_GT, 1 },
   { NULL }
 };
-
+#endif
 enum
 {
   DESCRIPTION_COLUMN,
@@ -171,6 +167,8 @@
   GladeXML *dialog;
 
   dialog = glade_xml_new (GNOMECC_GLADE_DIR "/gnome-keybinding-properties.glade", "gnome-keybinding-dialog", NULL);
+  if (!dialog)
+    dialog = glade_xml_new ("gnome-keybinding-properties.glade", "gnome-keybinding-dialog", NULL);
 
   return dialog;
 }
@@ -433,22 +431,35 @@
 static gboolean
 should_show_key (const KeyListEntry *entry)
 {
-  gint workspaces;
+  int value;
   GConfClient *client;
- 
-  switch (entry->visibility) {
-  case ALWAYS_VISIBLE:
+
+  if (entry->comparison == COMPARISON_NONE)
     return TRUE;
-  case N_WORKSPACES_GT:
-    client = gconf_client_get_default();
-    workspaces = gconf_client_get_int (client,
-				       "/apps/metacity/general/num_workspaces", NULL);
-    g_object_unref (client);
 
-    if (workspaces > entry->data)
+  g_return_val_if_fail (entry->key != NULL, FALSE);
+
+  client = gconf_client_get_default();
+  value = gconf_client_get_int (client, entry->key, NULL);
+  g_object_unref (client);
+
+  switch (entry->comparison) {
+  case COMPARISON_NONE:
+    /* For compiler warnings */
+    g_assert_not_reached ();
+    return FALSE;
+  case COMPARISON_GT:
+    if (value > entry->value)
       return TRUE;
-    else
-      return FALSE;
+    break;
+  case COMPARISON_LT:
+    if (value < entry->value)
+      return TRUE;
+    break;
+  case COMPARISON_EQ:
+    if (value == entry->value)
+      return TRUE;
+    break;
   }
 
   return FALSE;
@@ -487,7 +498,7 @@
 
       if (!should_show_key (&keys_list[j]))
 	continue;
-      
+
       key_string = keys_list[j].name;
 
       entry = gconf_client_get_entry (client,
@@ -505,7 +516,7 @@
 
       if (gconf_entry_get_schema_name (entry))
 	schema = gconf_client_get_schema (client, gconf_entry_get_schema_name (entry), &error);
-      
+
       if (error || schema == NULL)
 	{
 	  /* We don't actually want to popup a dialog - just skip this one */
@@ -565,17 +576,208 @@
 }
 
 static void
+parse_start_tag (GMarkupParseContext *ctx,
+		 const gchar         *element_name,
+		 const gchar        **attr_names,
+		 const gchar        **attr_values,
+		 gpointer             user_data,
+		 GError             **error)
+{
+  KeyList *keylist = (KeyList *) user_data;
+  KeyListEntry key;
+  const char *name, *gconf_key;
+  int value;
+  Comparison comparison;
+
+  name = NULL;
+
+  /* The top-level element, names the section in the tree */
+  if (g_str_equal (element_name, "KeyListEntries"))
+    {
+      const char *wm_name = NULL;
+
+      while (*attr_names && *attr_values)
+        {
+	  if (g_str_equal (*attr_names, "name"))
+	    {
+	      if (**attr_values)
+		name = *attr_values;
+	    } else if (g_str_equal (*attr_names, "wm_name")) {
+	      if (**attr_values)
+		wm_name = *attr_values;
+	    }
+	  ++attr_names;
+	  ++attr_values;
+	}
+
+      if (name)
+        {
+	  if (keylist->name)
+	    g_warning ("Duplicate section name");
+	  g_free (keylist->name);
+	  keylist->name = g_strdup (_(name));
+	}
+      if (wm_name)
+        {
+	  if (keylist->wm_name)
+	    g_warning ("Duplicate window manager name");
+	  g_free (keylist->wm_name);
+	  keylist->wm_name = g_strdup (wm_name);
+	}
+      return;
+    }
+
+  if (!g_str_equal (element_name, "KeyListEntry")
+      || attr_names == NULL
+      || attr_values == NULL)
+    return;
+
+  value = 0;
+  comparison = COMPARISON_NONE;
+  gconf_key = NULL;
+
+  while (*attr_names && *attr_values)
+    {
+      if (g_str_equal (*attr_names, "name"))
+        {
+	  /* skip if empty */
+	  if (**attr_values)
+	    name = *attr_values;
+	} else if (g_str_equal (*attr_names, "value")) {
+	  if (**attr_values) {
+	    value = (int) g_ascii_strtoull (*attr_values, NULL, 0);
+	  }
+	} else if (g_str_equal (*attr_names, "key")) {
+	  if (**attr_values) {
+	    gconf_key = *attr_values;
+	  }
+	} else if (g_str_equal (*attr_names, "comparison")) {
+	  if (**attr_values) {
+	    if (g_str_equal (*attr_values, "gt")) {
+	      comparison = COMPARISON_GT;
+	    } else if (g_str_equal (*attr_values, "lt")) {
+	      comparison = COMPARISON_LT;
+	    } else if (g_str_equal (*attr_values, "eq")) {
+	      comparison = COMPARISON_EQ;
+	    }
+	  }
+	}
+
+      ++attr_names;
+      ++attr_values;
+    }
+
+  if (name == NULL)
+    return;
+
+  key.name = g_strdup (name);
+  key.value = value;
+  if (gconf_key)
+    key.key = g_strdup (gconf_key);
+  else
+    key.key = NULL;
+  key.comparison = comparison;
+  g_array_append_val (keylist->entries, key);
+}
+
+static void
+append_keys_to_tree_from_file (GladeXML   *dialog,
+			       const char *filename,
+			       const char *wm_name)
+{
+  GMarkupParseContext *ctx;
+  GMarkupParser parser = { parse_start_tag, NULL, NULL, NULL, NULL };
+  KeyList *keylist;
+  KeyListEntry key, *keys;
+  GError *err = NULL;
+  char *buf;
+  gsize buf_len;
+  guint i;
+
+  if (!g_file_get_contents (filename, &buf, &buf_len, &err))
+    return;
+
+  keylist = g_new0 (KeyList, 1);
+  keylist->entries = g_array_new (FALSE, TRUE, sizeof (KeyListEntry));
+  ctx = g_markup_parse_context_new (&parser, 0, keylist, NULL);
+
+  if (!g_markup_parse_context_parse (ctx, buf, buf_len, &err))
+    {
+      g_warning ("Failed to parse '%s': '%s'", filename, err->message);
+      g_error_free (err);
+      g_free (keylist->name);
+      g_free (keylist->wm_name);
+      for (i = 0; i < keylist->entries->len; i++)
+	g_free (((KeyListEntry *) &(keylist->entries->data[i]))->name);
+      g_array_free (keylist->entries, TRUE);
+      g_free (keylist);
+      keylist = NULL;
+    }
+  g_markup_parse_context_free (ctx);
+  g_free (buf);
+
+  if (keylist == NULL)
+    return;
+
+  /* If there's no keys to add, or the settings apply to a window manager
+   * that's not the one we're running */
+  if (keylist->entries->len == 0
+      || (keylist->wm_name != NULL && !g_str_equal (wm_name, keylist->wm_name)))
+    {
+      g_free (keylist->name);
+      g_free (keylist->wm_name);
+      g_array_free (keylist->entries, TRUE);
+      g_free (keylist);
+      return;
+    }
+
+  /* Empty KeyListEntry to end the array */
+  key.name = NULL;
+  key.key = NULL;
+  key.value = 0;
+  key.comparison = COMPARISON_NONE;
+  g_array_append_val (keylist->entries, key);
+
+  keys = (KeyListEntry *) g_array_free (keylist->entries, FALSE);
+
+  append_keys_to_tree (dialog, keylist->name, keys);
+
+  g_free (keylist->name);
+  for (i = 0; keys[i].name != NULL; i++)
+    g_free (keys[i].name);
+  g_free (keylist);
+}
+
+static void
 reload_key_entries (gpointer wm_name, GladeXML *dialog)
 {
+  GDir *dir;
+  const char *name;
+
   clear_old_model (dialog);
   
-  append_keys_to_tree (dialog, _("Desktop"), desktop_key_list);
-  append_keys_to_tree (dialog, _("Sound"), sounds_key_list);
-  
+//  append_keys_to_tree (dialog, _("Desktop"), desktop_key_list);
+
+#if 0
+  //FIXME this should be in a separate file as well.
   if (strcmp((char *) wm_name, WM_COMMON_METACITY) == 0)
     {
-      append_keys_to_tree (dialog, _("Window Management"), metacity_key_list);
+//      append_keys_to_tree (dialog, _("Window Management"), metacity_key_list);
     }
+#endif
+  //FIXME path
+  dir = g_dir_open ("./", 0, NULL);
+  if (!dir)
+    {
+      return;
+    }
+
+  for (name = g_dir_read_name (dir) ; name ; name = g_dir_read_name (dir))
+    {
+      if (g_str_has_suffix (name, ".xml"))
+        append_keys_to_tree_from_file (dialog, name, wm_name);
+    }
+  g_dir_close (dir);
 }
 
 static void
@@ -910,10 +1112,10 @@
 
   g_signal_connect (GTK_TREE_VIEW (WID ("shortcut_treeview")),
 		    "button_press_event",
-		    G_CALLBACK (start_editing_cb), dialog),
-	g_signal_connect (GTK_TREE_VIEW (WID ("shortcut_treeview")),
-	      "row-activated",
-		    G_CALLBACK (start_editing_kb_cb), dialog),
+		    G_CALLBACK (start_editing_cb), dialog);
+  g_signal_connect (GTK_TREE_VIEW (WID ("shortcut_treeview")),
+		    "row-activated",
+		    G_CALLBACK (start_editing_kb_cb), dialog);
 		    
   column = gtk_tree_view_column_new_with_attributes (_("Action"),
 						     gtk_cell_renderer_text_new (),
@@ -945,7 +1147,7 @@
 
   gtk_tree_view_append_column (GTK_TREE_VIEW (WID ("shortcut_treeview")), column);
   gtk_tree_view_column_set_sort_column_id (column, KEYENTRY_COLUMN); 
-  
+
   gconf_client_add_dir (client, "/apps/gnome_keybinding_properties", GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
   gconf_client_add_dir (client, "/apps/metacity/general", GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
   gconf_client_notify_add (client,
@@ -995,3 +1197,7 @@
   g_object_unref (program);
   return 0;
 }
+
+/*
+ * vim: sw=2 ts=8 cindent noai bs=2
+ */
Index: capplets/keybindings/desktop-key.xml.in
===================================================================
--- capplets/keybindings/desktop-key.xml.in	(revision 0)
+++ capplets/keybindings/desktop-key.xml.in	(revision 0)
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<KeyListEntries _name="Desktop">
+
+	<KeyListEntry
+	name="/apps/gnome_settings_daemon/keybindings/help" />
+
+	<KeyListEntry
+	name="/apps/gnome_settings_daemon/keybindings/power" />
+
+	<KeyListEntry
+	name="/apps/gnome_settings_daemon/keybindings/sleep" />
+
+	<KeyListEntry
+	name="/apps/gnome_settings_daemon/keybindings/screensaver" />
+
+	<KeyListEntry
+	name="/apps/gnome_settings_daemon/keybindings/home" />
+
+	<KeyListEntry
+	name="/apps/gnome_settings_daemon/keybindings/search" />
+	
+	<KeyListEntry
+	name="/apps/gnome_settings_daemon/keybindings/email" />
+
+	<KeyListEntry
+	name="/apps/gnome_settings_daemon/keybindings/www" />
+
+</KeyListEntries>
Index: capplets/keybindings/multimedia-key.xml.in
===================================================================
--- capplets/keybindings/multimedia-key.xml.in	(revision 0)
+++ capplets/keybindings/multimedia-key.xml.in	(revision 0)
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<KeyListEntries _name="Sound">
+
+	<KeyListEntry
+	name="/apps/gnome_settings_daemon/keybindings/volume_mute" />
+
+	<KeyListEntry
+	name="/apps/gnome_settings_daemon/keybindings/volume_down" />
+
+	<KeyListEntry
+	name="/apps/gnome_settings_daemon/keybindings/volume_up" />
+
+	<KeyListEntry
+	name="/apps/gnome_settings_daemon/keybindings/play" />
+
+	<KeyListEntry
+	name="/apps/gnome_settings_daemon/keybindings/pause" />
+
+	<KeyListEntry
+	name="/apps/gnome_settings_daemon/keybindings/stop" />
+
+	<KeyListEntry
+	name="/apps/gnome_settings_daemon/keybindings/previous" />
+
+	<KeyListEntry
+	name="/apps/gnome_settings_daemon/keybindings/next" />
+
+	<KeyListEntry
+	name="/apps/gnome_settings_daemon/keybindings/eject" />
+
+</KeyListEntries>
Index: capplets/keybindings/Makefile.am
===================================================================
--- capplets/keybindings/Makefile.am	(revision 7350)
+++ capplets/keybindings/Makefile.am	(working copy)
@@ -20,6 +20,12 @@
 Desktop_in_files = keybinding.desktop.in
 desktop_DATA = $(Desktop_in_files:.desktop.in=.desktop)
 
+@INTLTOOL_XML_NOMERGE_RULE@
+
+xmldir       = $(pkgdatadir)/glade
+xml_in_files = multimedia-key.xml.in desktop-key.xml.in
+xml_DATA     = $(xml_in_files:.xml.in=.xml)
+
 INCLUDES = \
 	$(GNOMECC_CAPPLETS_CFLAGS) \
 	-DGNOMELOCALEDIR="\"$(datadir)/locale\"" \
Index: po/POTFILES.in
===================================================================
--- po/POTFILES.in	(revision 7350)
+++ po/POTFILES.in	(working copy)
@@ -37,6 +37,8 @@
 capplets/keybindings/gnome-keybinding-properties.c
 capplets/keybindings/gnome-keybinding-properties.glade
 capplets/keybindings/keybinding.desktop.in.in
+capplets/keybindings/multimedia-key.xml.in
+capplets/keybindings/desktop-key.xml.in
 capplets/keyboard/gnome-keyboard-properties-xkb.c
 capplets/keyboard/gnome-keyboard-properties-xkblt.c
 capplets/keyboard/gnome-keyboard-properties-xkbmc.c
