fix(tui): use Kitty flag 1 on Windows to fix Shift+letter input

WezTerm/ConPTY on Windows drops Shift+letter keypresses entirely when
Kitty keyboard protocol flag 4 (report alternate keys) is set. Fall
back to flag 1 (disambiguate only) on Windows so shifted printable
keys are delivered as raw characters instead of being silently eaten.

Also adds a defensive SHIFT_MAP fallback in decodeKittyPrintable for
terminals that send CSI-u sequences with the shift modifier but omit
the shifted_key secondary codepoint.
This commit is contained in:
Gergely Jutasi
2026-08-04 02:35:48 +02:00
parent 01c1f91ff5
commit 91be0eba77
2 changed files with 41 additions and 2 deletions
+35 -2
View File
@@ -307,6 +307,32 @@ const KITTY_MOD_CTRL = 4;
const KITTY_MOD_SUPER = 8;
const KITTY_MOD_NUM_LOCK = 128;
const KITTY_LOCK_MASK = 64 + KITTY_MOD_NUM_LOCK; // Caps Lock + Num Lock
const SHIFT_MAP: Record<number, number> = {
// US layout: unshifted codepoint → shifted codepoint
// digits
48: 41, // 0 → )
49: 33, // 1 → !
50: 64, // 2 → @
51: 35, // 3 → #
52: 36, // 4 → $
53: 37, // 5 → %
54: 94, // 6 → ^
55: 38, // 7 → &
56: 42, // 8 → *
57: 40, // 9 → (
// symbols
45: 95, // - → _
61: 43, // = → +
91: 123, // [ → {
93: 125, // ] → }
92: 124, // \ → |
59: 58, // ; → :
39: 34, // ' → "
96: 126, // ` → ~
44: 60, // , → <
46: 62, // . → >
47: 63, // / → ?
};
const MODIFY_OTHER_KEYS_PATTERN = /^\x1b\[27;(\d+);(\d+)~$/;
const KITTY_KEYPAD_OPERATOR_TEXT: Record<number, string> = {
57410: "/",
@@ -430,8 +456,15 @@ function decodeKittyPrintable(data: string): string | undefined {
}
let effectiveCodepoint = codepoint;
if (effectiveMod & KITTY_MOD_SHIFT && typeof shiftedKey === "number") {
effectiveCodepoint = shiftedKey;
if (effectiveMod & KITTY_MOD_SHIFT) {
if (typeof shiftedKey === "number") {
effectiveCodepoint = shiftedKey;
} else if (codepoint >= 97 && codepoint <= 122) {
effectiveCodepoint = codepoint - 32;
} else {
const shifted = SHIFT_MAP[codepoint];
if (shifted !== undefined) effectiveCodepoint = shifted;
}
}
if (effectiveCodepoint >= 0xe000 && effectiveCodepoint <= 0xf8ff) {
+6
View File
@@ -1105,6 +1105,12 @@ export class ProcessTerminal implements Terminal {
// Push level-2 to keep its shortcuts reporting consistently.
this.#kittyEnableSeq = "\x1b[>7u";
this.#safeWrite(this.#kittyEnableSeq);
} else if (process.platform === "win32") {
// WezTerm/ConPTY on Windows drops Shift+letter keypresses entirely
// when flag 4 (report alternate keys) is set. Use flag 1
// (disambiguate only) to keep shifted printable keys working.
this.#kittyEnableSeq = "\x1b[>1u";
this.#safeWrite(this.#kittyEnableSeq);
} else {
// Disambiguate escape codes and report base-layout keys for physical
// shortcut matching, without event reporting that caused regression #3259.