@xterm/xterm 6.1.0-beta.28 → 6.1.0-beta.280
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -38
- package/css/xterm.css +29 -22
- package/lib/xterm.js +1 -1
- package/lib/xterm.js.map +1 -1
- package/lib/xterm.mjs +8 -34
- package/lib/xterm.mjs.map +4 -4
- package/package.json +56 -45
- package/src/browser/AccessibilityManager.ts +18 -13
- package/src/browser/Clipboard.ts +8 -5
- package/src/browser/ColorContrastCache.ts +3 -3
- package/src/browser/CoreBrowserTerminal.ts +179 -348
- package/src/browser/Dom.ts +178 -0
- package/src/browser/Linkifier.ts +14 -14
- package/src/browser/OscLinkProvider.ts +86 -18
- package/src/browser/RenderDebouncer.ts +7 -9
- package/src/browser/TimeBasedDebouncer.ts +12 -5
- package/src/browser/Types.ts +16 -14
- package/src/browser/Viewport.ts +58 -23
- package/src/browser/decorations/BufferDecorationRenderer.ts +3 -3
- package/src/browser/decorations/ColorZoneStore.ts +1 -1
- package/src/browser/decorations/OverviewRulerRenderer.ts +36 -20
- package/src/browser/input/CompositionHelper.ts +47 -11
- package/src/browser/input/Mouse.ts +5 -9
- package/src/browser/input/MoveToCell.ts +3 -3
- package/src/browser/public/Terminal.ts +33 -36
- package/src/browser/renderer/dom/DomRenderer.ts +265 -89
- package/src/browser/renderer/dom/DomRendererRowFactory.ts +34 -27
- package/src/browser/renderer/dom/WidthCache.ts +57 -55
- package/src/browser/renderer/shared/Constants.ts +7 -0
- package/src/browser/renderer/shared/RendererUtils.ts +1 -1
- package/src/browser/renderer/shared/SelectionRenderModel.ts +2 -2
- package/src/browser/renderer/shared/TextBlinkStateManager.ts +97 -0
- package/src/browser/renderer/shared/Types.ts +10 -4
- package/src/browser/scrollable/abstractScrollbar.ts +300 -0
- package/src/browser/scrollable/fastDomNode.ts +126 -0
- package/src/browser/scrollable/globalPointerMoveMonitor.ts +90 -0
- package/src/browser/scrollable/horizontalScrollbar.ts +85 -0
- package/src/browser/scrollable/mouseEvent.ts +292 -0
- package/src/browser/scrollable/scrollable.ts +486 -0
- package/src/browser/scrollable/scrollableElement.ts +581 -0
- package/src/browser/scrollable/scrollableElementOptions.ts +161 -0
- package/src/browser/scrollable/scrollbarArrow.ts +110 -0
- package/src/browser/scrollable/scrollbarState.ts +246 -0
- package/src/browser/scrollable/scrollbarVisibilityController.ts +113 -0
- package/src/browser/scrollable/touch.ts +485 -0
- package/src/browser/scrollable/verticalScrollbar.ts +143 -0
- package/src/browser/scrollable/widget.ts +23 -0
- package/src/browser/selection/SelectionModel.ts +1 -1
- package/src/browser/services/CharSizeService.ts +4 -4
- package/src/browser/services/CharacterJoinerService.ts +13 -11
- package/src/browser/services/CoreBrowserService.ts +7 -5
- package/src/browser/services/KeyboardService.ts +67 -0
- package/src/browser/services/LinkProviderService.ts +3 -3
- package/src/browser/services/MouseCoordsService.ts +47 -0
- package/src/browser/services/MouseService.ts +619 -23
- package/src/browser/services/RenderService.ts +33 -21
- package/src/browser/services/SelectionService.ts +72 -54
- package/src/browser/services/Services.ts +44 -21
- package/src/browser/services/ThemeService.ts +9 -9
- package/src/common/Async.ts +141 -0
- package/src/common/CircularList.ts +24 -3
- package/src/common/Color.ts +13 -5
- package/src/common/CoreTerminal.ts +61 -35
- package/src/common/Event.ts +118 -0
- package/src/common/InputHandler.ts +286 -105
- package/src/common/Lifecycle.ts +113 -0
- package/src/common/Platform.ts +15 -5
- package/src/common/SortedList.ts +8 -4
- package/src/common/StringBuilder.ts +67 -0
- package/src/common/TaskQueue.ts +17 -8
- package/src/common/Types.ts +68 -206
- package/src/common/Version.ts +1 -1
- package/src/common/WindowsMode.ts +2 -2
- package/src/common/buffer/AttributeData.ts +3 -2
- package/src/common/buffer/Buffer.ts +47 -32
- package/src/common/buffer/BufferLine.ts +175 -100
- package/src/common/buffer/BufferLineStringCache.ts +69 -0
- package/src/common/buffer/BufferReflow.ts +7 -4
- package/src/common/buffer/BufferSet.ts +13 -9
- package/src/common/buffer/CellData.ts +61 -4
- package/src/common/buffer/Constants.ts +13 -13
- package/src/common/buffer/Marker.ts +4 -4
- package/src/common/buffer/Types.ts +153 -3
- package/src/common/data/Charsets.ts +4 -7
- package/src/common/data/EscapeSequences.ts +71 -70
- package/src/common/input/Keyboard.ts +17 -10
- package/src/common/input/KittyKeyboard.ts +526 -0
- package/src/common/input/TextDecoder.ts +3 -3
- package/src/common/input/UnicodeV6.ts +3 -2
- package/src/common/input/Win32InputMode.ts +297 -0
- package/src/common/input/WriteBuffer.ts +108 -39
- package/src/common/input/XParseColor.ts +2 -2
- package/src/common/parser/ApcParser.ts +196 -0
- package/src/common/parser/Constants.ts +14 -4
- package/src/common/parser/DcsParser.ts +15 -16
- package/src/common/parser/EscapeSequenceParser.ts +214 -72
- package/src/common/parser/OscParser.ts +14 -15
- package/src/common/parser/Params.ts +31 -12
- package/src/common/parser/Types.ts +40 -30
- package/src/common/public/BufferApiView.ts +3 -3
- package/src/common/public/BufferLineApiView.ts +4 -4
- package/src/common/public/BufferNamespaceApi.ts +5 -5
- package/src/common/public/ParserApi.ts +5 -2
- package/src/common/public/UnicodeApi.ts +1 -1
- package/src/common/services/BufferService.ts +17 -13
- package/src/common/services/CharsetService.ts +6 -2
- package/src/common/services/CoreService.ts +23 -10
- package/src/common/services/DecorationService.ts +260 -15
- package/src/common/services/InstantiationService.ts +2 -2
- package/src/common/services/LogService.ts +2 -32
- package/src/common/services/{CoreMouseService.ts → MouseStateService.ts} +22 -133
- package/src/common/services/OptionsService.ts +17 -7
- package/src/common/services/OscLinkService.ts +3 -2
- package/src/common/services/ServiceRegistry.ts +14 -8
- package/src/common/services/Services.ts +54 -50
- package/src/common/services/UnicodeService.ts +6 -11
- package/typings/xterm.d.ts +329 -34
- package/src/common/Clone.ts +0 -23
- package/src/common/TypedArrayUtils.ts +0 -17
- package/src/vs/base/browser/browser.ts +0 -141
- package/src/vs/base/browser/canIUse.ts +0 -49
- package/src/vs/base/browser/dom.ts +0 -2369
- package/src/vs/base/browser/fastDomNode.ts +0 -316
- package/src/vs/base/browser/globalPointerMoveMonitor.ts +0 -112
- package/src/vs/base/browser/iframe.ts +0 -135
- package/src/vs/base/browser/keyboardEvent.ts +0 -213
- package/src/vs/base/browser/mouseEvent.ts +0 -229
- package/src/vs/base/browser/touch.ts +0 -372
- package/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts +0 -303
- package/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts +0 -114
- package/src/vs/base/browser/ui/scrollbar/scrollableElement.ts +0 -720
- package/src/vs/base/browser/ui/scrollbar/scrollableElementOptions.ts +0 -165
- package/src/vs/base/browser/ui/scrollbar/scrollbarArrow.ts +0 -114
- package/src/vs/base/browser/ui/scrollbar/scrollbarState.ts +0 -243
- package/src/vs/base/browser/ui/scrollbar/scrollbarVisibilityController.ts +0 -118
- package/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts +0 -116
- package/src/vs/base/browser/ui/widget.ts +0 -57
- package/src/vs/base/browser/window.ts +0 -14
- package/src/vs/base/common/arrays.ts +0 -887
- package/src/vs/base/common/arraysFind.ts +0 -202
- package/src/vs/base/common/assert.ts +0 -71
- package/src/vs/base/common/async.ts +0 -1992
- package/src/vs/base/common/cancellation.ts +0 -148
- package/src/vs/base/common/charCode.ts +0 -450
- package/src/vs/base/common/collections.ts +0 -140
- package/src/vs/base/common/decorators.ts +0 -130
- package/src/vs/base/common/equals.ts +0 -146
- package/src/vs/base/common/errors.ts +0 -303
- package/src/vs/base/common/event.ts +0 -1778
- package/src/vs/base/common/functional.ts +0 -32
- package/src/vs/base/common/hash.ts +0 -316
- package/src/vs/base/common/iterator.ts +0 -159
- package/src/vs/base/common/keyCodes.ts +0 -526
- package/src/vs/base/common/keybindings.ts +0 -284
- package/src/vs/base/common/lazy.ts +0 -47
- package/src/vs/base/common/lifecycle.ts +0 -801
- package/src/vs/base/common/linkedList.ts +0 -142
- package/src/vs/base/common/map.ts +0 -202
- package/src/vs/base/common/numbers.ts +0 -98
- package/src/vs/base/common/observable.ts +0 -76
- package/src/vs/base/common/observableInternal/api.ts +0 -31
- package/src/vs/base/common/observableInternal/autorun.ts +0 -281
- package/src/vs/base/common/observableInternal/base.ts +0 -489
- package/src/vs/base/common/observableInternal/debugName.ts +0 -145
- package/src/vs/base/common/observableInternal/derived.ts +0 -428
- package/src/vs/base/common/observableInternal/lazyObservableValue.ts +0 -146
- package/src/vs/base/common/observableInternal/logging.ts +0 -328
- package/src/vs/base/common/observableInternal/promise.ts +0 -209
- package/src/vs/base/common/observableInternal/utils.ts +0 -610
- package/src/vs/base/common/platform.ts +0 -281
- package/src/vs/base/common/scrollable.ts +0 -522
- package/src/vs/base/common/sequence.ts +0 -34
- package/src/vs/base/common/stopwatch.ts +0 -43
- package/src/vs/base/common/strings.ts +0 -557
- package/src/vs/base/common/symbols.ts +0 -9
- package/src/vs/base/common/uint.ts +0 -59
- package/src/vs/patches/nls.ts +0 -90
- package/src/vs/typings/base-common.d.ts +0 -20
- package/src/vs/typings/require.d.ts +0 -42
- package/src/vs/typings/vscode-globals-nls.d.ts +0 -36
- package/src/vs/typings/vscode-globals-product.d.ts +0 -33
|
@@ -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
|
|
@@ -458,7 +505,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
458
505
|
this.textarea,
|
|
459
506
|
parent.ownerDocument.defaultView ?? window,
|
|
460
507
|
// Force unsafe null in node.js environment for tests
|
|
461
|
-
this._document ?? (typeof window !== 'undefined') ? window.document : null as any
|
|
508
|
+
this._document ?? ((typeof window !== 'undefined') ? window.document : null as any)
|
|
462
509
|
));
|
|
463
510
|
this._instantiationService.setService(ICoreBrowserService, this._coreBrowserService);
|
|
464
511
|
|
|
@@ -472,12 +519,33 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
472
519
|
this._themeService = this._instantiationService.createInstance(ThemeService);
|
|
473
520
|
this._instantiationService.setService(IThemeService, this._themeService);
|
|
474
521
|
|
|
522
|
+
// CSI ? 996 n - color scheme query (https://contour-terminal.org/vt-extensions/color-palette-update-notifications/)
|
|
523
|
+
this._register(this._inputHandler.onRequestColorSchemeQuery(() => this._reportColorScheme()));
|
|
524
|
+
|
|
525
|
+
// Emit unsolicited color scheme notification on theme change when DECSET 2031 is enabled
|
|
526
|
+
this._register(this._themeService.onChangeColors(() => {
|
|
527
|
+
if (this.coreService.decPrivateModes.colorSchemeUpdates) {
|
|
528
|
+
this._reportColorScheme();
|
|
529
|
+
}
|
|
530
|
+
}));
|
|
531
|
+
|
|
475
532
|
this._characterJoinerService = this._instantiationService.createInstance(CharacterJoinerService);
|
|
476
533
|
this._instantiationService.setService(ICharacterJoinerService, this._characterJoinerService);
|
|
477
534
|
|
|
478
535
|
this._renderService = this._register(this._instantiationService.createInstance(RenderService, this.rows, this.screenElement));
|
|
479
536
|
this._instantiationService.setService(IRenderService, this._renderService);
|
|
480
537
|
this._register(this._renderService.onRenderedViewportChange(e => this._onRender.fire(e)));
|
|
538
|
+
this._register(this._renderService.onDimensionsChange(e => this._onDimensionsChange.fire({
|
|
539
|
+
css: {
|
|
540
|
+
canvas: { ...e.css.canvas },
|
|
541
|
+
cell: { ...e.css.cell }
|
|
542
|
+
},
|
|
543
|
+
device: {
|
|
544
|
+
canvas: { ...e.device.canvas },
|
|
545
|
+
cell: { ...e.device.cell },
|
|
546
|
+
char: { ...e.device.char }
|
|
547
|
+
}
|
|
548
|
+
})));
|
|
481
549
|
this.onResize(e => this._renderService!.resize(e.cols, e.rows));
|
|
482
550
|
|
|
483
551
|
this._compositionView = this._document.createElement('div');
|
|
@@ -485,8 +553,8 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
485
553
|
this._compositionHelper = this._instantiationService.createInstance(CompositionHelper, this.textarea, this._compositionView);
|
|
486
554
|
this._helperContainer.appendChild(this._compositionView);
|
|
487
555
|
|
|
488
|
-
this.
|
|
489
|
-
this._instantiationService.setService(
|
|
556
|
+
this._mouseCoordsService = this._instantiationService.createInstance(MouseCoordsService);
|
|
557
|
+
this._instantiationService.setService(IMouseCoordsService, this._mouseCoordsService);
|
|
490
558
|
|
|
491
559
|
const linkifier = this._linkifier.value = this._register(this._instantiationService.createInstance(Linkifier, this.screenElement));
|
|
492
560
|
|
|
@@ -495,8 +563,9 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
495
563
|
|
|
496
564
|
try {
|
|
497
565
|
this._onWillOpen.fire(this.element);
|
|
566
|
+
} catch (e) {
|
|
567
|
+
this._logService.error('onWillOpen handler threw an exception', e);
|
|
498
568
|
}
|
|
499
|
-
catch { /* fails to load addon for some reason */ }
|
|
500
569
|
if (!this._renderService.hasRenderer()) {
|
|
501
570
|
this._renderService.setRenderer(this._createRenderer());
|
|
502
571
|
}
|
|
@@ -505,7 +574,10 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
505
574
|
this._renderService!.handleCursorMove();
|
|
506
575
|
this._syncTextArea();
|
|
507
576
|
}));
|
|
508
|
-
this._register(this.onResize(() =>
|
|
577
|
+
this._register(this.onResize(() => {
|
|
578
|
+
this._renderService!.handleResize(this.cols, this.rows);
|
|
579
|
+
this._syncTextArea();
|
|
580
|
+
}));
|
|
509
581
|
this._register(this.onBlur(() => this._renderService!.handleBlur()));
|
|
510
582
|
this._register(this.onFocus(() => this._renderService!.handleFocus()));
|
|
511
583
|
|
|
@@ -521,6 +593,8 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
521
593
|
linkifier
|
|
522
594
|
));
|
|
523
595
|
this._instantiationService.setService(ISelectionService, this._selectionService);
|
|
596
|
+
this._mouseService = this._instantiationService.createInstance(MouseService);
|
|
597
|
+
this._instantiationService.setService(IMouseService, this._mouseService);
|
|
524
598
|
this._register(this._selectionService.onRequestScrollLines(e => this.scrollLines(e.amount, e.suppressScrollEvent)));
|
|
525
599
|
this._register(this._selectionService.onSelectionChange(() => this._onSelectionChange.fire()));
|
|
526
600
|
this._register(this._selectionService.onRequestRedraw(e => this._renderService!.handleSelectionChanged(e.start, e.end, e.columnSelectMode)));
|
|
@@ -532,7 +606,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
532
606
|
this.textarea!.focus();
|
|
533
607
|
this.textarea!.select();
|
|
534
608
|
}));
|
|
535
|
-
this._register(
|
|
609
|
+
this._register(EventUtils.any(
|
|
536
610
|
this._onScroll.event,
|
|
537
611
|
this._inputHandler.onScroll
|
|
538
612
|
)(() => {
|
|
@@ -544,11 +618,12 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
544
618
|
this._register(addDisposableListener(this.element, 'mousedown', (e: MouseEvent) => this._selectionService!.handleMouseDown(e)));
|
|
545
619
|
|
|
546
620
|
// apply mouse event classes set by escape codes before terminal was attached
|
|
547
|
-
if (this.
|
|
621
|
+
if (this.mouseStateService.areMouseEventsActive && !this.options.mouseEventsRequireAlt) {
|
|
548
622
|
this._selectionService.disable();
|
|
549
|
-
this.element.classList.add(
|
|
623
|
+
this.element.classList.add(MouseEventCssClasses.ENABLE_MOUSE_EVENTS);
|
|
550
624
|
} else {
|
|
551
625
|
this._selectionService.enable();
|
|
626
|
+
this.element.classList.remove(MouseEventCssClasses.ENABLE_MOUSE_EVENTS);
|
|
552
627
|
}
|
|
553
628
|
|
|
554
629
|
if (this.options.screenReaderMode) {
|
|
@@ -558,11 +633,14 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
558
633
|
}
|
|
559
634
|
this._register(this.optionsService.onSpecificOptionChange('screenReaderMode', e => this._handleScreenReaderModeOptionChange(e)));
|
|
560
635
|
|
|
561
|
-
|
|
636
|
+
const showScrollbar = this.options.scrollbar?.showScrollbar ?? true;
|
|
637
|
+
const overviewRulerWidth = this.options.scrollbar?.width;
|
|
638
|
+
if (showScrollbar && overviewRulerWidth) {
|
|
562
639
|
this._overviewRulerRenderer = this._register(this._instantiationService.createInstance(OverviewRulerRenderer, this._viewportElement, this.screenElement));
|
|
563
640
|
}
|
|
564
|
-
this.optionsService.onSpecificOptionChange('
|
|
565
|
-
|
|
641
|
+
this.optionsService.onSpecificOptionChange('scrollbar', value => {
|
|
642
|
+
const shouldShow = (value?.showScrollbar ?? true) && !!value?.width;
|
|
643
|
+
if (!this._overviewRulerRenderer && shouldShow && this._viewportElement && this.screenElement) {
|
|
566
644
|
this._overviewRulerRenderer = this._register(this._instantiationService.createInstance(OverviewRulerRenderer, this._viewportElement, this.screenElement));
|
|
567
645
|
}
|
|
568
646
|
});
|
|
@@ -577,280 +655,26 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
577
655
|
|
|
578
656
|
// Listen for mouse events and translate
|
|
579
657
|
// them into terminal mouse protocols.
|
|
580
|
-
this.bindMouse(
|
|
658
|
+
this._mouseService.bindMouse({
|
|
659
|
+
element: this.element!,
|
|
660
|
+
screenElement: this.screenElement!,
|
|
661
|
+
document: this._document!,
|
|
662
|
+
handleTouchScroll: amount => this._viewport?.handleTouchScroll(amount)
|
|
663
|
+
}, disposable => this._register(disposable), () => this.focus());
|
|
581
664
|
}
|
|
582
665
|
|
|
583
666
|
private _createRenderer(): IRenderer {
|
|
584
667
|
return this._instantiationService.createInstance(DomRenderer, this, this._document!, this.element!, this.screenElement!, this._viewportElement!, this._helperContainer!, this.linkifier!);
|
|
585
668
|
}
|
|
586
669
|
|
|
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
670
|
/**
|
|
847
671
|
* Tells the renderer to refresh terminal content between two rows (inclusive) at the next
|
|
848
672
|
* opportunity.
|
|
849
673
|
* @param start The row to start from (between 0 and this.rows - 1).
|
|
850
674
|
* @param end The row to end at (between start and this.rows - 1).
|
|
851
675
|
*/
|
|
852
|
-
public refresh(start: number, end: number): void {
|
|
853
|
-
this._renderService?.refreshRows(start, end);
|
|
676
|
+
public refresh(start: number, end: number, sync: boolean = false): void {
|
|
677
|
+
this._renderService?.refreshRows(start, end, sync);
|
|
854
678
|
}
|
|
855
679
|
|
|
856
680
|
/**
|
|
@@ -916,7 +740,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
916
740
|
}
|
|
917
741
|
|
|
918
742
|
public attachCustomWheelEventHandler(customWheelEventHandler: CustomWheelEventHandler): void {
|
|
919
|
-
this.
|
|
743
|
+
this.mouseStateService.setCustomWheelEventHandler(customWheelEventHandler);
|
|
920
744
|
}
|
|
921
745
|
|
|
922
746
|
public registerLinkProvider(linkProvider: ILinkProvider): IDisposable {
|
|
@@ -1040,14 +864,16 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1040
864
|
this._unprocessedDeadKey = true;
|
|
1041
865
|
}
|
|
1042
866
|
|
|
1043
|
-
const result =
|
|
867
|
+
const result = this._keyboardService.evaluateKeyDown(event);
|
|
1044
868
|
|
|
1045
869
|
this.updateCursorStyle(event);
|
|
1046
870
|
|
|
1047
871
|
if (result.type === KeyboardResultType.PAGE_DOWN || result.type === KeyboardResultType.PAGE_UP) {
|
|
1048
872
|
const scrollCount = this.rows - 1;
|
|
1049
873
|
this.scrollLines(result.type === KeyboardResultType.PAGE_UP ? -scrollCount : scrollCount);
|
|
1050
|
-
|
|
874
|
+
event.preventDefault();
|
|
875
|
+
event.stopPropagation();
|
|
876
|
+
return false;
|
|
1051
877
|
}
|
|
1052
878
|
|
|
1053
879
|
if (result.type === KeyboardResultType.SELECT_ALL) {
|
|
@@ -1060,7 +886,8 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1060
886
|
|
|
1061
887
|
if (result.cancel) {
|
|
1062
888
|
// The event is canceled at the end already, is this necessary?
|
|
1063
|
-
|
|
889
|
+
event.preventDefault();
|
|
890
|
+
event.stopPropagation();
|
|
1064
891
|
}
|
|
1065
892
|
|
|
1066
893
|
if (!result.key) {
|
|
@@ -1068,8 +895,9 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1068
895
|
}
|
|
1069
896
|
|
|
1070
897
|
// 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
|
-
|
|
898
|
+
// letters cannot be input while caps lock is on. Skip this hack when using kitty protocol
|
|
899
|
+
// or Win32 input mode as they need to send proper sequences for all key events.
|
|
900
|
+
if (!this._keyboardService.useKitty && !this._keyboardService.useWin32InputMode && event.key && !event.ctrlKey && !event.altKey && !event.metaKey && event.key.length === 1) {
|
|
1073
901
|
if (event.key.charCodeAt(0) >= 65 && event.key.charCodeAt(0) <= 90) {
|
|
1074
902
|
return true;
|
|
1075
903
|
}
|
|
@@ -1087,16 +915,19 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1087
915
|
this.textarea!.value = '';
|
|
1088
916
|
}
|
|
1089
917
|
|
|
918
|
+
const wasModifierOnly = this._keyboardService.useWin32InputMode && wasModifierKeyOnlyEvent(event);
|
|
1090
919
|
this._onKey.fire({ key: result.key, domEvent: event });
|
|
1091
920
|
this._showCursor();
|
|
1092
|
-
this.coreService.triggerDataEvent(result.key,
|
|
921
|
+
this.coreService.triggerDataEvent(result.key, !wasModifierOnly);
|
|
1093
922
|
|
|
1094
923
|
// Cancel events when not in screen reader mode so events don't get bubbled up and handled by
|
|
1095
924
|
// other listeners. When screen reader mode is enabled, we don't cancel them (unless ctrl or alt
|
|
1096
925
|
// is also depressed) so that the cursor textarea can be updated, which triggers the screen
|
|
1097
926
|
// reader to read it.
|
|
1098
927
|
if (!this.optionsService.rawOptions.screenReaderMode || event.altKey || event.ctrlKey) {
|
|
1099
|
-
|
|
928
|
+
event.preventDefault();
|
|
929
|
+
event.stopPropagation();
|
|
930
|
+
return false;
|
|
1100
931
|
}
|
|
1101
932
|
|
|
1102
933
|
this._keyDownHandled = true;
|
|
@@ -1127,6 +958,13 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1127
958
|
this.focus();
|
|
1128
959
|
}
|
|
1129
960
|
|
|
961
|
+
// Handle key release for Kitty keyboard protocol
|
|
962
|
+
const result = this._keyboardService.evaluateKeyUp(ev);
|
|
963
|
+
if (result?.key) {
|
|
964
|
+
const wasModifierOnly = this._keyboardService.useWin32InputMode && wasModifierKeyOnlyEvent(ev);
|
|
965
|
+
this.coreService.triggerDataEvent(result.key, !wasModifierOnly);
|
|
966
|
+
}
|
|
967
|
+
|
|
1130
968
|
this.updateCursorStyle(ev);
|
|
1131
969
|
this._keyPressHandled = false;
|
|
1132
970
|
}
|
|
@@ -1150,8 +988,6 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1150
988
|
return false;
|
|
1151
989
|
}
|
|
1152
990
|
|
|
1153
|
-
this.cancel(ev);
|
|
1154
|
-
|
|
1155
991
|
if (ev.charCode) {
|
|
1156
992
|
key = ev.charCode;
|
|
1157
993
|
} else if (ev.which === null || ev.which === undefined) {
|
|
@@ -1204,8 +1040,6 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1204
1040
|
|
|
1205
1041
|
const text = ev.data;
|
|
1206
1042
|
this.coreService.triggerDataEvent(text, true);
|
|
1207
|
-
|
|
1208
|
-
this.cancel(ev);
|
|
1209
1043
|
return true;
|
|
1210
1044
|
}
|
|
1211
1045
|
|
|
@@ -1276,6 +1110,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1276
1110
|
|
|
1277
1111
|
this._setup();
|
|
1278
1112
|
super.reset();
|
|
1113
|
+
this._mouseService?.reset();
|
|
1279
1114
|
this._selectionService?.reset();
|
|
1280
1115
|
this._decorationService.reset();
|
|
1281
1116
|
|
|
@@ -1283,7 +1118,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1283
1118
|
this._customKeyEventHandler = customKeyEventHandler;
|
|
1284
1119
|
|
|
1285
1120
|
// do a full screen refresh
|
|
1286
|
-
this.refresh(0, this.rows - 1);
|
|
1121
|
+
this.refresh(0, this.rows - 1, true);
|
|
1287
1122
|
}
|
|
1288
1123
|
|
|
1289
1124
|
public clearTextureAtlas(): void {
|
|
@@ -1317,15 +1152,6 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1317
1152
|
}
|
|
1318
1153
|
}
|
|
1319
1154
|
|
|
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
1155
|
}
|
|
1330
1156
|
|
|
1331
1157
|
/**
|
|
@@ -1335,5 +1161,10 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
|
1335
1161
|
function wasModifierKeyOnlyEvent(ev: KeyboardEvent): boolean {
|
|
1336
1162
|
return ev.keyCode === 16 || // Shift
|
|
1337
1163
|
ev.keyCode === 17 || // Ctrl
|
|
1338
|
-
ev.keyCode === 18
|
|
1164
|
+
ev.keyCode === 18 || // Alt
|
|
1165
|
+
ev.keyCode === 91 || // Meta (Left)
|
|
1166
|
+
ev.keyCode === 92 || // Meta (Right)
|
|
1167
|
+
ev.keyCode === 93 || // Meta (Menu)
|
|
1168
|
+
ev.keyCode === 224 || // Meta (Firefox)
|
|
1169
|
+
ev.key === 'Meta';
|
|
1339
1170
|
}
|