Skip to content

Commit 2521bab

Browse files
authored
Merge pull request #5613 from Tyriar/tyriar/5611
Fix some control keys not sending correct sequences
2 parents 777a464 + 0f1c9a4 commit 2521bab

2 files changed

Lines changed: 43 additions & 4 deletions

File tree

src/common/input/Win32InputMode.test.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ describe('Win32InputMode', () => {
3838
});
3939
it('letter key release', () => test({ code: 'KeyA', key: 'a', keyCode: 65 }, false, p => assert.strictEqual(p!.kd, 0)));
4040
it('digit key', () => test({ code: 'Digit1', key: '1', keyCode: 49 }, true, p => assert.deepStrictEqual([p!.vk, p!.uc], [0x31, 49])));
41-
it('Enter key', () => test({ code: 'Enter', key: 'Enter', keyCode: 13 }, true, p => assert.deepStrictEqual([p!.vk, p!.uc], [0x0D, 0])));
42-
it('Escape key', () => test({ code: 'Escape', key: 'Escape', keyCode: 27 }, true, p => assert.strictEqual(p!.vk, 0x1B)));
41+
it('Enter key', () => test({ code: 'Enter', key: 'Enter', keyCode: 13 }, true, p => assert.deepStrictEqual([p!.vk, p!.uc], [0x0D, 13])));
42+
it('Escape key', () => test({ code: 'Escape', key: 'Escape', keyCode: 27 }, true, p => assert.deepStrictEqual([p!.vk, p!.uc], [0x1B, 27])));
4343
it('Space key', () => test({ code: 'Space', key: ' ', keyCode: 32 }, true, p => assert.deepStrictEqual([p!.vk, p!.uc], [0x20, 32])));
4444
});
4545

@@ -91,8 +91,8 @@ describe('Win32InputMode', () => {
9191
assert.ok(p!.cs & Win32ControlKeyState.ENHANCED_KEY);
9292
}));
9393
});
94-
it('Tab', () => test({ code: 'Tab', key: 'Tab', keyCode: 9 }, true, p => assert.strictEqual(p!.vk, 0x09)));
95-
it('Backspace', () => test({ code: 'Backspace', key: 'Backspace', keyCode: 8 }, true, p => assert.strictEqual(p!.vk, 0x08)));
94+
it('Tab', () => test({ code: 'Tab', key: 'Tab', keyCode: 9 }, true, p => assert.deepStrictEqual([p!.vk, p!.uc], [0x09, 9])));
95+
it('Backspace', () => test({ code: 'Backspace', key: 'Backspace', keyCode: 8 }, true, p => assert.deepStrictEqual([p!.vk, p!.uc], [0x08, 8])));
9696
});
9797

9898
describe('numpad keys', () => {
@@ -188,6 +188,16 @@ describe('Win32InputMode', () => {
188188
assert.ok(p!.cs & Win32ControlKeyState.LEFT_CTRL_PRESSED);
189189
assert.ok(p!.cs & Win32ControlKeyState.LEFT_ALT_PRESSED);
190190
}));
191+
it('Ctrl+Enter produces LF (0x0A)', () => test({ code: 'Enter', key: 'Enter', keyCode: 13, ctrlKey: true }, true, p => {
192+
assert.strictEqual(p!.vk, 0x0D);
193+
assert.strictEqual(p!.uc, 0x0A);
194+
assert.ok(p!.cs & Win32ControlKeyState.LEFT_CTRL_PRESSED);
195+
}));
196+
it('Ctrl+Backspace produces DEL (0x7F)', () => test({ code: 'Backspace', key: 'Backspace', keyCode: 8, ctrlKey: true }, true, p => {
197+
assert.strictEqual(p!.vk, 0x08);
198+
assert.strictEqual(p!.uc, 0x7F);
199+
assert.ok(p!.cs & Win32ControlKeyState.LEFT_CTRL_PRESSED);
200+
}));
191201
});
192202

193203
describe('meta key', () => {

src/common/input/Win32InputMode.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,18 @@ const ENHANCED_KEY_CODES = new Set([
156156
'MetaLeft', 'MetaRight',
157157
]);
158158

159+
/**
160+
* Mapping of special keys (ev.key values) to their Unicode control character codes.
161+
* These keys have multi-character ev.key strings but produce control characters.
162+
* @see https://docs.microsoft.com/en-us/windows/console/key-event-record-str
163+
*/
164+
const KEY_TO_CONTROL_CHAR: { [key: string]: number } = {
165+
'Enter': 0x0D, // Carriage return
166+
'Backspace': 0x08, // Backspace
167+
'Tab': 0x09, // Horizontal tab
168+
'Escape': 0x1B, // Escape
169+
};
170+
159171
/**
160172
* Get the Win32 virtual key code for a keyboard event.
161173
*/
@@ -184,6 +196,23 @@ function getScanCode(ev: IKeyboardEvent): number {
184196
* Returns 0 for non-character keys.
185197
*/
186198
function getUnicodeChar(ev: IKeyboardEvent): number {
199+
// Handle special keys that produce control characters
200+
// Ctrl modifies some of these: Ctrl+Enter=LF, Ctrl+Backspace=DEL
201+
if (ev.ctrlKey && !ev.altKey && !ev.metaKey) {
202+
if (ev.key === 'Enter') {
203+
return 0x0A; // Line feed (Ctrl+Enter)
204+
}
205+
if (ev.key === 'Backspace') {
206+
return 0x7F; // DEL (Ctrl+Backspace)
207+
}
208+
}
209+
210+
// Check for special keys that always produce control characters
211+
const controlChar = KEY_TO_CONTROL_CHAR[ev.key];
212+
if (controlChar !== undefined) {
213+
return controlChar;
214+
}
215+
187216
// Only single-character keys produce unicode output
188217
if (ev.key.length === 1) {
189218
const codePoint = ev.key.codePointAt(0) || 0;

0 commit comments

Comments
 (0)