If set to "no" (or is absent) the keybind will be layout agnostic.
Default is no.
+*<keyboard><keybind key="" onRelease="yes|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 key="Super_L" onRelease="yes">
+ <action name="Execute" command="rofi -show drun"/>
+ </keybind>
+ ```
+
*<keyboard><keybind key=""><action name="">*
Keybind action. See labwc-actions(5).
int keycodes_layout;
struct wl_list actions; /* struct action.link */
struct wl_list link; /* struct rcxml.keybinds */
+ bool on_release;
};
/**
struct keyboard;
struct wlr_keyboard;
+void keyboard_reset_current_keybind(void);
void keyboard_configure(struct seat *seat, struct wlr_keyboard *kb,
bool is_virtual);
} 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, ¤t_keybind->on_release);
} else if (!strcasecmp(nodename, "layoutDependent")) {
set_bool(content, ¤t_keybind->use_syms_only);
} else if (!strcmp(nodename, "name.action")) {
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)
{
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 */
/*
* 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;
}
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: