exec release binding even if other keys were pressed

This commit changes the "release binding" behavior to ignore foreign
keypresses (pressed keys that are not part of a given release binding's
definition) while still triggering the bound action when the original
key from the binding is released. This, unless foreign keypresses match
a different release binding, in which case the latter binding takes
over.

For instance, assuming a release binding is configured for <Mod>, a key
corresponding to one of the possible modifier keys. The previous behavior
for the following sequence was to trigger the action only for the following
sequence:

- <Mod>(press), <Mod>(release)

but *not* in the following case:

- <Mod>(press), <Tab>(press), <Tab>(release), <Mod>(release)

With this commit both sequences trigger the bound action.

This is useful to control external software by triggering possibly
repeated actions, e.g. to navigate windows using <Mod> + <Tab>
and triggering a final action when the <Mod> key is released (e.g.
hiding a UI, reactivating LRU accounting, ...)

Closes #6456
This commit is contained in:
lostmythread 2022-03-27 12:18:40 +02:00
parent fb3330c1fb
commit c9a9a13c6e
2 changed files with 8 additions and 3 deletions

View file

@ -65,6 +65,7 @@ struct sway_keyboard {
struct sway_shortcut_state state_keycodes;
struct sway_shortcut_state state_pressed_sent;
struct sway_binding *held_binding;
uint32_t held_keycode;
struct wl_event_source *key_repeat_source;
struct sway_binding *repeat_binding;

View file

@ -441,17 +441,21 @@ static void handle_key_event(struct sway_keyboard *keyboard,
shortcuts_inhibited, device_identifier,
exact_identifier, keyboard->effective_layout);
// Execute stored release binding once no longer active
if (keyboard->held_binding && binding_released != keyboard->held_binding &&
// Execute stored release binding when the key is released
if (keyboard->held_binding &&
keyinfo.keycode == keyboard->held_keycode &&
event->state == WL_KEYBOARD_KEY_STATE_RELEASED) {
seat_execute_command(seat, keyboard->held_binding);
handled = true;
}
if (binding_released != keyboard->held_binding) {
if (handled ||
(binding_released && binding_released != keyboard->held_binding)) {
keyboard->held_binding = NULL;
keyboard->held_keycode = 0;
}
if (binding_released && event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
keyboard->held_binding = binding_released;
keyboard->held_keycode = keyinfo.keycode;
}
// Identify and execute active pressed binding