[gnome-settings-daemon] media-keys: Port custom keybindings to GSettings



commit 95b1e9b41c255fafdc09b48079f0a6fc1d81d164
Author: Florian MÃllner <fmuellner gnome org>
Date:   Thu Nov 10 16:57:18 2011 +0100

    media-keys: Port custom keybindings to GSettings
    
    https://bugzilla.gnome.org/show_bug.cgi?id=631502

 configure.ac                                       |    2 +-
 ...ngs-daemon.plugins.media-keys.gschema.xml.in.in |   23 ++
 plugins/media-keys/gsd-media-keys-manager.c        |  294 ++++++++++----------
 plugins/media-keys/test-media-keys.c               |    2 +
 4 files changed, 178 insertions(+), 143 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 3fddbba..e32ede2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -217,7 +217,7 @@ dnl ---------------------------------------------------------------------------
 dnl - media-keys plugin stuff
 dnl ---------------------------------------------------------------------------
 
-PKG_CHECK_MODULES(MEDIA_KEYS, [gio-unix-2.0 libpulse >= $PA_REQUIRED_VERSION $GUDEV_PKG libpulse-mainloop-glib >= $PA_REQUIRED_VERSION libcanberra gconf-2.0 >= $GCONF_REQUIRED_VERSION])
+PKG_CHECK_MODULES(MEDIA_KEYS, [gio-unix-2.0 libpulse >= $PA_REQUIRED_VERSION $GUDEV_PKG libpulse-mainloop-glib >= $PA_REQUIRED_VERSION libcanberra])
 
 dnl ---------------------------------------------------------------------------
 dnl - color
diff --git a/data/org.gnome.settings-daemon.plugins.media-keys.gschema.xml.in.in b/data/org.gnome.settings-daemon.plugins.media-keys.gschema.xml.in.in
index 7383082..e58239e 100644
--- a/data/org.gnome.settings-daemon.plugins.media-keys.gschema.xml.in.in
+++ b/data/org.gnome.settings-daemon.plugins.media-keys.gschema.xml.in.in
@@ -5,6 +5,11 @@
       <_summary>Activation of this plugin</_summary>
       <_description>Whether this plugin would be activated by gnome-settings-daemon or not</_description>
     </key>
+    <key name="custom-keybindings" type="as">
+      <default>[]</default>
+      <_summary>Custom keybindings</_summary>
+      <_description>List of custom keybindings</_description>
+    </key>
     <key name="calculator" type="s">
       <default>'XF86Calculator'</default>
       <_summary>Launch calculator</_summary>
@@ -151,4 +156,22 @@
       <_description>Binding for the magnifier to zoom out</_description>
     </key>
   </schema>
+
+  <schema gettext-domain="@GETTEXT_PACKAGE@" id="org.gnome.settings-daemon.plugins.media-keys.custom-keybinding">
+    <key name="name" type="s">
+      <default>''</default>
+      <_summary>Name</_summary>
+      <_description>Name of the custom binding</_description>
+    </key>
+    <key name="binding" type="s">
+      <default>''</default>
+      <_summary>Binding</_summary>
+      <_description>Binding for the custom binding</_description>
+    </key>
+    <key name="command" type="s">
+      <default>''</default>
+      <_summary>Command</_summary>
+      <_description>Command to run when the binding is invoked</_description>
+    </key>
+  </schema>
 </schemalist>
diff --git a/plugins/media-keys/gsd-media-keys-manager.c b/plugins/media-keys/gsd-media-keys-manager.c
index 560de98..e67c123 100644
--- a/plugins/media-keys/gsd-media-keys-manager.c
+++ b/plugins/media-keys/gsd-media-keys-manager.c
@@ -39,7 +39,6 @@
 #include <gdk/gdkx.h>
 #include <gtk/gtk.h>
 #include <gio/gdesktopappinfo.h>
-#include <gconf/gconf-client.h>
 
 #ifdef HAVE_GUDEV
 #include <gudev/gudev.h>
@@ -67,7 +66,7 @@
 #define GNOME_SESSION_DBUS_PATH "/org/gnome/SessionManager"
 #define GNOME_SESSION_DBUS_INTERFACE "org.gnome.SessionManager"
 
-#define GCONF_BINDING_DIR "/desktop/gnome/keybindings"
+#define CUSTOM_BINDING_SCHEMA SETTINGS_BINDING_DIR ".custom-keybinding"
 
 static const gchar introspection_xml[] =
 "<node>"
@@ -110,7 +109,7 @@ typedef struct {
         MediaKeyType key_type;
         const char *settings_key;
         const char *hard_coded;
-        char *gconf_dir;
+        char *custom_path;
         char *custom_command;
         Key *key;
 } MediaKey;
@@ -129,10 +128,9 @@ struct GsdMediaKeysManagerPrivate
 
         GtkWidget       *dialog;
         GSettings       *settings;
+        GHashTable      *custom_settings;
 
         GPtrArray       *keys;
-        GConfClient     *gconf;
-        guint            gconf_id;
 
         /* HighContrast theme settings */
         GSettings       *interface_settings;
@@ -165,6 +163,9 @@ static void     gsd_media_keys_manager_class_init  (GsdMediaKeysManagerClass *kl
 static void     gsd_media_keys_manager_init        (GsdMediaKeysManager      *media_keys_manager);
 static void     gsd_media_keys_manager_finalize    (GObject                  *object);
 static void     register_manager                   (GsdMediaKeysManager      *manager);
+static void     custom_binding_changed             (GSettings           *settings,
+                                                    const char          *settings_key,
+                                                    GsdMediaKeysManager *manager);
 G_DEFINE_TYPE (GsdMediaKeysManager, gsd_media_keys_manager, G_TYPE_OBJECT)
 
 static gpointer manager_object = NULL;
@@ -195,7 +196,7 @@ media_key_free (MediaKey *key)
 {
         if (key == NULL)
                 return;
-        g_free (key->gconf_dir);
+        g_free (key->custom_path);
         g_free (key->custom_command);
         free_key (key->key);
         g_free (key);
@@ -304,13 +305,12 @@ get_key_string (GsdMediaKeysManager *manager,
 		return g_settings_get_string (manager->priv->settings, key->settings_key);
 	else if (key->hard_coded != NULL)
 		return g_strdup (key->hard_coded);
-	else if (key->gconf_dir != NULL) {
-		char *entry, *str;
+	else if (key->custom_path != NULL) {
+                GSettings *settings;
 
-		entry = g_strdup_printf ("%s/binding", key->gconf_dir);
-		str = gconf_client_get_string (manager->priv->gconf, entry, NULL);
-		g_free (entry);
-		return str;
+                settings = g_hash_table_lookup (manager->priv->custom_settings,
+                                                key->custom_path);
+		return g_settings_get_string (settings, "binding");
 	} else
 		g_assert_not_reached ();
 }
@@ -356,6 +356,10 @@ gsettings_changed_cb (GSettings           *settings,
         int      i;
         gboolean need_flush = TRUE;
 
+	/* handled in gsettings_custom_changed_cb() */
+        if (g_str_equal (settings_key, "custom-keybindings"))
+		return;
+
         gdk_error_trap_push ();
 
         /* Find the key that was modified */
@@ -380,148 +384,165 @@ gsettings_changed_cb (GSettings           *settings,
                 g_warning ("Grab failed for some keys, another application may already have access the them.");
 }
 
-static char *
-entry_get_string (GConfEntry *entry)
+static MediaKey *
+media_key_new_for_path (GsdMediaKeysManager *manager,
+			char                *path)
 {
-        GConfValue *value = gconf_entry_get_value (entry);
+        GSettings *settings;
+        char *command, *binding;
+        MediaKey *key;
+
+        g_debug ("media_key_new_for_path: %s", path);
 
-        if (value == NULL || value->type != GCONF_VALUE_STRING) {
+	settings = g_hash_table_lookup (manager->priv->custom_settings, path);
+	if (settings == NULL) {
+		settings = g_settings_new_with_path (CUSTOM_BINDING_SCHEMA, path);
+
+		g_signal_connect (settings, "changed",
+				  G_CALLBACK (custom_binding_changed), manager);
+		g_hash_table_insert (manager->priv->custom_settings,
+				     g_strdup (path), settings);
+	}
+
+        command = g_settings_get_string (settings, "command");
+        binding = g_settings_get_string (settings, "binding");
+
+        if (*command == '\0' && *binding == '\0') {
+                g_debug ("Key binding (%s) is incomplete", path);
+                g_free (command);
+                g_free (binding);
                 return NULL;
         }
+        g_free (binding);
+
+        key = g_new0 (MediaKey, 1);
+        key->key_type = CUSTOM_KEY;
+        key->custom_path = g_strdup (path);
+        key->custom_command = command;
 
-        return g_strdup (gconf_value_get_string (value));
+        return key;
 }
 
-static MediaKey *
-media_key_new_for_gconf (GsdMediaKeysManager *manager,
-			 char                *dir)
+static void
+update_custom_binding (GsdMediaKeysManager *manager,
+                       char                *path)
 {
-        GSList *list, *l;
-        char *action, *binding;
         MediaKey *key;
+        int i;
 
-        /* Get entries for this binding */
-        list = gconf_client_all_entries (manager->priv->gconf, dir, NULL);
-        action = NULL;
-        binding = NULL;
-
-        for (l = list; l != NULL; l = l->next) {
-                GConfEntry *entry = l->data;
-                char *key_name;
-
-                key_name = g_path_get_basename (gconf_entry_get_key (entry));
+        /* Remove the existing key */
+        for (i = 0; i < manager->priv->keys->len; i++) {
+                key = g_ptr_array_index (manager->priv->keys, i);
 
-                if (key_name == NULL) {
-                        /* ignore entry */
-                } else if (strcmp (key_name, "action") == 0) {
-                        action = entry_get_string (entry);
-                } else if (strcmp (key_name, "binding") == 0) {
-                        binding = entry_get_string (entry);
+                if (key->custom_path == NULL)
+                        continue;
+                if (strcmp (key->custom_path, path) == 0) {
+                        g_debug ("Removing custom key binding %s", path);
+                        if (key->key) {
+                                gdk_error_trap_push ();
+
+                                grab_key_unsafe (key->key,
+                                                 FALSE,
+                                                 manager->priv->screens);
+
+                                gdk_flush ();
+                                if (gdk_error_trap_pop ())
+                                        g_warning ("Ungrab failed for custom key '%s'", path);
+                        }
+                        g_ptr_array_remove_index_fast (manager->priv->keys, i);
+                        break;
                 }
-
-                g_free (key_name);
-                gconf_entry_free (entry);
         }
 
-        g_slist_free (list);
+        /* And create a new one! */
+        key = media_key_new_for_path (manager, path);
+        if (key) {
+                g_debug ("Adding new custom key binding %s", path);
+                g_ptr_array_add (manager->priv->keys, key);
 
-        if (action == NULL && binding == NULL) {
-                g_debug ("Key binding (%s) is incomplete", dir);
-                return NULL;
-        }
-        g_free (binding);
+                gdk_error_trap_push ();
 
-        key = g_new0 (MediaKey, 1);
-        key->key_type = CUSTOM_KEY;
-        key->gconf_dir = dir;
-        key->custom_command = action;
+                grab_media_key (key, manager);
 
-        return key;
+                gdk_flush ();
+                if (gdk_error_trap_pop ())
+                        g_warning ("Grab failed for custom key '%s'",
+                                   key->custom_path);
+        }
 }
 
 static void
-gconf_changed_cb (GConfClient         *client,
-                  guint                cnxn_id,
-                  GConfEntry          *entry,
-                  GsdMediaKeysManager *manager)
-{
-	char *gconf_key, **key_elems;
-	int      i;
-	MediaKey *key;
-
-	g_return_if_fail (entry != NULL);
-	g_return_if_fail (entry->key[0] == '/');
-
-	/* Look for the dir that changed, thus the MediaKey */
-	key_elems = g_strsplit (entry->key + 1, "/", -1);
-	if (key_elems == NULL ||
-	    (g_strv_length (key_elems) != 4 &&
-	     g_strv_length (key_elems) != 5)) {
-		g_warning ("Unexpected GConf notification for key '%s'", entry->key);
-		g_strfreev (key_elems);
-		return;
-	}
+custom_binding_changed (GSettings           *settings,
+                        const char          *settings_key,
+                        GsdMediaKeysManager *manager)
+{
+        char *path;
 
-	if (g_strv_length (key_elems) == 5 &&
-	    g_str_equal (key_elems[4], "binding") == FALSE &&
-	    g_str_equal (key_elems[4], "action") == FALSE) {
-		g_debug ("Not interested in notification for key '%s'", entry->key);
-		g_strfreev (key_elems);
-		return;
-	}
-	gconf_key = g_strdup_printf ("/%s/%s/%s/%s",
-				     key_elems[0],
-				     key_elems[1],
-				     key_elems[2],
-				     key_elems[3]);
-	g_strfreev (key_elems);
+        if (strcmp (settings_key, "name") == 0)
+                return; /* we don't care */
 
-	g_debug ("Got notification for key '%s' (dir: '%s')",
-		 entry->key, gconf_key);
+        g_object_get (settings, "path", &path, NULL);
+        update_custom_binding (manager, path);
+        g_free (path);
+}
 
-	/* Remove the existing key */
-	for (i = 0; i < manager->priv->keys->len; i++) {
-		key = g_ptr_array_index (manager->priv->keys, i);
+static void
+gsettings_custom_changed_cb (GSettings           *settings,
+                             const char          *settings_key,
+                             GsdMediaKeysManager *manager)
+{
+        char **bindings;
+        int i, j, n_bindings;
 
-		if (key->gconf_dir == NULL)
-			continue;
-		if (strcmp (key->gconf_dir, gconf_key) == 0) {
-			if (key->key) {
-				gdk_error_trap_push ();
+        bindings = g_settings_get_strv (settings, settings_key);
+        n_bindings = g_strv_length (bindings);
 
-				grab_key_unsafe (key->key, FALSE, manager->priv->screens);
+        /* Handle additions */
+        for (i = 0; i < n_bindings; i++) {
+                if (g_hash_table_lookup (manager->priv->custom_settings,
+                                         bindings[i]))
+                        continue;
+                update_custom_binding (manager, bindings[i]);
+        }
 
-				gdk_flush ();
-				if (gdk_error_trap_pop ())
-					g_warning ("Ungrab failed for GConf key '%s'", gconf_key);
-			}
-			g_ptr_array_remove_index_fast (manager->priv->keys, i);
-			break;
-		}
-	}
+        /* Handle removals */
+        for (i = 0; i < manager->priv->keys->len; i++) {
+                gboolean found = FALSE;
+                MediaKey *key = g_ptr_array_index (manager->priv->keys, i);
+                if (key->key_type != CUSTOM_KEY)
+                        continue;
+
+                for (j = 0; j < n_bindings && !found; j++)
+                        found = strcmp (bindings[j], key->custom_path) == 0;
 
-	/* And create a new one! */
-	key = media_key_new_for_gconf (manager, gconf_key);
-	if (key) {
-		g_ptr_array_add (manager->priv->keys, key);
+                if (found)
+                        continue;
 
-		gdk_error_trap_push ();
+                if (key->key) {
+                        gdk_error_trap_push ();
 
-		grab_media_key (key, manager);
+                        grab_key_unsafe (key->key,
+                                         FALSE,
+                                         manager->priv->screens);
 
-		gdk_flush ();
-		if (gdk_error_trap_pop ())
-			g_warning ("Grab failed for GConf key '%s'", key->gconf_dir);
-	} else {
-		g_free (gconf_key);
-	}
+                        gdk_flush ();
+                        if (gdk_error_trap_pop ())
+                                g_warning ("Ungrab failed for custom key '%s'", key->custom_path);
+                }
+                g_hash_table_remove (manager->priv->custom_settings,
+                                     key->custom_path);
+                g_ptr_array_remove_index_fast (manager->priv->keys, i);
+                --i; /* make up for the removed key */
+        }
+        g_strfreev (bindings);
 }
 
+
 static void
 init_kbd (GsdMediaKeysManager *manager)
 {
+        char **custom_paths;
         int i;
-        GSList *list, *l;
 
         gnome_settings_profile_start (NULL);
 
@@ -544,20 +565,23 @@ init_kbd (GsdMediaKeysManager *manager)
         }
 
         /* Custom shortcuts */
-        list = gconf_client_all_dirs (manager->priv->gconf, GCONF_BINDING_DIR, NULL);
-        for (l = list; l != NULL; l = l->next) {
+        custom_paths = g_settings_get_strv (manager->priv->settings,
+                                            "custom-keybindings");
+
+        for (i = 0; i < g_strv_length (custom_paths); i++) {
                 MediaKey *key;
 
-                key = media_key_new_for_gconf (manager, l->data);
+                g_debug ("Setting up custom keybinding %s", custom_paths[i]);
+
+                key = media_key_new_for_path (manager, custom_paths[i]);
                 if (!key) {
-                        g_free (l->data);
                         continue;
                 }
                 g_ptr_array_add (manager->priv->keys, key);
 
                 grab_media_key (key, manager);
         }
-        g_slist_free (list);
+        g_strfreev (custom_paths);
 
         gdk_flush ();
         if (gdk_error_trap_pop ())
@@ -1987,15 +2011,12 @@ start_media_keys_idle_cb (GsdMediaKeysManager *manager)
         manager->priv->settings = g_settings_new (SETTINGS_BINDING_DIR);
         g_signal_connect (G_OBJECT (manager->priv->settings), "changed",
                           G_CALLBACK (gsettings_changed_cb), manager);
+        g_signal_connect (G_OBJECT (manager->priv->settings), "changed::custom-keybindings",
+                          G_CALLBACK (gsettings_custom_changed_cb), manager);
 
-        manager->priv->gconf = gconf_client_get_default ();
-        gconf_client_add_dir (manager->priv->gconf, GCONF_BINDING_DIR, GCONF_CLIENT_PRELOAD_RECURSIVE, NULL);
-        manager->priv->gconf_id = gconf_client_notify_add (manager->priv->gconf,
-                                                           GCONF_BINDING_DIR,
-                                                           (GConfClientNotifyFunc) gconf_changed_cb,
-                                                           manager,
-                                                           NULL,
-                                                           NULL);
+        manager->priv->custom_settings =
+          g_hash_table_new_full (g_str_hash, g_str_equal,
+                                 g_free, g_object_unref);
 
         /* Sound events */
         ca_context_create (&manager->priv->ca);
@@ -2202,17 +2223,6 @@ gsd_media_keys_manager_stop (GsdMediaKeysManager *manager)
         gdk_flush ();
         gdk_error_trap_pop_ignored ();
 
-        if (priv->gconf_id) {
-                gconf_client_remove_dir (priv->gconf, GCONF_BINDING_DIR, NULL);
-                gconf_client_notify_remove (priv->gconf, priv->gconf_id);
-                priv->gconf_id = 0;
-        }
-
-        if (priv->gconf) {
-                g_object_unref (priv->gconf);
-                priv->gconf = NULL;
-        }
-
         if (priv->screens != NULL) {
                 g_slist_free (priv->screens);
                 priv->screens = NULL;
diff --git a/plugins/media-keys/test-media-keys.c b/plugins/media-keys/test-media-keys.c
index 1c5e536..4c882fe 100644
--- a/plugins/media-keys/test-media-keys.c
+++ b/plugins/media-keys/test-media-keys.c
@@ -45,6 +45,8 @@ main (int    argc,
         textdomain (GETTEXT_PACKAGE);
 #endif
 
+	g_setenv ("G_MESSAGES_DEBUG", "all", TRUE);
+
         error = NULL;
         if (! gtk_init_with_args (&argc, &argv, NULL, NULL, NULL, &error)) {
                 fprintf (stderr, "%s", error->message);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]