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

@ -403,6 +403,8 @@ fill_keybind(char *nodename, char *content)
} else if (!current_keybind) {
wlr_log(WLR_ERROR, "expect <keybind key=\"\"> element first. "
"nodename: '%s' content: '%s'", nodename, content);
} else if (!strcasecmp(nodename, "onRelease")) {
set_bool(content, &current_keybind->on_release);
} else if (!strcasecmp(nodename, "layoutDependent")) {
set_bool(content, &current_keybind->use_syms_only);
} else if (!strcmp(nodename, "name.action")) {

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

View file

@ -592,6 +592,7 @@ seat_reconfigure(struct server *server)
struct input *input;
cursor_reload(seat);
overlay_reconfigure(seat);
keyboard_reset_current_keybind();
wl_list_for_each(input, &seat->inputs, link) {
switch (input->wlr_input_device->type) {
case WLR_INPUT_DEVICE_KEYBOARD: