From: Johan Malm Date: Tue, 14 Nov 2023 18:57:40 +0000 (+0000) Subject: keyboard: fix key repeat bug on surface focus change X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=2734302fd2e2571102e075bb97738a952a46b856;p=proto%2Flabwc.git keyboard: fix key repeat bug on surface focus change The bug can be reproduced by using the following keybinds and then taking the steps below with an XWayland client, for example xterm: 1. Press C-S-h 2. Press C-S-l 3. Observe llllllll.... in xterm Store the key-state in `handle_keybind()` before any call to `action_run()` as this may lead to `seat_focus()` which passes 'pressed-sent' keys to the new surface. This partially reverts 7571c4b, which as a standalone commit was fine, but when 'pressed_mods' were then included in 'bound' in 98bf316, `key_state_store_pressed_keys_as_bound()` was again required in `handle_keybind()` to ensure modifers are not passed as non-modifiers in `wlr_seat_keyboard_notify_enter()` in `seat_focus()` --- diff --git a/src/input/keyboard.c b/src/input/keyboard.c index 078209a6..14b6864c 100644 --- a/src/input/keyboard.c +++ b/src/input/keyboard.c @@ -90,6 +90,8 @@ keyboard_modifiers_notify(struct wl_listener *listener, void *data) static bool handle_keybinding(struct server *server, uint32_t modifiers, xkb_keysym_t sym, xkb_keycode_t code) { + uint32_t evdev_scancode = code - 8; + struct keybind *keybind; wl_list_for_each(keybind, &rc.keybinds, link) { if (modifiers ^ keybind->modifiers) { @@ -104,7 +106,14 @@ handle_keybinding(struct server *server, uint32_t modifiers, xkb_keysym_t sym, x if (sym == XKB_KEY_NoSymbol) { /* Use keycodes */ for (size_t i = 0; i < keybind->keycodes_len; i++) { + /* + * 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. + */ if (keybind->keycodes[i] == code) { + key_state_store_pressed_key_as_bound(evdev_scancode); actions_run(NULL, server, &keybind->actions, 0); return true; } @@ -113,6 +122,7 @@ handle_keybinding(struct server *server, uint32_t modifiers, xkb_keysym_t sym, x /* Use syms */ for (size_t i = 0; i < keybind->keysyms_len; i++) { if (xkb_keysym_to_lower(sym) == keybind->keysyms[i]) { + key_state_store_pressed_key_as_bound(evdev_scancode); actions_run(NULL, server, &keybind->actions, 0); return true; } @@ -308,10 +318,10 @@ handle_compositor_keybindings(struct keyboard *keyboard, if (server->input_mode == LAB_INPUT_STATE_MENU) { if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { + key_state_store_pressed_key_as_bound(event->keycode); handle_menu_keys(server, &translated); } - handled = true; - goto out; + return true; } if (server->osd_state.cycle_view) { @@ -381,7 +391,7 @@ handle_compositor_keybindings(struct keyboard *keyboard, handled |= handle_keybinding(server, modifiers, XKB_KEY_NoSymbol, keycode); if (handled) { wlr_log(WLR_DEBUG, "keycodes matched"); - goto out; + return true; } /* Then fall back to keysyms */ @@ -391,7 +401,7 @@ handle_compositor_keybindings(struct keyboard *keyboard, } if (handled) { wlr_log(WLR_DEBUG, "translated keysyms matched"); - goto out; + return true; } /* And finally test for keysyms without modifier */ @@ -400,6 +410,7 @@ handle_compositor_keybindings(struct keyboard *keyboard, } if (handled) { wlr_log(WLR_DEBUG, "raw keysyms matched"); + return true; } }