mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-17 08:00:59 +00:00
fix(tui): enable VT input mode on Windows (#1495)
This fixes Shift+Tab not being recognized correctly
This commit is contained in:
parent
6312fc2e42
commit
9e22d3913a
4 changed files with 49 additions and 10 deletions
|
|
@ -39,6 +39,7 @@
|
|||
"@types/mime-types": "^2.1.4",
|
||||
"chalk": "^5.5.0",
|
||||
"get-east-asian-width": "^1.3.0",
|
||||
"koffi": "^2.9.0",
|
||||
"marked": "^15.0.12",
|
||||
"mime-types": "^3.0.1"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import * as fs from "node:fs";
|
||||
import koffi from "koffi";
|
||||
import { setKittyProtocolActive } from "./keys.js";
|
||||
import { StdinBuffer } from "./stdin-buffer.js";
|
||||
|
||||
|
|
@ -86,6 +87,12 @@ export class ProcessTerminal implements Terminal {
|
|||
process.kill(process.pid, "SIGWINCH");
|
||||
}
|
||||
|
||||
// On Windows, enable ENABLE_VIRTUAL_TERMINAL_INPUT so the console sends
|
||||
// VT escape sequences (e.g. \x1b[Z for Shift+Tab) instead of raw console
|
||||
// events that lose modifier information. Must run AFTER setRawMode(true)
|
||||
// since that resets console mode flags.
|
||||
this.enableWindowsVTInput();
|
||||
|
||||
// Query and enable Kitty keyboard protocol
|
||||
// The query handler intercepts input temporarily, then installs the user's handler
|
||||
// See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/
|
||||
|
|
@ -158,6 +165,31 @@ export class ProcessTerminal implements Terminal {
|
|||
process.stdout.write("\x1b[?u");
|
||||
}
|
||||
|
||||
/**
|
||||
* On Windows, add ENABLE_VIRTUAL_TERMINAL_INPUT (0x0200) to the stdin
|
||||
* console handle so the terminal sends VT sequences for modified keys
|
||||
* (e.g. \x1b[Z for Shift+Tab). Without this, libuv's ReadConsoleInputW
|
||||
* discards modifier state and Shift+Tab arrives as plain \t.
|
||||
*/
|
||||
private enableWindowsVTInput(): void {
|
||||
if (process.platform !== "win32") return;
|
||||
try {
|
||||
const k32 = koffi.load("kernel32.dll");
|
||||
const GetStdHandle = k32.func("void* __stdcall GetStdHandle(int)");
|
||||
const GetConsoleMode = k32.func("bool __stdcall GetConsoleMode(void*, _Out_ uint32_t*)");
|
||||
const SetConsoleMode = k32.func("bool __stdcall SetConsoleMode(void*, uint32_t)");
|
||||
|
||||
const STD_INPUT_HANDLE = -10;
|
||||
const ENABLE_VIRTUAL_TERMINAL_INPUT = 0x0200;
|
||||
const handle = GetStdHandle(STD_INPUT_HANDLE);
|
||||
const mode = new Uint32Array(1);
|
||||
GetConsoleMode(handle, mode);
|
||||
SetConsoleMode(handle, mode[0]! | ENABLE_VIRTUAL_TERMINAL_INPUT);
|
||||
} catch {
|
||||
// koffi not available — Shift+Tab won't be distinguishable from Tab
|
||||
}
|
||||
}
|
||||
|
||||
async drainInput(maxMs = 1000, idleMs = 50): Promise<void> {
|
||||
if (this._kittyProtocolActive) {
|
||||
// Disable Kitty keyboard protocol first so any late key releases
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue