From ce8420d97897908284929505e8144ad3a9cc9e47 Mon Sep 17 00:00:00 2001 From: Johan Malm Date: Sun, 29 Oct 2023 22:14:48 +0000 Subject: [PATCH] key-state: make nr-pressed-keys check more accurate ...to avoid counting keys which never send release events and thus disable all keybinds. We do not want to match keybinds if additional 'normal' (non-modifiers) are pressed at the samet time. We must ignore keys which do not send release events such as XKB_KEY_ISO_Next_Group and XKB_KEY_XF86WakeUP. Issue #1208 --- include/key-state.h | 2 +- src/key-state.c | 36 +++++++++++++++++++++++++++++++++--- src/keyboard.c | 2 +- 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/include/key-state.h b/include/key-state.h index 71a3eb63..538319e5 100644 --- a/include/key-state.h +++ b/include/key-state.h @@ -21,6 +21,6 @@ void key_state_store_pressed_keys_as_bound(void); bool key_state_corresponding_press_event_was_bound(uint32_t keycode); void key_state_bound_key_remove(uint32_t keycode); int key_state_nr_bound_keys(void); -int key_state_nr_pressed_keys(void); +bool key_state_multiple_normal_keys_pressed(void); #endif /* LABWC_KEY_STATE_H */ diff --git a/src/key-state.c b/src/key-state.c index 945ea6c6..0eb862d0 100644 --- a/src/key-state.c +++ b/src/key-state.c @@ -103,8 +103,38 @@ key_state_nr_bound_keys(void) return bound.nr_keys; } -int -key_state_nr_pressed_keys(void) +/* + * Reference: + * https://github.com/xkbcommon/libxkbcommon/blob/HEAD/include/xkbcommon/xkbcommon-keysyms.h + */ +bool +key_state_multiple_normal_keys_pressed(void) { - return pressed.nr_keys; + if (pressed.nr_keys < 2) { + return false; + } + + /* + * If the pressed array contains multiple keys, we have to analyze a bit + * further because some keys like those listed below do not always + * receive release events. + * - XKB_KEY_ISO_Group_Next + * - XKB_KEY_XF86WakeUp + * - XKB_KEY_XF86Suspend + * - XKB_KEY_XF86Hibernate + */ + size_t count = 0; + for (int i = 0; i < pressed.nr_keys; ++i) { + /* Convert from udev event to xkbcommon code */ + uint32_t keycode = pressed.keys[i] + 8; + if (keycode >= 0x1000000) { + /* XFree86 vendor specific keysyms */ + continue; + } else if (keycode >= 0xFE00 && keycode <= 0xFEFF) { + /* Extension function and modifier keys */ + continue; + } + ++count; + } + return count > 1; } diff --git a/src/keyboard.c b/src/keyboard.c index 2d6cae7c..e3bec27e 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -361,7 +361,7 @@ handle_compositor_keybindings(struct keyboard *keyboard, * avoids false positive matches where 'other' keys were pressed at the * same time. */ - if (key_state_nr_pressed_keys() > 1) { + if (key_state_multiple_normal_keys_pressed()) { return false; }