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.

    <windowRules>
      <windowRule identifier="blender" wantAbsorbedModifierReleaseEvents="yes"/>
    </windowRules>

Issue #1507
This commit is contained in:
Johan Malm 2024-11-26 20:02:36 +00:00 committed by GitHub
parent 665b39259a
commit 2f8afb2376
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 48 additions and 3 deletions

View file

@ -1055,6 +1055,18 @@ situation.
can be caused by *<margin>* settings or exclusive layer-shell clients
such as panels.
*<windowRules><windowRule wantAbsorbedModifierReleaseEvents="">* [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.
```
<windowRules>
<windowRule identifier="blender" wantAbsorbedModifierReleaseEvents="yes"/>
</windowRules>
```
## MENU
```

View file

@ -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 */
};

View file

@ -354,6 +354,8 @@ fill_window_rule(char *nodename, char *content)
set_property(content, &current_window_rule->ignore_configure_request);
} else if (!strcasecmp(nodename, "fixedPosition")) {
set_property(content, &current_window_rule->fixed_position);
} else if (!strcasecmp(nodename, "wantAbsorbedModifierReleaseEvents")) {
set_property(content, &current_window_rule->want_absorbed_modifier_release_events);
/* Actions */
} else if (!strcmp(nodename, "name.action")) {

View file

@ -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);
}
}

View file

@ -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;