From 2f8afb2376cfa8eeb89fc5afffa869be68d3988e Mon Sep 17 00:00:00 2001 From: Johan Malm Date: Tue, 26 Nov 2024 20:02:36 +0000 Subject: [PATCH] keyboard: add window rule to send release-events (#2377) ...of modifiers which are part of keybinds. This supports clients (for example blender) that want to see modifier-release-events even if they are part of a keybinds. Most clients (including those using Qt and GTK) are setup to not see these modifier release events and actually misbehave if they do. For example Firefox shows the menu bar if alt is pressed and then released, whereas if only pressed (because the release is absorbed) nothing happens. So, if Firefox saw bound modifier-release-events it would show the menu bar every time the window-switcher is used with alt-tab. Issue #1507 --- docs/labwc-config.5.scd | 12 ++++++++++++ include/window-rules.h | 1 + src/config/rcxml.c | 2 ++ src/input/keyboard.c | 31 ++++++++++++++++++++++++++++--- src/window-rules.c | 5 +++++ 5 files changed, 48 insertions(+), 3 deletions(-) diff --git a/docs/labwc-config.5.scd b/docs/labwc-config.5.scd index 5925a007..878ab60b 100644 --- a/docs/labwc-config.5.scd +++ b/docs/labwc-config.5.scd @@ -1055,6 +1055,18 @@ situation. can be caused by ** settings or exclusive layer-shell clients such as panels. +** [yes|no|default] + *wantAbsorbedModifierReleaseEvents* allows clients to receive modifier + release events even if they are part of keybinds. Most clients should + not receive these, but some (for example blender) need it in some + situations. + +``` + + + +``` + ## MENU ``` diff --git a/include/window-rules.h b/include/window-rules.h index b93bc367..30abfddb 100644 --- a/include/window-rules.h +++ b/include/window-rules.h @@ -38,6 +38,7 @@ struct window_rule { enum property ignore_focus_request; enum property ignore_configure_request; enum property fixed_position; + enum property want_absorbed_modifier_release_events; struct wl_list link; /* struct rcxml.window_rules */ }; diff --git a/src/config/rcxml.c b/src/config/rcxml.c index 84708664..eeb9d681 100644 --- a/src/config/rcxml.c +++ b/src/config/rcxml.c @@ -354,6 +354,8 @@ fill_window_rule(char *nodename, char *content) set_property(content, ¤t_window_rule->ignore_configure_request); } else if (!strcasecmp(nodename, "fixedPosition")) { set_property(content, ¤t_window_rule->fixed_position); + } else if (!strcasecmp(nodename, "wantAbsorbedModifierReleaseEvents")) { + set_property(content, ¤t_window_rule->want_absorbed_modifier_release_events); /* Actions */ } else if (!strcmp(nodename, "name.action")) { diff --git a/src/input/keyboard.c b/src/input/keyboard.c index f0ceb7da..cef86bbf 100644 --- a/src/input/keyboard.c +++ b/src/input/keyboard.c @@ -15,6 +15,7 @@ #include "osd.h" #include "regions.h" #include "view.h" +#include "window-rules.h" #include "workspaces.h" enum lab_key_handled { @@ -363,7 +364,8 @@ get_keyinfo(struct wlr_keyboard *wlr_keyboard, uint32_t evdev_keycode) } static bool -handle_key_release(struct server *server, uint32_t evdev_keycode) +handle_key_release(struct server *server, uint32_t evdev_keycode, + bool is_modifier_key) { /* * Release events for keys that were not bound should always be @@ -386,11 +388,33 @@ handle_key_release(struct server *server, uint32_t evdev_keycode) end_cycling(server); } + key_state_bound_key_remove(evdev_keycode); + + /* + * There are some clients (for example blender) that want to see the + * modifier-release-event even if it was part of a keybinds. This is + * treated as a special case and can only be achieved by configuration. + * + * Most clients (including those using Qt and GTK) are setup to not see + * these modifier release events - and actually misbehave if they do. + * For example Firefox shows the menu bar if alt is pressed and then + * released, whereas if only pressed (because the release is absorbed) + * nothing happens. So, if Firefox saw bound modifier-release-events it + * would show the menu bar every time the window-switcher is used with + * alt-tab. + */ + struct view *view = server->active_view; + if (is_modifier_key && view) { + if (window_rules_get_property(view, "wantAbsorbedModifierReleaseEvents") + == LAB_PROP_TRUE) { + return false; + } + } + /* * If a press event was handled by a compositor binding, then do * not forward the corresponding release event to clients. */ - key_state_bound_key_remove(evdev_keycode); return true; } @@ -525,7 +549,8 @@ handle_compositor_keybindings(struct keyboard *keyboard, actions_run(NULL, server, &cur_keybind->actions, NULL); return true; } else { - return handle_key_release(server, event->keycode); + return handle_key_release(server, event->keycode, + keyinfo.is_modifier); } } diff --git a/src/window-rules.c b/src/window-rules.c index 0f4f1952..7c88865f 100644 --- a/src/window-rules.c +++ b/src/window-rules.c @@ -108,6 +108,11 @@ window_rules_get_property(struct view *view, const char *property) && !strcasecmp(property, "fixedPosition")) { return rule->fixed_position; } + if (rule->want_absorbed_modifier_release_events + && !strcasecmp(property, + "wantAbsorbedModifierReleaseEvents")) { + return rule->want_absorbed_modifier_release_events; + } } } return LAB_PROP_UNSPECIFIED;