@xterm/xterm 6.1.0-beta.28 → 6.1.0-beta.280
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -38
- package/css/xterm.css +29 -22
- package/lib/xterm.js +1 -1
- package/lib/xterm.js.map +1 -1
- package/lib/xterm.mjs +8 -34
- package/lib/xterm.mjs.map +4 -4
- package/package.json +56 -45
- package/src/browser/AccessibilityManager.ts +18 -13
- package/src/browser/Clipboard.ts +8 -5
- package/src/browser/ColorContrastCache.ts +3 -3
- package/src/browser/CoreBrowserTerminal.ts +179 -348
- package/src/browser/Dom.ts +178 -0
- package/src/browser/Linkifier.ts +14 -14
- package/src/browser/OscLinkProvider.ts +86 -18
- package/src/browser/RenderDebouncer.ts +7 -9
- package/src/browser/TimeBasedDebouncer.ts +12 -5
- package/src/browser/Types.ts +16 -14
- package/src/browser/Viewport.ts +58 -23
- package/src/browser/decorations/BufferDecorationRenderer.ts +3 -3
- package/src/browser/decorations/ColorZoneStore.ts +1 -1
- package/src/browser/decorations/OverviewRulerRenderer.ts +36 -20
- package/src/browser/input/CompositionHelper.ts +47 -11
- package/src/browser/input/Mouse.ts +5 -9
- package/src/browser/input/MoveToCell.ts +3 -3
- package/src/browser/public/Terminal.ts +33 -36
- package/src/browser/renderer/dom/DomRenderer.ts +265 -89
- package/src/browser/renderer/dom/DomRendererRowFactory.ts +34 -27
- package/src/browser/renderer/dom/WidthCache.ts +57 -55
- package/src/browser/renderer/shared/Constants.ts +7 -0
- package/src/browser/renderer/shared/RendererUtils.ts +1 -1
- package/src/browser/renderer/shared/SelectionRenderModel.ts +2 -2
- package/src/browser/renderer/shared/TextBlinkStateManager.ts +97 -0
- package/src/browser/renderer/shared/Types.ts +10 -4
- package/src/browser/scrollable/abstractScrollbar.ts +300 -0
- package/src/browser/scrollable/fastDomNode.ts +126 -0
- package/src/browser/scrollable/globalPointerMoveMonitor.ts +90 -0
- package/src/browser/scrollable/horizontalScrollbar.ts +85 -0
- package/src/browser/scrollable/mouseEvent.ts +292 -0
- package/src/browser/scrollable/scrollable.ts +486 -0
- package/src/browser/scrollable/scrollableElement.ts +581 -0
- package/src/browser/scrollable/scrollableElementOptions.ts +161 -0
- package/src/browser/scrollable/scrollbarArrow.ts +110 -0
- package/src/browser/scrollable/scrollbarState.ts +246 -0
- package/src/browser/scrollable/scrollbarVisibilityController.ts +113 -0
- package/src/browser/scrollable/touch.ts +485 -0
- package/src/browser/scrollable/verticalScrollbar.ts +143 -0
- package/src/browser/scrollable/widget.ts +23 -0
- package/src/browser/selection/SelectionModel.ts +1 -1
- package/src/browser/services/CharSizeService.ts +4 -4
- package/src/browser/services/CharacterJoinerService.ts +13 -11
- package/src/browser/services/CoreBrowserService.ts +7 -5
- package/src/browser/services/KeyboardService.ts +67 -0
- package/src/browser/services/LinkProviderService.ts +3 -3
- package/src/browser/services/MouseCoordsService.ts +47 -0
- package/src/browser/services/MouseService.ts +619 -23
- package/src/browser/services/RenderService.ts +33 -21
- package/src/browser/services/SelectionService.ts +72 -54
- package/src/browser/services/Services.ts +44 -21
- package/src/browser/services/ThemeService.ts +9 -9
- package/src/common/Async.ts +141 -0
- package/src/common/CircularList.ts +24 -3
- package/src/common/Color.ts +13 -5
- package/src/common/CoreTerminal.ts +61 -35
- package/src/common/Event.ts +118 -0
- package/src/common/InputHandler.ts +286 -105
- package/src/common/Lifecycle.ts +113 -0
- package/src/common/Platform.ts +15 -5
- package/src/common/SortedList.ts +8 -4
- package/src/common/StringBuilder.ts +67 -0
- package/src/common/TaskQueue.ts +17 -8
- package/src/common/Types.ts +68 -206
- package/src/common/Version.ts +1 -1
- package/src/common/WindowsMode.ts +2 -2
- package/src/common/buffer/AttributeData.ts +3 -2
- package/src/common/buffer/Buffer.ts +47 -32
- package/src/common/buffer/BufferLine.ts +175 -100
- package/src/common/buffer/BufferLineStringCache.ts +69 -0
- package/src/common/buffer/BufferReflow.ts +7 -4
- package/src/common/buffer/BufferSet.ts +13 -9
- package/src/common/buffer/CellData.ts +61 -4
- package/src/common/buffer/Constants.ts +13 -13
- package/src/common/buffer/Marker.ts +4 -4
- package/src/common/buffer/Types.ts +153 -3
- package/src/common/data/Charsets.ts +4 -7
- package/src/common/data/EscapeSequences.ts +71 -70
- package/src/common/input/Keyboard.ts +17 -10
- package/src/common/input/KittyKeyboard.ts +526 -0
- package/src/common/input/TextDecoder.ts +3 -3
- package/src/common/input/UnicodeV6.ts +3 -2
- package/src/common/input/Win32InputMode.ts +297 -0
- package/src/common/input/WriteBuffer.ts +108 -39
- package/src/common/input/XParseColor.ts +2 -2
- package/src/common/parser/ApcParser.ts +196 -0
- package/src/common/parser/Constants.ts +14 -4
- package/src/common/parser/DcsParser.ts +15 -16
- package/src/common/parser/EscapeSequenceParser.ts +214 -72
- package/src/common/parser/OscParser.ts +14 -15
- package/src/common/parser/Params.ts +31 -12
- package/src/common/parser/Types.ts +40 -30
- package/src/common/public/BufferApiView.ts +3 -3
- package/src/common/public/BufferLineApiView.ts +4 -4
- package/src/common/public/BufferNamespaceApi.ts +5 -5
- package/src/common/public/ParserApi.ts +5 -2
- package/src/common/public/UnicodeApi.ts +1 -1
- package/src/common/services/BufferService.ts +17 -13
- package/src/common/services/CharsetService.ts +6 -2
- package/src/common/services/CoreService.ts +23 -10
- package/src/common/services/DecorationService.ts +260 -15
- package/src/common/services/InstantiationService.ts +2 -2
- package/src/common/services/LogService.ts +2 -32
- package/src/common/services/{CoreMouseService.ts → MouseStateService.ts} +22 -133
- package/src/common/services/OptionsService.ts +17 -7
- package/src/common/services/OscLinkService.ts +3 -2
- package/src/common/services/ServiceRegistry.ts +14 -8
- package/src/common/services/Services.ts +54 -50
- package/src/common/services/UnicodeService.ts +6 -11
- package/typings/xterm.d.ts +329 -34
- package/src/common/Clone.ts +0 -23
- package/src/common/TypedArrayUtils.ts +0 -17
- package/src/vs/base/browser/browser.ts +0 -141
- package/src/vs/base/browser/canIUse.ts +0 -49
- package/src/vs/base/browser/dom.ts +0 -2369
- package/src/vs/base/browser/fastDomNode.ts +0 -316
- package/src/vs/base/browser/globalPointerMoveMonitor.ts +0 -112
- package/src/vs/base/browser/iframe.ts +0 -135
- package/src/vs/base/browser/keyboardEvent.ts +0 -213
- package/src/vs/base/browser/mouseEvent.ts +0 -229
- package/src/vs/base/browser/touch.ts +0 -372
- package/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts +0 -303
- package/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts +0 -114
- package/src/vs/base/browser/ui/scrollbar/scrollableElement.ts +0 -720
- package/src/vs/base/browser/ui/scrollbar/scrollableElementOptions.ts +0 -165
- package/src/vs/base/browser/ui/scrollbar/scrollbarArrow.ts +0 -114
- package/src/vs/base/browser/ui/scrollbar/scrollbarState.ts +0 -243
- package/src/vs/base/browser/ui/scrollbar/scrollbarVisibilityController.ts +0 -118
- package/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts +0 -116
- package/src/vs/base/browser/ui/widget.ts +0 -57
- package/src/vs/base/browser/window.ts +0 -14
- package/src/vs/base/common/arrays.ts +0 -887
- package/src/vs/base/common/arraysFind.ts +0 -202
- package/src/vs/base/common/assert.ts +0 -71
- package/src/vs/base/common/async.ts +0 -1992
- package/src/vs/base/common/cancellation.ts +0 -148
- package/src/vs/base/common/charCode.ts +0 -450
- package/src/vs/base/common/collections.ts +0 -140
- package/src/vs/base/common/decorators.ts +0 -130
- package/src/vs/base/common/equals.ts +0 -146
- package/src/vs/base/common/errors.ts +0 -303
- package/src/vs/base/common/event.ts +0 -1778
- package/src/vs/base/common/functional.ts +0 -32
- package/src/vs/base/common/hash.ts +0 -316
- package/src/vs/base/common/iterator.ts +0 -159
- package/src/vs/base/common/keyCodes.ts +0 -526
- package/src/vs/base/common/keybindings.ts +0 -284
- package/src/vs/base/common/lazy.ts +0 -47
- package/src/vs/base/common/lifecycle.ts +0 -801
- package/src/vs/base/common/linkedList.ts +0 -142
- package/src/vs/base/common/map.ts +0 -202
- package/src/vs/base/common/numbers.ts +0 -98
- package/src/vs/base/common/observable.ts +0 -76
- package/src/vs/base/common/observableInternal/api.ts +0 -31
- package/src/vs/base/common/observableInternal/autorun.ts +0 -281
- package/src/vs/base/common/observableInternal/base.ts +0 -489
- package/src/vs/base/common/observableInternal/debugName.ts +0 -145
- package/src/vs/base/common/observableInternal/derived.ts +0 -428
- package/src/vs/base/common/observableInternal/lazyObservableValue.ts +0 -146
- package/src/vs/base/common/observableInternal/logging.ts +0 -328
- package/src/vs/base/common/observableInternal/promise.ts +0 -209
- package/src/vs/base/common/observableInternal/utils.ts +0 -610
- package/src/vs/base/common/platform.ts +0 -281
- package/src/vs/base/common/scrollable.ts +0 -522
- package/src/vs/base/common/sequence.ts +0 -34
- package/src/vs/base/common/stopwatch.ts +0 -43
- package/src/vs/base/common/strings.ts +0 -557
- package/src/vs/base/common/symbols.ts +0 -9
- package/src/vs/base/common/uint.ts +0 -59
- package/src/vs/patches/nls.ts +0 -90
- package/src/vs/typings/base-common.d.ts +0 -20
- package/src/vs/typings/require.d.ts +0 -42
- package/src/vs/typings/vscode-globals-nls.d.ts +0 -36
- package/src/vs/typings/vscode-globals-product.d.ts +0 -33
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* @license MIT
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { IKeyboardEvent, IKeyboardResult, KeyboardResultType } from '
|
|
8
|
-
import { C0 } from '
|
|
7
|
+
import { IKeyboardEvent, IKeyboardResult, KeyboardResultType } from '../Types';
|
|
8
|
+
import { C0 } from '../data/EscapeSequences';
|
|
9
9
|
|
|
10
10
|
// reg + shift key mappings for digits and special chars
|
|
11
11
|
const KEYCODE_KEY_MAPPINGS: { [key: number]: [string, string]} = {
|
|
@@ -46,7 +46,7 @@ export function evaluateKeyboardEvent(
|
|
|
46
46
|
// Whether to cancel event propagation (NOTE: this may not be needed since the event is
|
|
47
47
|
// canceled at the end of keyDown
|
|
48
48
|
cancel: false,
|
|
49
|
-
// The new key
|
|
49
|
+
// The new key event to emit
|
|
50
50
|
key: undefined
|
|
51
51
|
};
|
|
52
52
|
const modifiers = (ev.shiftKey ? 1 : 0) | (ev.altKey ? 2 : 0) | (ev.ctrlKey ? 4 : 0) | (ev.metaKey ? 8 : 0);
|
|
@@ -99,7 +99,13 @@ export function evaluateKeyboardEvent(
|
|
|
99
99
|
break;
|
|
100
100
|
case 13:
|
|
101
101
|
// return/enter
|
|
102
|
-
|
|
102
|
+
if (ev.key === 'c' && ev.ctrlKey) {
|
|
103
|
+
// HACK: Safari on iPad, iOS, AppleVisionPro sends key 13 when typing ctrl-c on hardware
|
|
104
|
+
// keyboard
|
|
105
|
+
result.key = C0.ETX;
|
|
106
|
+
} else {
|
|
107
|
+
result.key = ev.altKey ? C0.ESC + C0.CR : C0.CR;
|
|
108
|
+
}
|
|
103
109
|
result.cancel = true;
|
|
104
110
|
break;
|
|
105
111
|
case 27:
|
|
@@ -315,6 +321,8 @@ export function evaluateKeyboardEvent(
|
|
|
315
321
|
result.key = String.fromCharCode(ev.keyCode - 51 + 27);
|
|
316
322
|
} else if (ev.keyCode === 56) {
|
|
317
323
|
result.key = C0.DEL;
|
|
324
|
+
} else if (ev.key === '/') {
|
|
325
|
+
result.key = C0.US; // https://github.com/xtermjs/xterm.js/issues/5457
|
|
318
326
|
} else if (ev.keyCode === 219) {
|
|
319
327
|
result.key = C0.ESC;
|
|
320
328
|
} else if (ev.keyCode === 220) {
|
|
@@ -358,12 +366,11 @@ export function evaluateKeyboardEvent(
|
|
|
358
366
|
// Include only keys that that result in a _single_ character; don't include num lock,
|
|
359
367
|
// volume up, etc.
|
|
360
368
|
result.key = ev.key;
|
|
361
|
-
} else if (ev.key && ev.ctrlKey) {
|
|
362
|
-
|
|
363
|
-
result.key = C0.US;
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
result.key = C0.NUL;
|
|
369
|
+
} else if (ev.key && ev.ctrlKey && ev.shiftKey) {
|
|
370
|
+
switch (ev.code) {
|
|
371
|
+
case 'Minus': result.key = C0.US; break; // ^_ (Ctrl+Shift+-_
|
|
372
|
+
case 'Digit2': result.key = C0.NUL; break; // ^@ (Ctrl+Shift+2)
|
|
373
|
+
case 'Digit6': result.key = C0.RS; break; // ^^ (Ctrl+Shift+6)
|
|
367
374
|
}
|
|
368
375
|
}
|
|
369
376
|
break;
|
|
@@ -0,0 +1,526 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 The xterm.js authors. All rights reserved.
|
|
3
|
+
* @license MIT
|
|
4
|
+
*
|
|
5
|
+
* Kitty keyboard protocol implementation.
|
|
6
|
+
* @see https://sw.kovidgoyal.net/kitty/keyboard-protocol/
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { IKeyboardEvent, IKeyboardResult, KeyboardResultType } from '../Types';
|
|
10
|
+
import { C0 } from '../data/EscapeSequences';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Kitty keyboard protocol enhancement flags (bitfield).
|
|
14
|
+
*/
|
|
15
|
+
export const enum KittyKeyboardFlags {
|
|
16
|
+
NONE = 0b00000,
|
|
17
|
+
/** Disambiguate escape codes - fixes ambiguous legacy encodings */
|
|
18
|
+
DISAMBIGUATE_ESCAPE_CODES = 0b00001,
|
|
19
|
+
/** Report event types - press/repeat/release */
|
|
20
|
+
REPORT_EVENT_TYPES = 0b00010,
|
|
21
|
+
/** Report alternate keys - shifted key and base layout key */
|
|
22
|
+
REPORT_ALTERNATE_KEYS = 0b00100,
|
|
23
|
+
/** Report all keys as escape codes - text-producing keys as CSI u */
|
|
24
|
+
REPORT_ALL_KEYS_AS_ESCAPE_CODES = 0b01000,
|
|
25
|
+
/** Report associated text - includes text codepoints in escape code */
|
|
26
|
+
REPORT_ASSOCIATED_TEXT = 0b10000,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Kitty keyboard event types.
|
|
31
|
+
*/
|
|
32
|
+
export const enum KittyKeyboardEventType {
|
|
33
|
+
PRESS = 1,
|
|
34
|
+
REPEAT = 2,
|
|
35
|
+
RELEASE = 3,
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Kitty modifier bits (different from xterm modifier encoding).
|
|
40
|
+
* Value sent = 1 + modifier_bits
|
|
41
|
+
*/
|
|
42
|
+
export const enum KittyKeyboardModifiers {
|
|
43
|
+
SHIFT = 0b00000001,
|
|
44
|
+
ALT = 0b00000010,
|
|
45
|
+
CTRL = 0b00000100,
|
|
46
|
+
SUPER = 0b00001000,
|
|
47
|
+
HYPER = 0b00010000,
|
|
48
|
+
META = 0b00100000,
|
|
49
|
+
CAPS_LOCK = 0b01000000,
|
|
50
|
+
NUM_LOCK = 0b10000000,
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Kitty keyboard protocol handler class.
|
|
55
|
+
* Encapsulates all key code mappings and encoding logic.
|
|
56
|
+
*/
|
|
57
|
+
export class KittyKeyboard {
|
|
58
|
+
/**
|
|
59
|
+
* Functional key codes for Kitty protocol.
|
|
60
|
+
* Keys that don't produce text have specific unicode codepoint mappings.
|
|
61
|
+
*/
|
|
62
|
+
private readonly _functionalKeyCodes: { [key: string]: number } = {
|
|
63
|
+
'Escape': 27,
|
|
64
|
+
'Enter': 13,
|
|
65
|
+
'Tab': 9,
|
|
66
|
+
'Backspace': 127,
|
|
67
|
+
'CapsLock': 57358,
|
|
68
|
+
'ScrollLock': 57359,
|
|
69
|
+
'NumLock': 57360,
|
|
70
|
+
'PrintScreen': 57361,
|
|
71
|
+
'Pause': 57362,
|
|
72
|
+
'ContextMenu': 57363,
|
|
73
|
+
// F13-F35 (F1-F12 use legacy encoding)
|
|
74
|
+
'F13': 57376,
|
|
75
|
+
'F14': 57377,
|
|
76
|
+
'F15': 57378,
|
|
77
|
+
'F16': 57379,
|
|
78
|
+
'F17': 57380,
|
|
79
|
+
'F18': 57381,
|
|
80
|
+
'F19': 57382,
|
|
81
|
+
'F20': 57383,
|
|
82
|
+
'F21': 57384,
|
|
83
|
+
'F22': 57385,
|
|
84
|
+
'F23': 57386,
|
|
85
|
+
'F24': 57387,
|
|
86
|
+
'F25': 57388,
|
|
87
|
+
// Keypad keys
|
|
88
|
+
'KP_0': 57399,
|
|
89
|
+
'KP_1': 57400,
|
|
90
|
+
'KP_2': 57401,
|
|
91
|
+
'KP_3': 57402,
|
|
92
|
+
'KP_4': 57403,
|
|
93
|
+
'KP_5': 57404,
|
|
94
|
+
'KP_6': 57405,
|
|
95
|
+
'KP_7': 57406,
|
|
96
|
+
'KP_8': 57407,
|
|
97
|
+
'KP_9': 57408,
|
|
98
|
+
'KP_Decimal': 57409,
|
|
99
|
+
'KP_Divide': 57410,
|
|
100
|
+
'KP_Multiply': 57411,
|
|
101
|
+
'KP_Subtract': 57412,
|
|
102
|
+
'KP_Add': 57413,
|
|
103
|
+
'KP_Enter': 57414,
|
|
104
|
+
'KP_Equal': 57415,
|
|
105
|
+
// Modifier keys
|
|
106
|
+
'ShiftLeft': 57441,
|
|
107
|
+
'ShiftRight': 57447,
|
|
108
|
+
'ControlLeft': 57442,
|
|
109
|
+
'ControlRight': 57448,
|
|
110
|
+
'AltLeft': 57443,
|
|
111
|
+
'AltRight': 57449,
|
|
112
|
+
'MetaLeft': 57444,
|
|
113
|
+
'MetaRight': 57450,
|
|
114
|
+
// Media keys
|
|
115
|
+
'MediaPlayPause': 57430,
|
|
116
|
+
'MediaStop': 57432,
|
|
117
|
+
'MediaTrackNext': 57435,
|
|
118
|
+
'MediaTrackPrevious': 57436,
|
|
119
|
+
'AudioVolumeDown': 57438,
|
|
120
|
+
'AudioVolumeUp': 57439,
|
|
121
|
+
'AudioVolumeMute': 57440
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Keys that use CSI ~ encoding with a number parameter.
|
|
126
|
+
*/
|
|
127
|
+
private readonly _csiTildeKeys: { [key: string]: number } = {
|
|
128
|
+
'Insert': 2,
|
|
129
|
+
'Delete': 3,
|
|
130
|
+
'PageUp': 5,
|
|
131
|
+
'PageDown': 6,
|
|
132
|
+
'F5': 15,
|
|
133
|
+
'F6': 17,
|
|
134
|
+
'F7': 18,
|
|
135
|
+
'F8': 19,
|
|
136
|
+
'F9': 20,
|
|
137
|
+
'F10': 21,
|
|
138
|
+
'F11': 23,
|
|
139
|
+
'F12': 24
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Keys that use CSI letter encoding (arrows, Home, End).
|
|
144
|
+
*/
|
|
145
|
+
private readonly _csiLetterKeys: { [key: string]: string } = {
|
|
146
|
+
'ArrowUp': 'A',
|
|
147
|
+
'ArrowDown': 'B',
|
|
148
|
+
'ArrowRight': 'C',
|
|
149
|
+
'ArrowLeft': 'D',
|
|
150
|
+
'Home': 'H',
|
|
151
|
+
'End': 'F'
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Function keys F1-F4 use SS3 encoding without modifiers.
|
|
156
|
+
*/
|
|
157
|
+
private readonly _ss3FunctionKeys: { [key: string]: string } = {
|
|
158
|
+
'F1': 'P',
|
|
159
|
+
'F2': 'Q',
|
|
160
|
+
'F3': 'R',
|
|
161
|
+
'F4': 'S'
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Map browser key codes to Kitty numpad codes.
|
|
166
|
+
*/
|
|
167
|
+
private _getNumpadKeyCode(ev: IKeyboardEvent): number | undefined {
|
|
168
|
+
if (ev.code.startsWith('Numpad')) {
|
|
169
|
+
const suffix = ev.code.slice(6);
|
|
170
|
+
if (suffix >= '0' && suffix <= '9') {
|
|
171
|
+
return 57399 + parseInt(suffix, 10);
|
|
172
|
+
}
|
|
173
|
+
switch (suffix) {
|
|
174
|
+
case 'Decimal': return 57409;
|
|
175
|
+
case 'Divide': return 57410;
|
|
176
|
+
case 'Multiply': return 57411;
|
|
177
|
+
case 'Subtract': return 57412;
|
|
178
|
+
case 'Add': return 57413;
|
|
179
|
+
case 'Enter': return 57414;
|
|
180
|
+
case 'Equal': return 57415;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return undefined;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Get modifier key code from code property.
|
|
188
|
+
*/
|
|
189
|
+
private _getModifierKeyCode(ev: IKeyboardEvent): number | undefined {
|
|
190
|
+
switch (ev.code) {
|
|
191
|
+
case 'ShiftLeft': return 57441;
|
|
192
|
+
case 'ShiftRight': return 57447;
|
|
193
|
+
case 'ControlLeft': return 57442;
|
|
194
|
+
case 'ControlRight': return 57448;
|
|
195
|
+
case 'AltLeft': return 57443;
|
|
196
|
+
case 'AltRight': return 57449;
|
|
197
|
+
case 'MetaLeft': return 57444;
|
|
198
|
+
case 'MetaRight': return 57450;
|
|
199
|
+
}
|
|
200
|
+
return undefined;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Encode modifiers for Kitty protocol.
|
|
205
|
+
* Returns 1 + modifier bits, or 0 if no modifiers.
|
|
206
|
+
*/
|
|
207
|
+
private _encodeModifiers(ev: IKeyboardEvent): number {
|
|
208
|
+
let mods = 0;
|
|
209
|
+
if (ev.shiftKey) mods |= KittyKeyboardModifiers.SHIFT;
|
|
210
|
+
if (ev.altKey) mods |= KittyKeyboardModifiers.ALT;
|
|
211
|
+
if (ev.ctrlKey) mods |= KittyKeyboardModifiers.CTRL;
|
|
212
|
+
if (ev.metaKey) mods |= KittyKeyboardModifiers.SUPER;
|
|
213
|
+
return mods > 0 ? mods + 1 : 0;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Get the unicode key code for a keyboard event.
|
|
218
|
+
* Returns the lowercase codepoint for letters.
|
|
219
|
+
* For shifted keys, uses the code property to get the base key.
|
|
220
|
+
*/
|
|
221
|
+
private _getKeyCode(ev: IKeyboardEvent, macOptionAsAlt: boolean): number | undefined {
|
|
222
|
+
const numpadCode = this._getNumpadKeyCode(ev);
|
|
223
|
+
if (numpadCode !== undefined) {
|
|
224
|
+
return numpadCode;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const modifierCode = this._getModifierKeyCode(ev);
|
|
228
|
+
if (modifierCode !== undefined) {
|
|
229
|
+
return modifierCode;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const funcCode = this._functionalKeyCodes[ev.key];
|
|
233
|
+
if (funcCode !== undefined) {
|
|
234
|
+
return funcCode;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if ((ev.shiftKey || (macOptionAsAlt && ev.altKey)) && ev.code) {
|
|
238
|
+
if (ev.code.startsWith('Digit') && ev.code.length === 6) {
|
|
239
|
+
const digit = ev.code.charAt(5);
|
|
240
|
+
if (digit >= '0' && digit <= '9') {
|
|
241
|
+
return digit.charCodeAt(0);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
if (ev.code.startsWith('Key') && ev.code.length === 4) {
|
|
245
|
+
const letter = ev.code.charAt(3).toLowerCase();
|
|
246
|
+
return letter.charCodeAt(0);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if (ev.key.length === 1) {
|
|
251
|
+
const code = ev.key.codePointAt(0)!;
|
|
252
|
+
if (code >= 65 && code <= 90) {
|
|
253
|
+
return code + 32;
|
|
254
|
+
}
|
|
255
|
+
return code;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return undefined;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Check if a key is a modifier key.
|
|
263
|
+
*/
|
|
264
|
+
private _isModifierKey(ev: IKeyboardEvent): boolean {
|
|
265
|
+
return ev.key === 'Shift' || ev.key === 'Control' || ev.key === 'Alt' || ev.key === 'Meta';
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Check if a key is a lock key (CapsLock/NumLock/ScrollLock).
|
|
270
|
+
*
|
|
271
|
+
* Kitty's reference implementation classifies these as modifier keys for the
|
|
272
|
+
* purpose of suppressing press events (kitty/keys.c `is_modifier_key()`
|
|
273
|
+
* includes `GLFW_FKEY_CAPS_LOCK`, `GLFW_FKEY_SCROLL_LOCK`, `GLFW_FKEY_NUM_LOCK`),
|
|
274
|
+
* and its test suite asserts that a CapsLock press with no protocol flags
|
|
275
|
+
* produces empty output.
|
|
276
|
+
*/
|
|
277
|
+
private _isLockKey(ev: IKeyboardEvent): boolean {
|
|
278
|
+
return ev.key === 'CapsLock' || ev.key === 'NumLock' || ev.key === 'ScrollLock';
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Build CSI letter sequence for arrow keys, Home, End.
|
|
283
|
+
* Format: CSI [1;mod] letter
|
|
284
|
+
*/
|
|
285
|
+
private _buildCsiLetterSequence(
|
|
286
|
+
letter: string,
|
|
287
|
+
modifiers: number,
|
|
288
|
+
eventType: KittyKeyboardEventType,
|
|
289
|
+
reportEventTypes: boolean
|
|
290
|
+
): string {
|
|
291
|
+
const needsEventType = reportEventTypes && eventType !== KittyKeyboardEventType.PRESS;
|
|
292
|
+
|
|
293
|
+
if (modifiers > 0 || needsEventType) {
|
|
294
|
+
let seq = C0.ESC + '[1;' + (modifiers > 0 ? modifiers : '1');
|
|
295
|
+
if (needsEventType) {
|
|
296
|
+
seq += ':' + eventType;
|
|
297
|
+
}
|
|
298
|
+
seq += letter;
|
|
299
|
+
return seq;
|
|
300
|
+
}
|
|
301
|
+
return C0.ESC + '[' + letter;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Build SS3 sequence for F1-F4.
|
|
306
|
+
* Without modifiers: SS3 letter
|
|
307
|
+
* With modifiers: CSI 1;mod letter
|
|
308
|
+
*/
|
|
309
|
+
private _buildSs3Sequence(
|
|
310
|
+
letter: string,
|
|
311
|
+
modifiers: number,
|
|
312
|
+
eventType: KittyKeyboardEventType,
|
|
313
|
+
reportEventTypes: boolean
|
|
314
|
+
): string {
|
|
315
|
+
const needsEventType = reportEventTypes && eventType !== KittyKeyboardEventType.PRESS;
|
|
316
|
+
|
|
317
|
+
if (modifiers > 0 || needsEventType) {
|
|
318
|
+
let seq = C0.ESC + '[1;' + (modifiers > 0 ? modifiers : '1');
|
|
319
|
+
if (needsEventType) {
|
|
320
|
+
seq += ':' + eventType;
|
|
321
|
+
}
|
|
322
|
+
seq += letter;
|
|
323
|
+
return seq;
|
|
324
|
+
}
|
|
325
|
+
return C0.ESC + 'O' + letter;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Build CSI ~ sequence for Insert, Delete, PageUp/Down, F5-F12.
|
|
330
|
+
* Format: CSI number [;mod[:event]] ~
|
|
331
|
+
*/
|
|
332
|
+
private _buildCsiTildeSequence(
|
|
333
|
+
number: number,
|
|
334
|
+
modifiers: number,
|
|
335
|
+
eventType: KittyKeyboardEventType,
|
|
336
|
+
reportEventTypes: boolean
|
|
337
|
+
): string {
|
|
338
|
+
const needsEventType = reportEventTypes && eventType !== KittyKeyboardEventType.PRESS;
|
|
339
|
+
|
|
340
|
+
let seq = C0.ESC + '[' + number;
|
|
341
|
+
if (modifiers > 0 || needsEventType) {
|
|
342
|
+
seq += ';' + (modifiers > 0 ? modifiers : '1');
|
|
343
|
+
if (needsEventType) {
|
|
344
|
+
seq += ':' + eventType;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
seq += '~';
|
|
348
|
+
return seq;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Build CSI u sequence.
|
|
353
|
+
* Format: CSI keycode[:shifted[:base]] [;mod[:event][;text]] u
|
|
354
|
+
*/
|
|
355
|
+
private _buildCsiUSequence(
|
|
356
|
+
ev: IKeyboardEvent,
|
|
357
|
+
keyCode: number,
|
|
358
|
+
modifiers: number,
|
|
359
|
+
eventType: KittyKeyboardEventType,
|
|
360
|
+
flags: number,
|
|
361
|
+
isFunc: boolean,
|
|
362
|
+
isMod: boolean
|
|
363
|
+
): string {
|
|
364
|
+
const reportEventTypes = !!(flags & KittyKeyboardFlags.REPORT_EVENT_TYPES);
|
|
365
|
+
const reportAlternateKeys = !!(flags & KittyKeyboardFlags.REPORT_ALTERNATE_KEYS);
|
|
366
|
+
|
|
367
|
+
let seq = C0.ESC + '[' + keyCode;
|
|
368
|
+
|
|
369
|
+
let shiftedKey: number | undefined;
|
|
370
|
+
if (reportAlternateKeys && ev.shiftKey && ev.key.length === 1 && !isFunc && !isMod) {
|
|
371
|
+
shiftedKey = ev.key.codePointAt(0);
|
|
372
|
+
seq += ':' + shiftedKey;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
const reportAssociatedText = !!(flags & KittyKeyboardFlags.REPORT_ASSOCIATED_TEXT) &&
|
|
376
|
+
eventType !== KittyKeyboardEventType.RELEASE &&
|
|
377
|
+
ev.key.length === 1 &&
|
|
378
|
+
!isFunc &&
|
|
379
|
+
!isMod &&
|
|
380
|
+
!ev.ctrlKey;
|
|
381
|
+
const textCode = reportAssociatedText ? ev.key.codePointAt(0) : undefined;
|
|
382
|
+
|
|
383
|
+
const needsEventType = reportEventTypes &&
|
|
384
|
+
eventType !== KittyKeyboardEventType.PRESS &&
|
|
385
|
+
(eventType === KittyKeyboardEventType.RELEASE || textCode === undefined);
|
|
386
|
+
|
|
387
|
+
if (modifiers > 0 || needsEventType || textCode !== undefined) {
|
|
388
|
+
seq += ';';
|
|
389
|
+
if (modifiers > 0) {
|
|
390
|
+
seq += modifiers;
|
|
391
|
+
} else if (needsEventType) {
|
|
392
|
+
seq += '1';
|
|
393
|
+
}
|
|
394
|
+
if (needsEventType) {
|
|
395
|
+
seq += ':' + eventType;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
if (textCode !== undefined) {
|
|
400
|
+
seq += ';' + textCode;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
seq += 'u';
|
|
404
|
+
return seq;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Evaluate a keyboard event using Kitty keyboard protocol.
|
|
409
|
+
*
|
|
410
|
+
* @param ev The keyboard event.
|
|
411
|
+
* @param flags The active Kitty keyboard enhancement flags.
|
|
412
|
+
* @param eventType The event type (press, repeat, release).
|
|
413
|
+
* @param macOptionAsAlt When true, macOS Option-composed ev.key values are unwound via ev.code.
|
|
414
|
+
* @returns The keyboard result with the encoded key sequence.
|
|
415
|
+
*/
|
|
416
|
+
public evaluate(
|
|
417
|
+
ev: IKeyboardEvent,
|
|
418
|
+
flags: number,
|
|
419
|
+
eventType: KittyKeyboardEventType = KittyKeyboardEventType.PRESS,
|
|
420
|
+
macOptionAsAlt: boolean = false
|
|
421
|
+
): IKeyboardResult {
|
|
422
|
+
const result: IKeyboardResult = {
|
|
423
|
+
type: KeyboardResultType.SEND_KEY,
|
|
424
|
+
cancel: false,
|
|
425
|
+
key: undefined
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
const modifiers = this._encodeModifiers(ev);
|
|
429
|
+
const isMod = this._isModifierKey(ev);
|
|
430
|
+
const reportEventTypes = !!(flags & KittyKeyboardFlags.REPORT_EVENT_TYPES);
|
|
431
|
+
|
|
432
|
+
if (!reportEventTypes && eventType === KittyKeyboardEventType.RELEASE) {
|
|
433
|
+
return result;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
if (isMod && !(flags & KittyKeyboardFlags.REPORT_ALL_KEYS_AS_ESCAPE_CODES)) {
|
|
437
|
+
return result;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// Spec § "Report all keys as escape codes": "Additionally, with this mode,
|
|
441
|
+
// events for pressing modifier keys are reported." — i.e. *without* this
|
|
442
|
+
// mode, modifier-key press events are suppressed. Kitty's is_modifier_key()
|
|
443
|
+
// treats CapsLock/NumLock/ScrollLock as modifier keys for this rule.
|
|
444
|
+
if (this._isLockKey(ev) && !(flags & KittyKeyboardFlags.REPORT_ALL_KEYS_AS_ESCAPE_CODES)) {
|
|
445
|
+
return result;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
const csiLetter = this._csiLetterKeys[ev.key];
|
|
449
|
+
if (csiLetter) {
|
|
450
|
+
result.key = this._buildCsiLetterSequence(csiLetter, modifiers, eventType, reportEventTypes);
|
|
451
|
+
result.cancel = true;
|
|
452
|
+
return result;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
const ss3Letter = this._ss3FunctionKeys[ev.key];
|
|
456
|
+
if (ss3Letter) {
|
|
457
|
+
result.key = this._buildSs3Sequence(ss3Letter, modifiers, eventType, reportEventTypes);
|
|
458
|
+
result.cancel = true;
|
|
459
|
+
return result;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
const tildeCode = this._csiTildeKeys[ev.key];
|
|
463
|
+
if (tildeCode !== undefined) {
|
|
464
|
+
result.key = this._buildCsiTildeSequence(tildeCode, modifiers, eventType, reportEventTypes);
|
|
465
|
+
result.cancel = true;
|
|
466
|
+
return result;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
const keyCode = this._getKeyCode(ev, macOptionAsAlt);
|
|
470
|
+
if (keyCode === undefined) {
|
|
471
|
+
return result;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
// Special handling for Enter/Tab/Backspace.
|
|
475
|
+
const specialKey = keyCode === 13 || keyCode === 9 || keyCode === 127;
|
|
476
|
+
|
|
477
|
+
// Per spec, Enter/Tab/Backspace will not have release events unless "Report all keys as escape
|
|
478
|
+
// codes" is also set.
|
|
479
|
+
if (specialKey && eventType === KittyKeyboardEventType.RELEASE && !(flags & KittyKeyboardFlags.REPORT_ALL_KEYS_AS_ESCAPE_CODES)) {
|
|
480
|
+
return result;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
const isFunc = this._functionalKeyCodes[ev.key] !== undefined || this._getNumpadKeyCode(ev) !== undefined;
|
|
484
|
+
|
|
485
|
+
const useCsiU = !!(
|
|
486
|
+
flags & KittyKeyboardFlags.REPORT_ALL_KEYS_AS_ESCAPE_CODES ||
|
|
487
|
+
(reportEventTypes && eventType === KittyKeyboardEventType.RELEASE) ||
|
|
488
|
+
// Enabling REPORT_EVENT_TYPES without DISAMBIGUATE_ESCAPE_CODES doesn't really make sense, so
|
|
489
|
+
// just make REPORT_EVENT_TYPES imply DISAMBIGUATE_ESCAPE_CODES here for simplicity.
|
|
490
|
+
// See: https://github.com/kovidgoyal/kitty/issues/9999
|
|
491
|
+
((flags & KittyKeyboardFlags.DISAMBIGUATE_ESCAPE_CODES || reportEventTypes) &&
|
|
492
|
+
(
|
|
493
|
+
// Per spec, Enter/Tab/Backspace "still generate the same bytes as in legacy mode" and
|
|
494
|
+
// consider space to be a text-generating key, so these skip the isFunc fast-path and only
|
|
495
|
+
// get CSI u when modifiers are present (handled below).
|
|
496
|
+
(isFunc && !specialKey) ||
|
|
497
|
+
(
|
|
498
|
+
(modifiers > 0 && ev.key.length !== 1) ||
|
|
499
|
+
modifiers - 1 > KittyKeyboardModifiers.SHIFT
|
|
500
|
+
)
|
|
501
|
+
)
|
|
502
|
+
)
|
|
503
|
+
);
|
|
504
|
+
|
|
505
|
+
if (useCsiU) {
|
|
506
|
+
result.key = this._buildCsiUSequence(ev, keyCode, modifiers, eventType, flags, isFunc, isMod);
|
|
507
|
+
result.cancel = true;
|
|
508
|
+
} else {
|
|
509
|
+
const legacyByte = keyCode === 13 ? '\r' : keyCode === 9 ? '\t' : keyCode === 127 ? '\x7f' : undefined;
|
|
510
|
+
if (legacyByte) {
|
|
511
|
+
result.key = legacyByte;
|
|
512
|
+
} else if (ev.key.length === 1 && !ev.ctrlKey && !ev.altKey && !ev.metaKey) {
|
|
513
|
+
result.key = ev.key;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
return result;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
/**
|
|
521
|
+
* Check if Kitty protocol should be used based on flags.
|
|
522
|
+
*/
|
|
523
|
+
public static shouldUseProtocol(flags: number): boolean {
|
|
524
|
+
return flags > 0;
|
|
525
|
+
}
|
|
526
|
+
}
|
|
@@ -148,7 +148,7 @@ export class Utf8ToUtf32 {
|
|
|
148
148
|
let byte2: number;
|
|
149
149
|
let byte3: number;
|
|
150
150
|
let byte4: number;
|
|
151
|
-
let codepoint
|
|
151
|
+
let codepoint;
|
|
152
152
|
let startPos = 0;
|
|
153
153
|
|
|
154
154
|
// handle leftover bytes
|
|
@@ -158,9 +158,9 @@ export class Utf8ToUtf32 {
|
|
|
158
158
|
cp &= ((((cp & 0xE0) === 0xC0)) ? 0x1F : (((cp & 0xF0) === 0xE0)) ? 0x0F : 0x07);
|
|
159
159
|
let pos = 0;
|
|
160
160
|
let tmp: number;
|
|
161
|
-
while ((tmp = this.interim[++pos]
|
|
161
|
+
while ((tmp = this.interim[++pos]) && pos < 4) {
|
|
162
162
|
cp <<= 6;
|
|
163
|
-
cp |= tmp;
|
|
163
|
+
cp |= tmp & 0x3F;
|
|
164
164
|
}
|
|
165
165
|
// missing bytes - read ahead from input
|
|
166
166
|
const type = (((this.interim[0] & 0xE0) === 0xC0)) ? 2 : (((this.interim[0] & 0xF0) === 0xE0)) ? 3 : 4;
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
|
|
3
3
|
* @license MIT
|
|
4
4
|
*/
|
|
5
|
-
import { IUnicodeVersionProvider, UnicodeCharProperties, UnicodeCharWidth } from '
|
|
6
|
-
import { UnicodeService } from '
|
|
5
|
+
import { IUnicodeVersionProvider, UnicodeCharProperties, UnicodeCharWidth } from '../services/Services';
|
|
6
|
+
import { UnicodeService } from '../services/UnicodeService';
|
|
7
7
|
|
|
8
8
|
const BMP_COMBINING = [
|
|
9
9
|
[0x0300, 0x036F], [0x0483, 0x0486], [0x0488, 0x0489],
|
|
@@ -132,6 +132,7 @@ export class UnicodeV6 implements IUnicodeVersionProvider {
|
|
|
132
132
|
public charProperties(codepoint: number, preceding: UnicodeCharProperties): UnicodeCharProperties {
|
|
133
133
|
let width = this.wcwidth(codepoint);
|
|
134
134
|
let shouldJoin = width === 0 && preceding !== 0;
|
|
135
|
+
// HACK: Ideally this file would not depend on the service which uses it
|
|
135
136
|
if (shouldJoin) {
|
|
136
137
|
const oldWidth = UnicodeService.extractWidth(preceding);
|
|
137
138
|
if (oldWidth === 0) {
|