File gnome-settings-daemon-keybindings-become-unavaiable.patch of Package gnome-settings-daemon
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) {