summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRui Matos <tiagomatos@gmail.com>2017-02-13 17:53:48 +0100
committerBastien Nocera <hadess@hadess.net>2017-02-14 17:22:58 +0100
commitbfb7255ddccb7d88c49b3eef60dcdd8dac1edede (patch)
tree2d3856655ddf1ca1c89e894147af6e416fb1ea3e
parent6028195d9a3e2f57e85d9a521b3ead3f307ca27e (diff)
downloadgnome-settings-daemon-bfb7255ddccb7d88c49b3eef60dcdd8dac1edede.tar.gz
media-keys: Handle binding grabs when there's already one pending
Since grabbing is asynchronous, we might end up with requests to grab a binding combo while we already have a pending grab for that same combo. If this happens, the last request should win, so keep track of it to re-try when we get the reply for the pending grab. https://bugzilla.gnome.org/show_bug.cgi?id=758302
-rw-r--r--plugins/media-keys/gsd-media-keys-manager.c36
1 files changed, 31 insertions, 5 deletions
diff --git a/plugins/media-keys/gsd-media-keys-manager.c b/plugins/media-keys/gsd-media-keys-manager.c
index 04075173..33b6762c 100644
--- a/plugins/media-keys/gsd-media-keys-manager.c
+++ b/plugins/media-keys/gsd-media-keys-manager.c
@@ -183,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;
@@ -471,6 +473,7 @@ grab_accelerator_complete (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
+ char *binding;
GrabData *data = user_data;
MediaKey *key = data->key;
GsdMediaKeysManager *manager = data->manager;
@@ -486,8 +489,17 @@ grab_accelerator_complete (GObject *object,
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
@@ -495,21 +507,27 @@ grab_media_key (MediaKey *key,
GsdMediaKeysManager *manager)
{
GrabData *data;
- char *tmp;
+ char *binding;
- 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 = 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
@@ -2804,6 +2822,11 @@ start_media_keys_idle_cb (GsdMediaKeysManager *manager)
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);
manager->priv->settings = g_settings_new (SETTINGS_BINDING_DIR);
@@ -2962,6 +2985,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) {