From 786037791c2e775c98287d794277b6ef0752aab4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 20 Jan 2025 10:34:45 +0100 Subject: [PATCH] input: kitty: improve handling of alternate+base keys even more * Always do a base key lookup. Before this, we didn't do that if we matched the XKB sym to a lookup table entry (i.e. keypads, cursor keys etc.) * Try to retrieve the unshifted symbol also when we matched the symbol to a lookup table entry. When successful, we now report an alternate key for keypad and cursor keys; before this patch, we only did that for keys that didn't have an entry in the lookup table (i.e. ASCII chars etc). This improves compatibility with kitty (and the kitty keyboard protocol) in more corner cases. One particular example is the neo keyboard layout, where part of the regular keys act as keypad keys when num-lock is active. --- input.c | 74 ++++++++++++++++++++++++++++++++------------------------- 1 file changed, 41 insertions(+), 33 deletions(-) diff --git a/input.c b/input.c index 7b4cb667..615eb00d 100644 --- a/input.c +++ b/input.c @@ -1279,75 +1279,83 @@ emit_escapes: int key = -1, alternate = -1, base = -1; char final; + const bool use_level0_sym = + (ctx->mods & ~seat->kbd.kitty_significant) == 0 && ctx->level0_syms.count > 0; + if (info != NULL) { if (!info->is_modifier || report_all_as_escapes) { key = info->key; final = info->final; + + if (use_level0_sym) { + xkb_keysym_t unshifted = xkb_keysym_to_utf32(ctx->level0_syms.syms[0]); + if (unshifted > 0) { + alternate = key; + key = unshifted; + } + } } } else { /* * Use keysym (typically its Unicode codepoint value). * * If the keysym is shifted, use its unshifted codepoint - * instead. In other words, ctrl+a and ctrl+shift+a should - * both use the same value for 'key' (97 - i.a. 'a'). + * instead. In other words, ctrl+a and ctrl+shift+a should both + * use the same value for 'key' (97 - i.a. 'a'). * - * However, don't do this if a non-significant modifier was - * used to generate the symbol. This is needed since we cannot - * encode non-significant modifiers, and thus the "extra" - * modifier(s) would get lost. + * However, don't do this if a non-significant modifier was used + * to generate the symbol. This is needed since we cannot encode + * non-significant modifiers, and thus the "extra" modifier(s) + * would get lost. * * Example: * - * the Swedish layout has '2', QUOTATION MARK ("double - * quote"), '@', and '²' on the same key. '2' is the base - * symbol. + * the Swedish layout has '2', QUOTATION MARK ("double quote"), + * '@', and '²' on the same key. '2' is the base symbol. * * Shift+2 results in QUOTATION MARK * AltGr+2 results in '@' * AltGr+Shift+2 results in '²' * - * The kitty kbd protocol can't encode AltGr. So, if we - * always used the base symbol ('2'), Alt+Shift+2 would - * result in the same escape sequence as - * AltGr+Alt+Shift+2. + * The kitty kbd protocol can't encode AltGr. So, if we always + * used the base symbol ('2'), Alt+Shift+2 would result in the + * same escape sequence as AltGr+Alt+Shift+2. * * (yes, this matches what kitty does, as of 0.23.1) */ - const bool use_level0_sym = (ctx->mods & ~seat->kbd.kitty_significant) == 0; - const xkb_keysym_t sym_to_use = use_level0_sym && ctx->level0_syms.count > 0 - ? ctx->level0_syms.syms[0] - : sym; - if (composed) key = utf32[0]; /* TODO: what if there are multiple codepoints? */ else { - key = xkb_keysym_to_utf32(sym_to_use); + key = xkb_keysym_to_utf32( + use_level0_sym ? ctx->level0_syms.syms[0] : sym); + if (key == 0) return false; - - /* The *shifted* key. May be the same as the unshifted - * key - if so, this is filtered out below, when - * emitting the CSI */ - alternate = xkb_keysym_to_utf32(sym); } - /* Base layout key. I.e the symbol the pressed key produces in - * the base/default layout (layout idx 0) */ - const xkb_keysym_t *base_syms; - int base_sym_count = xkb_keymap_key_get_syms_by_level( - seat->kbd.xkb_keymap, ctx->key, 0, 0, &base_syms); - - if (base_sym_count > 0) - base = xkb_keysym_to_utf32(base_syms[0]); - + /* + * The *shifted* key. May be the same as the unshifted key - + * if so, this is filtered out below, when emitting the CSI. + * + * Note that normally, only the *unshifted* key is emitted - see below + */ + alternate = xkb_keysym_to_utf32(sym); final = 'u'; } if (key < 0) return false; + /* Base layout key. I.e the symbol the pressed key produces in + * the base/default layout (layout idx 0) */ + const xkb_keysym_t *base_syms; + int base_sym_count = xkb_keymap_key_get_syms_by_level( + seat->kbd.xkb_keymap, ctx->key, 0, 0, &base_syms); + + if (base_sym_count > 0) + base = xkb_keysym_to_utf32(base_syms[0]); + xassert(encoded_mods >= 1); char event[4];