@xterm/xterm 6.1.0-beta.19 → 6.1.0-beta.191
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 +60 -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 +25 -14
- package/src/browser/AccessibilityManager.ts +6 -3
- package/src/browser/Clipboard.ts +6 -3
- package/src/browser/CoreBrowserTerminal.ts +147 -318
- package/src/browser/Dom.ts +178 -0
- package/src/browser/Linkifier.ts +11 -11
- package/src/browser/OscLinkProvider.ts +3 -1
- package/src/browser/RenderDebouncer.ts +2 -2
- package/src/browser/TimeBasedDebouncer.ts +2 -2
- package/src/browser/Types.ts +12 -11
- package/src/browser/Viewport.ts +37 -20
- package/src/browser/decorations/BufferDecorationRenderer.ts +1 -1
- package/src/browser/decorations/OverviewRulerRenderer.ts +15 -16
- package/src/browser/input/CompositionHelper.ts +44 -8
- package/src/browser/public/Terminal.ts +25 -28
- package/src/browser/renderer/dom/DomRenderer.ts +131 -8
- package/src/browser/renderer/dom/DomRendererRowFactory.ts +19 -13
- package/src/browser/renderer/dom/WidthCache.ts +54 -52
- package/src/browser/renderer/shared/Constants.ts +7 -0
- package/src/browser/renderer/shared/TextBlinkStateManager.ts +97 -0
- package/src/browser/renderer/shared/Types.ts +8 -2
- 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 +579 -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/services/CharSizeService.ts +2 -2
- package/src/browser/services/CoreBrowserService.ts +7 -5
- package/src/browser/services/KeyboardService.ts +67 -0
- package/src/browser/services/LinkProviderService.ts +1 -1
- package/src/browser/services/MouseCoordsService.ts +47 -0
- package/src/browser/services/MouseService.ts +518 -25
- package/src/browser/services/RenderService.ts +22 -15
- package/src/browser/services/SelectionService.ts +16 -8
- package/src/browser/services/Services.ts +40 -17
- package/src/browser/services/ThemeService.ts +2 -2
- package/src/common/Async.ts +105 -0
- package/src/common/CircularList.ts +2 -2
- package/src/common/Color.ts +8 -0
- package/src/common/CoreTerminal.ts +28 -18
- package/src/common/Event.ts +118 -0
- package/src/common/InputHandler.ts +256 -36
- package/src/common/Lifecycle.ts +113 -0
- package/src/common/Platform.ts +13 -3
- package/src/common/SortedList.ts +7 -3
- package/src/common/TaskQueue.ts +9 -3
- package/src/common/Types.ts +35 -15
- package/src/common/Version.ts +9 -0
- package/src/common/buffer/Buffer.ts +20 -14
- package/src/common/buffer/BufferLine.ts +4 -5
- package/src/common/buffer/BufferSet.ts +7 -6
- package/src/common/buffer/CellData.ts +57 -0
- package/src/common/buffer/Marker.ts +2 -2
- package/src/common/buffer/Types.ts +6 -2
- package/src/common/data/EscapeSequences.ts +71 -70
- package/src/common/input/Keyboard.ts +14 -7
- package/src/common/input/KittyKeyboard.ts +496 -0
- package/src/common/input/Win32InputMode.ts +297 -0
- package/src/common/input/WriteBuffer.ts +34 -2
- package/src/common/input/XParseColor.ts +2 -2
- package/src/common/parser/ApcParser.ts +245 -0
- package/src/common/parser/Constants.ts +22 -4
- package/src/common/parser/DcsParser.ts +5 -5
- package/src/common/parser/EscapeSequenceParser.ts +75 -22
- package/src/common/parser/OscParser.ts +5 -5
- package/src/common/parser/Types.ts +34 -1
- package/src/common/public/BufferLineApiView.ts +2 -2
- package/src/common/public/BufferNamespaceApi.ts +2 -2
- package/src/common/public/ParserApi.ts +3 -0
- package/src/common/services/BufferService.ts +8 -5
- package/src/common/services/CharsetService.ts +4 -0
- package/src/common/services/CoreService.ts +18 -4
- package/src/common/services/DecorationService.ts +24 -8
- package/src/common/services/LogService.ts +1 -31
- package/src/common/services/{CoreMouseService.ts → MouseStateService.ts} +21 -132
- package/src/common/services/OptionsService.ts +13 -4
- package/src/common/services/Services.ts +47 -40
- package/src/common/services/UnicodeService.ts +1 -1
- package/typings/xterm.d.ts +319 -35
- 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
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* http://linux.die.net/man/7/urxvt
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
-
import { IDecoration, IDecorationOptions, IDisposable, ILinkProvider, IMarker } from '@xterm/xterm';
|
|
24
|
+
import { IDecoration, IDecorationOptions, IDisposable, ILinkProvider, IMarker, IRenderDimensions as IRenderDimensionsApi } from '@xterm/xterm';
|
|
25
25
|
import { copyHandler, handlePasteEvent, moveTextAreaUnderMouseCursor, paste, rightClickHandler } from 'browser/Clipboard';
|
|
26
26
|
import * as Strings from 'browser/LocalizableStrings';
|
|
27
27
|
import { OscLinkProvider } from 'browser/OscLinkProvider';
|
|
@@ -36,28 +36,29 @@ import { CharSizeService } from 'browser/services/CharSizeService';
|
|
|
36
36
|
import { CharacterJoinerService } from 'browser/services/CharacterJoinerService';
|
|
37
37
|
import { CoreBrowserService } from 'browser/services/CoreBrowserService';
|
|
38
38
|
import { LinkProviderService } from 'browser/services/LinkProviderService';
|
|
39
|
+
import { MouseCoordsService } from 'browser/services/MouseCoordsService';
|
|
39
40
|
import { MouseService } from 'browser/services/MouseService';
|
|
40
41
|
import { RenderService } from 'browser/services/RenderService';
|
|
41
42
|
import { SelectionService } from 'browser/services/SelectionService';
|
|
42
|
-
import { ICharSizeService, ICharacterJoinerService, ICoreBrowserService, ILinkProviderService, IMouseService, IRenderService, ISelectionService, IThemeService } from 'browser/services/Services';
|
|
43
|
+
import { ICharSizeService, ICharacterJoinerService, ICoreBrowserService, IKeyboardService, ILinkProviderService, IMouseCoordsService, IMouseService, IRenderService, ISelectionService, IThemeService } from 'browser/services/Services';
|
|
43
44
|
import { ThemeService } from 'browser/services/ThemeService';
|
|
44
|
-
import {
|
|
45
|
+
import { KeyboardService } from 'browser/services/KeyboardService';
|
|
46
|
+
import { channels, color, rgb } from 'common/Color';
|
|
45
47
|
import { CoreTerminal } from 'common/CoreTerminal';
|
|
46
48
|
import * as Browser from 'common/Platform';
|
|
47
|
-
import { ColorRequestType,
|
|
49
|
+
import { ColorRequestType, IColorEvent, ITerminalOptions, KeyboardResultType, SpecialColorIndex } from 'common/Types';
|
|
48
50
|
import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine';
|
|
49
51
|
import { IBuffer } from 'common/buffer/Types';
|
|
50
|
-
import { C0,
|
|
51
|
-
import { evaluateKeyboardEvent } from 'common/input/Keyboard';
|
|
52
|
+
import { C0, C1ESCAPED } from 'common/data/EscapeSequences';
|
|
52
53
|
import { toRgbString } from 'common/input/XParseColor';
|
|
53
54
|
import { DecorationService } from 'common/services/DecorationService';
|
|
54
55
|
import { IDecorationService } from 'common/services/Services';
|
|
55
56
|
import { WindowsOptionsReportType } from '../common/InputHandler';
|
|
56
57
|
import { AccessibilityManager } from './AccessibilityManager';
|
|
57
58
|
import { Linkifier } from './Linkifier';
|
|
58
|
-
import { Emitter,
|
|
59
|
-
import { addDisposableListener } from '
|
|
60
|
-
import { MutableDisposable, toDisposable } from '
|
|
59
|
+
import { Emitter, EventUtils, type IEvent } from 'common/Event';
|
|
60
|
+
import { addDisposableListener } from 'browser/Dom';
|
|
61
|
+
import { MutableDisposable, toDisposable } from 'common/Lifecycle';
|
|
61
62
|
|
|
62
63
|
export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
63
64
|
public textarea: HTMLTextAreaElement | undefined;
|
|
@@ -77,15 +78,16 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
77
78
|
public browser: IBrowser = Browser as any;
|
|
78
79
|
|
|
79
80
|
private _customKeyEventHandler: CustomKeyEventHandler | undefined;
|
|
80
|
-
private _customWheelEventHandler: CustomWheelEventHandler | undefined;
|
|
81
81
|
|
|
82
82
|
// Browser services
|
|
83
|
-
private _decorationService: DecorationService;
|
|
84
|
-
private
|
|
83
|
+
private readonly _decorationService: DecorationService;
|
|
84
|
+
private readonly _keyboardService: IKeyboardService;
|
|
85
|
+
private readonly _linkProviderService: ILinkProviderService;
|
|
85
86
|
|
|
86
87
|
// Optional browser services
|
|
87
88
|
private _charSizeService: ICharSizeService | undefined;
|
|
88
89
|
private _coreBrowserService: ICoreBrowserService | undefined;
|
|
90
|
+
private _mouseCoordsService: IMouseCoordsService | undefined;
|
|
89
91
|
private _mouseService: IMouseService | undefined;
|
|
90
92
|
private _renderService: IRenderService | undefined;
|
|
91
93
|
private _themeService: IThemeService | undefined;
|
|
@@ -126,8 +128,6 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
126
128
|
public readonly onCursorMove = this._onCursorMove.event;
|
|
127
129
|
private readonly _onKey = this._register(new Emitter<{ key: string, domEvent: KeyboardEvent }>());
|
|
128
130
|
public readonly onKey = this._onKey.event;
|
|
129
|
-
private readonly _onRender = this._register(new Emitter<{ start: number, end: number }>());
|
|
130
|
-
public readonly onRender = this._onRender.event;
|
|
131
131
|
private readonly _onSelectionChange = this._register(new Emitter<void>());
|
|
132
132
|
public readonly onSelectionChange = this._onSelectionChange.event;
|
|
133
133
|
private readonly _onTitleChange = this._register(new Emitter<string>());
|
|
@@ -136,15 +136,35 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
136
136
|
public readonly onBell = this._onBell.event;
|
|
137
137
|
|
|
138
138
|
private _onFocus = this._register(new Emitter<void>());
|
|
139
|
-
public get onFocus():
|
|
139
|
+
public get onFocus(): IEvent<void> { return this._onFocus.event; }
|
|
140
140
|
private _onBlur = this._register(new Emitter<void>());
|
|
141
|
-
public get onBlur():
|
|
141
|
+
public get onBlur(): IEvent<void> { return this._onBlur.event; }
|
|
142
142
|
private _onA11yCharEmitter = this._register(new Emitter<string>());
|
|
143
|
-
public get onA11yChar():
|
|
143
|
+
public get onA11yChar(): IEvent<string> { return this._onA11yCharEmitter.event; }
|
|
144
144
|
private _onA11yTabEmitter = this._register(new Emitter<number>());
|
|
145
|
-
public get onA11yTab():
|
|
145
|
+
public get onA11yTab(): IEvent<number> { return this._onA11yTabEmitter.event; }
|
|
146
146
|
private _onWillOpen = this._register(new Emitter<HTMLElement>());
|
|
147
|
-
public get onWillOpen():
|
|
147
|
+
public get onWillOpen(): IEvent<HTMLElement> { return this._onWillOpen.event; }
|
|
148
|
+
private readonly _onDimensionsChange = this._register(new Emitter<IRenderDimensionsApi>());
|
|
149
|
+
public readonly onDimensionsChange = this._onDimensionsChange.event;
|
|
150
|
+
|
|
151
|
+
public get dimensions(): IRenderDimensionsApi | undefined {
|
|
152
|
+
if (!this._renderService) {
|
|
153
|
+
return undefined;
|
|
154
|
+
}
|
|
155
|
+
const dimensions = this._renderService.dimensions;
|
|
156
|
+
return {
|
|
157
|
+
css: {
|
|
158
|
+
canvas: { ...dimensions.css.canvas },
|
|
159
|
+
cell: { ...dimensions.css.cell }
|
|
160
|
+
},
|
|
161
|
+
device: {
|
|
162
|
+
canvas: { ...dimensions.device.canvas },
|
|
163
|
+
cell: { ...dimensions.device.cell },
|
|
164
|
+
char: { ...dimensions.device.char }
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
}
|
|
148
168
|
|
|
149
169
|
constructor(
|
|
150
170
|
options: Partial<ITerminalOptions> = {}
|
|
@@ -155,6 +175,8 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
155
175
|
|
|
156
176
|
this._decorationService = this._instantiationService.createInstance(DecorationService);
|
|
157
177
|
this._instantiationService.setService(IDecorationService, this._decorationService);
|
|
178
|
+
this._keyboardService = this._instantiationService.createInstance(KeyboardService);
|
|
179
|
+
this._instantiationService.setService(IKeyboardService, this._keyboardService);
|
|
158
180
|
this._linkProviderService = this._instantiationService.createInstance(LinkProviderService);
|
|
159
181
|
this._instantiationService.setService(ILinkProviderService, this._linkProviderService);
|
|
160
182
|
this._linkProviderService.registerLinkProvider(this._instantiationService.createInstance(OscLinkProvider));
|
|
@@ -166,10 +188,10 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
166
188
|
this._register(this._inputHandler.onRequestReset(() => this.reset()));
|
|
167
189
|
this._register(this._inputHandler.onRequestWindowsOptionsReport(type => this._reportWindowsOptions(type)));
|
|
168
190
|
this._register(this._inputHandler.onColor((event) => this._handleColorEvent(event)));
|
|
169
|
-
this._register(
|
|
170
|
-
this._register(
|
|
171
|
-
this._register(
|
|
172
|
-
this._register(
|
|
191
|
+
this._register(EventUtils.forward(this._inputHandler.onCursorMove, this._onCursorMove));
|
|
192
|
+
this._register(EventUtils.forward(this._inputHandler.onTitleChange, this._onTitleChange));
|
|
193
|
+
this._register(EventUtils.forward(this._inputHandler.onA11yChar, this._onA11yCharEmitter));
|
|
194
|
+
this._register(EventUtils.forward(this._inputHandler.onA11yTab, this._onA11yTabEmitter));
|
|
173
195
|
|
|
174
196
|
// Setup listeners
|
|
175
197
|
this._register(this._bufferService.onResize(e => this._afterResize(e.cols, e.rows)));
|
|
@@ -214,7 +236,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
214
236
|
const colorRgb = color.toColorRGB(acc === 'ansi'
|
|
215
237
|
? this._themeService.colors.ansi[req.index]
|
|
216
238
|
: this._themeService.colors[acc]);
|
|
217
|
-
this.coreService.triggerDataEvent(`${C0.ESC}]${ident};${toRgbString(colorRgb)}${
|
|
239
|
+
this.coreService.triggerDataEvent(`${C0.ESC}]${ident};${toRgbString(colorRgb)}${C1ESCAPED.ST}`);
|
|
218
240
|
break;
|
|
219
241
|
case ColorRequestType.SET:
|
|
220
242
|
if (acc === 'ansi') {
|
|
@@ -231,6 +253,20 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
231
253
|
}
|
|
232
254
|
}
|
|
233
255
|
|
|
256
|
+
/**
|
|
257
|
+
* Reports the current color scheme (dark or light) based on the relative luminance
|
|
258
|
+
* of the background and foreground theme colors.
|
|
259
|
+
* Sends CSI ? 997 ; 1 n for dark mode or CSI ? 997 ; 2 n for light mode.
|
|
260
|
+
*/
|
|
261
|
+
private _reportColorScheme(): void {
|
|
262
|
+
if (!this._themeService) return;
|
|
263
|
+
const bgLuminance = rgb.relativeLuminance(this._themeService.colors.background.rgba >> 8);
|
|
264
|
+
const fgLuminance = rgb.relativeLuminance(this._themeService.colors.foreground.rgba >> 8);
|
|
265
|
+
// Dark mode = background is darker than foreground (lower luminance)
|
|
266
|
+
const colorSchemeMode = bgLuminance < fgLuminance ? 1 : 2;
|
|
267
|
+
this.coreService.triggerDataEvent(`${C0.ESC}[?997;${colorSchemeMode}n`);
|
|
268
|
+
}
|
|
269
|
+
|
|
234
270
|
protected _setup(): void {
|
|
235
271
|
super._setup();
|
|
236
272
|
|
|
@@ -378,7 +414,16 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
378
414
|
this._register(addDisposableListener(this.textarea!, 'keyup', (ev: KeyboardEvent) => this._keyUp(ev), true));
|
|
379
415
|
this._register(addDisposableListener(this.textarea!, 'keydown', (ev: KeyboardEvent) => this._keyDown(ev), true));
|
|
380
416
|
this._register(addDisposableListener(this.textarea!, 'keypress', (ev: KeyboardEvent) => this._keyPress(ev), true));
|
|
381
|
-
this._register(addDisposableListener(this.textarea!, 'compositionstart', () =>
|
|
417
|
+
this._register(addDisposableListener(this.textarea!, 'compositionstart', () => {
|
|
418
|
+
// Ensure the textarea is synced to the latest cursor location before composition begins. This
|
|
419
|
+
// is to workaround a problem where highly dynamic TUIs like agentic CLIs reprint agressively
|
|
420
|
+
// would cause the IME to appear in the wrong position. The theory is that when the IME is
|
|
421
|
+
// triggered during a partial render the textarea position becomes locked and will not move
|
|
422
|
+
// until it is hidden and a custom move occurs.
|
|
423
|
+
this._syncTextArea();
|
|
424
|
+
this._compositionHelper!.compositionstart();
|
|
425
|
+
this._compositionHelper!.updateCompositionElements();
|
|
426
|
+
}));
|
|
382
427
|
this._register(addDisposableListener(this.textarea!, 'compositionupdate', (e: CompositionEvent) => this._compositionHelper!.compositionupdate(e)));
|
|
383
428
|
this._register(addDisposableListener(this.textarea!, 'compositionend', () => this._compositionHelper!.compositionend()));
|
|
384
429
|
this._register(addDisposableListener(this.textarea!, 'input', (ev: InputEvent) => this._inputEvent(ev), true));
|
|
@@ -418,6 +463,8 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
418
463
|
this.element.dir = 'ltr'; // xterm.css assumes LTR
|
|
419
464
|
this.element.classList.add('terminal');
|
|
420
465
|
this.element.classList.add('xterm');
|
|
466
|
+
this.element.classList.toggle('allow-transparency', this.options.allowTransparency);
|
|
467
|
+
this._register(this.optionsService.onSpecificOptionChange('allowTransparency', value => this.element!.classList.toggle('allow-transparency', value)));
|
|
421
468
|
parent.appendChild(this.element);
|
|
422
469
|
|
|
423
470
|
// Performance: Use a document fragment to build the terminal
|
|
@@ -472,12 +519,33 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
472
519
|
this._themeService = this._instantiationService.createInstance(ThemeService);
|
|
473
520
|
this._instantiationService.setService(IThemeService, this._themeService);
|
|
474
521
|
|
|
522
|
+
// CSI ? 996 n - color scheme query (https://contour-terminal.org/vt-extensions/color-palette-update-notifications/)
|
|
523
|
+
this._register(this._inputHandler.onRequestColorSchemeQuery(() => this._reportColorScheme()));
|
|
524
|
+
|
|
525
|
+
// Emit unsolicited color scheme notification on theme change when DECSET 2031 is enabled
|
|
526
|
+
this._register(this._themeService.onChangeColors(() => {
|
|
527
|
+
if (this.coreService.decPrivateModes.colorSchemeUpdates) {
|
|
528
|
+
this._reportColorScheme();
|
|
529
|
+
}
|
|
530
|
+
}));
|
|
531
|
+
|
|
475
532
|
this._characterJoinerService = this._instantiationService.createInstance(CharacterJoinerService);
|
|
476
533
|
this._instantiationService.setService(ICharacterJoinerService, this._characterJoinerService);
|
|
477
534
|
|
|
478
535
|
this._renderService = this._register(this._instantiationService.createInstance(RenderService, this.rows, this.screenElement));
|
|
479
536
|
this._instantiationService.setService(IRenderService, this._renderService);
|
|
480
537
|
this._register(this._renderService.onRenderedViewportChange(e => this._onRender.fire(e)));
|
|
538
|
+
this._register(this._renderService.onDimensionsChange(e => this._onDimensionsChange.fire({
|
|
539
|
+
css: {
|
|
540
|
+
canvas: { ...e.css.canvas },
|
|
541
|
+
cell: { ...e.css.cell }
|
|
542
|
+
},
|
|
543
|
+
device: {
|
|
544
|
+
canvas: { ...e.device.canvas },
|
|
545
|
+
cell: { ...e.device.cell },
|
|
546
|
+
char: { ...e.device.char }
|
|
547
|
+
}
|
|
548
|
+
})));
|
|
481
549
|
this.onResize(e => this._renderService!.resize(e.cols, e.rows));
|
|
482
550
|
|
|
483
551
|
this._compositionView = this._document.createElement('div');
|
|
@@ -485,8 +553,8 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
485
553
|
this._compositionHelper = this._instantiationService.createInstance(CompositionHelper, this.textarea, this._compositionView);
|
|
486
554
|
this._helperContainer.appendChild(this._compositionView);
|
|
487
555
|
|
|
488
|
-
this.
|
|
489
|
-
this._instantiationService.setService(
|
|
556
|
+
this._mouseCoordsService = this._instantiationService.createInstance(MouseCoordsService);
|
|
557
|
+
this._instantiationService.setService(IMouseCoordsService, this._mouseCoordsService);
|
|
490
558
|
|
|
491
559
|
const linkifier = this._linkifier.value = this._register(this._instantiationService.createInstance(Linkifier, this.screenElement));
|
|
492
560
|
|
|
@@ -505,7 +573,10 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
505
573
|
this._renderService!.handleCursorMove();
|
|
506
574
|
this._syncTextArea();
|
|
507
575
|
}));
|
|
508
|
-
this._register(this.onResize(() =>
|
|
576
|
+
this._register(this.onResize(() => {
|
|
577
|
+
this._renderService!.handleResize(this.cols, this.rows);
|
|
578
|
+
this._syncTextArea();
|
|
579
|
+
}));
|
|
509
580
|
this._register(this.onBlur(() => this._renderService!.handleBlur()));
|
|
510
581
|
this._register(this.onFocus(() => this._renderService!.handleFocus()));
|
|
511
582
|
|
|
@@ -521,6 +592,8 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
521
592
|
linkifier
|
|
522
593
|
));
|
|
523
594
|
this._instantiationService.setService(ISelectionService, this._selectionService);
|
|
595
|
+
this._mouseService = this._instantiationService.createInstance(MouseService);
|
|
596
|
+
this._instantiationService.setService(IMouseService, this._mouseService);
|
|
524
597
|
this._register(this._selectionService.onRequestScrollLines(e => this.scrollLines(e.amount, e.suppressScrollEvent)));
|
|
525
598
|
this._register(this._selectionService.onSelectionChange(() => this._onSelectionChange.fire()));
|
|
526
599
|
this._register(this._selectionService.onRequestRedraw(e => this._renderService!.handleSelectionChanged(e.start, e.end, e.columnSelectMode)));
|
|
@@ -532,7 +605,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
532
605
|
this.textarea!.focus();
|
|
533
606
|
this.textarea!.select();
|
|
534
607
|
}));
|
|
535
|
-
this._register(
|
|
608
|
+
this._register(EventUtils.any(
|
|
536
609
|
this._onScroll.event,
|
|
537
610
|
this._inputHandler.onScroll
|
|
538
611
|
)(() => {
|
|
@@ -544,7 +617,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
544
617
|
this._register(addDisposableListener(this.element, 'mousedown', (e: MouseEvent) => this._selectionService!.handleMouseDown(e)));
|
|
545
618
|
|
|
546
619
|
// apply mouse event classes set by escape codes before terminal was attached
|
|
547
|
-
if (this.
|
|
620
|
+
if (this.mouseStateService.areMouseEventsActive) {
|
|
548
621
|
this._selectionService.disable();
|
|
549
622
|
this.element.classList.add('enable-mouse-events');
|
|
550
623
|
} else {
|
|
@@ -558,11 +631,14 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
558
631
|
}
|
|
559
632
|
this._register(this.optionsService.onSpecificOptionChange('screenReaderMode', e => this._handleScreenReaderModeOptionChange(e)));
|
|
560
633
|
|
|
561
|
-
|
|
634
|
+
const showScrollbar = this.options.scrollbar?.showScrollbar ?? true;
|
|
635
|
+
const overviewRulerWidth = this.options.scrollbar?.width;
|
|
636
|
+
if (showScrollbar && overviewRulerWidth) {
|
|
562
637
|
this._overviewRulerRenderer = this._register(this._instantiationService.createInstance(OverviewRulerRenderer, this._viewportElement, this.screenElement));
|
|
563
638
|
}
|
|
564
|
-
this.optionsService.onSpecificOptionChange('
|
|
565
|
-
|
|
639
|
+
this.optionsService.onSpecificOptionChange('scrollbar', value => {
|
|
640
|
+
const shouldShow = (value?.showScrollbar ?? true) && !!value?.width;
|
|
641
|
+
if (!this._overviewRulerRenderer && shouldShow && this._viewportElement && this.screenElement) {
|
|
566
642
|
this._overviewRulerRenderer = this._register(this._instantiationService.createInstance(OverviewRulerRenderer, this._viewportElement, this.screenElement));
|
|
567
643
|
}
|
|
568
644
|
});
|
|
@@ -577,280 +653,26 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
577
653
|
|
|
578
654
|
// Listen for mouse events and translate
|
|
579
655
|
// them into terminal mouse protocols.
|
|
580
|
-
this.bindMouse(
|
|
656
|
+
this._mouseService.bindMouse({
|
|
657
|
+
element: this.element!,
|
|
658
|
+
screenElement: this.screenElement!,
|
|
659
|
+
document: this._document!,
|
|
660
|
+
handleTouchScroll: amount => this._viewport?.handleTouchScroll(amount)
|
|
661
|
+
}, disposable => this._register(disposable), () => this.focus());
|
|
581
662
|
}
|
|
582
663
|
|
|
583
664
|
private _createRenderer(): IRenderer {
|
|
584
665
|
return this._instantiationService.createInstance(DomRenderer, this, this._document!, this.element!, this.screenElement!, this._viewportElement!, this._helperContainer!, this.linkifier!);
|
|
585
666
|
}
|
|
586
667
|
|
|
587
|
-
/**
|
|
588
|
-
* Bind certain mouse events to the terminal.
|
|
589
|
-
* By default only 3 button + wheel up/down is ativated. For higher buttons
|
|
590
|
-
* no mouse report will be created. Typically the standard actions will be active.
|
|
591
|
-
*
|
|
592
|
-
* There are several reasons not to enable support for higher buttons/wheel:
|
|
593
|
-
* - Button 4 and 5 are typically used for history back and forward navigation,
|
|
594
|
-
* there is no straight forward way to supress/intercept those standard actions.
|
|
595
|
-
* - Support for higher buttons does not work in some platform/browser combinations.
|
|
596
|
-
* - Left/right wheel was not tested.
|
|
597
|
-
* - Emulators vary in mouse button support, typically only 3 buttons and
|
|
598
|
-
* wheel up/down work reliable.
|
|
599
|
-
*
|
|
600
|
-
* TODO: Move mouse event code into its own file.
|
|
601
|
-
*/
|
|
602
|
-
public bindMouse(): void {
|
|
603
|
-
const self = this;
|
|
604
|
-
const el = this.element!;
|
|
605
|
-
|
|
606
|
-
// send event to CoreMouseService
|
|
607
|
-
function sendEvent(ev: MouseEvent | WheelEvent): boolean {
|
|
608
|
-
// get mouse coordinates
|
|
609
|
-
const pos = self._mouseService!.getMouseReportCoords(ev, self.screenElement!);
|
|
610
|
-
if (!pos) {
|
|
611
|
-
return false;
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
let but: CoreMouseButton;
|
|
615
|
-
let action: CoreMouseAction | undefined;
|
|
616
|
-
switch ((ev as any).overrideType || ev.type) {
|
|
617
|
-
case 'mousemove':
|
|
618
|
-
action = CoreMouseAction.MOVE;
|
|
619
|
-
if (ev.buttons === undefined) {
|
|
620
|
-
// buttons is not supported on macOS, try to get a value from button instead
|
|
621
|
-
but = CoreMouseButton.NONE;
|
|
622
|
-
if (ev.button !== undefined) {
|
|
623
|
-
but = ev.button < 3 ? ev.button : CoreMouseButton.NONE;
|
|
624
|
-
}
|
|
625
|
-
} else {
|
|
626
|
-
// according to MDN buttons only reports up to button 5 (AUX2)
|
|
627
|
-
but = ev.buttons & 1 ? CoreMouseButton.LEFT :
|
|
628
|
-
ev.buttons & 4 ? CoreMouseButton.MIDDLE :
|
|
629
|
-
ev.buttons & 2 ? CoreMouseButton.RIGHT :
|
|
630
|
-
CoreMouseButton.NONE; // fallback to NONE
|
|
631
|
-
}
|
|
632
|
-
break;
|
|
633
|
-
case 'mouseup':
|
|
634
|
-
action = CoreMouseAction.UP;
|
|
635
|
-
but = ev.button < 3 ? ev.button : CoreMouseButton.NONE;
|
|
636
|
-
break;
|
|
637
|
-
case 'mousedown':
|
|
638
|
-
action = CoreMouseAction.DOWN;
|
|
639
|
-
but = ev.button < 3 ? ev.button : CoreMouseButton.NONE;
|
|
640
|
-
break;
|
|
641
|
-
case 'wheel':
|
|
642
|
-
if (self._customWheelEventHandler && self._customWheelEventHandler(ev as WheelEvent) === false) {
|
|
643
|
-
return false;
|
|
644
|
-
}
|
|
645
|
-
const deltaY = (ev as WheelEvent).deltaY;
|
|
646
|
-
if (deltaY === 0) {
|
|
647
|
-
return false;
|
|
648
|
-
}
|
|
649
|
-
const lines = self.coreMouseService.consumeWheelEvent(
|
|
650
|
-
ev as WheelEvent,
|
|
651
|
-
self._renderService?.dimensions?.device?.cell?.height,
|
|
652
|
-
self._coreBrowserService?.dpr
|
|
653
|
-
);
|
|
654
|
-
if (lines === 0) {
|
|
655
|
-
return false;
|
|
656
|
-
}
|
|
657
|
-
action = deltaY < 0 ? CoreMouseAction.UP : CoreMouseAction.DOWN;
|
|
658
|
-
but = CoreMouseButton.WHEEL;
|
|
659
|
-
break;
|
|
660
|
-
default:
|
|
661
|
-
// dont handle other event types by accident
|
|
662
|
-
return false;
|
|
663
|
-
}
|
|
664
|
-
|
|
665
|
-
// exit if we cannot determine valid button/action values
|
|
666
|
-
// do nothing for higher buttons than wheel
|
|
667
|
-
if (action === undefined || but === undefined || but > CoreMouseButton.WHEEL) {
|
|
668
|
-
return false;
|
|
669
|
-
}
|
|
670
|
-
|
|
671
|
-
return self.coreMouseService.triggerMouseEvent({
|
|
672
|
-
col: pos.col,
|
|
673
|
-
row: pos.row,
|
|
674
|
-
x: pos.x,
|
|
675
|
-
y: pos.y,
|
|
676
|
-
button: but,
|
|
677
|
-
action,
|
|
678
|
-
ctrl: ev.ctrlKey,
|
|
679
|
-
alt: ev.altKey,
|
|
680
|
-
shift: ev.shiftKey
|
|
681
|
-
});
|
|
682
|
-
}
|
|
683
|
-
|
|
684
|
-
/**
|
|
685
|
-
* Event listener state handling.
|
|
686
|
-
* We listen to the onProtocolChange event of CoreMouseService and put
|
|
687
|
-
* requested listeners in `requestedEvents`. With this the listeners
|
|
688
|
-
* have all bits to do the event listener juggling.
|
|
689
|
-
* Note: 'mousedown' currently is "always on" and not managed
|
|
690
|
-
* by onProtocolChange.
|
|
691
|
-
*/
|
|
692
|
-
const requestedEvents: { [key: string]: ((ev: MouseEvent | WheelEvent) => void) | null } = {
|
|
693
|
-
mouseup: null,
|
|
694
|
-
wheel: null,
|
|
695
|
-
mousedrag: null,
|
|
696
|
-
mousemove: null
|
|
697
|
-
};
|
|
698
|
-
const eventListeners: { [key: string]: (ev: any) => void | boolean } = {
|
|
699
|
-
mouseup: (ev: MouseEvent) => {
|
|
700
|
-
sendEvent(ev);
|
|
701
|
-
if (!ev.buttons) {
|
|
702
|
-
// if no other button is held remove global handlers
|
|
703
|
-
this._document!.removeEventListener('mouseup', requestedEvents.mouseup!);
|
|
704
|
-
if (requestedEvents.mousedrag) {
|
|
705
|
-
this._document!.removeEventListener('mousemove', requestedEvents.mousedrag);
|
|
706
|
-
}
|
|
707
|
-
}
|
|
708
|
-
return this.cancel(ev);
|
|
709
|
-
},
|
|
710
|
-
wheel: (ev: WheelEvent) => {
|
|
711
|
-
sendEvent(ev);
|
|
712
|
-
return this.cancel(ev, true);
|
|
713
|
-
},
|
|
714
|
-
mousedrag: (ev: MouseEvent) => {
|
|
715
|
-
// deal only with move while a button is held
|
|
716
|
-
if (ev.buttons) {
|
|
717
|
-
sendEvent(ev);
|
|
718
|
-
}
|
|
719
|
-
},
|
|
720
|
-
mousemove: (ev: MouseEvent) => {
|
|
721
|
-
// deal only with move without any button
|
|
722
|
-
if (!ev.buttons) {
|
|
723
|
-
sendEvent(ev);
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
};
|
|
727
|
-
this._register(this.coreMouseService.onProtocolChange(events => {
|
|
728
|
-
// apply global changes on events
|
|
729
|
-
if (events) {
|
|
730
|
-
if (this.optionsService.rawOptions.logLevel === 'debug') {
|
|
731
|
-
this._logService.debug('Binding to mouse events:', this.coreMouseService.explainEvents(events));
|
|
732
|
-
}
|
|
733
|
-
this.element!.classList.add('enable-mouse-events');
|
|
734
|
-
this._selectionService!.disable();
|
|
735
|
-
} else {
|
|
736
|
-
this._logService.debug('Unbinding from mouse events.');
|
|
737
|
-
this.element!.classList.remove('enable-mouse-events');
|
|
738
|
-
this._selectionService!.enable();
|
|
739
|
-
}
|
|
740
|
-
|
|
741
|
-
// add/remove handlers from requestedEvents
|
|
742
|
-
|
|
743
|
-
if (!(events & CoreMouseEventType.MOVE)) {
|
|
744
|
-
el.removeEventListener('mousemove', requestedEvents.mousemove!);
|
|
745
|
-
requestedEvents.mousemove = null;
|
|
746
|
-
} else if (!requestedEvents.mousemove) {
|
|
747
|
-
el.addEventListener('mousemove', eventListeners.mousemove);
|
|
748
|
-
requestedEvents.mousemove = eventListeners.mousemove;
|
|
749
|
-
}
|
|
750
|
-
|
|
751
|
-
if (!(events & CoreMouseEventType.WHEEL)) {
|
|
752
|
-
el.removeEventListener('wheel', requestedEvents.wheel!);
|
|
753
|
-
requestedEvents.wheel = null;
|
|
754
|
-
} else if (!requestedEvents.wheel) {
|
|
755
|
-
el.addEventListener('wheel', eventListeners.wheel, { passive: false });
|
|
756
|
-
requestedEvents.wheel = eventListeners.wheel;
|
|
757
|
-
}
|
|
758
|
-
|
|
759
|
-
if (!(events & CoreMouseEventType.UP)) {
|
|
760
|
-
this._document!.removeEventListener('mouseup', requestedEvents.mouseup!);
|
|
761
|
-
requestedEvents.mouseup = null;
|
|
762
|
-
} else if (!requestedEvents.mouseup) {
|
|
763
|
-
requestedEvents.mouseup = eventListeners.mouseup;
|
|
764
|
-
}
|
|
765
|
-
|
|
766
|
-
if (!(events & CoreMouseEventType.DRAG)) {
|
|
767
|
-
this._document!.removeEventListener('mousemove', requestedEvents.mousedrag!);
|
|
768
|
-
requestedEvents.mousedrag = null;
|
|
769
|
-
} else if (!requestedEvents.mousedrag) {
|
|
770
|
-
requestedEvents.mousedrag = eventListeners.mousedrag;
|
|
771
|
-
}
|
|
772
|
-
}));
|
|
773
|
-
// force initial onProtocolChange so we dont miss early mouse requests
|
|
774
|
-
this.coreMouseService.activeProtocol = this.coreMouseService.activeProtocol;
|
|
775
|
-
|
|
776
|
-
/**
|
|
777
|
-
* "Always on" event listeners.
|
|
778
|
-
*/
|
|
779
|
-
this._register(addDisposableListener(el, 'mousedown', (ev: MouseEvent) => {
|
|
780
|
-
ev.preventDefault();
|
|
781
|
-
this.focus();
|
|
782
|
-
|
|
783
|
-
// Don't send the mouse button to the pty if mouse events are disabled or
|
|
784
|
-
// if the selection manager is having selection forced (ie. a modifier is
|
|
785
|
-
// held).
|
|
786
|
-
if (!this.coreMouseService.areMouseEventsActive || this._selectionService!.shouldForceSelection(ev)) {
|
|
787
|
-
return;
|
|
788
|
-
}
|
|
789
|
-
|
|
790
|
-
sendEvent(ev);
|
|
791
|
-
|
|
792
|
-
// Register additional global handlers which should keep reporting outside
|
|
793
|
-
// of the terminal element.
|
|
794
|
-
// Note: Other emulators also do this for 'mousedown' while a button
|
|
795
|
-
// is held, we currently limit 'mousedown' to the terminal only.
|
|
796
|
-
if (requestedEvents.mouseup) {
|
|
797
|
-
this._document!.addEventListener('mouseup', requestedEvents.mouseup);
|
|
798
|
-
}
|
|
799
|
-
if (requestedEvents.mousedrag) {
|
|
800
|
-
this._document!.addEventListener('mousemove', requestedEvents.mousedrag);
|
|
801
|
-
}
|
|
802
|
-
|
|
803
|
-
return this.cancel(ev);
|
|
804
|
-
}));
|
|
805
|
-
|
|
806
|
-
this._register(addDisposableListener(el, 'wheel', (ev: WheelEvent) => {
|
|
807
|
-
// do nothing, if app side handles wheel itself
|
|
808
|
-
if (requestedEvents.wheel) return;
|
|
809
|
-
|
|
810
|
-
if (this._customWheelEventHandler && this._customWheelEventHandler(ev) === false) {
|
|
811
|
-
return false;
|
|
812
|
-
}
|
|
813
|
-
|
|
814
|
-
if (!this.buffer.hasScrollback) {
|
|
815
|
-
// Convert wheel events into up/down events when the buffer does not have scrollback, this
|
|
816
|
-
// enables scrolling in apps hosted in the alt buffer such as vim or tmux even when mouse
|
|
817
|
-
// events are not enabled.
|
|
818
|
-
// This used implementation used get the actual lines/partial lines scrolled from the
|
|
819
|
-
// viewport but since moving to the new viewport implementation has been simplified to
|
|
820
|
-
// simply send a single up or down sequence.
|
|
821
|
-
|
|
822
|
-
// Do nothing if there's no vertical scroll
|
|
823
|
-
const deltaY = (ev as WheelEvent).deltaY;
|
|
824
|
-
if (deltaY === 0) {
|
|
825
|
-
return false;
|
|
826
|
-
}
|
|
827
|
-
|
|
828
|
-
const lines = self.coreMouseService.consumeWheelEvent(
|
|
829
|
-
ev as WheelEvent,
|
|
830
|
-
self._renderService?.dimensions?.device?.cell?.height,
|
|
831
|
-
self._coreBrowserService?.dpr
|
|
832
|
-
);
|
|
833
|
-
if (lines === 0) {
|
|
834
|
-
return this.cancel(ev, true);
|
|
835
|
-
}
|
|
836
|
-
|
|
837
|
-
// Construct and send sequences
|
|
838
|
-
const sequence = C0.ESC + (this.coreService.decPrivateModes.applicationCursorKeys ? 'O' : '[') + (ev.deltaY < 0 ? 'A' : 'B');
|
|
839
|
-
this.coreService.triggerDataEvent(sequence, true);
|
|
840
|
-
return this.cancel(ev, true);
|
|
841
|
-
}
|
|
842
|
-
}, { passive: false }));
|
|
843
|
-
}
|
|
844
|
-
|
|
845
|
-
|
|
846
668
|
/**
|
|
847
669
|
* Tells the renderer to refresh terminal content between two rows (inclusive) at the next
|
|
848
670
|
* opportunity.
|
|
849
671
|
* @param start The row to start from (between 0 and this.rows - 1).
|
|
850
672
|
* @param end The row to end at (between start and this.rows - 1).
|
|
851
673
|
*/
|
|
852
|
-
public refresh(start: number, end: number): void {
|
|
853
|
-
this._renderService?.refreshRows(start, end);
|
|
674
|
+
public refresh(start: number, end: number, sync: boolean = false): void {
|
|
675
|
+
this._renderService?.refreshRows(start, end, sync);
|
|
854
676
|
}
|
|
855
677
|
|
|
856
678
|
/**
|
|
@@ -916,7 +738,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
916
738
|
}
|
|
917
739
|
|
|
918
740
|
public attachCustomWheelEventHandler(customWheelEventHandler: CustomWheelEventHandler): void {
|
|
919
|
-
this.
|
|
741
|
+
this.mouseStateService.setCustomWheelEventHandler(customWheelEventHandler);
|
|
920
742
|
}
|
|
921
743
|
|
|
922
744
|
public registerLinkProvider(linkProvider: ILinkProvider): IDisposable {
|
|
@@ -1040,14 +862,16 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1040
862
|
this._unprocessedDeadKey = true;
|
|
1041
863
|
}
|
|
1042
864
|
|
|
1043
|
-
const result =
|
|
865
|
+
const result = this._keyboardService.evaluateKeyDown(event);
|
|
1044
866
|
|
|
1045
867
|
this.updateCursorStyle(event);
|
|
1046
868
|
|
|
1047
869
|
if (result.type === KeyboardResultType.PAGE_DOWN || result.type === KeyboardResultType.PAGE_UP) {
|
|
1048
870
|
const scrollCount = this.rows - 1;
|
|
1049
871
|
this.scrollLines(result.type === KeyboardResultType.PAGE_UP ? -scrollCount : scrollCount);
|
|
1050
|
-
|
|
872
|
+
event.preventDefault();
|
|
873
|
+
event.stopPropagation();
|
|
874
|
+
return false;
|
|
1051
875
|
}
|
|
1052
876
|
|
|
1053
877
|
if (result.type === KeyboardResultType.SELECT_ALL) {
|
|
@@ -1060,7 +884,8 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1060
884
|
|
|
1061
885
|
if (result.cancel) {
|
|
1062
886
|
// The event is canceled at the end already, is this necessary?
|
|
1063
|
-
|
|
887
|
+
event.preventDefault();
|
|
888
|
+
event.stopPropagation();
|
|
1064
889
|
}
|
|
1065
890
|
|
|
1066
891
|
if (!result.key) {
|
|
@@ -1068,8 +893,9 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1068
893
|
}
|
|
1069
894
|
|
|
1070
895
|
// HACK: Process A-Z in the keypress event to fix an issue with macOS IMEs where lower case
|
|
1071
|
-
// letters cannot be input while caps lock is on.
|
|
1072
|
-
|
|
896
|
+
// letters cannot be input while caps lock is on. Skip this hack when using kitty protocol
|
|
897
|
+
// or Win32 input mode as they need to send proper sequences for all key events.
|
|
898
|
+
if (!this._keyboardService.useKitty && !this._keyboardService.useWin32InputMode && event.key && !event.ctrlKey && !event.altKey && !event.metaKey && event.key.length === 1) {
|
|
1073
899
|
if (event.key.charCodeAt(0) >= 65 && event.key.charCodeAt(0) <= 90) {
|
|
1074
900
|
return true;
|
|
1075
901
|
}
|
|
@@ -1087,16 +913,19 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1087
913
|
this.textarea!.value = '';
|
|
1088
914
|
}
|
|
1089
915
|
|
|
916
|
+
const wasModifierOnly = this._keyboardService.useWin32InputMode && wasModifierKeyOnlyEvent(event);
|
|
1090
917
|
this._onKey.fire({ key: result.key, domEvent: event });
|
|
1091
918
|
this._showCursor();
|
|
1092
|
-
this.coreService.triggerDataEvent(result.key,
|
|
919
|
+
this.coreService.triggerDataEvent(result.key, !wasModifierOnly);
|
|
1093
920
|
|
|
1094
921
|
// Cancel events when not in screen reader mode so events don't get bubbled up and handled by
|
|
1095
922
|
// other listeners. When screen reader mode is enabled, we don't cancel them (unless ctrl or alt
|
|
1096
923
|
// is also depressed) so that the cursor textarea can be updated, which triggers the screen
|
|
1097
924
|
// reader to read it.
|
|
1098
925
|
if (!this.optionsService.rawOptions.screenReaderMode || event.altKey || event.ctrlKey) {
|
|
1099
|
-
|
|
926
|
+
event.preventDefault();
|
|
927
|
+
event.stopPropagation();
|
|
928
|
+
return false;
|
|
1100
929
|
}
|
|
1101
930
|
|
|
1102
931
|
this._keyDownHandled = true;
|
|
@@ -1127,6 +956,13 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1127
956
|
this.focus();
|
|
1128
957
|
}
|
|
1129
958
|
|
|
959
|
+
// Handle key release for Kitty keyboard protocol
|
|
960
|
+
const result = this._keyboardService.evaluateKeyUp(ev);
|
|
961
|
+
if (result?.key) {
|
|
962
|
+
const wasModifierOnly = this._keyboardService.useWin32InputMode && wasModifierKeyOnlyEvent(ev);
|
|
963
|
+
this.coreService.triggerDataEvent(result.key, !wasModifierOnly);
|
|
964
|
+
}
|
|
965
|
+
|
|
1130
966
|
this.updateCursorStyle(ev);
|
|
1131
967
|
this._keyPressHandled = false;
|
|
1132
968
|
}
|
|
@@ -1150,8 +986,6 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1150
986
|
return false;
|
|
1151
987
|
}
|
|
1152
988
|
|
|
1153
|
-
this.cancel(ev);
|
|
1154
|
-
|
|
1155
989
|
if (ev.charCode) {
|
|
1156
990
|
key = ev.charCode;
|
|
1157
991
|
} else if (ev.which === null || ev.which === undefined) {
|
|
@@ -1204,8 +1038,6 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1204
1038
|
|
|
1205
1039
|
const text = ev.data;
|
|
1206
1040
|
this.coreService.triggerDataEvent(text, true);
|
|
1207
|
-
|
|
1208
|
-
this.cancel(ev);
|
|
1209
1041
|
return true;
|
|
1210
1042
|
}
|
|
1211
1043
|
|
|
@@ -1276,6 +1108,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1276
1108
|
|
|
1277
1109
|
this._setup();
|
|
1278
1110
|
super.reset();
|
|
1111
|
+
this._mouseService?.reset();
|
|
1279
1112
|
this._selectionService?.reset();
|
|
1280
1113
|
this._decorationService.reset();
|
|
1281
1114
|
|
|
@@ -1283,7 +1116,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1283
1116
|
this._customKeyEventHandler = customKeyEventHandler;
|
|
1284
1117
|
|
|
1285
1118
|
// do a full screen refresh
|
|
1286
|
-
this.refresh(0, this.rows - 1);
|
|
1119
|
+
this.refresh(0, this.rows - 1, true);
|
|
1287
1120
|
}
|
|
1288
1121
|
|
|
1289
1122
|
public clearTextureAtlas(): void {
|
|
@@ -1317,15 +1150,6 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1317
1150
|
}
|
|
1318
1151
|
}
|
|
1319
1152
|
|
|
1320
|
-
// TODO: Remove cancel function and cancelEvents option
|
|
1321
|
-
public cancel(ev: MouseEvent | WheelEvent | KeyboardEvent | InputEvent, force?: boolean): boolean | undefined {
|
|
1322
|
-
if (!this.options.cancelEvents && !force) {
|
|
1323
|
-
return;
|
|
1324
|
-
}
|
|
1325
|
-
ev.preventDefault();
|
|
1326
|
-
ev.stopPropagation();
|
|
1327
|
-
return false;
|
|
1328
|
-
}
|
|
1329
1153
|
}
|
|
1330
1154
|
|
|
1331
1155
|
/**
|
|
@@ -1335,5 +1159,10 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1335
1159
|
function wasModifierKeyOnlyEvent(ev: KeyboardEvent): boolean {
|
|
1336
1160
|
return ev.keyCode === 16 || // Shift
|
|
1337
1161
|
ev.keyCode === 17 || // Ctrl
|
|
1338
|
-
ev.keyCode === 18
|
|
1162
|
+
ev.keyCode === 18 || // Alt
|
|
1163
|
+
ev.keyCode === 91 || // Meta (Left)
|
|
1164
|
+
ev.keyCode === 92 || // Meta (Right)
|
|
1165
|
+
ev.keyCode === 93 || // Meta (Menu)
|
|
1166
|
+
ev.keyCode === 224 || // Meta (Firefox)
|
|
1167
|
+
ev.key === 'Meta';
|
|
1339
1168
|
}
|