Merge pull request #5613 from Tyriar/tyriar/5611

Fix some control keys not sending correct sequences
This commit is contained in:
Daniel Imms
2026-01-16 06:14:01 -08:00
committed by GitHub
2 changed files with 43 additions and 4 deletions
+14 -4
View File
@@ -38,8 +38,8 @@ describe('Win32InputMode', () => {
});
it('letter key release', () => test({ code: 'KeyA', key: 'a', keyCode: 65 }, false, p => assert.strictEqual(p!.kd, 0)));
it('digit key', () => test({ code: 'Digit1', key: '1', keyCode: 49 }, true, p => assert.deepStrictEqual([p!.vk, p!.uc], [0x31, 49])));
it('Enter key', () => test({ code: 'Enter', key: 'Enter', keyCode: 13 }, true, p => assert.deepStrictEqual([p!.vk, p!.uc], [0x0D, 0])));
it('Escape key', () => test({ code: 'Escape', key: 'Escape', keyCode: 27 }, true, p => assert.strictEqual(p!.vk, 0x1B)));
it('Enter key', () => test({ code: 'Enter', key: 'Enter', keyCode: 13 }, true, p => assert.deepStrictEqual([p!.vk, p!.uc], [0x0D, 13])));
it('Escape key', () => test({ code: 'Escape', key: 'Escape', keyCode: 27 }, true, p => assert.deepStrictEqual([p!.vk, p!.uc], [0x1B, 27])));
it('Space key', () => test({ code: 'Space', key: ' ', keyCode: 32 }, true, p => assert.deepStrictEqual([p!.vk, p!.uc], [0x20, 32])));
});
@@ -91,8 +91,8 @@ describe('Win32InputMode', () => {
assert.ok(p!.cs & Win32ControlKeyState.ENHANCED_KEY);
}));
});
it('Tab', () => test({ code: 'Tab', key: 'Tab', keyCode: 9 }, true, p => assert.strictEqual(p!.vk, 0x09)));
it('Backspace', () => test({ code: 'Backspace', key: 'Backspace', keyCode: 8 }, true, p => assert.strictEqual(p!.vk, 0x08)));
it('Tab', () => test({ code: 'Tab', key: 'Tab', keyCode: 9 }, true, p => assert.deepStrictEqual([p!.vk, p!.uc], [0x09, 9])));
it('Backspace', () => test({ code: 'Backspace', key: 'Backspace', keyCode: 8 }, true, p => assert.deepStrictEqual([p!.vk, p!.uc], [0x08, 8])));
});
describe('numpad keys', () => {
@@ -188,6 +188,16 @@ describe('Win32InputMode', () => {
assert.ok(p!.cs & Win32ControlKeyState.LEFT_CTRL_PRESSED);
assert.ok(p!.cs & Win32ControlKeyState.LEFT_ALT_PRESSED);
}));
it('Ctrl+Enter produces LF (0x0A)', () => test({ code: 'Enter', key: 'Enter', keyCode: 13, ctrlKey: true }, true, p => {
assert.strictEqual(p!.vk, 0x0D);
assert.strictEqual(p!.uc, 0x0A);
assert.ok(p!.cs & Win32ControlKeyState.LEFT_CTRL_PRESSED);
}));
it('Ctrl+Backspace produces DEL (0x7F)', () => test({ code: 'Backspace', key: 'Backspace', keyCode: 8, ctrlKey: true }, true, p => {
assert.strictEqual(p!.vk, 0x08);
assert.strictEqual(p!.uc, 0x7F);
assert.ok(p!.cs & Win32ControlKeyState.LEFT_CTRL_PRESSED);
}));
});
describe('meta key', () => {
+29
View File
@@ -156,6 +156,18 @@ const ENHANCED_KEY_CODES = new Set([
'MetaLeft', 'MetaRight',
]);
/**
* Mapping of special keys (ev.key values) to their Unicode control character codes.
* These keys have multi-character ev.key strings but produce control characters.
* @see https://docs.microsoft.com/en-us/windows/console/key-event-record-str
*/
const KEY_TO_CONTROL_CHAR: { [key: string]: number } = {
'Enter': 0x0D, // Carriage return
'Backspace': 0x08, // Backspace
'Tab': 0x09, // Horizontal tab
'Escape': 0x1B, // Escape
};
/**
* Get the Win32 virtual key code for a keyboard event.
*/
@@ -184,6 +196,23 @@ function getScanCode(ev: IKeyboardEvent): number {
* Returns 0 for non-character keys.
*/
function getUnicodeChar(ev: IKeyboardEvent): number {
// Handle special keys that produce control characters
// Ctrl modifies some of these: Ctrl+Enter=LF, Ctrl+Backspace=DEL
if (ev.ctrlKey && !ev.altKey && !ev.metaKey) {
if (ev.key === 'Enter') {
return 0x0A; // Line feed (Ctrl+Enter)
}
if (ev.key === 'Backspace') {
return 0x7F; // DEL (Ctrl+Backspace)
}
}
// Check for special keys that always produce control characters
const controlChar = KEY_TO_CONTROL_CHAR[ev.key];
if (controlChar !== undefined) {
return controlChar;
}
// Only single-character keys produce unicode output
if (ev.key.length === 1) {
const codePoint = ev.key.codePointAt(0) || 0;