@xterm/xterm 6.1.0-beta.30 → 6.1.0-beta.301
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 +69 -38
- package/css/xterm.css +29 -22
- package/lib/xterm.js +1 -1
- package/lib/xterm.js.map +1 -1
- package/lib/xterm.mjs +8 -34
- package/lib/xterm.mjs.map +4 -4
- package/package.json +56 -45
- package/src/browser/AccessibilityManager.ts +18 -13
- package/src/browser/Clipboard.ts +8 -5
- package/src/browser/ColorContrastCache.ts +3 -3
- package/src/browser/CoreBrowserTerminal.ts +180 -350
- package/src/browser/Dom.ts +178 -0
- package/src/browser/Linkifier.ts +14 -14
- package/src/browser/OscLinkProvider.ts +86 -18
- package/src/browser/RenderDebouncer.ts +7 -9
- package/src/browser/TimeBasedDebouncer.ts +12 -5
- package/src/browser/Types.ts +16 -14
- package/src/browser/Viewport.ts +58 -23
- package/src/browser/decorations/BufferDecorationRenderer.ts +3 -3
- package/src/browser/decorations/ColorZoneStore.ts +1 -1
- package/src/browser/decorations/OverviewRulerRenderer.ts +36 -20
- package/src/browser/input/CompositionHelper.ts +47 -11
- package/src/browser/input/Mouse.ts +5 -9
- package/src/browser/input/MoveToCell.ts +3 -3
- package/src/browser/public/Terminal.ts +33 -36
- package/src/browser/renderer/dom/DomRenderer.ts +265 -89
- package/src/browser/renderer/dom/DomRendererRowFactory.ts +34 -27
- package/src/browser/renderer/dom/WidthCache.ts +57 -55
- package/src/browser/renderer/shared/Constants.ts +7 -0
- package/src/browser/renderer/shared/RendererUtils.ts +1 -1
- package/src/browser/renderer/shared/SelectionRenderModel.ts +2 -2
- package/src/browser/renderer/shared/TextBlinkStateManager.ts +97 -0
- package/src/browser/renderer/shared/Types.ts +10 -4
- package/src/browser/scrollable/abstractScrollbar.ts +300 -0
- package/src/browser/scrollable/fastDomNode.ts +126 -0
- package/src/browser/scrollable/globalPointerMoveMonitor.ts +90 -0
- package/src/browser/scrollable/horizontalScrollbar.ts +85 -0
- package/src/browser/scrollable/mouseEvent.ts +292 -0
- package/src/browser/scrollable/scrollable.ts +486 -0
- package/src/browser/scrollable/scrollableElement.ts +581 -0
- package/src/browser/scrollable/scrollableElementOptions.ts +161 -0
- package/src/browser/scrollable/scrollbarArrow.ts +110 -0
- package/src/browser/scrollable/scrollbarState.ts +246 -0
- package/src/browser/scrollable/scrollbarVisibilityController.ts +113 -0
- package/src/browser/scrollable/touch.ts +485 -0
- package/src/browser/scrollable/verticalScrollbar.ts +143 -0
- package/src/browser/scrollable/widget.ts +23 -0
- package/src/browser/selection/SelectionModel.ts +4 -3
- package/src/browser/services/CharSizeService.ts +4 -4
- package/src/browser/services/CharacterJoinerService.ts +13 -11
- package/src/browser/services/CoreBrowserService.ts +7 -5
- package/src/browser/services/KeyboardService.ts +67 -0
- package/src/browser/services/LinkProviderService.ts +3 -3
- package/src/browser/services/MouseCoordsService.ts +47 -0
- package/src/browser/services/MouseService.ts +610 -23
- package/src/browser/services/RenderService.ts +33 -21
- package/src/browser/services/SelectionService.ts +73 -55
- package/src/browser/services/Services.ts +44 -21
- package/src/browser/services/ThemeService.ts +9 -9
- package/src/common/Async.ts +141 -0
- package/src/common/CircularList.ts +24 -3
- package/src/common/Color.ts +13 -5
- package/src/common/CoreTerminal.ts +59 -34
- package/src/common/Event.ts +118 -0
- package/src/common/InputHandler.ts +286 -105
- package/src/common/Lifecycle.ts +113 -0
- package/src/common/Platform.ts +15 -5
- package/src/common/SortedList.ts +8 -4
- package/src/common/StringBuilder.ts +67 -0
- package/src/common/TaskQueue.ts +17 -8
- package/src/common/Types.ts +68 -206
- package/src/common/Version.ts +1 -1
- package/src/common/WindowsMode.ts +2 -2
- package/src/common/buffer/AttributeData.ts +3 -2
- package/src/common/buffer/Buffer.ts +47 -32
- package/src/common/buffer/BufferLine.ts +175 -100
- package/src/common/buffer/BufferLineStringCache.ts +69 -0
- package/src/common/buffer/BufferReflow.ts +7 -4
- package/src/common/buffer/BufferSet.ts +13 -9
- package/src/common/buffer/CellData.ts +61 -4
- package/src/common/buffer/Constants.ts +13 -13
- package/src/common/buffer/Marker.ts +4 -4
- package/src/common/buffer/Types.ts +153 -3
- package/src/common/data/Charsets.ts +4 -7
- package/src/common/data/EscapeSequences.ts +71 -70
- package/src/common/input/Keyboard.ts +17 -10
- package/src/common/input/KittyKeyboard.ts +526 -0
- package/src/common/input/TextDecoder.ts +3 -3
- package/src/common/input/UnicodeV6.ts +3 -2
- package/src/common/input/Win32InputMode.ts +297 -0
- package/src/common/input/WriteBuffer.ts +108 -39
- package/src/common/input/XParseColor.ts +2 -2
- package/src/common/parser/ApcParser.ts +196 -0
- package/src/common/parser/Constants.ts +14 -4
- package/src/common/parser/DcsParser.ts +15 -16
- package/src/common/parser/EscapeSequenceParser.ts +214 -72
- package/src/common/parser/OscParser.ts +14 -15
- package/src/common/parser/Params.ts +31 -12
- package/src/common/parser/Types.ts +40 -30
- package/src/common/public/BufferApiView.ts +3 -3
- package/src/common/public/BufferLineApiView.ts +4 -4
- package/src/common/public/BufferNamespaceApi.ts +5 -5
- package/src/common/public/ParserApi.ts +5 -2
- package/src/common/public/UnicodeApi.ts +1 -1
- package/src/common/services/BufferService.ts +17 -13
- package/src/common/services/CharsetService.ts +6 -2
- package/src/common/services/CoreService.ts +23 -10
- package/src/common/services/DecorationService.ts +260 -15
- package/src/common/services/InstantiationService.ts +2 -2
- package/src/common/services/LogService.ts +2 -32
- package/src/common/services/{CoreMouseService.ts → MouseStateService.ts} +22 -133
- package/src/common/services/OptionsService.ts +17 -7
- package/src/common/services/OscLinkService.ts +3 -2
- package/src/common/services/ServiceRegistry.ts +14 -8
- package/src/common/services/Services.ts +54 -50
- package/src/common/services/UnicodeService.ts +6 -11
- package/typings/xterm.d.ts +329 -34
- package/src/common/Clone.ts +0 -23
- package/src/common/TypedArrayUtils.ts +0 -17
- package/src/vs/base/browser/browser.ts +0 -141
- package/src/vs/base/browser/canIUse.ts +0 -49
- package/src/vs/base/browser/dom.ts +0 -2369
- package/src/vs/base/browser/fastDomNode.ts +0 -316
- package/src/vs/base/browser/globalPointerMoveMonitor.ts +0 -112
- package/src/vs/base/browser/iframe.ts +0 -135
- package/src/vs/base/browser/keyboardEvent.ts +0 -213
- package/src/vs/base/browser/mouseEvent.ts +0 -229
- package/src/vs/base/browser/touch.ts +0 -372
- package/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts +0 -303
- package/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts +0 -114
- package/src/vs/base/browser/ui/scrollbar/scrollableElement.ts +0 -720
- package/src/vs/base/browser/ui/scrollbar/scrollableElementOptions.ts +0 -165
- package/src/vs/base/browser/ui/scrollbar/scrollbarArrow.ts +0 -114
- package/src/vs/base/browser/ui/scrollbar/scrollbarState.ts +0 -243
- package/src/vs/base/browser/ui/scrollbar/scrollbarVisibilityController.ts +0 -118
- package/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts +0 -116
- package/src/vs/base/browser/ui/widget.ts +0 -57
- package/src/vs/base/browser/window.ts +0 -14
- package/src/vs/base/common/arrays.ts +0 -887
- package/src/vs/base/common/arraysFind.ts +0 -202
- package/src/vs/base/common/assert.ts +0 -71
- package/src/vs/base/common/async.ts +0 -1992
- package/src/vs/base/common/cancellation.ts +0 -148
- package/src/vs/base/common/charCode.ts +0 -450
- package/src/vs/base/common/collections.ts +0 -140
- package/src/vs/base/common/decorators.ts +0 -130
- package/src/vs/base/common/equals.ts +0 -146
- package/src/vs/base/common/errors.ts +0 -303
- package/src/vs/base/common/event.ts +0 -1778
- package/src/vs/base/common/functional.ts +0 -32
- package/src/vs/base/common/hash.ts +0 -316
- package/src/vs/base/common/iterator.ts +0 -159
- package/src/vs/base/common/keyCodes.ts +0 -526
- package/src/vs/base/common/keybindings.ts +0 -284
- package/src/vs/base/common/lazy.ts +0 -47
- package/src/vs/base/common/lifecycle.ts +0 -801
- package/src/vs/base/common/linkedList.ts +0 -142
- package/src/vs/base/common/map.ts +0 -202
- package/src/vs/base/common/numbers.ts +0 -98
- package/src/vs/base/common/observable.ts +0 -76
- package/src/vs/base/common/observableInternal/api.ts +0 -31
- package/src/vs/base/common/observableInternal/autorun.ts +0 -281
- package/src/vs/base/common/observableInternal/base.ts +0 -489
- package/src/vs/base/common/observableInternal/debugName.ts +0 -145
- package/src/vs/base/common/observableInternal/derived.ts +0 -428
- package/src/vs/base/common/observableInternal/lazyObservableValue.ts +0 -146
- package/src/vs/base/common/observableInternal/logging.ts +0 -328
- package/src/vs/base/common/observableInternal/promise.ts +0 -209
- package/src/vs/base/common/observableInternal/utils.ts +0 -610
- package/src/vs/base/common/platform.ts +0 -281
- package/src/vs/base/common/scrollable.ts +0 -522
- package/src/vs/base/common/sequence.ts +0 -34
- package/src/vs/base/common/stopwatch.ts +0 -43
- package/src/vs/base/common/strings.ts +0 -557
- package/src/vs/base/common/symbols.ts +0 -9
- package/src/vs/base/common/uint.ts +0 -59
- package/src/vs/patches/nls.ts +0 -90
- package/src/vs/typings/base-common.d.ts +0 -20
- package/src/vs/typings/require.d.ts +0 -42
- package/src/vs/typings/vscode-globals-nls.d.ts +0 -36
- package/src/vs/typings/vscode-globals-product.d.ts +0 -33
|
@@ -21,43 +21,44 @@
|
|
|
21
21
|
* http://linux.die.net/man/7/urxvt
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
-
import { IDecoration, IDecorationOptions, IDisposable, ILinkProvider, IMarker } from '@xterm/xterm';
|
|
25
|
-
import { copyHandler, handlePasteEvent, moveTextAreaUnderMouseCursor, paste, rightClickHandler } from '
|
|
26
|
-
import * as Strings from '
|
|
27
|
-
import { OscLinkProvider } from '
|
|
28
|
-
import { CharacterJoinerHandler, CustomKeyEventHandler, CustomWheelEventHandler, IBrowser, IBufferRange, ICompositionHelper, ILinkifier2, ITerminal } from '
|
|
29
|
-
import { Viewport } from '
|
|
30
|
-
import { BufferDecorationRenderer } from '
|
|
31
|
-
import { OverviewRulerRenderer } from '
|
|
32
|
-
import { CompositionHelper } from '
|
|
33
|
-
import { DomRenderer } from '
|
|
34
|
-
import { IRenderer } from '
|
|
35
|
-
import { CharSizeService } from '
|
|
36
|
-
import { CharacterJoinerService } from '
|
|
37
|
-
import { CoreBrowserService } from '
|
|
38
|
-
import { LinkProviderService } from '
|
|
39
|
-
import {
|
|
40
|
-
import {
|
|
41
|
-
import {
|
|
42
|
-
import {
|
|
43
|
-
import {
|
|
44
|
-
import {
|
|
45
|
-
import {
|
|
46
|
-
import
|
|
47
|
-
import {
|
|
48
|
-
import
|
|
49
|
-
import {
|
|
50
|
-
import {
|
|
51
|
-
import {
|
|
52
|
-
import {
|
|
53
|
-
import {
|
|
54
|
-
import {
|
|
24
|
+
import { IDecoration, IDecorationOptions, IDisposable, ILinkProvider, IMarker, IRenderDimensions as IRenderDimensionsApi } from '@xterm/xterm';
|
|
25
|
+
import { copyHandler, handlePasteEvent, moveTextAreaUnderMouseCursor, paste, rightClickHandler } from './Clipboard';
|
|
26
|
+
import * as Strings from './LocalizableStrings';
|
|
27
|
+
import { OscLinkProvider } from './OscLinkProvider';
|
|
28
|
+
import { CharacterJoinerHandler, CustomKeyEventHandler, CustomWheelEventHandler, IBrowser, IBufferRange, ICompositionHelper, ILinkifier2, ITerminal } from './Types';
|
|
29
|
+
import { Viewport } from './Viewport';
|
|
30
|
+
import { BufferDecorationRenderer } from './decorations/BufferDecorationRenderer';
|
|
31
|
+
import { OverviewRulerRenderer } from './decorations/OverviewRulerRenderer';
|
|
32
|
+
import { CompositionHelper } from './input/CompositionHelper';
|
|
33
|
+
import { DomRenderer } from './renderer/dom/DomRenderer';
|
|
34
|
+
import { IRenderer } from './renderer/shared/Types';
|
|
35
|
+
import { CharSizeService } from './services/CharSizeService';
|
|
36
|
+
import { CharacterJoinerService } from './services/CharacterJoinerService';
|
|
37
|
+
import { CoreBrowserService } from './services/CoreBrowserService';
|
|
38
|
+
import { LinkProviderService } from './services/LinkProviderService';
|
|
39
|
+
import { MouseCoordsService } from './services/MouseCoordsService';
|
|
40
|
+
import { MouseEventCssClasses, MouseService } from './services/MouseService';
|
|
41
|
+
import { RenderService } from './services/RenderService';
|
|
42
|
+
import { SelectionService } from './services/SelectionService';
|
|
43
|
+
import { ICharSizeService, ICharacterJoinerService, ICoreBrowserService, IKeyboardService, ILinkProviderService, IMouseCoordsService, IMouseService, IRenderService, ISelectionService, IThemeService } from './services/Services';
|
|
44
|
+
import { ThemeService } from './services/ThemeService';
|
|
45
|
+
import { KeyboardService } from './services/KeyboardService';
|
|
46
|
+
import { channels, color, rgb } from '../common/Color';
|
|
47
|
+
import { CoreTerminal } from '../common/CoreTerminal';
|
|
48
|
+
import * as Browser from '../common/Platform';
|
|
49
|
+
import { ColorRequestType, IColorEvent, ITerminalOptions, KeyboardResultType, SpecialColorIndex } from '../common/Types';
|
|
50
|
+
import { DEFAULT_ATTR_DATA } from '../common/buffer/BufferLine';
|
|
51
|
+
import { IBuffer } from '../common/buffer/Types';
|
|
52
|
+
import { C0, C1ESCAPED } from '../common/data/EscapeSequences';
|
|
53
|
+
import { toRgbString } from '../common/input/XParseColor';
|
|
54
|
+
import { DecorationService } from '../common/services/DecorationService';
|
|
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 './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;
|
|
@@ -100,7 +102,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
100
102
|
private _keyDownHandled: boolean = false;
|
|
101
103
|
|
|
102
104
|
/**
|
|
103
|
-
* Records whether a keydown event has
|
|
105
|
+
* Records whether a keydown event has occurred since the last keyup event, i.e. whether a key
|
|
104
106
|
* is currently "pressed".
|
|
105
107
|
*/
|
|
106
108
|
private _keyDownSeen: boolean = false;
|
|
@@ -134,15 +136,35 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
134
136
|
public readonly onBell = this._onBell.event;
|
|
135
137
|
|
|
136
138
|
private _onFocus = this._register(new Emitter<void>());
|
|
137
|
-
public get onFocus():
|
|
139
|
+
public get onFocus(): IEvent<void> { return this._onFocus.event; }
|
|
138
140
|
private _onBlur = this._register(new Emitter<void>());
|
|
139
|
-
public get onBlur():
|
|
141
|
+
public get onBlur(): IEvent<void> { return this._onBlur.event; }
|
|
140
142
|
private _onA11yCharEmitter = this._register(new Emitter<string>());
|
|
141
|
-
public get onA11yChar():
|
|
143
|
+
public get onA11yChar(): IEvent<string> { return this._onA11yCharEmitter.event; }
|
|
142
144
|
private _onA11yTabEmitter = this._register(new Emitter<number>());
|
|
143
|
-
public get onA11yTab():
|
|
145
|
+
public get onA11yTab(): IEvent<number> { return this._onA11yTabEmitter.event; }
|
|
144
146
|
private _onWillOpen = this._register(new Emitter<HTMLElement>());
|
|
145
|
-
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
|
+
}
|
|
146
168
|
|
|
147
169
|
constructor(
|
|
148
170
|
options: Partial<ITerminalOptions> = {}
|
|
@@ -153,6 +175,8 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
153
175
|
|
|
154
176
|
this._decorationService = this._instantiationService.createInstance(DecorationService);
|
|
155
177
|
this._instantiationService.setService(IDecorationService, this._decorationService);
|
|
178
|
+
this._keyboardService = this._instantiationService.createInstance(KeyboardService);
|
|
179
|
+
this._instantiationService.setService(IKeyboardService, this._keyboardService);
|
|
156
180
|
this._linkProviderService = this._instantiationService.createInstance(LinkProviderService);
|
|
157
181
|
this._instantiationService.setService(ILinkProviderService, this._linkProviderService);
|
|
158
182
|
this._linkProviderService.registerLinkProvider(this._instantiationService.createInstance(OscLinkProvider));
|
|
@@ -164,10 +188,10 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
164
188
|
this._register(this._inputHandler.onRequestReset(() => this.reset()));
|
|
165
189
|
this._register(this._inputHandler.onRequestWindowsOptionsReport(type => this._reportWindowsOptions(type)));
|
|
166
190
|
this._register(this._inputHandler.onColor((event) => this._handleColorEvent(event)));
|
|
167
|
-
this._register(
|
|
168
|
-
this._register(
|
|
169
|
-
this._register(
|
|
170
|
-
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));
|
|
171
195
|
|
|
172
196
|
// Setup listeners
|
|
173
197
|
this._register(this._bufferService.onResize(e => this._afterResize(e.cols, e.rows)));
|
|
@@ -188,7 +212,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
188
212
|
if (!this._themeService) return;
|
|
189
213
|
for (const req of event) {
|
|
190
214
|
let acc: 'foreground' | 'background' | 'cursor' | 'ansi';
|
|
191
|
-
let ident
|
|
215
|
+
let ident: string;
|
|
192
216
|
switch (req.index) {
|
|
193
217
|
case SpecialColorIndex.FOREGROUND: // OSC 10 | 110
|
|
194
218
|
acc = 'foreground';
|
|
@@ -212,7 +236,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
212
236
|
const colorRgb = color.toColorRGB(acc === 'ansi'
|
|
213
237
|
? this._themeService.colors.ansi[req.index]
|
|
214
238
|
: this._themeService.colors[acc]);
|
|
215
|
-
this.coreService.triggerDataEvent(`${C0.ESC}]${ident};${toRgbString(colorRgb)}${
|
|
239
|
+
this.coreService.triggerDataEvent(`${C0.ESC}]${ident};${toRgbString(colorRgb)}${C1ESCAPED.ST}`);
|
|
216
240
|
break;
|
|
217
241
|
case ColorRequestType.SET:
|
|
218
242
|
if (acc === 'ansi') {
|
|
@@ -229,6 +253,20 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
229
253
|
}
|
|
230
254
|
}
|
|
231
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
|
+
|
|
232
270
|
protected _setup(): void {
|
|
233
271
|
super._setup();
|
|
234
272
|
|
|
@@ -376,7 +414,16 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
376
414
|
this._register(addDisposableListener(this.textarea!, 'keyup', (ev: KeyboardEvent) => this._keyUp(ev), true));
|
|
377
415
|
this._register(addDisposableListener(this.textarea!, 'keydown', (ev: KeyboardEvent) => this._keyDown(ev), true));
|
|
378
416
|
this._register(addDisposableListener(this.textarea!, 'keypress', (ev: KeyboardEvent) => this._keyPress(ev), true));
|
|
379
|
-
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
|
+
}));
|
|
380
427
|
this._register(addDisposableListener(this.textarea!, 'compositionupdate', (e: CompositionEvent) => this._compositionHelper!.compositionupdate(e)));
|
|
381
428
|
this._register(addDisposableListener(this.textarea!, 'compositionend', () => this._compositionHelper!.compositionend()));
|
|
382
429
|
this._register(addDisposableListener(this.textarea!, 'input', (ev: InputEvent) => this._inputEvent(ev), true));
|
|
@@ -416,6 +463,8 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
416
463
|
this.element.dir = 'ltr'; // xterm.css assumes LTR
|
|
417
464
|
this.element.classList.add('terminal');
|
|
418
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)));
|
|
419
468
|
parent.appendChild(this.element);
|
|
420
469
|
|
|
421
470
|
// Performance: Use a document fragment to build the terminal
|
|
@@ -443,6 +492,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
443
492
|
// https://issuetracker.google.com/issues/260170397
|
|
444
493
|
this.textarea.setAttribute('aria-multiline', 'false');
|
|
445
494
|
}
|
|
495
|
+
this.textarea.setAttribute('autocomplete', 'off');
|
|
446
496
|
this.textarea.setAttribute('autocorrect', 'off');
|
|
447
497
|
this.textarea.setAttribute('autocapitalize', 'off');
|
|
448
498
|
this.textarea.setAttribute('spellcheck', 'false');
|
|
@@ -456,7 +506,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
456
506
|
this.textarea,
|
|
457
507
|
parent.ownerDocument.defaultView ?? window,
|
|
458
508
|
// Force unsafe null in node.js environment for tests
|
|
459
|
-
this._document ?? (typeof window !== 'undefined') ? window.document : null as any
|
|
509
|
+
this._document ?? ((typeof window !== 'undefined') ? window.document : null as any)
|
|
460
510
|
));
|
|
461
511
|
this._instantiationService.setService(ICoreBrowserService, this._coreBrowserService);
|
|
462
512
|
|
|
@@ -470,12 +520,33 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
470
520
|
this._themeService = this._instantiationService.createInstance(ThemeService);
|
|
471
521
|
this._instantiationService.setService(IThemeService, this._themeService);
|
|
472
522
|
|
|
523
|
+
// CSI ? 996 n - color scheme query (https://contour-terminal.org/vt-extensions/color-palette-update-notifications/)
|
|
524
|
+
this._register(this._inputHandler.onRequestColorSchemeQuery(() => this._reportColorScheme()));
|
|
525
|
+
|
|
526
|
+
// Emit unsolicited color scheme notification on theme change when DECSET 2031 is enabled
|
|
527
|
+
this._register(this._themeService.onChangeColors(() => {
|
|
528
|
+
if (this.coreService.decPrivateModes.colorSchemeUpdates) {
|
|
529
|
+
this._reportColorScheme();
|
|
530
|
+
}
|
|
531
|
+
}));
|
|
532
|
+
|
|
473
533
|
this._characterJoinerService = this._instantiationService.createInstance(CharacterJoinerService);
|
|
474
534
|
this._instantiationService.setService(ICharacterJoinerService, this._characterJoinerService);
|
|
475
535
|
|
|
476
536
|
this._renderService = this._register(this._instantiationService.createInstance(RenderService, this.rows, this.screenElement));
|
|
477
537
|
this._instantiationService.setService(IRenderService, this._renderService);
|
|
478
538
|
this._register(this._renderService.onRenderedViewportChange(e => this._onRender.fire(e)));
|
|
539
|
+
this._register(this._renderService.onDimensionsChange(e => this._onDimensionsChange.fire({
|
|
540
|
+
css: {
|
|
541
|
+
canvas: { ...e.css.canvas },
|
|
542
|
+
cell: { ...e.css.cell }
|
|
543
|
+
},
|
|
544
|
+
device: {
|
|
545
|
+
canvas: { ...e.device.canvas },
|
|
546
|
+
cell: { ...e.device.cell },
|
|
547
|
+
char: { ...e.device.char }
|
|
548
|
+
}
|
|
549
|
+
})));
|
|
479
550
|
this.onResize(e => this._renderService!.resize(e.cols, e.rows));
|
|
480
551
|
|
|
481
552
|
this._compositionView = this._document.createElement('div');
|
|
@@ -483,8 +554,8 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
483
554
|
this._compositionHelper = this._instantiationService.createInstance(CompositionHelper, this.textarea, this._compositionView);
|
|
484
555
|
this._helperContainer.appendChild(this._compositionView);
|
|
485
556
|
|
|
486
|
-
this.
|
|
487
|
-
this._instantiationService.setService(
|
|
557
|
+
this._mouseCoordsService = this._instantiationService.createInstance(MouseCoordsService);
|
|
558
|
+
this._instantiationService.setService(IMouseCoordsService, this._mouseCoordsService);
|
|
488
559
|
|
|
489
560
|
const linkifier = this._linkifier.value = this._register(this._instantiationService.createInstance(Linkifier, this.screenElement));
|
|
490
561
|
|
|
@@ -493,8 +564,9 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
493
564
|
|
|
494
565
|
try {
|
|
495
566
|
this._onWillOpen.fire(this.element);
|
|
567
|
+
} catch (e) {
|
|
568
|
+
this._logService.error('onWillOpen handler threw an exception', e);
|
|
496
569
|
}
|
|
497
|
-
catch { /* fails to load addon for some reason */ }
|
|
498
570
|
if (!this._renderService.hasRenderer()) {
|
|
499
571
|
this._renderService.setRenderer(this._createRenderer());
|
|
500
572
|
}
|
|
@@ -503,7 +575,10 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
503
575
|
this._renderService!.handleCursorMove();
|
|
504
576
|
this._syncTextArea();
|
|
505
577
|
}));
|
|
506
|
-
this._register(this.onResize(() =>
|
|
578
|
+
this._register(this.onResize(() => {
|
|
579
|
+
this._renderService!.handleResize(this.cols, this.rows);
|
|
580
|
+
this._syncTextArea();
|
|
581
|
+
}));
|
|
507
582
|
this._register(this.onBlur(() => this._renderService!.handleBlur()));
|
|
508
583
|
this._register(this.onFocus(() => this._renderService!.handleFocus()));
|
|
509
584
|
|
|
@@ -519,6 +594,8 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
519
594
|
linkifier
|
|
520
595
|
));
|
|
521
596
|
this._instantiationService.setService(ISelectionService, this._selectionService);
|
|
597
|
+
this._mouseService = this._instantiationService.createInstance(MouseService);
|
|
598
|
+
this._instantiationService.setService(IMouseService, this._mouseService);
|
|
522
599
|
this._register(this._selectionService.onRequestScrollLines(e => this.scrollLines(e.amount, e.suppressScrollEvent)));
|
|
523
600
|
this._register(this._selectionService.onSelectionChange(() => this._onSelectionChange.fire()));
|
|
524
601
|
this._register(this._selectionService.onRequestRedraw(e => this._renderService!.handleSelectionChanged(e.start, e.end, e.columnSelectMode)));
|
|
@@ -530,7 +607,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
530
607
|
this.textarea!.focus();
|
|
531
608
|
this.textarea!.select();
|
|
532
609
|
}));
|
|
533
|
-
this._register(
|
|
610
|
+
this._register(EventUtils.any(
|
|
534
611
|
this._onScroll.event,
|
|
535
612
|
this._inputHandler.onScroll
|
|
536
613
|
)(() => {
|
|
@@ -542,11 +619,12 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
542
619
|
this._register(addDisposableListener(this.element, 'mousedown', (e: MouseEvent) => this._selectionService!.handleMouseDown(e)));
|
|
543
620
|
|
|
544
621
|
// apply mouse event classes set by escape codes before terminal was attached
|
|
545
|
-
if (this.
|
|
622
|
+
if (this.mouseStateService.areMouseEventsActive && !this.options.mouseEventsRequireAlt) {
|
|
546
623
|
this._selectionService.disable();
|
|
547
|
-
this.element.classList.add(
|
|
624
|
+
this.element.classList.add(MouseEventCssClasses.ENABLE_MOUSE_EVENTS);
|
|
548
625
|
} else {
|
|
549
626
|
this._selectionService.enable();
|
|
627
|
+
this.element.classList.remove(MouseEventCssClasses.ENABLE_MOUSE_EVENTS);
|
|
550
628
|
}
|
|
551
629
|
|
|
552
630
|
if (this.options.screenReaderMode) {
|
|
@@ -556,11 +634,14 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
556
634
|
}
|
|
557
635
|
this._register(this.optionsService.onSpecificOptionChange('screenReaderMode', e => this._handleScreenReaderModeOptionChange(e)));
|
|
558
636
|
|
|
559
|
-
|
|
637
|
+
const showScrollbar = this.options.scrollbar?.showScrollbar ?? true;
|
|
638
|
+
const overviewRulerWidth = this.options.scrollbar?.width;
|
|
639
|
+
if (showScrollbar && overviewRulerWidth) {
|
|
560
640
|
this._overviewRulerRenderer = this._register(this._instantiationService.createInstance(OverviewRulerRenderer, this._viewportElement, this.screenElement));
|
|
561
641
|
}
|
|
562
|
-
this.optionsService.onSpecificOptionChange('
|
|
563
|
-
|
|
642
|
+
this.optionsService.onSpecificOptionChange('scrollbar', value => {
|
|
643
|
+
const shouldShow = (value?.showScrollbar ?? true) && !!value?.width;
|
|
644
|
+
if (!this._overviewRulerRenderer && shouldShow && this._viewportElement && this.screenElement) {
|
|
564
645
|
this._overviewRulerRenderer = this._register(this._instantiationService.createInstance(OverviewRulerRenderer, this._viewportElement, this.screenElement));
|
|
565
646
|
}
|
|
566
647
|
});
|
|
@@ -575,280 +656,26 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
575
656
|
|
|
576
657
|
// Listen for mouse events and translate
|
|
577
658
|
// them into terminal mouse protocols.
|
|
578
|
-
this.bindMouse(
|
|
659
|
+
this._mouseService.bindMouse({
|
|
660
|
+
element: this.element!,
|
|
661
|
+
screenElement: this.screenElement!,
|
|
662
|
+
document: this._document!,
|
|
663
|
+
handleTouchScroll: amount => this._viewport?.handleTouchScroll(amount)
|
|
664
|
+
}, disposable => this._register(disposable), () => this.focus());
|
|
579
665
|
}
|
|
580
666
|
|
|
581
667
|
private _createRenderer(): IRenderer {
|
|
582
668
|
return this._instantiationService.createInstance(DomRenderer, this, this._document!, this.element!, this.screenElement!, this._viewportElement!, this._helperContainer!, this.linkifier!);
|
|
583
669
|
}
|
|
584
670
|
|
|
585
|
-
/**
|
|
586
|
-
* Bind certain mouse events to the terminal.
|
|
587
|
-
* By default only 3 button + wheel up/down is ativated. For higher buttons
|
|
588
|
-
* no mouse report will be created. Typically the standard actions will be active.
|
|
589
|
-
*
|
|
590
|
-
* There are several reasons not to enable support for higher buttons/wheel:
|
|
591
|
-
* - Button 4 and 5 are typically used for history back and forward navigation,
|
|
592
|
-
* there is no straight forward way to supress/intercept those standard actions.
|
|
593
|
-
* - Support for higher buttons does not work in some platform/browser combinations.
|
|
594
|
-
* - Left/right wheel was not tested.
|
|
595
|
-
* - Emulators vary in mouse button support, typically only 3 buttons and
|
|
596
|
-
* wheel up/down work reliable.
|
|
597
|
-
*
|
|
598
|
-
* TODO: Move mouse event code into its own file.
|
|
599
|
-
*/
|
|
600
|
-
public bindMouse(): void {
|
|
601
|
-
const self = this;
|
|
602
|
-
const el = this.element!;
|
|
603
|
-
|
|
604
|
-
// send event to CoreMouseService
|
|
605
|
-
function sendEvent(ev: MouseEvent | WheelEvent): boolean {
|
|
606
|
-
// get mouse coordinates
|
|
607
|
-
const pos = self._mouseService!.getMouseReportCoords(ev, self.screenElement!);
|
|
608
|
-
if (!pos) {
|
|
609
|
-
return false;
|
|
610
|
-
}
|
|
611
|
-
|
|
612
|
-
let but: CoreMouseButton;
|
|
613
|
-
let action: CoreMouseAction | undefined;
|
|
614
|
-
switch ((ev as any).overrideType || ev.type) {
|
|
615
|
-
case 'mousemove':
|
|
616
|
-
action = CoreMouseAction.MOVE;
|
|
617
|
-
if (ev.buttons === undefined) {
|
|
618
|
-
// buttons is not supported on macOS, try to get a value from button instead
|
|
619
|
-
but = CoreMouseButton.NONE;
|
|
620
|
-
if (ev.button !== undefined) {
|
|
621
|
-
but = ev.button < 3 ? ev.button : CoreMouseButton.NONE;
|
|
622
|
-
}
|
|
623
|
-
} else {
|
|
624
|
-
// according to MDN buttons only reports up to button 5 (AUX2)
|
|
625
|
-
but = ev.buttons & 1 ? CoreMouseButton.LEFT :
|
|
626
|
-
ev.buttons & 4 ? CoreMouseButton.MIDDLE :
|
|
627
|
-
ev.buttons & 2 ? CoreMouseButton.RIGHT :
|
|
628
|
-
CoreMouseButton.NONE; // fallback to NONE
|
|
629
|
-
}
|
|
630
|
-
break;
|
|
631
|
-
case 'mouseup':
|
|
632
|
-
action = CoreMouseAction.UP;
|
|
633
|
-
but = ev.button < 3 ? ev.button : CoreMouseButton.NONE;
|
|
634
|
-
break;
|
|
635
|
-
case 'mousedown':
|
|
636
|
-
action = CoreMouseAction.DOWN;
|
|
637
|
-
but = ev.button < 3 ? ev.button : CoreMouseButton.NONE;
|
|
638
|
-
break;
|
|
639
|
-
case 'wheel':
|
|
640
|
-
if (self._customWheelEventHandler && self._customWheelEventHandler(ev as WheelEvent) === false) {
|
|
641
|
-
return false;
|
|
642
|
-
}
|
|
643
|
-
const deltaY = (ev as WheelEvent).deltaY;
|
|
644
|
-
if (deltaY === 0) {
|
|
645
|
-
return false;
|
|
646
|
-
}
|
|
647
|
-
const lines = self.coreMouseService.consumeWheelEvent(
|
|
648
|
-
ev as WheelEvent,
|
|
649
|
-
self._renderService?.dimensions?.device?.cell?.height,
|
|
650
|
-
self._coreBrowserService?.dpr
|
|
651
|
-
);
|
|
652
|
-
if (lines === 0) {
|
|
653
|
-
return false;
|
|
654
|
-
}
|
|
655
|
-
action = deltaY < 0 ? CoreMouseAction.UP : CoreMouseAction.DOWN;
|
|
656
|
-
but = CoreMouseButton.WHEEL;
|
|
657
|
-
break;
|
|
658
|
-
default:
|
|
659
|
-
// dont handle other event types by accident
|
|
660
|
-
return false;
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
// exit if we cannot determine valid button/action values
|
|
664
|
-
// do nothing for higher buttons than wheel
|
|
665
|
-
if (action === undefined || but === undefined || but > CoreMouseButton.WHEEL) {
|
|
666
|
-
return false;
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
return self.coreMouseService.triggerMouseEvent({
|
|
670
|
-
col: pos.col,
|
|
671
|
-
row: pos.row,
|
|
672
|
-
x: pos.x,
|
|
673
|
-
y: pos.y,
|
|
674
|
-
button: but,
|
|
675
|
-
action,
|
|
676
|
-
ctrl: ev.ctrlKey,
|
|
677
|
-
alt: ev.altKey,
|
|
678
|
-
shift: ev.shiftKey
|
|
679
|
-
});
|
|
680
|
-
}
|
|
681
|
-
|
|
682
|
-
/**
|
|
683
|
-
* Event listener state handling.
|
|
684
|
-
* We listen to the onProtocolChange event of CoreMouseService and put
|
|
685
|
-
* requested listeners in `requestedEvents`. With this the listeners
|
|
686
|
-
* have all bits to do the event listener juggling.
|
|
687
|
-
* Note: 'mousedown' currently is "always on" and not managed
|
|
688
|
-
* by onProtocolChange.
|
|
689
|
-
*/
|
|
690
|
-
const requestedEvents: { [key: string]: ((ev: MouseEvent | WheelEvent) => void) | null } = {
|
|
691
|
-
mouseup: null,
|
|
692
|
-
wheel: null,
|
|
693
|
-
mousedrag: null,
|
|
694
|
-
mousemove: null
|
|
695
|
-
};
|
|
696
|
-
const eventListeners: { [key: string]: (ev: any) => void | boolean } = {
|
|
697
|
-
mouseup: (ev: MouseEvent) => {
|
|
698
|
-
sendEvent(ev);
|
|
699
|
-
if (!ev.buttons) {
|
|
700
|
-
// if no other button is held remove global handlers
|
|
701
|
-
this._document!.removeEventListener('mouseup', requestedEvents.mouseup!);
|
|
702
|
-
if (requestedEvents.mousedrag) {
|
|
703
|
-
this._document!.removeEventListener('mousemove', requestedEvents.mousedrag);
|
|
704
|
-
}
|
|
705
|
-
}
|
|
706
|
-
return this.cancel(ev);
|
|
707
|
-
},
|
|
708
|
-
wheel: (ev: WheelEvent) => {
|
|
709
|
-
sendEvent(ev);
|
|
710
|
-
return this.cancel(ev, true);
|
|
711
|
-
},
|
|
712
|
-
mousedrag: (ev: MouseEvent) => {
|
|
713
|
-
// deal only with move while a button is held
|
|
714
|
-
if (ev.buttons) {
|
|
715
|
-
sendEvent(ev);
|
|
716
|
-
}
|
|
717
|
-
},
|
|
718
|
-
mousemove: (ev: MouseEvent) => {
|
|
719
|
-
// deal only with move without any button
|
|
720
|
-
if (!ev.buttons) {
|
|
721
|
-
sendEvent(ev);
|
|
722
|
-
}
|
|
723
|
-
}
|
|
724
|
-
};
|
|
725
|
-
this._register(this.coreMouseService.onProtocolChange(events => {
|
|
726
|
-
// apply global changes on events
|
|
727
|
-
if (events) {
|
|
728
|
-
if (this.optionsService.rawOptions.logLevel === 'debug') {
|
|
729
|
-
this._logService.debug('Binding to mouse events:', this.coreMouseService.explainEvents(events));
|
|
730
|
-
}
|
|
731
|
-
this.element!.classList.add('enable-mouse-events');
|
|
732
|
-
this._selectionService!.disable();
|
|
733
|
-
} else {
|
|
734
|
-
this._logService.debug('Unbinding from mouse events.');
|
|
735
|
-
this.element!.classList.remove('enable-mouse-events');
|
|
736
|
-
this._selectionService!.enable();
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
// add/remove handlers from requestedEvents
|
|
740
|
-
|
|
741
|
-
if (!(events & CoreMouseEventType.MOVE)) {
|
|
742
|
-
el.removeEventListener('mousemove', requestedEvents.mousemove!);
|
|
743
|
-
requestedEvents.mousemove = null;
|
|
744
|
-
} else if (!requestedEvents.mousemove) {
|
|
745
|
-
el.addEventListener('mousemove', eventListeners.mousemove);
|
|
746
|
-
requestedEvents.mousemove = eventListeners.mousemove;
|
|
747
|
-
}
|
|
748
|
-
|
|
749
|
-
if (!(events & CoreMouseEventType.WHEEL)) {
|
|
750
|
-
el.removeEventListener('wheel', requestedEvents.wheel!);
|
|
751
|
-
requestedEvents.wheel = null;
|
|
752
|
-
} else if (!requestedEvents.wheel) {
|
|
753
|
-
el.addEventListener('wheel', eventListeners.wheel, { passive: false });
|
|
754
|
-
requestedEvents.wheel = eventListeners.wheel;
|
|
755
|
-
}
|
|
756
|
-
|
|
757
|
-
if (!(events & CoreMouseEventType.UP)) {
|
|
758
|
-
this._document!.removeEventListener('mouseup', requestedEvents.mouseup!);
|
|
759
|
-
requestedEvents.mouseup = null;
|
|
760
|
-
} else if (!requestedEvents.mouseup) {
|
|
761
|
-
requestedEvents.mouseup = eventListeners.mouseup;
|
|
762
|
-
}
|
|
763
|
-
|
|
764
|
-
if (!(events & CoreMouseEventType.DRAG)) {
|
|
765
|
-
this._document!.removeEventListener('mousemove', requestedEvents.mousedrag!);
|
|
766
|
-
requestedEvents.mousedrag = null;
|
|
767
|
-
} else if (!requestedEvents.mousedrag) {
|
|
768
|
-
requestedEvents.mousedrag = eventListeners.mousedrag;
|
|
769
|
-
}
|
|
770
|
-
}));
|
|
771
|
-
// force initial onProtocolChange so we dont miss early mouse requests
|
|
772
|
-
this.coreMouseService.activeProtocol = this.coreMouseService.activeProtocol;
|
|
773
|
-
|
|
774
|
-
/**
|
|
775
|
-
* "Always on" event listeners.
|
|
776
|
-
*/
|
|
777
|
-
this._register(addDisposableListener(el, 'mousedown', (ev: MouseEvent) => {
|
|
778
|
-
ev.preventDefault();
|
|
779
|
-
this.focus();
|
|
780
|
-
|
|
781
|
-
// Don't send the mouse button to the pty if mouse events are disabled or
|
|
782
|
-
// if the selection manager is having selection forced (ie. a modifier is
|
|
783
|
-
// held).
|
|
784
|
-
if (!this.coreMouseService.areMouseEventsActive || this._selectionService!.shouldForceSelection(ev)) {
|
|
785
|
-
return;
|
|
786
|
-
}
|
|
787
|
-
|
|
788
|
-
sendEvent(ev);
|
|
789
|
-
|
|
790
|
-
// Register additional global handlers which should keep reporting outside
|
|
791
|
-
// of the terminal element.
|
|
792
|
-
// Note: Other emulators also do this for 'mousedown' while a button
|
|
793
|
-
// is held, we currently limit 'mousedown' to the terminal only.
|
|
794
|
-
if (requestedEvents.mouseup) {
|
|
795
|
-
this._document!.addEventListener('mouseup', requestedEvents.mouseup);
|
|
796
|
-
}
|
|
797
|
-
if (requestedEvents.mousedrag) {
|
|
798
|
-
this._document!.addEventListener('mousemove', requestedEvents.mousedrag);
|
|
799
|
-
}
|
|
800
|
-
|
|
801
|
-
return this.cancel(ev);
|
|
802
|
-
}));
|
|
803
|
-
|
|
804
|
-
this._register(addDisposableListener(el, 'wheel', (ev: WheelEvent) => {
|
|
805
|
-
// do nothing, if app side handles wheel itself
|
|
806
|
-
if (requestedEvents.wheel) return;
|
|
807
|
-
|
|
808
|
-
if (this._customWheelEventHandler && this._customWheelEventHandler(ev) === false) {
|
|
809
|
-
return false;
|
|
810
|
-
}
|
|
811
|
-
|
|
812
|
-
if (!this.buffer.hasScrollback) {
|
|
813
|
-
// Convert wheel events into up/down events when the buffer does not have scrollback, this
|
|
814
|
-
// enables scrolling in apps hosted in the alt buffer such as vim or tmux even when mouse
|
|
815
|
-
// events are not enabled.
|
|
816
|
-
// This used implementation used get the actual lines/partial lines scrolled from the
|
|
817
|
-
// viewport but since moving to the new viewport implementation has been simplified to
|
|
818
|
-
// simply send a single up or down sequence.
|
|
819
|
-
|
|
820
|
-
// Do nothing if there's no vertical scroll
|
|
821
|
-
const deltaY = (ev as WheelEvent).deltaY;
|
|
822
|
-
if (deltaY === 0) {
|
|
823
|
-
return false;
|
|
824
|
-
}
|
|
825
|
-
|
|
826
|
-
const lines = self.coreMouseService.consumeWheelEvent(
|
|
827
|
-
ev as WheelEvent,
|
|
828
|
-
self._renderService?.dimensions?.device?.cell?.height,
|
|
829
|
-
self._coreBrowserService?.dpr
|
|
830
|
-
);
|
|
831
|
-
if (lines === 0) {
|
|
832
|
-
return this.cancel(ev, true);
|
|
833
|
-
}
|
|
834
|
-
|
|
835
|
-
// Construct and send sequences
|
|
836
|
-
const sequence = C0.ESC + (this.coreService.decPrivateModes.applicationCursorKeys ? 'O' : '[') + (ev.deltaY < 0 ? 'A' : 'B');
|
|
837
|
-
this.coreService.triggerDataEvent(sequence, true);
|
|
838
|
-
return this.cancel(ev, true);
|
|
839
|
-
}
|
|
840
|
-
}, { passive: false }));
|
|
841
|
-
}
|
|
842
|
-
|
|
843
|
-
|
|
844
671
|
/**
|
|
845
672
|
* Tells the renderer to refresh terminal content between two rows (inclusive) at the next
|
|
846
673
|
* opportunity.
|
|
847
674
|
* @param start The row to start from (between 0 and this.rows - 1).
|
|
848
675
|
* @param end The row to end at (between start and this.rows - 1).
|
|
849
676
|
*/
|
|
850
|
-
public refresh(start: number, end: number): void {
|
|
851
|
-
this._renderService?.refreshRows(start, end);
|
|
677
|
+
public refresh(start: number, end: number, sync: boolean = false): void {
|
|
678
|
+
this._renderService?.refreshRows(start, end, sync);
|
|
852
679
|
}
|
|
853
680
|
|
|
854
681
|
/**
|
|
@@ -914,7 +741,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
914
741
|
}
|
|
915
742
|
|
|
916
743
|
public attachCustomWheelEventHandler(customWheelEventHandler: CustomWheelEventHandler): void {
|
|
917
|
-
this.
|
|
744
|
+
this.mouseStateService.setCustomWheelEventHandler(customWheelEventHandler);
|
|
918
745
|
}
|
|
919
746
|
|
|
920
747
|
public registerLinkProvider(linkProvider: ILinkProvider): IDisposable {
|
|
@@ -1038,14 +865,16 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1038
865
|
this._unprocessedDeadKey = true;
|
|
1039
866
|
}
|
|
1040
867
|
|
|
1041
|
-
const result =
|
|
868
|
+
const result = this._keyboardService.evaluateKeyDown(event);
|
|
1042
869
|
|
|
1043
870
|
this.updateCursorStyle(event);
|
|
1044
871
|
|
|
1045
872
|
if (result.type === KeyboardResultType.PAGE_DOWN || result.type === KeyboardResultType.PAGE_UP) {
|
|
1046
873
|
const scrollCount = this.rows - 1;
|
|
1047
874
|
this.scrollLines(result.type === KeyboardResultType.PAGE_UP ? -scrollCount : scrollCount);
|
|
1048
|
-
|
|
875
|
+
event.preventDefault();
|
|
876
|
+
event.stopPropagation();
|
|
877
|
+
return false;
|
|
1049
878
|
}
|
|
1050
879
|
|
|
1051
880
|
if (result.type === KeyboardResultType.SELECT_ALL) {
|
|
@@ -1058,7 +887,8 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1058
887
|
|
|
1059
888
|
if (result.cancel) {
|
|
1060
889
|
// The event is canceled at the end already, is this necessary?
|
|
1061
|
-
|
|
890
|
+
event.preventDefault();
|
|
891
|
+
event.stopPropagation();
|
|
1062
892
|
}
|
|
1063
893
|
|
|
1064
894
|
if (!result.key) {
|
|
@@ -1066,8 +896,9 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1066
896
|
}
|
|
1067
897
|
|
|
1068
898
|
// HACK: Process A-Z in the keypress event to fix an issue with macOS IMEs where lower case
|
|
1069
|
-
// letters cannot be input while caps lock is on.
|
|
1070
|
-
|
|
899
|
+
// letters cannot be input while caps lock is on. Skip this hack when using kitty protocol
|
|
900
|
+
// or Win32 input mode as they need to send proper sequences for all key events.
|
|
901
|
+
if (!this._keyboardService.useKitty && !this._keyboardService.useWin32InputMode && event.key && !event.ctrlKey && !event.altKey && !event.metaKey && event.key.length === 1) {
|
|
1071
902
|
if (event.key.charCodeAt(0) >= 65 && event.key.charCodeAt(0) <= 90) {
|
|
1072
903
|
return true;
|
|
1073
904
|
}
|
|
@@ -1085,16 +916,19 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1085
916
|
this.textarea!.value = '';
|
|
1086
917
|
}
|
|
1087
918
|
|
|
919
|
+
const wasModifierOnly = this._keyboardService.useWin32InputMode && wasModifierKeyOnlyEvent(event);
|
|
1088
920
|
this._onKey.fire({ key: result.key, domEvent: event });
|
|
1089
921
|
this._showCursor();
|
|
1090
|
-
this.coreService.triggerDataEvent(result.key,
|
|
922
|
+
this.coreService.triggerDataEvent(result.key, !wasModifierOnly);
|
|
1091
923
|
|
|
1092
924
|
// Cancel events when not in screen reader mode so events don't get bubbled up and handled by
|
|
1093
925
|
// other listeners. When screen reader mode is enabled, we don't cancel them (unless ctrl or alt
|
|
1094
926
|
// is also depressed) so that the cursor textarea can be updated, which triggers the screen
|
|
1095
927
|
// reader to read it.
|
|
1096
928
|
if (!this.optionsService.rawOptions.screenReaderMode || event.altKey || event.ctrlKey) {
|
|
1097
|
-
|
|
929
|
+
event.preventDefault();
|
|
930
|
+
event.stopPropagation();
|
|
931
|
+
return false;
|
|
1098
932
|
}
|
|
1099
933
|
|
|
1100
934
|
this._keyDownHandled = true;
|
|
@@ -1125,6 +959,13 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1125
959
|
this.focus();
|
|
1126
960
|
}
|
|
1127
961
|
|
|
962
|
+
// Handle key release for Kitty keyboard protocol
|
|
963
|
+
const result = this._keyboardService.evaluateKeyUp(ev);
|
|
964
|
+
if (result?.key) {
|
|
965
|
+
const wasModifierOnly = this._keyboardService.useWin32InputMode && wasModifierKeyOnlyEvent(ev);
|
|
966
|
+
this.coreService.triggerDataEvent(result.key, !wasModifierOnly);
|
|
967
|
+
}
|
|
968
|
+
|
|
1128
969
|
this.updateCursorStyle(ev);
|
|
1129
970
|
this._keyPressHandled = false;
|
|
1130
971
|
}
|
|
@@ -1148,8 +989,6 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1148
989
|
return false;
|
|
1149
990
|
}
|
|
1150
991
|
|
|
1151
|
-
this.cancel(ev);
|
|
1152
|
-
|
|
1153
992
|
if (ev.charCode) {
|
|
1154
993
|
key = ev.charCode;
|
|
1155
994
|
} else if (ev.which === null || ev.which === undefined) {
|
|
@@ -1202,8 +1041,6 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1202
1041
|
|
|
1203
1042
|
const text = ev.data;
|
|
1204
1043
|
this.coreService.triggerDataEvent(text, true);
|
|
1205
|
-
|
|
1206
|
-
this.cancel(ev);
|
|
1207
1044
|
return true;
|
|
1208
1045
|
}
|
|
1209
1046
|
|
|
@@ -1236,10 +1073,6 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1236
1073
|
* Clear the entire buffer, making the prompt line the new first line.
|
|
1237
1074
|
*/
|
|
1238
1075
|
public clear(): void {
|
|
1239
|
-
if (this.buffer.ybase === 0 && this.buffer.y === 0) {
|
|
1240
|
-
// Don't clear if it's already clear
|
|
1241
|
-
return;
|
|
1242
|
-
}
|
|
1243
1076
|
this.buffer.clearAllMarkers();
|
|
1244
1077
|
this.buffer.lines.set(0, this.buffer.lines.get(this.buffer.ybase + this.buffer.y)!);
|
|
1245
1078
|
this.buffer.lines.length = 1;
|
|
@@ -1274,6 +1107,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1274
1107
|
|
|
1275
1108
|
this._setup();
|
|
1276
1109
|
super.reset();
|
|
1110
|
+
this._mouseService?.reset();
|
|
1277
1111
|
this._selectionService?.reset();
|
|
1278
1112
|
this._decorationService.reset();
|
|
1279
1113
|
|
|
@@ -1281,7 +1115,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1281
1115
|
this._customKeyEventHandler = customKeyEventHandler;
|
|
1282
1116
|
|
|
1283
1117
|
// do a full screen refresh
|
|
1284
|
-
this.refresh(0, this.rows - 1);
|
|
1118
|
+
this.refresh(0, this.rows - 1, true);
|
|
1285
1119
|
}
|
|
1286
1120
|
|
|
1287
1121
|
public clearTextureAtlas(): void {
|
|
@@ -1315,15 +1149,6 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1315
1149
|
}
|
|
1316
1150
|
}
|
|
1317
1151
|
|
|
1318
|
-
// TODO: Remove cancel function and cancelEvents option
|
|
1319
|
-
public cancel(ev: MouseEvent | WheelEvent | KeyboardEvent | InputEvent, force?: boolean): boolean | undefined {
|
|
1320
|
-
if (!this.options.cancelEvents && !force) {
|
|
1321
|
-
return;
|
|
1322
|
-
}
|
|
1323
|
-
ev.preventDefault();
|
|
1324
|
-
ev.stopPropagation();
|
|
1325
|
-
return false;
|
|
1326
|
-
}
|
|
1327
1152
|
}
|
|
1328
1153
|
|
|
1329
1154
|
/**
|
|
@@ -1333,5 +1158,10 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1333
1158
|
function wasModifierKeyOnlyEvent(ev: KeyboardEvent): boolean {
|
|
1334
1159
|
return ev.keyCode === 16 || // Shift
|
|
1335
1160
|
ev.keyCode === 17 || // Ctrl
|
|
1336
|
-
ev.keyCode === 18
|
|
1161
|
+
ev.keyCode === 18 || // Alt
|
|
1162
|
+
ev.keyCode === 91 || // Meta (Left)
|
|
1163
|
+
ev.keyCode === 92 || // Meta (Right)
|
|
1164
|
+
ev.keyCode === 93 || // Meta (Menu)
|
|
1165
|
+
ev.keyCode === 224 || // Meta (Firefox)
|
|
1166
|
+
ev.key === 'Meta';
|
|
1337
1167
|
}
|