From 1a9885aa52151dd239d6dea46e3c6890148e4d30 Mon Sep 17 00:00:00 2001 From: Simon Long Date: Fri, 26 Apr 2024 11:05:12 +0100 Subject: [PATCH 1/5] Only respond to modifier-only keybindings on release --- include/config/keybind.h | 1 + include/input/keyboard.h | 1 + src/config/keybind.c | 3 +++ src/input/keyboard.c | 24 +++++++++++++++++------- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/include/config/keybind.h b/include/config/keybind.h index c61392aa..139442e5 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 mod_only; /* set if only modifier keys used */ }; /** diff --git a/include/input/keyboard.h b/include/input/keyboard.h index ff4fbe60..c44d12b3 100644 --- a/include/input/keyboard.h +++ b/include/input/keyboard.h @@ -20,5 +20,6 @@ void keyboard_set_numlock(struct wlr_keyboard *keyboard); void keyboard_update_layout(struct seat *seat, xkb_layout_index_t layout); void keyboard_cancel_keybind_repeat(struct keyboard *keyboard); bool keyboard_any_modifiers_pressed(struct wlr_keyboard *keyboard); +bool keyboard_is_modifier_key(xkb_keysym_t sym); #endif /* LABWC_KEYBOARD_H */ diff --git a/src/config/keybind.c b/src/config/keybind.c index 1de02513..1b060cc5 100644 --- a/src/config/keybind.c +++ b/src/config/keybind.c @@ -10,6 +10,7 @@ #include "common/mem.h" #include "config/keybind.h" #include "config/rcxml.h" +#include "input/keyboard.h" #include "labwc.h" uint32_t @@ -122,6 +123,7 @@ keybind_create(const char *keybind) struct keybind *k = znew(*k); xkb_keysym_t keysyms[MAX_KEYSYMS]; gchar **symnames = g_strsplit(keybind, "-", -1); + k->mod_only = TRUE; for (size_t i = 0; symnames[i]; i++) { char *symname = symnames[i]; uint32_t modifier = parse_modifier(symname); @@ -129,6 +131,7 @@ keybind_create(const char *keybind) k->modifiers |= modifier; } else { sym = xkb_keysym_from_name(symname, XKB_KEYSYM_CASE_INSENSITIVE); + if (!keyboard_is_modifier_key (sym)) k->mod_only = FALSE; if (sym == XKB_KEY_NoSymbol && g_utf8_strlen(symname, -1) == 1) { /* * xkb_keysym_from_name() only handles a legacy set of single diff --git a/src/input/keyboard.c b/src/input/keyboard.c index 59761681..46152590 100644 --- a/src/input/keyboard.c +++ b/src/input/keyboard.c @@ -38,6 +38,8 @@ struct keyinfo { static bool should_cancel_cycling_on_next_key_release; +struct keybind *cur_keybind = NULL; + static void change_vt(struct server *server, unsigned int vt) { @@ -207,8 +209,8 @@ process_syms: return NULL; } -static bool -is_modifier_key(xkb_keysym_t sym) +bool +keyboard_is_modifier_key(xkb_keysym_t sym) { switch (sym) { case XKB_KEY_Shift_L: case XKB_KEY_Shift_R: @@ -273,7 +275,7 @@ get_keyinfo(struct wlr_keyboard *wlr_keyboard, uint32_t evdev_keycode) keyinfo.is_modifier = false; for (int i = 0; i < keyinfo.translated.nr_syms; i++) { keyinfo.is_modifier |= - is_modifier_key(keyinfo.translated.syms[i]); + keyboard_is_modifier_key(keyinfo.translated.syms[i]); } return keyinfo; @@ -407,7 +409,14 @@ 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->mod_only) { + key_state_store_pressed_key_as_bound(event->keycode); + 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 +452,17 @@ handle_compositor_keybindings(struct keyboard *keyboard, /* * Handle compositor keybinds */ - struct keybind *keybind = + cur_keybind = match_keybinding(server, &keyinfo, keyboard->is_virtual); - if (keybind) { + if (cur_keybind && !cur_keybind->mod_only) { /* * 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); + actions_run(NULL, server, &cur_keybind->actions, 0); + cur_keybind = NULL; return true; } From 5e6f9285aa6c47bfd061d269888abab228372a2a Mon Sep 17 00:00:00 2001 From: Simon Long Date: Fri, 26 Apr 2024 11:13:25 +0100 Subject: [PATCH 2/5] Code style --- src/config/keybind.c | 4 +++- src/input/keyboard.c | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/config/keybind.c b/src/config/keybind.c index 1b060cc5..894ddf94 100644 --- a/src/config/keybind.c +++ b/src/config/keybind.c @@ -131,7 +131,9 @@ keybind_create(const char *keybind) k->modifiers |= modifier; } else { sym = xkb_keysym_from_name(symname, XKB_KEYSYM_CASE_INSENSITIVE); - if (!keyboard_is_modifier_key (sym)) k->mod_only = FALSE; + if (!keyboard_is_modifier_key(sym)) { + k->mod_only = FALSE; + } if (sym == XKB_KEY_NoSymbol && g_utf8_strlen(symname, -1) == 1) { /* * xkb_keysym_from_name() only handles a legacy set of single diff --git a/src/input/keyboard.c b/src/input/keyboard.c index 46152590..f7b70e74 100644 --- a/src/input/keyboard.c +++ b/src/input/keyboard.c @@ -38,7 +38,7 @@ struct keyinfo { static bool should_cancel_cycling_on_next_key_release; -struct keybind *cur_keybind = NULL; +struct keybind *cur_keybind; static void change_vt(struct server *server, unsigned int vt) From 8c6379cb599b6a21d9a57d397cfdecdd984e9b39 Mon Sep 17 00:00:00 2001 From: Simon Long Date: Fri, 26 Apr 2024 11:22:45 +0100 Subject: [PATCH 3/5] Fix warning --- src/config/keybind.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/config/keybind.c b/src/config/keybind.c index 894ddf94..c0d8362a 100644 --- a/src/config/keybind.c +++ b/src/config/keybind.c @@ -122,8 +122,8 @@ keybind_create(const char *keybind) xkb_keysym_t sym; struct keybind *k = znew(*k); xkb_keysym_t keysyms[MAX_KEYSYMS]; + bool mod_only = TRUE; gchar **symnames = g_strsplit(keybind, "-", -1); - k->mod_only = TRUE; for (size_t i = 0; symnames[i]; i++) { char *symname = symnames[i]; uint32_t modifier = parse_modifier(symname); @@ -132,7 +132,7 @@ keybind_create(const char *keybind) } else { sym = xkb_keysym_from_name(symname, XKB_KEYSYM_CASE_INSENSITIVE); if (!keyboard_is_modifier_key(sym)) { - k->mod_only = FALSE; + mod_only = FALSE; } if (sym == XKB_KEY_NoSymbol && g_utf8_strlen(symname, -1) == 1) { /* @@ -168,6 +168,7 @@ keybind_create(const char *keybind) if (!k) { return NULL; } + k->mod_only = mod_only; wl_list_append(&rc.keybinds, &k->link); k->keysyms = xmalloc(k->keysyms_len * sizeof(xkb_keysym_t)); memcpy(k->keysyms, keysyms, k->keysyms_len * sizeof(xkb_keysym_t)); From 522897d5afcb60e16eea5fd571eaf260f2f1de5e Mon Sep 17 00:00:00 2001 From: Simon Long Date: Fri, 26 Apr 2024 15:36:02 +0100 Subject: [PATCH 4/5] Prevent key release bindings running when session locked --- src/input/keyboard.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/input/keyboard.c b/src/input/keyboard.c index f7b70e74..e43d2655 100644 --- a/src/input/keyboard.c +++ b/src/input/keyboard.c @@ -410,6 +410,11 @@ handle_compositor_keybindings(struct keyboard *keyboard, if (event->state == WL_KEYBOARD_KEY_STATE_RELEASED) { if (cur_keybind && cur_keybind->mod_only) { + if (seat->active_client_while_inhibited + || seat->server->session_lock) { + cur_keybind = NULL; + return false; + } key_state_store_pressed_key_as_bound(event->keycode); actions_run(NULL, server, &cur_keybind->actions, 0); cur_keybind = NULL; From fe5704d40398e29c05087e282df3cfd7dc0402e4 Mon Sep 17 00:00:00 2001 From: Simon Long Date: Mon, 29 Apr 2024 07:52:04 +0100 Subject: [PATCH 5/5] Only store key state on press --- src/input/keyboard.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/input/keyboard.c b/src/input/keyboard.c index e43d2655..11fe0181 100644 --- a/src/input/keyboard.c +++ b/src/input/keyboard.c @@ -415,7 +415,6 @@ handle_compositor_keybindings(struct keyboard *keyboard, cur_keybind = NULL; return false; } - key_state_store_pressed_key_as_bound(event->keycode); actions_run(NULL, server, &cur_keybind->actions, 0); cur_keybind = NULL; return true; @@ -459,15 +458,17 @@ handle_compositor_keybindings(struct keyboard *keyboard, */ cur_keybind = match_keybinding(server, &keyinfo, keyboard->is_virtual); - if (cur_keybind && !cur_keybind->mod_only) { + 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, &cur_keybind->actions, 0); - cur_keybind = NULL; + if (!cur_keybind->mod_only) { + actions_run(NULL, server, &cur_keybind->actions, 0); + cur_keybind = NULL; + } return true; }