From 8d6f0d0583a1cb7c245ff54ec472a03ebcdb6949 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 27 Jan 2025 10:51:03 +0100 Subject: [PATCH] key-bindings: try all bindings in translated mode before matching untranslated, and then finally raw When trying to match key bindings, we do three types of matching: * Match the _translated_ symbol (e.g. Control+C) * Match the _untranslated_ symbol (e.g. Control+Shift+c) * Match raw keyboard codes This was done for *each* key binding. This meant we sometimes matched a keybinding in raw mode, even though there was a translated/untranslated binding that would match it too. All depending on the internal order of the key binding list. This patch changes it, so that we first try all bindings in translated mode, then all bindings in untranslated mode, and finally all bindings in raw mode. Closes #1929 --- CHANGELOG.md | 3 +++ input.c | 17 ++++++++++++++--- search.c | 22 ++++++++++++++++++---- url-mode.c | 19 +++++++++++++++++-- 4 files changed, 52 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 97becf79..61559359 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -89,8 +89,11 @@ double-width glyph that was pushed to the next line due to there being only one cell left on current line, did not remove the virtual space inserted at the end of the current line. +* Wrong key bindings executed when using alternative keyboard layouts + ([#1929][1929]). [1918]: https://codeberg.org/dnkl/foot/issues/1918 +[1929]: https://codeberg.org/dnkl/foot/issues/1929 ### Security diff --git a/input.c b/input.c index f5daf6b4..2db696c1 100644 --- a/input.c +++ b/input.c @@ -1582,21 +1582,25 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial, * User configurable bindings */ if (pressed) { + /* Match translated symbol */ tll_foreach(bindings->key, it) { const struct key_binding *bind = &it->item; - /* Match translated symbol */ if (bind->k.sym == sym && bind->mods == (mods & ~consumed) && execute_binding(seat, term, bind, serial, 1)) { goto maybe_repeat; } + } + + /* Match untranslated symbols */ + tll_foreach(bindings->key, it) { + const struct key_binding *bind = &it->item; if (bind->mods != mods) continue; - /* Match untranslated symbols */ for (size_t i = 0; i < raw_count; i++) { if (bind->k.sym == raw_syms[i] && execute_binding(seat, term, bind, serial, 1)) @@ -1604,8 +1608,15 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial, goto maybe_repeat; } } + } + + /* Match raw key code */ + tll_foreach(bindings->key, it) { + const struct key_binding *bind = &it->item; + + if (bind->mods != mods) + continue; - /* Match raw key code */ tll_foreach(bind->k.key_codes, code) { if (code->item == key && execute_binding(seat, term, bind, serial, 1)) diff --git a/search.c b/search.c index eaf8c34e..bcb354d6 100644 --- a/search.c +++ b/search.c @@ -1388,11 +1388,14 @@ search_input(struct seat *seat, struct terminal *term, bool update_search_result = false; bool redraw = false; - /* Key bindings */ + /* + * Key bindings + */ + + /* Match translated symbol */ tll_foreach(bindings->search, it) { const struct key_binding *bind = &it->item; - /* Match translated symbol */ if (bind->k.sym == sym && bind->mods == (mods & ~consumed)) { @@ -1404,11 +1407,15 @@ search_input(struct seat *seat, struct terminal *term, } return; } + } + + /* Match untranslated symbols */ + tll_foreach(bindings->search, it) { + const struct key_binding *bind = &it->item; if (bind->mods != mods) continue; - /* Match untranslated symbols */ for (size_t i = 0; i < raw_count; i++) { if (bind->k.sym == raw_syms[i]) { if (execute_binding(seat, term, bind, serial, @@ -1420,8 +1427,15 @@ search_input(struct seat *seat, struct terminal *term, return; } } + } + + /* Match raw key code */ + tll_foreach(bindings->search, it) { + const struct key_binding *bind = &it->item; + + if (bind->mods != mods) + continue; - /* Match raw key code */ tll_foreach(bind->k.key_codes, code) { if (code->item == key) { if (execute_binding(seat, term, bind, serial, diff --git a/url-mode.c b/url-mode.c index 20c9820b..cca7bd22 100644 --- a/url-mode.c +++ b/url-mode.c @@ -178,11 +178,14 @@ urls_input(struct seat *seat, struct terminal *term, const xkb_keysym_t *raw_syms, size_t raw_count, uint32_t serial) { - /* Key bindings */ + /* + * Key bindings + */ + + /* Match translated symbol */ tll_foreach(bindings->url, it) { const struct key_binding *bind = &it->item; - /* Match translated symbol */ if (bind->k.sym == sym && bind->mods == (mods & ~consumed)) { @@ -190,6 +193,11 @@ urls_input(struct seat *seat, struct terminal *term, return; } + } + + /* Match untranslated symbols */ + tll_foreach(bindings->url, it) { + const struct key_binding *bind = &it->item; if (bind->mods != mods) continue; @@ -199,6 +207,13 @@ urls_input(struct seat *seat, struct terminal *term, return; } } + } + + /* Match raw key code */ + tll_foreach(bindings->url, it) { + const struct key_binding *bind = &it->item; + if (bind->mods != mods) + continue; /* Match raw key code */ tll_foreach(bind->k.key_codes, code) {