From ec73e4d10d1f3aa899000c1dd4c58f371c7b926f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 29 Feb 2024 09:32:38 +0100 Subject: [PATCH] kitty kbd: switch from GTK to XKB mode for 'consumed' modifiers This fixes an issue where some key combinations resulted in different output (e.g. escape code vs. plain text) depending on the state of e.g. the NumLock key. One such example is Shift+space. Another example is Shift+BackSpace. This patch also removes the hardcoded CapsLock filter, when determining whether a key combo produces text or not, and instead uses the locked modifiers as reported by XKB. --- CHANGELOG.md | 7 +++++++ input.c | 22 ++++++++-------------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e6b6bcd9..82416455 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -91,6 +91,13 @@ * Use XRGB pixel format (instead of ARGB) when there is no transparency. * Prefer CSS xcursor names, and fallback to legacy X11 names. +* Kitty keyboard protocol: use the `XKB` mode when retrieving locked + modifiers, instead of the `GTK` mode. This fixes an issue where some + key combinations (e.g. Shift+space) produces different results + depending on the state of e.g. the NumLock key. +* Kitty keyboard protocol: filter out **all** locked modifiers (as + reported by XKB), rather than hardcoding it to CapsLock only, when + determining whether a key combination produces text or not. [1526]: https://codeberg.org/dnkl/foot/issues/1526 [1528]: https://codeberg.org/dnkl/foot/issues/1528 diff --git a/input.c b/input.c index 67cb484f..1bdc9b65 100644 --- a/input.c +++ b/input.c @@ -1158,7 +1158,7 @@ kitty_kbd_protocol(struct seat *seat, struct terminal *term, xassert(info == NULL || info->sym == sym); xkb_mod_mask_t mods = 0; - xkb_mod_mask_t consumed = 0; + xkb_mod_mask_t consumed = ctx->consumed; if (info != NULL && info->is_modifier) { /* @@ -1186,7 +1186,7 @@ kitty_kbd_protocol(struct seat *seat, struct terminal *term, get_current_modifiers(seat, &mods, NULL, ctx->key, false); consumed = xkb_state_key_get_consumed_mods2( - seat->kbd.xkb_state, ctx->key, XKB_CONSUMED_MODE_GTK); + seat->kbd.xkb_state, ctx->key, XKB_CONSUMED_MODE_XKB); #if 0 /* @@ -1204,22 +1204,14 @@ kitty_kbd_protocol(struct seat *seat, struct terminal *term, /* Same as ctx->mods, but without locked modifiers being filtered out */ get_current_modifiers(seat, &mods, NULL, ctx->key, false); - - /* Re-retrieve the consumed modifiers using the GTK mode, to - better match kitty. */ - consumed = xkb_state_key_get_consumed_mods2( - seat->kbd.xkb_state, ctx->key, XKB_CONSUMED_MODE_GTK); } mods &= seat->kbd.kitty_significant; consumed &= seat->kbd.kitty_significant; - const xkb_mod_mask_t effective = mods & ~consumed; - const xkb_mod_mask_t caps_num = - (seat->kbd.mod_caps != XKB_MOD_INVALID ? 1 << seat->kbd.mod_caps : 0) | - (seat->kbd.mod_num != XKB_MOD_INVALID ? 1 << seat->kbd.mod_num : 0); - - bool is_text = count > 0 && utf32 != NULL && (effective & ~caps_num) == 0; + /* Use ctx->mods, rather than 'mods', since we *do* want locked + modifiers filtered here */ + bool is_text = count > 0 && utf32 != NULL && (ctx->mods & ~consumed) == 0; for (size_t i = 0; utf32[i] != U'\0'; i++) { if (!iswprint(utf32[i])) { is_text = false; @@ -1242,7 +1234,9 @@ kitty_kbd_protocol(struct seat *seat, struct terminal *term, if (report_all_as_escapes) goto emit_escapes; - if (effective == 0) { + /* Use ctx->mods rather than 'mods', since we *do* want locked + modifiers filtered here */ + if ((ctx->mods & ~consumed) == 0) { switch (sym) { case XKB_KEY_Return: term_to_slave(term, "\r", 1); return true; case XKB_KEY_BackSpace: term_to_slave(term, "\x7f", 1); return true;