diff --git a/plugins/media-keys/gsd-media-keys-manager.c b/plugins/media-keys/gsd-media-keys-manager.c
index 719e041..ff84f49 100644
--- a/plugins/media-keys/gsd-media-keys-manager.c
+++ b/plugins/media-keys/gsd-media-keys-manager.c
@@ -126,6 +126,8 @@ typedef struct {
 } MediaPlayer;
 
 typedef struct {
+        gint ref_count;
+
         MediaKeyType key_type;
         ShellActionMode modes;
         const char *settings_key;
@@ -133,6 +135,7 @@ typedef struct {
         char *custom_path;
         char *custom_command;
         guint accel_id;
+        gboolean ungrab_requested;
 } MediaKey;
 
 typedef struct {
@@ -180,6 +183,8 @@ struct GsdMediaKeysManagerPrivate
         GsdShell        *shell_proxy;
         ShellKeyGrabber *key_grabber;
         GCancellable    *grab_cancellable;
+        GHashTable      *keys_pending_grab;
+        GHashTable      *keys_to_grab;
 
         /* ScreenSaver stuff */
         GsdScreenSaver  *screen_saver_proxy;
@@ -235,15 +240,31 @@ static gpointer manager_object = NULL;
 
 
 static void
-media_key_free (MediaKey *key)
+media_key_unref (MediaKey *key)
 {
         if (key == NULL)
                 return;
+        if (!g_atomic_int_dec_and_test (&key->ref_count))
+                return;
         g_free (key->custom_path);
         g_free (key->custom_command);
         g_free (key);
 }
 
+static MediaKey *
+media_key_ref (MediaKey *key)
+{
+        g_atomic_int_inc (&key->ref_count);
+        return key;
+}
+
+static MediaKey *
+media_key_new (void)
+{
+        MediaKey *key = g_new0 (MediaKey, 1);
+        return media_key_ref (key);
+}
+
 static void
 set_launch_context_env (GsdMediaKeysManager *manager,
 			GAppLaunchContext   *launch_context)
@@ -452,8 +473,10 @@ grab_accelerator_complete (GObject      *object,
                            GAsyncResult *result,
                            gpointer      user_data)
 {
+        char *binding;
         GrabData *data = user_data;
         MediaKey *key = data->key;
+        GsdMediaKeysManager *manager = data->manager;
         GError *error = NULL;
 
         if (!shell_key_grabber_call_grab_accelerator_finish (SHELL_KEY_GRABBER (object),
@@ -463,7 +486,20 @@ grab_accelerator_complete (GObject      *object,
                 g_error_free (error);
         }
 
+        if (key->ungrab_requested)
+                ungrab_media_key (key, manager);
+
+        binding = get_key_string (manager, key);
+        g_hash_table_remove (manager->priv->keys_pending_grab, binding);
+        media_key_unref (key);
         g_slice_free (GrabData, data);
+
+        if ((key = g_hash_table_lookup (manager->priv->keys_to_grab, binding)) != NULL) {
+                grab_media_key (key, manager);
+                g_hash_table_remove (manager->priv->keys_to_grab, binding);
+        }
+        g_free (binding);
+
 }
 
 static void
@@ -471,23 +507,27 @@ grab_media_key (MediaKey            *key,
 		GsdMediaKeysManager *manager)
 {
 	GrabData *data;
-	char *tmp;
+	char *binding;
 
-	ungrab_media_key (key, manager);
-
-	tmp = get_key_string (manager, key);
+	binding = get_key_string (manager, key);
+        if (g_hash_table_lookup (manager->priv->keys_pending_grab, binding)) {
+                g_hash_table_insert (manager->priv->keys_to_grab,
+                                     g_strdup (binding), media_key_ref (key));
+                goto out;
+        }
 
 	data = g_slice_new0 (GrabData);
 	data->manager = manager;
-	data->key = key;
+	data->key = media_key_ref (key);
 
 	shell_key_grabber_call_grab_accelerator (manager->priv->key_grabber,
-	                                         tmp, key->modes,
+	                                         binding, key->modes,
 	                                         manager->priv->grab_cancellable,
 	                                         grab_accelerator_complete,
 	                                         data);
-
-	g_free (tmp);
+        g_hash_table_add (manager->priv->keys_pending_grab, g_strdup (binding));
+ out:
+	g_free (binding);
 }
 
 static void
@@ -509,8 +549,10 @@ static void
 ungrab_media_key (MediaKey            *key,
                   GsdMediaKeysManager *manager)
 {
-	if (key->accel_id == 0)
-		return;
+        if (key->accel_id == 0) {
+                key->ungrab_requested = TRUE;
+                return;
+        }
 
 	shell_key_grabber_call_ungrab_accelerator (manager->priv->key_grabber,
 	                                           key->accel_id,
@@ -556,6 +598,7 @@ gsettings_changed_cb (GSettings           *settings,
                 if (key->settings_key == NULL)
                         continue;
                 if (strcmp (settings_key, key->settings_key) == 0) {
+                        ungrab_media_key (key, manager);
                         grab_media_key (key, manager);
                         break;
                 }
@@ -576,7 +619,7 @@ media_key_new_for_path (GsdMediaKeysManager *manager,
 	if (settings == NULL) {
 		settings = g_settings_new_with_path (CUSTOM_BINDING_SCHEMA, path);
 
-		g_signal_connect (settings, "changed",
+		g_signal_connect (settings, "changed::binding",
 				  G_CALLBACK (custom_binding_changed), manager);
 		g_hash_table_insert (manager->priv->custom_settings,
 				     g_strdup (path), settings);
@@ -593,7 +636,7 @@ media_key_new_for_path (GsdMediaKeysManager *manager,
         }
         g_free (binding);
 
-        key = g_new0 (MediaKey, 1);
+        key = media_key_new ();
         key->key_type = CUSTOM_KEY;
         key->modes = GSD_ACTION_MODE_LAUNCHER;
         key->custom_path = g_strdup (path);
@@ -640,7 +683,7 @@ custom_binding_changed (GSettings           *settings,
 {
         char *path;
 
-        if (strcmp (settings_key, "name") == 0)
+        if (strcmp (settings_key, "binding") != 0)
                 return; /* we don't care */
 
         g_object_get (settings, "path", &path, NULL);
@@ -694,7 +737,7 @@ add_key (GsdMediaKeysManager *manager, guint i)
 {
 	MediaKey *key;
 
-	key = g_new0 (MediaKey, 1);
+	key = media_key_new ();
 	key->key_type = media_keys[i].key_type;
 	key->settings_key = media_keys[i].settings_key;
 	key->hard_coded = media_keys[i].hard_coded;
@@ -2783,7 +2826,12 @@ start_media_keys_idle_cb (GsdMediaKeysManager *manager)
         g_debug ("Starting media_keys manager");
         gnome_settings_profile_start (NULL);
 
-        manager->priv->keys = g_ptr_array_new_with_free_func ((GDestroyNotify) media_key_free);
+        manager->priv->keys = g_ptr_array_new_with_free_func ((GDestroyNotify) media_key_unref);
+
+        manager->priv->keys_pending_grab = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                                                  g_free, NULL);
+        manager->priv->keys_to_grab = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                                             g_free, (GDestroyNotify) media_key_unref);
 
         initialize_volume_handler (manager);
 
@@ -2943,6 +2991,9 @@ gsd_media_keys_manager_stop (GsdMediaKeysManager *manager)
                 priv->keys = NULL;
         }
 
+        g_clear_pointer (&priv->keys_pending_grab, g_hash_table_destroy);
+        g_clear_pointer (&priv->keys_to_grab, g_hash_table_destroy);
+
         g_clear_object (&priv->key_grabber);
 
         if (priv->grab_cancellable != NULL) {
