input: don’t use seat->kbd_focus as terminal when processing a key press

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
This commit is contained in:
Daniel Eklöf 2020-11-03 19:44:51 +01:00
parent f3e6941c9a
commit 9209adf6fa
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
2 changed files with 27 additions and 15 deletions

View file

@ -73,6 +73,8 @@
* Compilation error _"overflow in conversion from long 'unsigned int' * Compilation error _"overflow in conversion from long 'unsigned int'
to 'int' changes value... "_ seen on platforms where the `request` to 'int' changes value... "_ seen on platforms where the `request`
argument in `ioctl(3)` is an `int` (for example: linux/ppc64). 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 ### Security

40
input.c
View file

@ -748,12 +748,9 @@ keymap_lookup(struct terminal *term, xkb_keysym_t sym, enum modifier mods)
} }
static void static void
keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, key_press_release(struct seat *seat, struct terminal *term, uint32_t serial,
uint32_t time, uint32_t key, uint32_t state) uint32_t key, uint32_t state)
{ {
struct seat *seat = data;
struct terminal *term = seat->kbd_focus;
if (seat->kbd.xkb == NULL || if (seat->kbd.xkb == NULL ||
seat->kbd.xkb_keymap == NULL || seat->kbd.xkb_keymap == NULL ||
seat->kbd.xkb_state == NULL) seat->kbd.xkb_state == NULL)
@ -761,8 +758,6 @@ keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial,
return; return;
} }
assert(term != NULL);
const xkb_mod_mask_t ctrl = 1 << seat->kbd.mod_ctrl; 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 alt = 1 << seat->kbd.mod_alt;
const xkb_mod_mask_t shift = 1 << seat->kbd.mod_shift; 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; return;
} }
key += 8;
bool should_repeat = xkb_keymap_key_repeats(seat->kbd.xkb_keymap, key); 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); 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 (term->is_searching) {
if (should_repeat) if (should_repeat)
start_repeater(seat, key - 8); start_repeater(seat, key);
search_input(seat, term, key, sym, effective_mods, serial); search_input(seat, term, key, sym, effective_mods, serial);
return; return;
} }
@ -832,10 +826,10 @@ keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial,
} }
#endif #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, " "sym=%u, mod=0x%08x, consumed=0x%08x, significant=0x%08x, "
"effective=0x%08x, repeats=%d", "effective=0x%08x, repeats=%d",
(void *)wl_keyboard, serial, seat->name, (void *)term, serial,
sym, mods, consumed, significant, effective_mods, should_repeat); sym, mods, consumed, significant, effective_mods, should_repeat);
/* /*
@ -1001,7 +995,15 @@ maybe_repeat:
term->wl->presentation_clock_id, &term->render.input_time); term->wl->presentation_clock_id, &term->render.input_time);
if (should_repeat) 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 static void
@ -1055,7 +1057,11 @@ const struct wl_keyboard_listener keyboard_listener = {
void void
input_repeat(struct seat *seat, uint32_t key) 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 static bool
@ -1703,12 +1709,16 @@ alternate_scroll(struct seat *seat, int amount, int button)
if (seat->wl_keyboard == NULL) if (seat->wl_keyboard == NULL)
return; 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 xkb_keycode_t key = button == BTN_BACK
? seat->kbd.key_arrow_up : seat->kbd.key_arrow_down; ? seat->kbd.key_arrow_up : seat->kbd.key_arrow_down;
for (int i = 0; i < amount; i++) for (int i = 0; i < amount; i++)
keyboard_key(seat, NULL, seat->kbd.serial, 0, key - 8, XKB_KEY_DOWN); key_press_release(seat, term, seat->kbd.serial, key, 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_UP);
} }
static void static void