@xterm/xterm 6.1.0-beta.25 → 6.1.0-beta.250
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 +25 -22
- package/src/browser/AccessibilityManager.ts +11 -6
- package/src/browser/Clipboard.ts +6 -3
- package/src/browser/CoreBrowserTerminal.ts +149 -319
- package/src/browser/Dom.ts +178 -0
- package/src/browser/Linkifier.ts +11 -11
- package/src/browser/OscLinkProvider.ts +82 -14
- 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 +55 -20
- package/src/browser/decorations/BufferDecorationRenderer.ts +1 -1
- package/src/browser/decorations/OverviewRulerRenderer.ts +33 -17
- package/src/browser/input/CompositionHelper.ts +44 -8
- package/src/browser/public/Terminal.ts +25 -28
- package/src/browser/renderer/dom/DomRenderer.ts +242 -76
- 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 +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/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 +28 -16
- package/src/browser/services/SelectionService.ts +45 -39
- package/src/browser/services/Services.ts +40 -17
- package/src/browser/services/ThemeService.ts +2 -2
- package/src/common/Async.ts +141 -0
- package/src/common/CircularList.ts +2 -2
- package/src/common/Color.ts +8 -0
- package/src/common/CoreTerminal.ts +32 -22
- package/src/common/Event.ts +118 -0
- package/src/common/InputHandler.ts +286 -87
- package/src/common/Lifecycle.ts +113 -0
- package/src/common/Platform.ts +13 -3
- package/src/common/SortedList.ts +7 -3
- package/src/common/StringBuilder.ts +67 -0
- package/src/common/TaskQueue.ts +14 -5
- package/src/common/Types.ts +51 -31
- package/src/common/Version.ts +9 -0
- package/src/common/buffer/Buffer.ts +34 -19
- package/src/common/buffer/BufferLine.ts +140 -68
- package/src/common/buffer/BufferLineStringCache.ts +69 -0
- package/src/common/buffer/BufferReflow.ts +4 -1
- package/src/common/buffer/BufferSet.ts +11 -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 +526 -0
- package/src/common/input/Win32InputMode.ts +297 -0
- package/src/common/input/WriteBuffer.ts +107 -38
- 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 +11 -12
- package/src/common/parser/EscapeSequenceParser.ts +205 -63
- package/src/common/parser/OscParser.ts +11 -12
- package/src/common/parser/Params.ts +27 -8
- package/src/common/parser/Types.ts +36 -2
- package/src/common/public/BufferLineApiView.ts +2 -2
- package/src/common/public/BufferNamespaceApi.ts +3 -3
- package/src/common/public/ParserApi.ts +3 -0
- package/src/common/services/BufferService.ts +14 -9
- package/src/common/services/CharsetService.ts +4 -0
- package/src/common/services/CoreService.ts +22 -9
- package/src/common/services/DecorationService.ts +255 -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/ServiceRegistry.ts +9 -7
- package/src/common/services/Services.ts +49 -40
- package/src/common/services/UnicodeService.ts +1 -1
- package/typings/xterm.d.ts +318 -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
|
@@ -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
|
|
|
@@ -495,8 +563,9 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
495
563
|
|
|
496
564
|
try {
|
|
497
565
|
this._onWillOpen.fire(this.element);
|
|
566
|
+
} catch (e) {
|
|
567
|
+
this._logService.error('onWillOpen handler threw an exception', e);
|
|
498
568
|
}
|
|
499
|
-
catch { /* fails to load addon for some reason */ }
|
|
500
569
|
if (!this._renderService.hasRenderer()) {
|
|
501
570
|
this._renderService.setRenderer(this._createRenderer());
|
|
502
571
|
}
|
|
@@ -505,7 +574,10 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
505
574
|
this._renderService!.handleCursorMove();
|
|
506
575
|
this._syncTextArea();
|
|
507
576
|
}));
|
|
508
|
-
this._register(this.onResize(() =>
|
|
577
|
+
this._register(this.onResize(() => {
|
|
578
|
+
this._renderService!.handleResize(this.cols, this.rows);
|
|
579
|
+
this._syncTextArea();
|
|
580
|
+
}));
|
|
509
581
|
this._register(this.onBlur(() => this._renderService!.handleBlur()));
|
|
510
582
|
this._register(this.onFocus(() => this._renderService!.handleFocus()));
|
|
511
583
|
|
|
@@ -521,6 +593,8 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
521
593
|
linkifier
|
|
522
594
|
));
|
|
523
595
|
this._instantiationService.setService(ISelectionService, this._selectionService);
|
|
596
|
+
this._mouseService = this._instantiationService.createInstance(MouseService);
|
|
597
|
+
this._instantiationService.setService(IMouseService, this._mouseService);
|
|
524
598
|
this._register(this._selectionService.onRequestScrollLines(e => this.scrollLines(e.amount, e.suppressScrollEvent)));
|
|
525
599
|
this._register(this._selectionService.onSelectionChange(() => this._onSelectionChange.fire()));
|
|
526
600
|
this._register(this._selectionService.onRequestRedraw(e => this._renderService!.handleSelectionChanged(e.start, e.end, e.columnSelectMode)));
|
|
@@ -532,7 +606,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
532
606
|
this.textarea!.focus();
|
|
533
607
|
this.textarea!.select();
|
|
534
608
|
}));
|
|
535
|
-
this._register(
|
|
609
|
+
this._register(EventUtils.any(
|
|
536
610
|
this._onScroll.event,
|
|
537
611
|
this._inputHandler.onScroll
|
|
538
612
|
)(() => {
|
|
@@ -544,7 +618,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
544
618
|
this._register(addDisposableListener(this.element, 'mousedown', (e: MouseEvent) => this._selectionService!.handleMouseDown(e)));
|
|
545
619
|
|
|
546
620
|
// apply mouse event classes set by escape codes before terminal was attached
|
|
547
|
-
if (this.
|
|
621
|
+
if (this.mouseStateService.areMouseEventsActive) {
|
|
548
622
|
this._selectionService.disable();
|
|
549
623
|
this.element.classList.add('enable-mouse-events');
|
|
550
624
|
} else {
|
|
@@ -558,11 +632,14 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
558
632
|
}
|
|
559
633
|
this._register(this.optionsService.onSpecificOptionChange('screenReaderMode', e => this._handleScreenReaderModeOptionChange(e)));
|
|
560
634
|
|
|
561
|
-
|
|
635
|
+
const showScrollbar = this.options.scrollbar?.showScrollbar ?? true;
|
|
636
|
+
const overviewRulerWidth = this.options.scrollbar?.width;
|
|
637
|
+
if (showScrollbar && overviewRulerWidth) {
|
|
562
638
|
this._overviewRulerRenderer = this._register(this._instantiationService.createInstance(OverviewRulerRenderer, this._viewportElement, this.screenElement));
|
|
563
639
|
}
|
|
564
|
-
this.optionsService.onSpecificOptionChange('
|
|
565
|
-
|
|
640
|
+
this.optionsService.onSpecificOptionChange('scrollbar', value => {
|
|
641
|
+
const shouldShow = (value?.showScrollbar ?? true) && !!value?.width;
|
|
642
|
+
if (!this._overviewRulerRenderer && shouldShow && this._viewportElement && this.screenElement) {
|
|
566
643
|
this._overviewRulerRenderer = this._register(this._instantiationService.createInstance(OverviewRulerRenderer, this._viewportElement, this.screenElement));
|
|
567
644
|
}
|
|
568
645
|
});
|
|
@@ -577,280 +654,26 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
577
654
|
|
|
578
655
|
// Listen for mouse events and translate
|
|
579
656
|
// them into terminal mouse protocols.
|
|
580
|
-
this.bindMouse(
|
|
657
|
+
this._mouseService.bindMouse({
|
|
658
|
+
element: this.element!,
|
|
659
|
+
screenElement: this.screenElement!,
|
|
660
|
+
document: this._document!,
|
|
661
|
+
handleTouchScroll: amount => this._viewport?.handleTouchScroll(amount)
|
|
662
|
+
}, disposable => this._register(disposable), () => this.focus());
|
|
581
663
|
}
|
|
582
664
|
|
|
583
665
|
private _createRenderer(): IRenderer {
|
|
584
666
|
return this._instantiationService.createInstance(DomRenderer, this, this._document!, this.element!, this.screenElement!, this._viewportElement!, this._helperContainer!, this.linkifier!);
|
|
585
667
|
}
|
|
586
668
|
|
|
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
669
|
/**
|
|
847
670
|
* Tells the renderer to refresh terminal content between two rows (inclusive) at the next
|
|
848
671
|
* opportunity.
|
|
849
672
|
* @param start The row to start from (between 0 and this.rows - 1).
|
|
850
673
|
* @param end The row to end at (between start and this.rows - 1).
|
|
851
674
|
*/
|
|
852
|
-
public refresh(start: number, end: number): void {
|
|
853
|
-
this._renderService?.refreshRows(start, end);
|
|
675
|
+
public refresh(start: number, end: number, sync: boolean = false): void {
|
|
676
|
+
this._renderService?.refreshRows(start, end, sync);
|
|
854
677
|
}
|
|
855
678
|
|
|
856
679
|
/**
|
|
@@ -916,7 +739,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
916
739
|
}
|
|
917
740
|
|
|
918
741
|
public attachCustomWheelEventHandler(customWheelEventHandler: CustomWheelEventHandler): void {
|
|
919
|
-
this.
|
|
742
|
+
this.mouseStateService.setCustomWheelEventHandler(customWheelEventHandler);
|
|
920
743
|
}
|
|
921
744
|
|
|
922
745
|
public registerLinkProvider(linkProvider: ILinkProvider): IDisposable {
|
|
@@ -1040,14 +863,16 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1040
863
|
this._unprocessedDeadKey = true;
|
|
1041
864
|
}
|
|
1042
865
|
|
|
1043
|
-
const result =
|
|
866
|
+
const result = this._keyboardService.evaluateKeyDown(event);
|
|
1044
867
|
|
|
1045
868
|
this.updateCursorStyle(event);
|
|
1046
869
|
|
|
1047
870
|
if (result.type === KeyboardResultType.PAGE_DOWN || result.type === KeyboardResultType.PAGE_UP) {
|
|
1048
871
|
const scrollCount = this.rows - 1;
|
|
1049
872
|
this.scrollLines(result.type === KeyboardResultType.PAGE_UP ? -scrollCount : scrollCount);
|
|
1050
|
-
|
|
873
|
+
event.preventDefault();
|
|
874
|
+
event.stopPropagation();
|
|
875
|
+
return false;
|
|
1051
876
|
}
|
|
1052
877
|
|
|
1053
878
|
if (result.type === KeyboardResultType.SELECT_ALL) {
|
|
@@ -1060,7 +885,8 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1060
885
|
|
|
1061
886
|
if (result.cancel) {
|
|
1062
887
|
// The event is canceled at the end already, is this necessary?
|
|
1063
|
-
|
|
888
|
+
event.preventDefault();
|
|
889
|
+
event.stopPropagation();
|
|
1064
890
|
}
|
|
1065
891
|
|
|
1066
892
|
if (!result.key) {
|
|
@@ -1068,8 +894,9 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1068
894
|
}
|
|
1069
895
|
|
|
1070
896
|
// 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
|
-
|
|
897
|
+
// letters cannot be input while caps lock is on. Skip this hack when using kitty protocol
|
|
898
|
+
// or Win32 input mode as they need to send proper sequences for all key events.
|
|
899
|
+
if (!this._keyboardService.useKitty && !this._keyboardService.useWin32InputMode && event.key && !event.ctrlKey && !event.altKey && !event.metaKey && event.key.length === 1) {
|
|
1073
900
|
if (event.key.charCodeAt(0) >= 65 && event.key.charCodeAt(0) <= 90) {
|
|
1074
901
|
return true;
|
|
1075
902
|
}
|
|
@@ -1087,16 +914,19 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1087
914
|
this.textarea!.value = '';
|
|
1088
915
|
}
|
|
1089
916
|
|
|
917
|
+
const wasModifierOnly = this._keyboardService.useWin32InputMode && wasModifierKeyOnlyEvent(event);
|
|
1090
918
|
this._onKey.fire({ key: result.key, domEvent: event });
|
|
1091
919
|
this._showCursor();
|
|
1092
|
-
this.coreService.triggerDataEvent(result.key,
|
|
920
|
+
this.coreService.triggerDataEvent(result.key, !wasModifierOnly);
|
|
1093
921
|
|
|
1094
922
|
// Cancel events when not in screen reader mode so events don't get bubbled up and handled by
|
|
1095
923
|
// other listeners. When screen reader mode is enabled, we don't cancel them (unless ctrl or alt
|
|
1096
924
|
// is also depressed) so that the cursor textarea can be updated, which triggers the screen
|
|
1097
925
|
// reader to read it.
|
|
1098
926
|
if (!this.optionsService.rawOptions.screenReaderMode || event.altKey || event.ctrlKey) {
|
|
1099
|
-
|
|
927
|
+
event.preventDefault();
|
|
928
|
+
event.stopPropagation();
|
|
929
|
+
return false;
|
|
1100
930
|
}
|
|
1101
931
|
|
|
1102
932
|
this._keyDownHandled = true;
|
|
@@ -1127,6 +957,13 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1127
957
|
this.focus();
|
|
1128
958
|
}
|
|
1129
959
|
|
|
960
|
+
// Handle key release for Kitty keyboard protocol
|
|
961
|
+
const result = this._keyboardService.evaluateKeyUp(ev);
|
|
962
|
+
if (result?.key) {
|
|
963
|
+
const wasModifierOnly = this._keyboardService.useWin32InputMode && wasModifierKeyOnlyEvent(ev);
|
|
964
|
+
this.coreService.triggerDataEvent(result.key, !wasModifierOnly);
|
|
965
|
+
}
|
|
966
|
+
|
|
1130
967
|
this.updateCursorStyle(ev);
|
|
1131
968
|
this._keyPressHandled = false;
|
|
1132
969
|
}
|
|
@@ -1150,8 +987,6 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1150
987
|
return false;
|
|
1151
988
|
}
|
|
1152
989
|
|
|
1153
|
-
this.cancel(ev);
|
|
1154
|
-
|
|
1155
990
|
if (ev.charCode) {
|
|
1156
991
|
key = ev.charCode;
|
|
1157
992
|
} else if (ev.which === null || ev.which === undefined) {
|
|
@@ -1204,8 +1039,6 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1204
1039
|
|
|
1205
1040
|
const text = ev.data;
|
|
1206
1041
|
this.coreService.triggerDataEvent(text, true);
|
|
1207
|
-
|
|
1208
|
-
this.cancel(ev);
|
|
1209
1042
|
return true;
|
|
1210
1043
|
}
|
|
1211
1044
|
|
|
@@ -1276,6 +1109,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1276
1109
|
|
|
1277
1110
|
this._setup();
|
|
1278
1111
|
super.reset();
|
|
1112
|
+
this._mouseService?.reset();
|
|
1279
1113
|
this._selectionService?.reset();
|
|
1280
1114
|
this._decorationService.reset();
|
|
1281
1115
|
|
|
@@ -1283,7 +1117,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1283
1117
|
this._customKeyEventHandler = customKeyEventHandler;
|
|
1284
1118
|
|
|
1285
1119
|
// do a full screen refresh
|
|
1286
|
-
this.refresh(0, this.rows - 1);
|
|
1120
|
+
this.refresh(0, this.rows - 1, true);
|
|
1287
1121
|
}
|
|
1288
1122
|
|
|
1289
1123
|
public clearTextureAtlas(): void {
|
|
@@ -1317,15 +1151,6 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1317
1151
|
}
|
|
1318
1152
|
}
|
|
1319
1153
|
|
|
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
1154
|
}
|
|
1330
1155
|
|
|
1331
1156
|
/**
|
|
@@ -1335,5 +1160,10 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1335
1160
|
function wasModifierKeyOnlyEvent(ev: KeyboardEvent): boolean {
|
|
1336
1161
|
return ev.keyCode === 16 || // Shift
|
|
1337
1162
|
ev.keyCode === 17 || // Ctrl
|
|
1338
|
-
ev.keyCode === 18
|
|
1163
|
+
ev.keyCode === 18 || // Alt
|
|
1164
|
+
ev.keyCode === 91 || // Meta (Left)
|
|
1165
|
+
ev.keyCode === 92 || // Meta (Right)
|
|
1166
|
+
ev.keyCode === 93 || // Meta (Menu)
|
|
1167
|
+
ev.keyCode === 224 || // Meta (Firefox)
|
|
1168
|
+
ev.key === 'Meta';
|
|
1339
1169
|
}
|