mirror of
https://github.com/labwc/labwc.git
synced 2025-10-29 05:40:24 -04:00
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:
parent
f6c91c8d13
commit
84c222a84f
6 changed files with 51 additions and 5 deletions
|
|
@ -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.
|
||||
|
||||
*<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).
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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, ¤t_keybind->on_release);
|
||||
} else if (!strcasecmp(nodename, "layoutDependent")) {
|
||||
set_bool(content, ¤t_keybind->use_syms_only);
|
||||
} else if (!strcmp(nodename, "name.action")) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue