]> git.mdlowis.com Git - proto/labwc.git/commitdiff
keyboard: make keybind match stricter
authorJohan Malm <jgm323@gmail.com>
Tue, 26 Sep 2023 16:51:54 +0000 (17:51 +0100)
committerJohan Malm <johanmalm@users.noreply.github.com>
Wed, 27 Sep 2023 20:34:28 +0000 (21:34 +0100)
...and avoid failing to send release events to clients for any keys that were
not absorbed by a keybind.

Do not match keybinds if there are other non-modifier keys (not part of any
defined bind) pressed at the same time.

Only store non-modifier keycodes in the key-state.c 'pressed' array.
This makes the call to wlr_seat_keyboard_notify_enter() in seat_focus()
consistent with the equivalent in sway (in seat_keyboard_notify_enter()).

Fixes: issue #1091
include/key-state.h
src/key-state.c
src/keyboard.c

index a45b349497e64a5dfd90ab2c030f1ffd862d2f56..fd029881bb93fd553db3a684967095d5e31b803b 100644 (file)
@@ -21,5 +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_keys(void);
+int key_state_nr_pressed_keys(void);
 
 #endif /* LABWC_KEY_STATE_H */
index f95d480c2dd2ea72b55c69d8adb79f1f126d09aa..06e193a74ce8155466825128dc4ae1ac147cab31 100644 (file)
@@ -102,3 +102,9 @@ key_state_nr_keys(void)
 {
        return bound.nr_keys;
 }
+
+int
+key_state_nr_pressed_keys(void)
+{
+       return pressed.nr_keys;
+}
index 0d5b4c2afb81746247371c3fb440e3bb8fe77100..73b8c9febb47fa3b8df2842a86cab9cb1c0ca469 100644 (file)
@@ -203,8 +203,34 @@ handle_compositor_keybindings(struct keyboard *keyboard,
 
        bool handled = false;
 
-       key_state_set_pressed(event->keycode,
-               event->state == WL_KEYBOARD_KEY_STATE_PRESSED);
+       /*
+        * keyboard_key_notify() is called before keyboard_key_modifier(), so
+        * 'modifiers' refers to modifiers that were pressed before the key
+        * event in hand. Consequently, we use is_modifier_key() to find out if
+        * the key event being processed is a modifier.
+        *
+        * Sway solves this differently by saving the 'modifiers' state and
+        * checking if it has changed each time we get to the equivalent of this
+        * function. If it has changed, it concludes that the last key was a
+        * modifier and then deletes it from the buffer of pressed keycodes.
+        * For us the equivalent would look something like this:
+        *
+        * static uint32_t last_modifiers;
+        * bool last_key_was_a_modifier = last_modifiers != modifiers;
+        * last_modifiers = modifiers;
+        * if (last_key_was_a_modifier) {
+        *      key_state_remove_last_pressed_key(last_pressed_keycode);
+        * }
+        */
+
+       bool ismodifier = false;
+       for (int i = 0; i < translated.nr_syms; i++) {
+               ismodifier |= is_modifier_key(translated.syms[i]);
+       }
+       if (!ismodifier) {
+               key_state_set_pressed(event->keycode,
+                       event->state == WL_KEYBOARD_KEY_STATE_PRESSED);
+       }
 
        /*
         * Ignore labwc keybindings if input is inhibited
@@ -293,13 +319,7 @@ handle_compositor_keybindings(struct keyboard *keyboard,
 
                        /* cycle to next */
                        bool backwards = modifiers & WLR_MODIFIER_SHIFT;
-                       /* ignore if this is a modifier key being pressed */
-                       bool ignore = false;
-                       for (int i = 0; i < translated.nr_syms; i++) {
-                               ignore |= is_modifier_key(translated.syms[i]);
-                       }
-
-                       if (!ignore) {
+                       if (!ismodifier) {
                                enum lab_cycle_dir dir = backwards
                                        ? LAB_CYCLE_DIR_BACKWARD
                                        : LAB_CYCLE_DIR_FORWARD;
@@ -313,6 +333,19 @@ handle_compositor_keybindings(struct keyboard *keyboard,
                goto out;
        }
 
+       /*
+        * A keybind is not considered valid if other keys are pressed at the
+        * same time.
+        *
+        * In labwc, a keybind is defined by one/many modifier keys + _one_
+        * non-modifier key. Returning early on >1 pressed non-modifier keys
+        * avoids false positive matches where 'other' keys were pressed at the
+        * same time.
+        */
+       if (key_state_nr_pressed_keys() > 1) {
+               return false;
+       }
+
        /*
         * Handle compositor keybinds
         *