@xterm/xterm 6.1.0-beta.3 → 6.1.0-beta.300
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 +57 -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 -352
- package/src/browser/Dom.ts +178 -0
- package/src/browser/Linkifier.ts +14 -14
- package/src/browser/OscLinkProvider.ts +87 -19
- 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 -22
- 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 +62 -38
- package/src/common/Event.ts +118 -0
- package/src/common/InputHandler.ts +303 -104
- 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 +9 -0
- package/src/common/WindowsMode.ts +2 -2
- package/src/common/buffer/AttributeData.ts +3 -2
- package/src/common/buffer/Buffer.ts +49 -34
- 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 +5 -8
- 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 -10
- package/src/common/services/OscLinkService.ts +3 -2
- package/src/common/services/ServiceRegistry.ts +14 -8
- package/src/common/services/Services.ts +54 -54
- package/src/common/services/UnicodeService.ts +6 -11
- package/typings/xterm.d.ts +333 -47
- 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;
|
|
@@ -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)));
|
|
@@ -190,7 +212,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
190
212
|
if (!this._themeService) return;
|
|
191
213
|
for (const req of event) {
|
|
192
214
|
let acc: 'foreground' | 'background' | 'cursor' | 'ansi';
|
|
193
|
-
let ident
|
|
215
|
+
let ident: string;
|
|
194
216
|
switch (req.index) {
|
|
195
217
|
case SpecialColorIndex.FOREGROUND: // OSC 10 | 110
|
|
196
218
|
acc = 'foreground';
|
|
@@ -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
|
|
@@ -445,6 +492,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
445
492
|
// https://issuetracker.google.com/issues/260170397
|
|
446
493
|
this.textarea.setAttribute('aria-multiline', 'false');
|
|
447
494
|
}
|
|
495
|
+
this.textarea.setAttribute('autocomplete', 'off');
|
|
448
496
|
this.textarea.setAttribute('autocorrect', 'off');
|
|
449
497
|
this.textarea.setAttribute('autocapitalize', 'off');
|
|
450
498
|
this.textarea.setAttribute('spellcheck', 'false');
|
|
@@ -458,7 +506,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
458
506
|
this.textarea,
|
|
459
507
|
parent.ownerDocument.defaultView ?? window,
|
|
460
508
|
// Force unsafe null in node.js environment for tests
|
|
461
|
-
this._document ?? (typeof window !== 'undefined') ? window.document : null as any
|
|
509
|
+
this._document ?? ((typeof window !== 'undefined') ? window.document : null as any)
|
|
462
510
|
));
|
|
463
511
|
this._instantiationService.setService(ICoreBrowserService, this._coreBrowserService);
|
|
464
512
|
|
|
@@ -472,12 +520,33 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
472
520
|
this._themeService = this._instantiationService.createInstance(ThemeService);
|
|
473
521
|
this._instantiationService.setService(IThemeService, this._themeService);
|
|
474
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
|
+
|
|
475
533
|
this._characterJoinerService = this._instantiationService.createInstance(CharacterJoinerService);
|
|
476
534
|
this._instantiationService.setService(ICharacterJoinerService, this._characterJoinerService);
|
|
477
535
|
|
|
478
536
|
this._renderService = this._register(this._instantiationService.createInstance(RenderService, this.rows, this.screenElement));
|
|
479
537
|
this._instantiationService.setService(IRenderService, this._renderService);
|
|
480
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
|
+
})));
|
|
481
550
|
this.onResize(e => this._renderService!.resize(e.cols, e.rows));
|
|
482
551
|
|
|
483
552
|
this._compositionView = this._document.createElement('div');
|
|
@@ -485,8 +554,8 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
485
554
|
this._compositionHelper = this._instantiationService.createInstance(CompositionHelper, this.textarea, this._compositionView);
|
|
486
555
|
this._helperContainer.appendChild(this._compositionView);
|
|
487
556
|
|
|
488
|
-
this.
|
|
489
|
-
this._instantiationService.setService(
|
|
557
|
+
this._mouseCoordsService = this._instantiationService.createInstance(MouseCoordsService);
|
|
558
|
+
this._instantiationService.setService(IMouseCoordsService, this._mouseCoordsService);
|
|
490
559
|
|
|
491
560
|
const linkifier = this._linkifier.value = this._register(this._instantiationService.createInstance(Linkifier, this.screenElement));
|
|
492
561
|
|
|
@@ -495,8 +564,9 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
495
564
|
|
|
496
565
|
try {
|
|
497
566
|
this._onWillOpen.fire(this.element);
|
|
567
|
+
} catch (e) {
|
|
568
|
+
this._logService.error('onWillOpen handler threw an exception', e);
|
|
498
569
|
}
|
|
499
|
-
catch { /* fails to load addon for some reason */ }
|
|
500
570
|
if (!this._renderService.hasRenderer()) {
|
|
501
571
|
this._renderService.setRenderer(this._createRenderer());
|
|
502
572
|
}
|
|
@@ -505,7 +575,10 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
505
575
|
this._renderService!.handleCursorMove();
|
|
506
576
|
this._syncTextArea();
|
|
507
577
|
}));
|
|
508
|
-
this._register(this.onResize(() =>
|
|
578
|
+
this._register(this.onResize(() => {
|
|
579
|
+
this._renderService!.handleResize(this.cols, this.rows);
|
|
580
|
+
this._syncTextArea();
|
|
581
|
+
}));
|
|
509
582
|
this._register(this.onBlur(() => this._renderService!.handleBlur()));
|
|
510
583
|
this._register(this.onFocus(() => this._renderService!.handleFocus()));
|
|
511
584
|
|
|
@@ -521,6 +594,8 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
521
594
|
linkifier
|
|
522
595
|
));
|
|
523
596
|
this._instantiationService.setService(ISelectionService, this._selectionService);
|
|
597
|
+
this._mouseService = this._instantiationService.createInstance(MouseService);
|
|
598
|
+
this._instantiationService.setService(IMouseService, this._mouseService);
|
|
524
599
|
this._register(this._selectionService.onRequestScrollLines(e => this.scrollLines(e.amount, e.suppressScrollEvent)));
|
|
525
600
|
this._register(this._selectionService.onSelectionChange(() => this._onSelectionChange.fire()));
|
|
526
601
|
this._register(this._selectionService.onRequestRedraw(e => this._renderService!.handleSelectionChanged(e.start, e.end, e.columnSelectMode)));
|
|
@@ -532,7 +607,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
532
607
|
this.textarea!.focus();
|
|
533
608
|
this.textarea!.select();
|
|
534
609
|
}));
|
|
535
|
-
this._register(
|
|
610
|
+
this._register(EventUtils.any(
|
|
536
611
|
this._onScroll.event,
|
|
537
612
|
this._inputHandler.onScroll
|
|
538
613
|
)(() => {
|
|
@@ -544,11 +619,12 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
544
619
|
this._register(addDisposableListener(this.element, 'mousedown', (e: MouseEvent) => this._selectionService!.handleMouseDown(e)));
|
|
545
620
|
|
|
546
621
|
// apply mouse event classes set by escape codes before terminal was attached
|
|
547
|
-
if (this.
|
|
622
|
+
if (this.mouseStateService.areMouseEventsActive && !this.options.mouseEventsRequireAlt) {
|
|
548
623
|
this._selectionService.disable();
|
|
549
|
-
this.element.classList.add(
|
|
624
|
+
this.element.classList.add(MouseEventCssClasses.ENABLE_MOUSE_EVENTS);
|
|
550
625
|
} else {
|
|
551
626
|
this._selectionService.enable();
|
|
627
|
+
this.element.classList.remove(MouseEventCssClasses.ENABLE_MOUSE_EVENTS);
|
|
552
628
|
}
|
|
553
629
|
|
|
554
630
|
if (this.options.screenReaderMode) {
|
|
@@ -558,11 +634,14 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
558
634
|
}
|
|
559
635
|
this._register(this.optionsService.onSpecificOptionChange('screenReaderMode', e => this._handleScreenReaderModeOptionChange(e)));
|
|
560
636
|
|
|
561
|
-
|
|
637
|
+
const showScrollbar = this.options.scrollbar?.showScrollbar ?? true;
|
|
638
|
+
const overviewRulerWidth = this.options.scrollbar?.width;
|
|
639
|
+
if (showScrollbar && overviewRulerWidth) {
|
|
562
640
|
this._overviewRulerRenderer = this._register(this._instantiationService.createInstance(OverviewRulerRenderer, this._viewportElement, this.screenElement));
|
|
563
641
|
}
|
|
564
|
-
this.optionsService.onSpecificOptionChange('
|
|
565
|
-
|
|
642
|
+
this.optionsService.onSpecificOptionChange('scrollbar', value => {
|
|
643
|
+
const shouldShow = (value?.showScrollbar ?? true) && !!value?.width;
|
|
644
|
+
if (!this._overviewRulerRenderer && shouldShow && this._viewportElement && this.screenElement) {
|
|
566
645
|
this._overviewRulerRenderer = this._register(this._instantiationService.createInstance(OverviewRulerRenderer, this._viewportElement, this.screenElement));
|
|
567
646
|
}
|
|
568
647
|
});
|
|
@@ -577,280 +656,26 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
577
656
|
|
|
578
657
|
// Listen for mouse events and translate
|
|
579
658
|
// them into terminal mouse protocols.
|
|
580
|
-
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());
|
|
581
665
|
}
|
|
582
666
|
|
|
583
667
|
private _createRenderer(): IRenderer {
|
|
584
668
|
return this._instantiationService.createInstance(DomRenderer, this, this._document!, this.element!, this.screenElement!, this._viewportElement!, this._helperContainer!, this.linkifier!);
|
|
585
669
|
}
|
|
586
670
|
|
|
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
671
|
/**
|
|
847
672
|
* Tells the renderer to refresh terminal content between two rows (inclusive) at the next
|
|
848
673
|
* opportunity.
|
|
849
674
|
* @param start The row to start from (between 0 and this.rows - 1).
|
|
850
675
|
* @param end The row to end at (between start and this.rows - 1).
|
|
851
676
|
*/
|
|
852
|
-
public refresh(start: number, end: number): void {
|
|
853
|
-
this._renderService?.refreshRows(start, end);
|
|
677
|
+
public refresh(start: number, end: number, sync: boolean = false): void {
|
|
678
|
+
this._renderService?.refreshRows(start, end, sync);
|
|
854
679
|
}
|
|
855
680
|
|
|
856
681
|
/**
|
|
@@ -916,7 +741,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
916
741
|
}
|
|
917
742
|
|
|
918
743
|
public attachCustomWheelEventHandler(customWheelEventHandler: CustomWheelEventHandler): void {
|
|
919
|
-
this.
|
|
744
|
+
this.mouseStateService.setCustomWheelEventHandler(customWheelEventHandler);
|
|
920
745
|
}
|
|
921
746
|
|
|
922
747
|
public registerLinkProvider(linkProvider: ILinkProvider): IDisposable {
|
|
@@ -1040,14 +865,16 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1040
865
|
this._unprocessedDeadKey = true;
|
|
1041
866
|
}
|
|
1042
867
|
|
|
1043
|
-
const result =
|
|
868
|
+
const result = this._keyboardService.evaluateKeyDown(event);
|
|
1044
869
|
|
|
1045
870
|
this.updateCursorStyle(event);
|
|
1046
871
|
|
|
1047
872
|
if (result.type === KeyboardResultType.PAGE_DOWN || result.type === KeyboardResultType.PAGE_UP) {
|
|
1048
873
|
const scrollCount = this.rows - 1;
|
|
1049
874
|
this.scrollLines(result.type === KeyboardResultType.PAGE_UP ? -scrollCount : scrollCount);
|
|
1050
|
-
|
|
875
|
+
event.preventDefault();
|
|
876
|
+
event.stopPropagation();
|
|
877
|
+
return false;
|
|
1051
878
|
}
|
|
1052
879
|
|
|
1053
880
|
if (result.type === KeyboardResultType.SELECT_ALL) {
|
|
@@ -1060,7 +887,8 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1060
887
|
|
|
1061
888
|
if (result.cancel) {
|
|
1062
889
|
// The event is canceled at the end already, is this necessary?
|
|
1063
|
-
|
|
890
|
+
event.preventDefault();
|
|
891
|
+
event.stopPropagation();
|
|
1064
892
|
}
|
|
1065
893
|
|
|
1066
894
|
if (!result.key) {
|
|
@@ -1068,8 +896,9 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1068
896
|
}
|
|
1069
897
|
|
|
1070
898
|
// 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
|
-
|
|
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) {
|
|
1073
902
|
if (event.key.charCodeAt(0) >= 65 && event.key.charCodeAt(0) <= 90) {
|
|
1074
903
|
return true;
|
|
1075
904
|
}
|
|
@@ -1087,16 +916,19 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1087
916
|
this.textarea!.value = '';
|
|
1088
917
|
}
|
|
1089
918
|
|
|
919
|
+
const wasModifierOnly = this._keyboardService.useWin32InputMode && wasModifierKeyOnlyEvent(event);
|
|
1090
920
|
this._onKey.fire({ key: result.key, domEvent: event });
|
|
1091
921
|
this._showCursor();
|
|
1092
|
-
this.coreService.triggerDataEvent(result.key,
|
|
922
|
+
this.coreService.triggerDataEvent(result.key, !wasModifierOnly);
|
|
1093
923
|
|
|
1094
924
|
// Cancel events when not in screen reader mode so events don't get bubbled up and handled by
|
|
1095
925
|
// other listeners. When screen reader mode is enabled, we don't cancel them (unless ctrl or alt
|
|
1096
926
|
// is also depressed) so that the cursor textarea can be updated, which triggers the screen
|
|
1097
927
|
// reader to read it.
|
|
1098
928
|
if (!this.optionsService.rawOptions.screenReaderMode || event.altKey || event.ctrlKey) {
|
|
1099
|
-
|
|
929
|
+
event.preventDefault();
|
|
930
|
+
event.stopPropagation();
|
|
931
|
+
return false;
|
|
1100
932
|
}
|
|
1101
933
|
|
|
1102
934
|
this._keyDownHandled = true;
|
|
@@ -1127,6 +959,13 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1127
959
|
this.focus();
|
|
1128
960
|
}
|
|
1129
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
|
+
|
|
1130
969
|
this.updateCursorStyle(ev);
|
|
1131
970
|
this._keyPressHandled = false;
|
|
1132
971
|
}
|
|
@@ -1150,8 +989,6 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1150
989
|
return false;
|
|
1151
990
|
}
|
|
1152
991
|
|
|
1153
|
-
this.cancel(ev);
|
|
1154
|
-
|
|
1155
992
|
if (ev.charCode) {
|
|
1156
993
|
key = ev.charCode;
|
|
1157
994
|
} else if (ev.which === null || ev.which === undefined) {
|
|
@@ -1204,8 +1041,6 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1204
1041
|
|
|
1205
1042
|
const text = ev.data;
|
|
1206
1043
|
this.coreService.triggerDataEvent(text, true);
|
|
1207
|
-
|
|
1208
|
-
this.cancel(ev);
|
|
1209
1044
|
return true;
|
|
1210
1045
|
}
|
|
1211
1046
|
|
|
@@ -1238,10 +1073,6 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1238
1073
|
* Clear the entire buffer, making the prompt line the new first line.
|
|
1239
1074
|
*/
|
|
1240
1075
|
public clear(): void {
|
|
1241
|
-
if (this.buffer.ybase === 0 && this.buffer.y === 0) {
|
|
1242
|
-
// Don't clear if it's already clear
|
|
1243
|
-
return;
|
|
1244
|
-
}
|
|
1245
1076
|
this.buffer.clearAllMarkers();
|
|
1246
1077
|
this.buffer.lines.set(0, this.buffer.lines.get(this.buffer.ybase + this.buffer.y)!);
|
|
1247
1078
|
this.buffer.lines.length = 1;
|
|
@@ -1276,6 +1107,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1276
1107
|
|
|
1277
1108
|
this._setup();
|
|
1278
1109
|
super.reset();
|
|
1110
|
+
this._mouseService?.reset();
|
|
1279
1111
|
this._selectionService?.reset();
|
|
1280
1112
|
this._decorationService.reset();
|
|
1281
1113
|
|
|
@@ -1283,7 +1115,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1283
1115
|
this._customKeyEventHandler = customKeyEventHandler;
|
|
1284
1116
|
|
|
1285
1117
|
// do a full screen refresh
|
|
1286
|
-
this.refresh(0, this.rows - 1);
|
|
1118
|
+
this.refresh(0, this.rows - 1, true);
|
|
1287
1119
|
}
|
|
1288
1120
|
|
|
1289
1121
|
public clearTextureAtlas(): void {
|
|
@@ -1317,15 +1149,6 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1317
1149
|
}
|
|
1318
1150
|
}
|
|
1319
1151
|
|
|
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
1152
|
}
|
|
1330
1153
|
|
|
1331
1154
|
/**
|
|
@@ -1335,5 +1158,10 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1335
1158
|
function wasModifierKeyOnlyEvent(ev: KeyboardEvent): boolean {
|
|
1336
1159
|
return ev.keyCode === 16 || // Shift
|
|
1337
1160
|
ev.keyCode === 17 || // Ctrl
|
|
1338
|
-
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';
|
|
1339
1167
|
}
|