mirror of
https://github.com/labwc/labwc.git
synced 2025-11-03 09:01:51 -05:00
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:
<keybind key="C-S-h">
<action name="GoToDesktop" to="left" wrap="yes"/>
</keybind>
<keybind key="C-S-l">
<action name="GoToDesktop" to="right" wrap="yes"/>
</keybind>
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()`
This commit is contained in:
parent
ba76b26165
commit
2734302fd2
1 changed files with 15 additions and 4 deletions
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue