diff --git a/src/browser/KeyboardTest.debug.ts b/src/browser/KeyboardTest.debug.ts new file mode 100644 index 000000000..584a36d37 --- /dev/null +++ b/src/browser/KeyboardTest.debug.ts @@ -0,0 +1,121 @@ +/** + * Debug test to reproduce the Alt+- keyboard issue + */ + +import { MockCompositionHelper, MockRenderer, MockViewport, TestTerminal } from 'browser/TestUtils.test'; +import type { IBrowser } from 'browser/Types'; +import { evaluateKeyboardEvent } from 'common/input/Keyboard'; + +// Create a test to simulate the keyboard event handling +function testAltMinusKeyHandling() { + const term = new TestTerminal({ cols: 80, rows: 24 }); + (term as any).renderer = new MockRenderer(); + (term as any).viewport = new MockViewport(); + + // Mock the composition helper to not intercept our events + const mockCompositionHelper = { + keydown: () => true, + isComposing: false + }; + (term as any)._compositionHelper = mockCompositionHelper; + + (term as any).element = { + classList: { + toggle: () => { }, + remove: () => { } + } + }; + + // Mock browser detection for Linux + (term as any).browser = { + isMac: false, + isWindows: false, + isNode: false, + userAgent: 'Mozilla/5.0 (X11; Linux x86_64; rv:141.0) Gecko/20100101 Firefox/141.0', + platform: 'linux', + isFirefox: true, + isIpad: false, + isIphone: false + } as IBrowser; + + // Mock textarea element + (term as any).textarea = { + value: '' + }; + + // Mock necessary services + (term as any).coreService = { + decPrivateModes: { + applicationCursorKeys: false + }, + triggerDataEvent: () => {} + }; + + // Mock necessary options directly on term.options + (term as any).options.macOptionIsMeta = false; + (term as any).options.scrollOnUserInput = false; + + (term as any).optionsService = { + rawOptions: { + screenReaderMode: false + } + }; + + let keyEventFired = false; + let capturedKey = ''; + + // Listen for onKey events + term.onKey((event) => { + keyEventFired = true; + capturedKey = event.key; + console.log('Key event fired:', event); + }); + + // Create a mock KeyboardEvent for Alt+- + const mockEvent = { + type: 'keydown', + keyCode: 189, + key: '-', + altKey: true, + ctrlKey: false, + shiftKey: false, + metaKey: false, + getModifierState: (modifier: string) => { + if (modifier === 'AltGraph') return false; + return false; + }, + preventDefault: () => {}, + stopPropagation: () => {} + } as KeyboardEvent; + + console.log('Testing Alt+- key handling...'); + console.log('Mock event:', mockEvent); + + // Test the individual components + console.log('\n=== Testing evaluateKeyboardEvent directly ==='); + const keyResult = evaluateKeyboardEvent(mockEvent, false, false, false); + console.log('evaluateKeyboardEvent result:', keyResult); + + console.log('\n=== Testing _isThirdLevelShift ==='); + const isThirdLevel = (term as any)._isThirdLevelShift((term as any).browser, mockEvent); + console.log('_isThirdLevelShift result:', isThirdLevel); + + console.log('\n=== Testing full _keyDown method ==='); + // Call the _keyDown method directly + const result = (term as any)._keyDown(mockEvent); + + console.log('_keyDown result:', result); + console.log('Key event fired:', keyEventFired); + console.log('Captured key:', capturedKey); + console.log('Expected key: \\x1b-'); + + return { + keyEventFired, + capturedKey, + result, + keyResult, + isThirdLevel + }; +} + +export { testAltMinusKeyHandling }; \ No newline at end of file diff --git a/src/common/input/Keyboard.altminus.test.ts b/src/common/input/Keyboard.altminus.test.ts new file mode 100644 index 000000000..06d865716 --- /dev/null +++ b/src/common/input/Keyboard.altminus.test.ts @@ -0,0 +1,116 @@ +/** + * Test for Alt+- keyboard handling specifically + * This tests both the evaluateKeyboardEvent function and potential browser integration issues + */ + +import { assert } from 'chai'; +import { evaluateKeyboardEvent } from 'common/input/Keyboard'; +import { IKeyboardResult, IKeyboardEvent } from 'common/Types'; + +function createMockKeyboardEvent(partialEvent: Partial): IKeyboardEvent { + return { + altKey: false, + ctrlKey: false, + shiftKey: false, + metaKey: false, + keyCode: 0, + code: '', + key: '', + type: 'keydown', + ...partialEvent + }; +} + +describe('Alt+- keyboard handling', () => { + it('should return correct escape sequence for Alt+- on all platforms', () => { + const event = createMockKeyboardEvent({ + altKey: true, + keyCode: 189, + key: '-', + type: 'keydown' + }); + + // Test on non-Mac (Linux/Windows) + const resultLinux = evaluateKeyboardEvent(event, false, false, false); + assert.equal(resultLinux.key, '\x1b-', 'Alt+- should produce \\x1b- on Linux'); + assert.equal(resultLinux.cancel, false, 'Alt+- should not be cancelled on Linux'); + + // Test on Windows + const resultWindows = evaluateKeyboardEvent(event, false, false, false); + assert.equal(resultWindows.key, '\x1b-', 'Alt+- should produce \\x1b- on Windows'); + + // Test on Mac with macOptionIsMeta: true + const resultMacMeta = evaluateKeyboardEvent(event, false, true, true); + assert.equal(resultMacMeta.key, '\x1b-', 'Alt+- should produce \\x1b- on Mac with macOptionIsMeta'); + + // Test on Mac with macOptionIsMeta: false (third level shift) + const resultMacNoMeta = evaluateKeyboardEvent(event, false, true, false); + assert.equal(resultMacNoMeta.key, undefined, 'Alt+- should not produce escape sequence on Mac without macOptionIsMeta'); + }); + + it('should handle Alt+- with shift key (underscore)', () => { + const event = createMockKeyboardEvent({ + altKey: true, + shiftKey: true, + keyCode: 189, + key: '_', + type: 'keydown' + }); + + const result = evaluateKeyboardEvent(event, false, false, false); + assert.equal(result.key, '\x1b_', 'Alt+Shift+- should produce \\x1b_'); + }); + + it('should verify keyCode 189 maps to minus character', () => { + // This test verifies that keyCode 189 is correctly mapped in KEYCODE_KEY_MAPPINGS + const event = createMockKeyboardEvent({ + altKey: true, + keyCode: 189, + key: '-', + type: 'keydown' + }); + + const result = evaluateKeyboardEvent(event, false, false, false); + assert.isDefined(result.key, 'Result should have a key'); + assert.equal(result.key, '\x1b-', 'Should produce the correct escape sequence'); + }); + + it('should handle various browser scenarios for Alt+-', () => { + // Test with different keyCode values that might be used for minus + const keyCodes = [189, 109]; // 189 is standard minus, 109 is numpad minus + + keyCodes.forEach(keyCode => { + const event = createMockKeyboardEvent({ + altKey: true, + keyCode: keyCode, + key: '-', + type: 'keydown' + }); + + const result = evaluateKeyboardEvent(event, false, false, false); + if (keyCode === 189) { + assert.equal(result.key, '\x1b-', `keyCode ${keyCode} should produce \\x1b-`); + } else { + // For numpad minus or other codes, the behavior might be different + // but we should still handle them gracefully + assert.isDefined(result, `keyCode ${keyCode} should return a result`); + } + }); + }); + + it('should not be affected by composition state for regular Alt combinations', () => { + // This tests that Alt+- is not treated as a composition character + const event = createMockKeyboardEvent({ + altKey: true, + keyCode: 189, + key: '-', + type: 'keydown' + }); + + // Ensure the keyCode is not 229 (composition character) + assert.notEqual(event.keyCode, 229, 'Alt+- should not use composition keyCode'); + + const result = evaluateKeyboardEvent(event, false, false, false); + assert.equal(result.key, '\x1b-', 'Alt+- should work normally without composition interference'); + }); +}); \ No newline at end of file diff --git a/test_alt_minus.html b/test_alt_minus.html new file mode 100644 index 000000000..b5b6b54fa --- /dev/null +++ b/test_alt_minus.html @@ -0,0 +1,60 @@ + + + + Alt+- Key Test + + + + +
+
+

Key Events:

+
+
+ + + + \ No newline at end of file