diff options
author | Rui Matos <tiagomatos@gmail.com> | 2017-02-13 17:53:48 +0100 |
---|---|---|
committer | Bastien Nocera <hadess@hadess.net> | 2017-02-14 17:22:58 +0100 |
commit | bfb7255ddccb7d88c49b3eef60dcdd8dac1edede (patch) | |
tree | 2d3856655ddf1ca1c89e894147af6e416fb1ea3e | |
parent | 6028195d9a3e2f57e85d9a521b3ead3f307ca27e (diff) | |
download | gnome-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.c | 36 |
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) { |