From 9209adf6faa1222d9a60b63e69eadd04820976db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 3 Nov 2020 19:44:51 +0100 Subject: [PATCH] =?UTF-8?q?input:=20don=E2=80=99t=20use=20seat->kbd=5Ffocu?= =?UTF-8?q?s=20as=20terminal=20when=20processing=20a=20key=20press?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When converting mouse scroll events to keyboard input (in alternate scroll mode), we need to use seat->mouse_focus, not seat->kbd_focus. To enable this, break out key press/release handling code to a separate function that takes an explicit term argument. Call this function from keyboard_key(), input_repeat() and in alternate scroll mode. Closes #179 --- CHANGELOG.md | 2 ++ input.c | 40 +++++++++++++++++++++++++--------------- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e31c396..7e0c8aaf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -73,6 +73,8 @@ * Compilation error _"overflow in conversion from long 'unsigned int' to 'int' changes value... "_ seen on platforms where the `request` argument in `ioctl(3)` is an `int` (for example: linux/ppc64). +* Crash when using the mouse in alternate scroll mode in an unfocused + window (https://codeberg.org/dnkl/foot/issues/179). ### Security diff --git a/input.c b/input.c index 0de94391..8140e250 100644 --- a/input.c +++ b/input.c @@ -748,12 +748,9 @@ keymap_lookup(struct terminal *term, xkb_keysym_t sym, enum modifier mods) } static void -keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, - uint32_t time, uint32_t key, uint32_t state) +key_press_release(struct seat *seat, struct terminal *term, uint32_t serial, + uint32_t key, uint32_t state) { - struct seat *seat = data; - struct terminal *term = seat->kbd_focus; - if (seat->kbd.xkb == NULL || seat->kbd.xkb_keymap == NULL || seat->kbd.xkb_state == NULL) @@ -761,8 +758,6 @@ keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, return; } - assert(term != NULL); - const xkb_mod_mask_t ctrl = 1 << seat->kbd.mod_ctrl; const xkb_mod_mask_t alt = 1 << seat->kbd.mod_alt; const xkb_mod_mask_t shift = 1 << seat->kbd.mod_shift; @@ -773,7 +768,6 @@ keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, return; } - key += 8; bool should_repeat = xkb_keymap_key_repeats(seat->kbd.xkb_keymap, key); xkb_keysym_t sym = xkb_state_key_get_one_sym(seat->kbd.xkb_state, key); @@ -819,7 +813,7 @@ keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, if (term->is_searching) { if (should_repeat) - start_repeater(seat, key - 8); + start_repeater(seat, key); search_input(seat, term, key, sym, effective_mods, serial); return; } @@ -832,10 +826,10 @@ keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, } #endif - LOG_DBG("keyboard_key: keyboard=%p, serial=%u, " + LOG_DBG("seat: %s, term=%p, serial=%u, " "sym=%u, mod=0x%08x, consumed=0x%08x, significant=0x%08x, " "effective=0x%08x, repeats=%d", - (void *)wl_keyboard, serial, + seat->name, (void *)term, serial, sym, mods, consumed, significant, effective_mods, should_repeat); /* @@ -1001,7 +995,15 @@ maybe_repeat: term->wl->presentation_clock_id, &term->render.input_time); if (should_repeat) - start_repeater(seat, key - 8); + start_repeater(seat, key); +} + +static void +keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, + uint32_t time, uint32_t key, uint32_t state) +{ + struct seat *seat = data; + key_press_release(seat, seat->kbd_focus, serial, key + 8, state); } static void @@ -1055,7 +1057,11 @@ const struct wl_keyboard_listener keyboard_listener = { void input_repeat(struct seat *seat, uint32_t key) { - keyboard_key(seat, NULL, seat->kbd.serial, 0, key, XKB_KEY_DOWN); + /* Should be cleared as soon as we loose focus */ + assert(seat->kbd_focus != NULL); + struct terminal *term = seat->kbd_focus; + + key_press_release(seat, term, seat->kbd.serial, key, XKB_KEY_DOWN); } static bool @@ -1703,12 +1709,16 @@ alternate_scroll(struct seat *seat, int amount, int button) if (seat->wl_keyboard == NULL) return; + /* Should be cleared in leave event */ + assert(seat->mouse_focus != NULL); + struct terminal *term = seat->mouse_focus; + xkb_keycode_t key = button == BTN_BACK ? seat->kbd.key_arrow_up : seat->kbd.key_arrow_down; for (int i = 0; i < amount; i++) - keyboard_key(seat, NULL, seat->kbd.serial, 0, key - 8, XKB_KEY_DOWN); - keyboard_key(seat, NULL, seat->kbd.serial, 0, key - 8, XKB_KEY_UP); + key_press_release(seat, term, seat->kbd.serial, key, XKB_KEY_DOWN); + key_press_release(seat, term, seat->kbd.serial, key, XKB_KEY_UP); } static void