From 11a4d56185d3a951b9f6fc4265c4c29fd7d21038 Mon Sep 17 00:00:00 2001 From: dcz Date: Sun, 31 Mar 2024 14:09:56 +0000 Subject: [PATCH] keybindings: Send trigger when a key accelerator is deactivated This is neccessary to support the GlobalShortcuts portal which demands Deactivate events. https://gitlab.gnome.org/GNOME/xdg-desktop-portal-gnome/-/issues/47 Part-of: --- src/core/display-private.h | 3 +++ src/core/display.c | 20 +++++++++++++++ src/core/keybindings-private.h | 2 ++ src/core/keybindings.c | 47 +++++++++++++++++++++++++++------- src/meta/prefs.h | 2 ++ 5 files changed, 65 insertions(+), 9 deletions(-) diff --git a/src/core/display-private.h b/src/core/display-private.h index 9bb6c4493..19926d383 100644 --- a/src/core/display-private.h +++ b/src/core/display-private.h @@ -254,6 +254,9 @@ void meta_display_overlay_key_activate (MetaDisplay *display); void meta_display_accelerator_activate (MetaDisplay *display, guint action, const ClutterKeyEvent *event); +void meta_display_accelerator_deactivate (MetaDisplay *display, + guint action, + const ClutterKeyEvent *event); gboolean meta_display_modifiers_accelerator_activate (MetaDisplay *display); void meta_display_update_focus_window (MetaDisplay *display, diff --git a/src/core/display.c b/src/core/display.c index 4fd4deae5..8a2cc7490 100644 --- a/src/core/display.c +++ b/src/core/display.c @@ -156,6 +156,7 @@ enum X11_DISPLAY_CLOSING, OVERLAY_KEY, ACCELERATOR_ACTIVATED, + ACCELERATOR_DEACTIVATED, MODIFIERS_ACCELERATOR_ACTIVATED, FOCUS_WINDOW, WINDOW_CREATED, @@ -330,6 +331,14 @@ meta_display_class_init (MetaDisplayClass *klass) NULL, NULL, NULL, G_TYPE_NONE, 3, G_TYPE_UINT, CLUTTER_TYPE_INPUT_DEVICE, G_TYPE_UINT); + display_signals[ACCELERATOR_DEACTIVATED] = + g_signal_new ("accelerator-deactivated", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, NULL, + G_TYPE_NONE, 3, G_TYPE_UINT, CLUTTER_TYPE_INPUT_DEVICE, G_TYPE_UINT); + /** * MetaDisplay::modifiers-accelerator-activated: * @display: the #MetaDisplay instance @@ -2528,6 +2537,17 @@ meta_display_accelerator_activate (MetaDisplay *display, clutter_event_get_time ((const ClutterEvent *) event)); } +void +meta_display_accelerator_deactivate (MetaDisplay *display, + guint action, + const ClutterKeyEvent *event) +{ + g_signal_emit (display, display_signals[ACCELERATOR_DEACTIVATED], 0, + action, + clutter_event_get_source_device ((const ClutterEvent *) event), + clutter_event_get_time ((const ClutterEvent *) event)); +} + gboolean meta_display_modifiers_accelerator_activate (MetaDisplay *display) { diff --git a/src/core/keybindings-private.h b/src/core/keybindings-private.h index 81ee7a32a..bf21bc1b4 100644 --- a/src/core/keybindings-private.h +++ b/src/core/keybindings-private.h @@ -71,6 +71,8 @@ struct _MetaKeyBinding MetaKeyCombo combo; MetaResolvedKeyCombo resolved_combo; gint flags; + /* The binding should respond to release, and was just pressed */ + gboolean release_pending; MetaKeyHandler *handler; }; diff --git a/src/core/keybindings.c b/src/core/keybindings.c index e91978219..51ebd432e 100644 --- a/src/core/keybindings.c +++ b/src/core/keybindings.c @@ -1698,7 +1698,10 @@ handle_external_grab (MetaDisplay *display, { MetaKeyBindingManager *keys = &display->key_binding_manager; guint action = get_keybinding_action (keys, &binding->resolved_combo); - meta_display_accelerator_activate (display, action, event); + if (clutter_event_type ((ClutterEvent *) event) == CLUTTER_KEY_RELEASE) + meta_display_accelerator_deactivate (display, action, event); + else + meta_display_accelerator_activate (display, action, event); } @@ -1855,10 +1858,6 @@ process_event (MetaDisplay *display, MetaKeyBinding *binding; ClutterModifierType modifiers; - /* we used to have release-based bindings but no longer. */ - if (clutter_event_type ((ClutterEvent *) event) == CLUTTER_KEY_RELEASE) - return FALSE; - modifiers = get_modifiers ((ClutterEvent *) event); resolved_combo.mask = mask_from_event_params (keys, modifiers); @@ -1904,11 +1903,40 @@ process_event (MetaDisplay *display, return TRUE; } - meta_topic (META_DEBUG_KEYBINDINGS, - "Running handler for %s", - binding->name); + if (clutter_event_type ((ClutterEvent *) event) == CLUTTER_KEY_RELEASE) + { + if (binding->release_pending) + { + meta_topic (META_DEBUG_KEYBINDINGS, + "Running release handler for %s", + binding->name); - invoke_handler (display, binding->handler, window, event, binding); + invoke_handler (display, binding->handler, window, event, binding); + binding->release_pending = FALSE; + } + else + { + meta_topic (META_DEBUG_KEYBINDINGS, + "Ignore release for handler %s", + binding->name); + } + } + else + { + meta_topic (META_DEBUG_KEYBINDINGS, + "Running handler for %s", + binding->name); + + invoke_handler (display, binding->handler, window, event, binding); + if (!binding->release_pending && + ((binding->flags & META_KEY_BINDING_TRIGGER_RELEASE) != 0)) + { + meta_topic (META_DEBUG_KEYBINDINGS, + "Preparing release for handler %s", + binding->name); + binding->release_pending = TRUE; + } + } return TRUE; @@ -3260,6 +3288,7 @@ meta_display_init_keys (MetaDisplay *display) handler = g_new0 (MetaKeyHandler, 1); handler->name = g_strdup ("external-grab"); + handler->flags = META_KEY_BINDING_TRIGGER_RELEASE; handler->func = handle_external_grab; handler->default_func = handle_external_grab; g_ref_count_init (&handler->ref_count); diff --git a/src/meta/prefs.h b/src/meta/prefs.h index 1afc3dc2e..501165ffa 100644 --- a/src/meta/prefs.h +++ b/src/meta/prefs.h @@ -430,6 +430,7 @@ typedef enum _MetaKeyBindingAction * @META_KEY_BINDING_IGNORE_AUTOREPEAT: ignore autorepeat * @META_KEY_BINDING_NO_AUTO_GRAB: not grabbed automatically * @META_KEY_BINDING_CUSTOM_TRIGGER: uses a custom keybinding action + * @META_KEY_BINDING_TRIGGER_RELEASE: notifies on release in addition to press */ typedef enum { @@ -441,6 +442,7 @@ typedef enum META_KEY_BINDING_IGNORE_AUTOREPEAT = 1 << 4, META_KEY_BINDING_NO_AUTO_GRAB = 1 << 5, META_KEY_BINDING_CUSTOM_TRIGGER = 1 << 6, + META_KEY_BINDING_TRIGGER_RELEASE = 1 << 7, } MetaKeyBindingFlags; /**