From 6cf5098f6b4d9bc4a6a48c708b940aeb75fd5f02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kao=20F=C3=A9lix?= Date: Tue, 14 Apr 2026 19:36:08 +0100 Subject: [PATCH] Fix Ctrl+Alt key matching in tmux (#2989) --- packages/tui/src/keys.ts | 6 ++++-- packages/tui/test/keys.test.ts | 12 ++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/packages/tui/src/keys.ts b/packages/tui/src/keys.ts index e0d044a3..4987ba97 100644 --- a/packages/tui/src/keys.ts +++ b/packages/tui/src/keys.ts @@ -1130,8 +1130,10 @@ export function matchesKey(data: string, keyId: KeyId): boolean { const isDigit = isDigitKey(key); if (ctrl && alt && !shift && !_kittyProtocolActive && rawCtrl) { - // Legacy: ctrl+alt+key is ESC followed by the control character - return data === `\x1b${rawCtrl}`; + // Legacy: ctrl+alt+key is ESC followed by the control character. + // If that legacy form does not match, continue so CSI-u and + // modifyOtherKeys sequences from tmux can still be recognized. + if (data === `\x1b${rawCtrl}`) return true; } if (alt && !ctrl && !shift && !_kittyProtocolActive && (isLetter || isDigit)) { diff --git a/packages/tui/test/keys.test.ts b/packages/tui/test/keys.test.ts index f1e21f37..976d5fc8 100644 --- a/packages/tui/test/keys.test.ts +++ b/packages/tui/test/keys.test.ts @@ -239,6 +239,18 @@ describe("matchesKey", () => { assert.strictEqual(parseKey("\x1b[27;5;49~"), "ctrl+1"); assert.strictEqual(parseKey("\x1b[27;2;49~"), "shift+1"); }); + + it("should match Ctrl+Alt+letter via CSI-u when kitty inactive", () => { + setKittyProtocolActive(false); + assert.strictEqual(matchesKey("\x1b[104;7u", "ctrl+alt+h"), true); + assert.strictEqual(parseKey("\x1b[104;7u"), "ctrl+alt+h"); + }); + + it("should match Ctrl+Alt+letter via xterm modifyOtherKeys", () => { + setKittyProtocolActive(false); + assert.strictEqual(matchesKey("\x1b[27;7;104~", "ctrl+alt+h"), true); + assert.strictEqual(parseKey("\x1b[27;7;104~"), "ctrl+alt+h"); + }); }); describe("Legacy key matching", () => {