From: Simon Long Date: Fri, 26 Apr 2024 10:05:12 +0000 (+0100) Subject: Add onRelease option to X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=84c222a84f7e04c1282729d6c1376f334878666d;p=proto%2Flabwc.git Add onRelease option to ...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: If another keybind is issued between the press and release, the on-release keybind is cancelled. Co-authored-by: @johanmalm --- diff --git a/docs/labwc-config.5.scd b/docs/labwc-config.5.scd index 7d8982dc..4ab1a23e 100644 --- a/docs/labwc-config.5.scd +++ b/docs/labwc-config.5.scd @@ -492,6 +492,23 @@ extending outward from the snapped edge. If set to "no" (or is absent) the keybind will be layout agnostic. Default is no. +** + *onRelease*, when yes, fires the keybind action when the key or key + combination is released, rather than first pressed. This is useful to + bind actions to only modifier keys, where the action should fire when + the modifier is used without another key. Default is no. + + The example below will trigger the launch of rofi when the super key is + pressed & released, without interference from other multi-key + combinations that include the super key: + + + ``` + + + + ``` + ** Keybind action. See labwc-actions(5). diff --git a/include/config/keybind.h b/include/config/keybind.h index c61392aa..fc573316 100644 --- a/include/config/keybind.h +++ b/include/config/keybind.h @@ -20,6 +20,7 @@ struct keybind { int keycodes_layout; struct wl_list actions; /* struct action.link */ struct wl_list link; /* struct rcxml.keybinds */ + bool on_release; }; /** diff --git a/include/input/keyboard.h b/include/input/keyboard.h index ff4fbe60..ff2d8500 100644 --- a/include/input/keyboard.h +++ b/include/input/keyboard.h @@ -9,6 +9,7 @@ struct seat; struct keyboard; struct wlr_keyboard; +void keyboard_reset_current_keybind(void); void keyboard_configure(struct seat *seat, struct wlr_keyboard *kb, bool is_virtual); diff --git a/src/config/rcxml.c b/src/config/rcxml.c index 4f3db549..0a5d225d 100644 --- a/src/config/rcxml.c +++ b/src/config/rcxml.c @@ -403,6 +403,8 @@ fill_keybind(char *nodename, char *content) } else if (!current_keybind) { wlr_log(WLR_ERROR, "expect element first. " "nodename: '%s' content: '%s'", nodename, content); + } else if (!strcasecmp(nodename, "onRelease")) { + set_bool(content, ¤t_keybind->on_release); } else if (!strcasecmp(nodename, "layoutDependent")) { set_bool(content, ¤t_keybind->use_syms_only); } else if (!strcmp(nodename, "name.action")) { diff --git a/src/input/keyboard.c b/src/input/keyboard.c index 1d1467ce..6ba6ab23 100644 --- a/src/input/keyboard.c +++ b/src/input/keyboard.c @@ -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; } diff --git a/src/seat.c b/src/seat.c index 5b4afe59..5eca16a3 100644 --- a/src/seat.c +++ b/src/seat.c @@ -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: