From 1e63dddb89a27de702fced65d7b6ba3b39812bb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 19 Mar 2022 18:59:15 +0100 Subject: [PATCH] =?UTF-8?q?input:=20don=E2=80=99t=20allow=20non-significan?= =?UTF-8?q?t=20modifiers=20when=20matching=20untranslated=20symbols?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When matching “untranslated” bindings (by matching the base symbol of the key, e.g. ctrl+shift+2 in US layout), require that no non-significant modifiers are active. This fixes an issue where AltGr was “ignored”, and would cause certain combinations to match a key binding. Example: ctrl+altgr+0, on many European layouts matched against the default ctrl+0 (reset the font size), instead of emitting ^] To make this work, we now need to filter out “locked” modifiers (e.g. NumLock and CapsLock). Otherwise having e.g. NumLock active would prevent *all* untranslated matching to fail. Closes #983 --- CHANGELOG.md | 2 ++ input.c | 19 ++++++++++++++----- search.c | 9 +++++++-- search.h | 1 + url-mode.c | 10 ++++++++-- url-mode.h | 1 + 6 files changed, 33 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fb7015b..0522978d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -89,6 +89,8 @@ overrides on the command line. * Crash when seat has no keyboard (https://codeberg.org/dnkl/foot/issues/963). +* Key presses with e.g. `AltGr` triggering key combinations with the + base symbol (https://codeberg.org/dnkl/foot/issues/983). ### Security diff --git a/input.c b/input.c index 047d7c86..6dbf7fe3 100644 --- a/input.c +++ b/input.c @@ -1030,6 +1030,12 @@ get_current_modifiers(const struct seat *seat, } } +static xkb_mod_mask_t +get_locked_modifiers(const struct seat *seat) +{ + return xkb_state_serialize_mods(seat->kbd.xkb_state, XKB_STATE_MODS_LOCKED); +} + struct kbd_ctx { xkb_layout_index_t layout; xkb_keycode_t key; @@ -1488,8 +1494,11 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial, xkb_mod_mask_t mods, consumed; get_current_modifiers(seat, &mods, &consumed, key); - xkb_mod_mask_t bind_mods = mods & seat->kbd.bind_significant; - xkb_mod_mask_t bind_consumed = consumed & seat->kbd.bind_significant; + const xkb_mod_mask_t locked = get_locked_modifiers(seat); + const xkb_mod_mask_t bind_mods + = mods & seat->kbd.bind_significant & ~locked; + const xkb_mod_mask_t bind_consumed = + consumed & seat->kbd.bind_significant & ~locked; xkb_layout_index_t layout_idx = xkb_state_key_get_layout(seat->kbd.xkb_state, key); @@ -1504,7 +1513,7 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial, start_repeater(seat, key); search_input( - seat, term, key, sym, bind_mods, bind_consumed, + seat, term, key, sym, mods, consumed, locked, raw_syms, raw_count, serial); return; } @@ -1514,7 +1523,7 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial, start_repeater(seat, key); urls_input( - seat, term, key, sym, bind_mods, bind_consumed, + seat, term, key, sym, mods, consumed, locked, raw_syms, raw_count, serial); return; } @@ -1553,7 +1562,7 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial, goto maybe_repeat; } - if (bind->mods != bind_mods) + if (bind->mods != bind_mods || bind_mods != (mods & ~locked)) continue; /* Match untranslated symbols */ diff --git a/search.c b/search.c index 6251c697..b422d957 100644 --- a/search.c +++ b/search.c @@ -822,11 +822,16 @@ execute_binding(struct seat *seat, struct terminal *term, void search_input(struct seat *seat, struct terminal *term, uint32_t key, xkb_keysym_t sym, xkb_mod_mask_t mods, xkb_mod_mask_t consumed, + xkb_mod_mask_t locked, const xkb_keysym_t *raw_syms, size_t raw_count, uint32_t serial) { LOG_DBG("search: input: sym=%d/0x%x, mods=0x%08x", sym, sym, mods); + const xkb_mod_mask_t bind_mods = + mods & seat->kbd.bind_significant & ~locked; + const xkb_mod_mask_t bind_consumed = + consumed & seat->kbd.bind_significant & ~locked; enum xkb_compose_status compose_status = seat->kbd.xkb_compose_state != NULL ? xkb_compose_state_get_status(seat->kbd.xkb_compose_state) : XKB_COMPOSE_NOTHING; @@ -840,7 +845,7 @@ search_input(struct seat *seat, struct terminal *term, uint32_t key, /* Match translated symbol */ if (bind->k.sym == sym && - bind->mods == (mods & ~consumed)) { + bind->mods == (bind_mods & ~bind_consumed)) { if (execute_binding(seat, term, bind, serial, &update_search_result, &redraw)) @@ -850,7 +855,7 @@ search_input(struct seat *seat, struct terminal *term, uint32_t key, return; } - if (bind->mods != mods) + if (bind->mods != bind_mods || bind_mods != (mods & ~locked)) continue; /* Match untranslated symbols */ diff --git a/search.h b/search.h index f4dfa5b9..18af0d62 100644 --- a/search.h +++ b/search.h @@ -8,6 +8,7 @@ void search_cancel(struct terminal *term); void search_input( struct seat *seat, struct terminal *term, uint32_t key, xkb_keysym_t sym, xkb_mod_mask_t mods, xkb_mod_mask_t consumed, + xkb_mod_mask_t locked, const xkb_keysym_t *raw_syms, size_t raw_count, uint32_t serial); void search_add_chars(struct terminal *term, const char *text, size_t len); diff --git a/url-mode.c b/url-mode.c index 350bdf25..6625e99a 100644 --- a/url-mode.c +++ b/url-mode.c @@ -119,22 +119,28 @@ activate_url(struct seat *seat, struct terminal *term, const struct url *url) void urls_input(struct seat *seat, struct terminal *term, uint32_t key, xkb_keysym_t sym, xkb_mod_mask_t mods, xkb_mod_mask_t consumed, + xkb_mod_mask_t locked, const xkb_keysym_t *raw_syms, size_t raw_count, uint32_t serial) { + const xkb_mod_mask_t bind_mods = + mods & seat->kbd.bind_significant & ~locked; + const xkb_mod_mask_t bind_consumed = + consumed & seat->kbd.bind_significant & ~locked; + /* Key bindings */ tll_foreach(seat->kbd.bindings.url, it) { const struct key_binding *bind = &it->item; /* Match translated symbol */ if (bind->k.sym == sym && - bind->mods == (mods & ~consumed)) + bind->mods == (bind_mods & ~bind_consumed)) { execute_binding(seat, term, bind, serial); return; } - if (bind->mods != mods) + if (bind->mods != bind_mods || bind_mods != (mods & ~locked)) continue; for (size_t i = 0; i < raw_count; i++) { diff --git a/url-mode.h b/url-mode.h index b1314780..0f1451da 100644 --- a/url-mode.h +++ b/url-mode.h @@ -21,5 +21,6 @@ void urls_reset(struct terminal *term); void urls_input(struct seat *seat, struct terminal *term, uint32_t key, xkb_keysym_t sym, xkb_mod_mask_t mods, xkb_mod_mask_t consumed, + xkb_mod_mask_t locked, const xkb_keysym_t *raw_syms, size_t raw_count, uint32_t serial);