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;