Add onRelease option to <keybind>

...to make keybind actions fire on the release event rather then when the
key is first pressed. This is useful for binding actions to modifier keys
only. The most likely use-case for this is the binding of a Super key to a
menu, for example:

    <keybind key="Super_L" onRelease="yes">
      <action name="Execute" command="rofi -show drun"/>
    </keybind>

If another keybind is issued between the press and release, the on-release
keybind is cancelled.

Co-authored-by: @johanmalm
This commit is contained in:
Simon Long 2024-04-26 11:05:12 +01:00 committed by Johan Malm
parent f6c91c8d13
commit 84c222a84f
6 changed files with 51 additions and 5 deletions

View file

@ -38,6 +38,15 @@ struct keyinfo {
static bool should_cancel_cycling_on_next_key_release;
static struct keybind *cur_keybind;
/* Called on --reconfigure to prevent segfault when handling release keybinds */
void
keyboard_reset_current_keybind(void)
{
cur_keybind = NULL;
}
static void
change_vt(struct server *server, unsigned int vt)
{
@ -407,7 +416,19 @@ handle_compositor_keybindings(struct keyboard *keyboard,
keyinfo.is_modifier);
if (event->state == WL_KEYBOARD_KEY_STATE_RELEASED) {
return handle_key_release(server, event->keycode);
if (cur_keybind && cur_keybind->on_release) {
key_state_bound_key_remove(event->keycode);
if (seat->server->session_lock_manager->locked
|| seat->active_client_while_inhibited) {
cur_keybind = NULL;
return true;
}
actions_run(NULL, server, &cur_keybind->actions, 0);
cur_keybind = NULL;
return true;
} else {
return handle_key_release(server, event->keycode);
}
}
/* Catch C-A-F1 to C-A-F12 to change tty */
@ -443,16 +464,19 @@ handle_compositor_keybindings(struct keyboard *keyboard,
/*
* Handle compositor keybinds
*/
struct keybind *keybind =
match_keybinding(server, &keyinfo, keyboard->is_virtual);
if (keybind) {
cur_keybind = match_keybinding(server, &keyinfo, keyboard->is_virtual);
if (cur_keybind) {
/*
* Update key-state before action_run() because the action
* might lead to seat_focus() in which case we pass the
* 'pressed-sent' keys to the new surface.
*/
key_state_store_pressed_key_as_bound(event->keycode);
actions_run(NULL, server, &keybind->actions, 0);
if (!cur_keybind->on_release) {
actions_run(NULL, server, &cur_keybind->actions, 0);
/* This cancels any pending on-release keybinds */
cur_keybind = NULL;
}
return true;
}