@xterm/xterm 6.1.0-beta.20 → 6.1.0-beta.201
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +60 -38
- package/css/xterm.css +29 -22
- package/lib/xterm.js +1 -1
- package/lib/xterm.js.map +1 -1
- package/lib/xterm.mjs +8 -34
- package/lib/xterm.mjs.map +4 -4
- package/package.json +25 -14
- package/src/browser/AccessibilityManager.ts +6 -3
- package/src/browser/Clipboard.ts +6 -3
- package/src/browser/CoreBrowserTerminal.ts +147 -318
- package/src/browser/Dom.ts +178 -0
- package/src/browser/Linkifier.ts +11 -11
- package/src/browser/OscLinkProvider.ts +3 -1
- package/src/browser/RenderDebouncer.ts +2 -2
- package/src/browser/TimeBasedDebouncer.ts +2 -2
- package/src/browser/Types.ts +12 -11
- package/src/browser/Viewport.ts +55 -20
- package/src/browser/decorations/BufferDecorationRenderer.ts +1 -1
- package/src/browser/decorations/OverviewRulerRenderer.ts +33 -17
- package/src/browser/input/CompositionHelper.ts +44 -8
- package/src/browser/public/Terminal.ts +25 -28
- package/src/browser/renderer/dom/DomRenderer.ts +205 -41
- package/src/browser/renderer/dom/DomRendererRowFactory.ts +19 -13
- package/src/browser/renderer/dom/WidthCache.ts +54 -52
- package/src/browser/renderer/shared/Constants.ts +7 -0
- package/src/browser/renderer/shared/TextBlinkStateManager.ts +97 -0
- package/src/browser/renderer/shared/Types.ts +8 -2
- package/src/browser/scrollable/abstractScrollbar.ts +300 -0
- package/src/browser/scrollable/fastDomNode.ts +126 -0
- package/src/browser/scrollable/globalPointerMoveMonitor.ts +90 -0
- package/src/browser/scrollable/horizontalScrollbar.ts +85 -0
- package/src/browser/scrollable/mouseEvent.ts +292 -0
- package/src/browser/scrollable/scrollable.ts +486 -0
- package/src/browser/scrollable/scrollableElement.ts +579 -0
- package/src/browser/scrollable/scrollableElementOptions.ts +161 -0
- package/src/browser/scrollable/scrollbarArrow.ts +110 -0
- package/src/browser/scrollable/scrollbarState.ts +246 -0
- package/src/browser/scrollable/scrollbarVisibilityController.ts +113 -0
- package/src/browser/scrollable/touch.ts +485 -0
- package/src/browser/scrollable/verticalScrollbar.ts +143 -0
- package/src/browser/scrollable/widget.ts +23 -0
- package/src/browser/services/CharSizeService.ts +2 -2
- package/src/browser/services/CoreBrowserService.ts +7 -5
- package/src/browser/services/KeyboardService.ts +67 -0
- package/src/browser/services/LinkProviderService.ts +1 -1
- package/src/browser/services/MouseCoordsService.ts +47 -0
- package/src/browser/services/MouseService.ts +518 -25
- package/src/browser/services/RenderService.ts +22 -15
- package/src/browser/services/SelectionService.ts +16 -8
- package/src/browser/services/Services.ts +40 -17
- package/src/browser/services/ThemeService.ts +2 -2
- package/src/common/Async.ts +105 -0
- package/src/common/CircularList.ts +2 -2
- package/src/common/Color.ts +8 -0
- package/src/common/CoreTerminal.ts +28 -18
- package/src/common/Event.ts +118 -0
- package/src/common/InputHandler.ts +256 -36
- package/src/common/Lifecycle.ts +113 -0
- package/src/common/Platform.ts +13 -3
- package/src/common/SortedList.ts +7 -3
- package/src/common/TaskQueue.ts +14 -5
- package/src/common/Types.ts +35 -15
- package/src/common/Version.ts +9 -0
- package/src/common/buffer/Buffer.ts +20 -14
- package/src/common/buffer/BufferLine.ts +4 -5
- package/src/common/buffer/BufferSet.ts +7 -6
- package/src/common/buffer/CellData.ts +57 -0
- package/src/common/buffer/Marker.ts +2 -2
- package/src/common/buffer/Types.ts +6 -2
- package/src/common/data/EscapeSequences.ts +71 -70
- package/src/common/input/Keyboard.ts +14 -7
- package/src/common/input/KittyKeyboard.ts +519 -0
- package/src/common/input/Win32InputMode.ts +297 -0
- package/src/common/input/WriteBuffer.ts +34 -2
- package/src/common/input/XParseColor.ts +2 -2
- package/src/common/parser/ApcParser.ts +245 -0
- package/src/common/parser/Constants.ts +22 -4
- package/src/common/parser/DcsParser.ts +5 -5
- package/src/common/parser/EscapeSequenceParser.ts +158 -55
- package/src/common/parser/OscParser.ts +5 -5
- package/src/common/parser/Params.ts +13 -0
- package/src/common/parser/Types.ts +35 -1
- package/src/common/public/BufferLineApiView.ts +2 -2
- package/src/common/public/BufferNamespaceApi.ts +2 -2
- package/src/common/public/ParserApi.ts +3 -0
- package/src/common/services/BufferService.ts +8 -5
- package/src/common/services/CharsetService.ts +4 -0
- package/src/common/services/CoreService.ts +18 -4
- package/src/common/services/DecorationService.ts +24 -8
- package/src/common/services/LogService.ts +1 -31
- package/src/common/services/{CoreMouseService.ts → MouseStateService.ts} +21 -132
- package/src/common/services/OptionsService.ts +13 -4
- package/src/common/services/Services.ts +47 -40
- package/src/common/services/UnicodeService.ts +1 -1
- package/typings/xterm.d.ts +316 -32
- 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
|
@@ -30,6 +30,12 @@ export class CompositionHelper {
|
|
|
30
30
|
*/
|
|
31
31
|
private _compositionPosition: IPosition;
|
|
32
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Text that existed after the composing range when composition started.
|
|
35
|
+
* This is used to avoid treating existing trailing text as new input.
|
|
36
|
+
*/
|
|
37
|
+
private _compositionSuffix: string;
|
|
38
|
+
|
|
33
39
|
/**
|
|
34
40
|
* Whether a composition is in the process of being sent, setting this to false will cancel any
|
|
35
41
|
* in-progress composition.
|
|
@@ -41,6 +47,11 @@ export class CompositionHelper {
|
|
|
41
47
|
*/
|
|
42
48
|
private _dataAlreadySent: string;
|
|
43
49
|
|
|
50
|
+
/**
|
|
51
|
+
* The pending textarea change timer, if any.
|
|
52
|
+
*/
|
|
53
|
+
private _textareaChangeTimer?: number;
|
|
54
|
+
|
|
44
55
|
constructor(
|
|
45
56
|
private readonly _textarea: HTMLTextAreaElement,
|
|
46
57
|
private readonly _compositionView: HTMLElement,
|
|
@@ -52,6 +63,7 @@ export class CompositionHelper {
|
|
|
52
63
|
this._isComposing = false;
|
|
53
64
|
this._isSendingComposition = false;
|
|
54
65
|
this._compositionPosition = { start: 0, end: 0 };
|
|
66
|
+
this._compositionSuffix = '';
|
|
55
67
|
this._dataAlreadySent = '';
|
|
56
68
|
}
|
|
57
69
|
|
|
@@ -60,7 +72,13 @@ export class CompositionHelper {
|
|
|
60
72
|
*/
|
|
61
73
|
public compositionstart(): void {
|
|
62
74
|
this._isComposing = true;
|
|
63
|
-
|
|
75
|
+
// It's important to use the selection here instead of textarea length to avoid conflicts with
|
|
76
|
+
// screen reader mode
|
|
77
|
+
const start = this._textarea.selectionStart ?? this._textarea.value.length;
|
|
78
|
+
const end = this._textarea.selectionEnd ?? start;
|
|
79
|
+
this._compositionPosition.start = Math.min(start, end);
|
|
80
|
+
this._compositionPosition.end = Math.max(start, end);
|
|
81
|
+
this._compositionSuffix = this._textarea.value.substring(this._compositionPosition.end);
|
|
64
82
|
this._compositionView.textContent = '';
|
|
65
83
|
this._dataAlreadySent = '';
|
|
66
84
|
this._compositionView.classList.add('active');
|
|
@@ -71,10 +89,13 @@ export class CompositionHelper {
|
|
|
71
89
|
* @param ev The event.
|
|
72
90
|
*/
|
|
73
91
|
public compositionupdate(ev: Pick<CompositionEvent, 'data'>): void {
|
|
74
|
-
|
|
92
|
+
// Mark text as LTR, direction=rtl is used in CSS so the end of the text is followed for long
|
|
93
|
+
// compositions
|
|
94
|
+
this._compositionView.textContent = `\u200E${ev.data}\u200E`;
|
|
75
95
|
this.updateCompositionElements();
|
|
76
96
|
setTimeout(() => {
|
|
77
|
-
this.
|
|
97
|
+
const end = this._textarea.selectionEnd ?? this._textarea.value.length;
|
|
98
|
+
this._compositionPosition.end = Math.max( this._compositionPosition.start, end);
|
|
78
99
|
}, 0);
|
|
79
100
|
}
|
|
80
101
|
|
|
@@ -141,6 +162,7 @@ export class CompositionHelper {
|
|
|
141
162
|
start: this._compositionPosition.start,
|
|
142
163
|
end: this._compositionPosition.end
|
|
143
164
|
};
|
|
165
|
+
const currentCompositionSuffix = this._compositionSuffix;
|
|
144
166
|
|
|
145
167
|
// Since composition* events happen before the changes take place in the textarea on most
|
|
146
168
|
// browsers, use a setTimeout with 0ms time to allow the native compositionend event to
|
|
@@ -164,10 +186,14 @@ export class CompositionHelper {
|
|
|
164
186
|
// if a new composition has started.
|
|
165
187
|
input = this._textarea.value.substring(currentCompositionPosition.start, this._compositionPosition.start);
|
|
166
188
|
} else {
|
|
167
|
-
//
|
|
168
|
-
//
|
|
169
|
-
//
|
|
170
|
-
|
|
189
|
+
// Keep support for non-composition characters typed immediately after composition end
|
|
190
|
+
// while avoiding re-sending the trailing text that was already present
|
|
191
|
+
// before composition started.
|
|
192
|
+
const value = this._textarea.value;
|
|
193
|
+
const valueEnd = currentCompositionSuffix.length > 0 && value.endsWith(currentCompositionSuffix)
|
|
194
|
+
? value.length - currentCompositionSuffix.length
|
|
195
|
+
: value.length;
|
|
196
|
+
input = value.substring(currentCompositionPosition.start, Math.max(currentCompositionPosition.start, valueEnd));
|
|
171
197
|
}
|
|
172
198
|
if (input.length > 0) {
|
|
173
199
|
this._coreService.triggerDataEvent(input, true);
|
|
@@ -184,8 +210,12 @@ export class CompositionHelper {
|
|
|
184
210
|
* IME is active.
|
|
185
211
|
*/
|
|
186
212
|
private _handleAnyTextareaChanges(): void {
|
|
213
|
+
if (this._textareaChangeTimer) {
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
187
216
|
const oldValue = this._textarea.value;
|
|
188
|
-
setTimeout(() => {
|
|
217
|
+
this._textareaChangeTimer = window.setTimeout(() => {
|
|
218
|
+
this._textareaChangeTimer = undefined;
|
|
189
219
|
// Ignore if a composition has started since the timeout
|
|
190
220
|
if (!this._isComposing) {
|
|
191
221
|
const newValue = this._textarea.value;
|
|
@@ -230,6 +260,12 @@ export class CompositionHelper {
|
|
|
230
260
|
this._compositionView.style.lineHeight = cellHeight + 'px';
|
|
231
261
|
this._compositionView.style.fontFamily = this._optionsService.rawOptions.fontFamily;
|
|
232
262
|
this._compositionView.style.fontSize = this._optionsService.rawOptions.fontSize + 'px';
|
|
263
|
+
// Limit the composition view width to the space between the cursor and
|
|
264
|
+
// the terminal's right edge, preventing it from overflowing the terminal.
|
|
265
|
+
const maxWidth = this._bufferService.cols * this._renderService.dimensions.css.cell.width - cursorLeft;
|
|
266
|
+
this._compositionView.style.maxWidth = maxWidth + 'px';
|
|
267
|
+
this._compositionView.style.overflow = 'hidden';
|
|
268
|
+
this._compositionView.style.direction = 'rtl';
|
|
233
269
|
// Sync the textarea to the exact position of the composition view so the IME knows where the
|
|
234
270
|
// text is.
|
|
235
271
|
const compositionViewBounds = this._compositionView.getBoundingClientRect();
|
|
@@ -6,14 +6,14 @@
|
|
|
6
6
|
import * as Strings from 'browser/LocalizableStrings';
|
|
7
7
|
import { CoreBrowserTerminal as TerminalCore } from 'browser/CoreBrowserTerminal';
|
|
8
8
|
import { IBufferRange, ITerminal } from 'browser/Types';
|
|
9
|
-
import { Disposable } from '
|
|
9
|
+
import { Disposable } from 'common/Lifecycle';
|
|
10
10
|
import { ITerminalOptions } from 'common/Types';
|
|
11
11
|
import { AddonManager } from 'common/public/AddonManager';
|
|
12
12
|
import { BufferNamespaceApi } from 'common/public/BufferNamespaceApi';
|
|
13
13
|
import { ParserApi } from 'common/public/ParserApi';
|
|
14
14
|
import { UnicodeApi } from 'common/public/UnicodeApi';
|
|
15
|
-
import { IBufferNamespace as IBufferNamespaceApi, IDecoration, IDecorationOptions, IDisposable, ILinkProvider, ILocalizableStrings, IMarker, IModes, IParser, ITerminalAddon, Terminal as ITerminalApi, ITerminalInitOnlyOptions, IUnicodeHandling } from '@xterm/xterm';
|
|
16
|
-
import type {
|
|
15
|
+
import { IBufferNamespace as IBufferNamespaceApi, IDecoration, IDecorationOptions, IDisposable, ILinkProvider, ILocalizableStrings, IMarker, IModes, IParser, IRenderDimensions, ITerminalAddon, Terminal as ITerminalApi, ITerminalInitOnlyOptions, IUnicodeHandling } from '@xterm/xterm';
|
|
16
|
+
import type { IEvent } from 'common/Event';
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* The set of options that only have an effect when set in the Terminal constructor.
|
|
@@ -68,25 +68,24 @@ export class Terminal extends Disposable implements ITerminalApi {
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
public get onBell():
|
|
72
|
-
public get onBinary():
|
|
73
|
-
public get onCursorMove():
|
|
74
|
-
public get onData():
|
|
75
|
-
public get onKey():
|
|
76
|
-
public get onLineFeed():
|
|
77
|
-
public get onRender():
|
|
78
|
-
public get onResize():
|
|
79
|
-
public get onScroll():
|
|
80
|
-
public get onSelectionChange():
|
|
81
|
-
public get onTitleChange():
|
|
82
|
-
public get onWriteParsed():
|
|
71
|
+
public get onBell(): IEvent<void> { return this._core.onBell; }
|
|
72
|
+
public get onBinary(): IEvent<string> { return this._core.onBinary; }
|
|
73
|
+
public get onCursorMove(): IEvent<void> { return this._core.onCursorMove; }
|
|
74
|
+
public get onData(): IEvent<string> { return this._core.onData; }
|
|
75
|
+
public get onKey(): IEvent<{ key: string, domEvent: KeyboardEvent }> { return this._core.onKey; }
|
|
76
|
+
public get onLineFeed(): IEvent<void> { return this._core.onLineFeed; }
|
|
77
|
+
public get onRender(): IEvent<{ start: number, end: number }> { return this._core.onRender; }
|
|
78
|
+
public get onResize(): IEvent<{ cols: number, rows: number }> { return this._core.onResize; }
|
|
79
|
+
public get onScroll(): IEvent<number> { return this._core.onScroll; }
|
|
80
|
+
public get onSelectionChange(): IEvent<void> { return this._core.onSelectionChange; }
|
|
81
|
+
public get onTitleChange(): IEvent<string> { return this._core.onTitleChange; }
|
|
82
|
+
public get onWriteParsed(): IEvent<void> { return this._core.onWriteParsed; }
|
|
83
|
+
public get onDimensionsChange(): IEvent<IRenderDimensions> { return this._core.onDimensionsChange; }
|
|
83
84
|
|
|
84
85
|
public get element(): HTMLElement | undefined { return this._core.element; }
|
|
86
|
+
public get screenElement(): HTMLElement | undefined { return this._core.screenElement; }
|
|
85
87
|
public get parser(): IParser {
|
|
86
|
-
|
|
87
|
-
this._parser = new ParserApi(this._core);
|
|
88
|
-
}
|
|
89
|
-
return this._parser;
|
|
88
|
+
return this._parser ??= new ParserApi(this._core);
|
|
90
89
|
}
|
|
91
90
|
public get unicode(): IUnicodeHandling {
|
|
92
91
|
this._checkProposedApi();
|
|
@@ -96,19 +95,15 @@ export class Terminal extends Disposable implements ITerminalApi {
|
|
|
96
95
|
public get rows(): number { return this._core.rows; }
|
|
97
96
|
public get cols(): number { return this._core.cols; }
|
|
98
97
|
public get buffer(): IBufferNamespaceApi {
|
|
99
|
-
|
|
100
|
-
this._buffer = this._register(new BufferNamespaceApi(this._core));
|
|
101
|
-
}
|
|
102
|
-
return this._buffer;
|
|
98
|
+
return this._buffer ??= this._register(new BufferNamespaceApi(this._core));
|
|
103
99
|
}
|
|
104
100
|
public get markers(): ReadonlyArray<IMarker> {
|
|
105
|
-
this._checkProposedApi();
|
|
106
101
|
return this._core.markers;
|
|
107
102
|
}
|
|
108
103
|
public get modes(): IModes {
|
|
109
104
|
const m = this._core.coreService.decPrivateModes;
|
|
110
105
|
let mouseTrackingMode: 'none' | 'x10' | 'vt200' | 'drag' | 'any' = 'none';
|
|
111
|
-
switch (this._core.
|
|
106
|
+
switch (this._core.mouseStateService.activeProtocol) {
|
|
112
107
|
case 'X10': mouseTrackingMode = 'x10'; break;
|
|
113
108
|
case 'VT200': mouseTrackingMode = 'vt200'; break;
|
|
114
109
|
case 'DRAG': mouseTrackingMode = 'drag'; break;
|
|
@@ -123,10 +118,15 @@ export class Terminal extends Disposable implements ITerminalApi {
|
|
|
123
118
|
originMode: m.origin,
|
|
124
119
|
reverseWraparoundMode: m.reverseWraparound,
|
|
125
120
|
sendFocusMode: m.sendFocus,
|
|
121
|
+
showCursor: !this._core.coreService.isCursorHidden,
|
|
126
122
|
synchronizedOutputMode: m.synchronizedOutput,
|
|
123
|
+
win32InputMode: m.win32InputMode,
|
|
127
124
|
wraparoundMode: m.wraparound
|
|
128
125
|
};
|
|
129
126
|
}
|
|
127
|
+
public get dimensions(): IRenderDimensions | undefined {
|
|
128
|
+
return this._core.dimensions;
|
|
129
|
+
}
|
|
130
130
|
public get options(): Required<ITerminalOptions> {
|
|
131
131
|
return this._publicOptions;
|
|
132
132
|
}
|
|
@@ -161,11 +161,9 @@ export class Terminal extends Disposable implements ITerminalApi {
|
|
|
161
161
|
return this._core.registerLinkProvider(linkProvider);
|
|
162
162
|
}
|
|
163
163
|
public registerCharacterJoiner(handler: (text: string) => [number, number][]): number {
|
|
164
|
-
this._checkProposedApi();
|
|
165
164
|
return this._core.registerCharacterJoiner(handler);
|
|
166
165
|
}
|
|
167
166
|
public deregisterCharacterJoiner(joinerId: number): void {
|
|
168
|
-
this._checkProposedApi();
|
|
169
167
|
this._core.deregisterCharacterJoiner(joinerId);
|
|
170
168
|
}
|
|
171
169
|
public registerMarker(cursorYOffset: number = 0): IMarker {
|
|
@@ -173,7 +171,6 @@ export class Terminal extends Disposable implements ITerminalApi {
|
|
|
173
171
|
return this._core.registerMarker(cursorYOffset);
|
|
174
172
|
}
|
|
175
173
|
public registerDecoration(decorationOptions: IDecorationOptions): IDecoration | undefined {
|
|
176
|
-
this._checkProposedApi();
|
|
177
174
|
this._verifyPositiveIntegers(decorationOptions.x ?? 0, decorationOptions.width ?? 0, decorationOptions.height ?? 0);
|
|
178
175
|
return this._core.registerDecoration(decorationOptions);
|
|
179
176
|
}
|
|
@@ -5,16 +5,18 @@
|
|
|
5
5
|
|
|
6
6
|
import { DomRendererRowFactory, RowCss } from 'browser/renderer/dom/DomRendererRowFactory';
|
|
7
7
|
import { WidthCache } from 'browser/renderer/dom/WidthCache';
|
|
8
|
-
import { INVERTED_DEFAULT_COLOR } from 'browser/renderer/shared/Constants';
|
|
8
|
+
import { INVERTED_DEFAULT_COLOR, RendererConstants } from 'browser/renderer/shared/Constants';
|
|
9
9
|
import { createRenderDimensions } from 'browser/renderer/shared/RendererUtils';
|
|
10
10
|
import { createSelectionRenderModel } from 'browser/renderer/shared/SelectionRenderModel';
|
|
11
|
+
import { TextBlinkStateManager } from 'browser/renderer/shared/TextBlinkStateManager';
|
|
11
12
|
import { IRenderDimensions, IRenderer, IRequestRedrawEvent, ISelectionRenderModel } from 'browser/renderer/shared/Types';
|
|
12
13
|
import { ICharSizeService, ICoreBrowserService, IThemeService } from 'browser/services/Services';
|
|
13
14
|
import { ILinkifier2, ILinkifierEvent, ITerminal, ReadonlyColorSet } from 'browser/Types';
|
|
14
15
|
import { color } from 'common/Color';
|
|
15
|
-
import { Disposable, toDisposable } from '
|
|
16
|
+
import { Disposable, toDisposable } from 'common/Lifecycle';
|
|
16
17
|
import { IBufferService, ICoreService, IInstantiationService, IOptionsService } from 'common/services/Services';
|
|
17
|
-
import { Emitter } from '
|
|
18
|
+
import { Emitter } from 'common/Event';
|
|
19
|
+
import { addDisposableListener } from 'browser/Dom';
|
|
18
20
|
|
|
19
21
|
|
|
20
22
|
const TERMINAL_CLASS_PREFIX = 'xterm-dom-renderer-owner-';
|
|
@@ -23,6 +25,7 @@ const FG_CLASS_PREFIX = 'xterm-fg-';
|
|
|
23
25
|
const BG_CLASS_PREFIX = 'xterm-bg-';
|
|
24
26
|
const FOCUS_CLASS = 'xterm-focus';
|
|
25
27
|
const SELECTION_CLASS = 'xterm-selection';
|
|
28
|
+
const CURSOR_BLINK_IDLE_CLASS = 'xterm-cursor-blink-idle';
|
|
26
29
|
|
|
27
30
|
let nextTerminalId = 1;
|
|
28
31
|
|
|
@@ -42,10 +45,18 @@ export class DomRenderer extends Disposable implements IRenderer {
|
|
|
42
45
|
private _selectionContainer: HTMLElement;
|
|
43
46
|
private _widthCache: WidthCache;
|
|
44
47
|
private _selectionRenderModel: ISelectionRenderModel = createSelectionRenderModel();
|
|
48
|
+
private _lastSelectionStart: [number, number] | undefined;
|
|
49
|
+
private _lastSelectionEnd: [number, number] | undefined;
|
|
50
|
+
private _lastSelectionColumnMode: boolean = false;
|
|
51
|
+
private _cursorBlinkStateManager: CursorBlinkStateManager;
|
|
52
|
+
private _textBlinkStateManager: TextBlinkStateManager;
|
|
53
|
+
private _rowHasBlinkingCells: boolean[] = [];
|
|
54
|
+
private _rowHasBlinkingCellsCount: number = 0;
|
|
45
55
|
|
|
46
56
|
public dimensions: IRenderDimensions;
|
|
47
57
|
|
|
48
|
-
|
|
58
|
+
private readonly _onRequestRedraw = this._register(new Emitter<IRequestRedrawEvent>());
|
|
59
|
+
public readonly onRequestRedraw = this._onRequestRedraw.event;
|
|
49
60
|
|
|
50
61
|
constructor(
|
|
51
62
|
private readonly _terminal: ITerminal,
|
|
@@ -89,6 +100,15 @@ export class DomRenderer extends Disposable implements IRenderer {
|
|
|
89
100
|
this._register(this._linkifier2.onShowLinkUnderline(e => this._handleLinkHover(e)));
|
|
90
101
|
this._register(this._linkifier2.onHideLinkUnderline(e => this._handleLinkLeave(e)));
|
|
91
102
|
|
|
103
|
+
this._cursorBlinkStateManager = new CursorBlinkStateManager(this._rowContainer, this._coreBrowserService);
|
|
104
|
+
this._register(addDisposableListener(this._document, 'mousedown', () => this._cursorBlinkStateManager.restartBlinkAnimation()));
|
|
105
|
+
this._register(toDisposable(() => this._cursorBlinkStateManager.dispose()));
|
|
106
|
+
this._textBlinkStateManager = this._register(new TextBlinkStateManager(
|
|
107
|
+
() => this._onRequestRedraw.fire({ start: 0, end: this._bufferService.rows - 1 }),
|
|
108
|
+
this._coreBrowserService,
|
|
109
|
+
this._optionsService
|
|
110
|
+
));
|
|
111
|
+
|
|
92
112
|
this._register(toDisposable(() => {
|
|
93
113
|
this._element.classList.remove(TERMINAL_CLASS_PREFIX + this._terminalClass);
|
|
94
114
|
|
|
@@ -101,7 +121,7 @@ export class DomRenderer extends Disposable implements IRenderer {
|
|
|
101
121
|
this._dimensionsStyleElement.remove();
|
|
102
122
|
}));
|
|
103
123
|
|
|
104
|
-
this._widthCache = new WidthCache(
|
|
124
|
+
this._widthCache = new WidthCache();
|
|
105
125
|
this._widthCache.setFont(
|
|
106
126
|
this._optionsService.rawOptions.fontFamily,
|
|
107
127
|
this._optionsService.rawOptions.fontSize,
|
|
@@ -167,6 +187,9 @@ export class DomRenderer extends Disposable implements IRenderer {
|
|
|
167
187
|
// refresh() being called during the mousedown handler to start a selection.
|
|
168
188
|
` pointer-events: none;` +
|
|
169
189
|
` color: ${colors.foreground.css};` +
|
|
190
|
+
`}`;
|
|
191
|
+
styles +=
|
|
192
|
+
`${this._terminalSelector} .${ROW_CONTAINER_CLASS}, ${this._terminalSelector} .${ROW_CONTAINER_CLASS} span {` +
|
|
170
193
|
` font-family: ${this._optionsService.rawOptions.fontFamily};` +
|
|
171
194
|
` font-size: ${this._optionsService.rawOptions.fontSize}px;` +
|
|
172
195
|
` font-kerning: none;` +
|
|
@@ -186,6 +209,9 @@ export class DomRenderer extends Disposable implements IRenderer {
|
|
|
186
209
|
`}` +
|
|
187
210
|
`${this._terminalSelector} span.${RowCss.ITALIC_CLASS} {` +
|
|
188
211
|
` font-style: italic;` +
|
|
212
|
+
`}` +
|
|
213
|
+
`${this._terminalSelector} span.${RowCss.BLINK_HIDDEN_CLASS} {` +
|
|
214
|
+
` visibility: hidden;` +
|
|
189
215
|
`}`;
|
|
190
216
|
// Blink animation
|
|
191
217
|
const blinkAnimationUnderlineId = `blink_underline_${this._terminalClass}`;
|
|
@@ -225,6 +251,10 @@ export class DomRenderer extends Disposable implements IRenderer {
|
|
|
225
251
|
`${this._terminalSelector} .${ROW_CONTAINER_CLASS}.${FOCUS_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_BLINK_CLASS}.${RowCss.CURSOR_STYLE_BLOCK_CLASS} {` +
|
|
226
252
|
` animation: ${blinkAnimationBlockId} 1s step-end infinite;` +
|
|
227
253
|
`}` +
|
|
254
|
+
// Disable cursor blinking when idle
|
|
255
|
+
`${this._terminalSelector} .${ROW_CONTAINER_CLASS}.${CURSOR_BLINK_IDLE_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_BLINK_CLASS} {` +
|
|
256
|
+
` animation: none !important;` +
|
|
257
|
+
`}` +
|
|
228
258
|
// !important helps fix an issue where the cursor will not render on top of the selection,
|
|
229
259
|
// however it's very hard to fix this issue and retain the blink animation without the use of
|
|
230
260
|
// !important. So this edge case fails when cursor blink is on.
|
|
@@ -307,10 +337,14 @@ export class DomRenderer extends Disposable implements IRenderer {
|
|
|
307
337
|
const row = this._document.createElement('div');
|
|
308
338
|
this._rowContainer.appendChild(row);
|
|
309
339
|
this._rowElements.push(row);
|
|
340
|
+
this._rowHasBlinkingCells.push(false);
|
|
310
341
|
}
|
|
311
342
|
// Remove excess elements
|
|
312
343
|
while (this._rowElements.length > rows) {
|
|
313
344
|
this._rowContainer.removeChild(this._rowElements.pop()!);
|
|
345
|
+
if (this._rowHasBlinkingCells.pop()) {
|
|
346
|
+
this._rowHasBlinkingCellsCount--;
|
|
347
|
+
}
|
|
314
348
|
}
|
|
315
349
|
}
|
|
316
350
|
|
|
@@ -328,60 +362,104 @@ export class DomRenderer extends Disposable implements IRenderer {
|
|
|
328
362
|
|
|
329
363
|
public handleBlur(): void {
|
|
330
364
|
this._rowContainer.classList.remove(FOCUS_CLASS);
|
|
365
|
+
this._cursorBlinkStateManager.pause();
|
|
331
366
|
this.renderRows(0, this._bufferService.rows - 1);
|
|
332
367
|
}
|
|
333
368
|
|
|
334
369
|
public handleFocus(): void {
|
|
335
370
|
this._rowContainer.classList.add(FOCUS_CLASS);
|
|
371
|
+
this._cursorBlinkStateManager.resume();
|
|
336
372
|
this.renderRows(this._bufferService.buffer.y, this._bufferService.buffer.y);
|
|
337
373
|
}
|
|
338
374
|
|
|
375
|
+
public handleViewportVisibilityChange(isVisible: boolean): void {
|
|
376
|
+
this._textBlinkStateManager.setViewportVisible(isVisible);
|
|
377
|
+
}
|
|
378
|
+
|
|
339
379
|
public handleSelectionChanged(start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode: boolean): void {
|
|
380
|
+
const rows = this._bufferService.rows;
|
|
381
|
+
|
|
340
382
|
// Remove all selections
|
|
341
383
|
this._selectionContainer.replaceChildren();
|
|
342
384
|
this._rowFactory.handleSelectionChanged(start, end, columnSelectMode);
|
|
343
|
-
this.renderRows(0, this._bufferService.rows - 1);
|
|
344
385
|
|
|
345
|
-
//
|
|
386
|
+
// Determine old selection viewport band
|
|
387
|
+
let oldViewportStart = 0;
|
|
388
|
+
let oldViewportEnd = -1;
|
|
389
|
+
if (this._lastSelectionStart && this._lastSelectionEnd) {
|
|
390
|
+
this._selectionRenderModel.update(this._terminal, this._lastSelectionStart, this._lastSelectionEnd, this._lastSelectionColumnMode);
|
|
391
|
+
if (this._selectionRenderModel.hasSelection) {
|
|
392
|
+
oldViewportStart = this._selectionRenderModel.viewportCappedStartRow;
|
|
393
|
+
oldViewportEnd = this._selectionRenderModel.viewportCappedEndRow;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// Determine new selection viewport band and create overlays
|
|
398
|
+
let newViewportStart = 0;
|
|
399
|
+
let newViewportEnd = -1;
|
|
346
400
|
if (!start || !end) {
|
|
347
401
|
return;
|
|
348
402
|
}
|
|
349
|
-
|
|
350
403
|
this._selectionRenderModel.update(this._terminal, start, end, columnSelectMode);
|
|
351
|
-
if (
|
|
352
|
-
|
|
404
|
+
if (this._selectionRenderModel.hasSelection) {
|
|
405
|
+
const viewportStartRow = this._selectionRenderModel.viewportStartRow;
|
|
406
|
+
const viewportEndRow = this._selectionRenderModel.viewportEndRow;
|
|
407
|
+
const viewportCappedStartRow = this._selectionRenderModel.viewportCappedStartRow;
|
|
408
|
+
const viewportCappedEndRow = this._selectionRenderModel.viewportCappedEndRow;
|
|
409
|
+
|
|
410
|
+
newViewportStart = viewportCappedStartRow;
|
|
411
|
+
newViewportEnd = viewportCappedEndRow;
|
|
412
|
+
|
|
413
|
+
// Create the selections
|
|
414
|
+
const documentFragment = this._document.createDocumentFragment();
|
|
415
|
+
|
|
416
|
+
if (columnSelectMode) {
|
|
417
|
+
const isXFlipped = start[0] > end[0];
|
|
418
|
+
documentFragment.appendChild(
|
|
419
|
+
this._createSelectionElement(viewportCappedStartRow, isXFlipped ? end[0] : start[0], isXFlipped ? start[0] : end[0], viewportCappedEndRow - viewportCappedStartRow + 1)
|
|
420
|
+
);
|
|
421
|
+
} else {
|
|
422
|
+
// Draw first row
|
|
423
|
+
const startCol = viewportStartRow === viewportCappedStartRow ? start[0] : 0;
|
|
424
|
+
const endCol = viewportCappedStartRow === viewportEndRow ? end[0] : this._bufferService.cols;
|
|
425
|
+
documentFragment.appendChild(this._createSelectionElement(viewportCappedStartRow, startCol, endCol));
|
|
426
|
+
// Draw middle rows
|
|
427
|
+
const middleRowsCount = viewportCappedEndRow - viewportCappedStartRow - 1;
|
|
428
|
+
documentFragment.appendChild(this._createSelectionElement(viewportCappedStartRow + 1, 0, this._bufferService.cols, middleRowsCount));
|
|
429
|
+
// Draw final row
|
|
430
|
+
if (viewportCappedStartRow !== viewportCappedEndRow) {
|
|
431
|
+
// Only draw viewportEndRow if it's not the same as viewporttartRow
|
|
432
|
+
const finalEndCol = viewportEndRow === viewportCappedEndRow ? end[0] : this._bufferService.cols;
|
|
433
|
+
documentFragment.appendChild(this._createSelectionElement(viewportCappedEndRow, 0, finalEndCol));
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
this._selectionContainer.appendChild(documentFragment);
|
|
353
437
|
}
|
|
354
438
|
|
|
355
|
-
//
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
const
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
// Draw first row
|
|
371
|
-
const startCol = viewportStartRow === viewportCappedStartRow ? start[0] : 0;
|
|
372
|
-
const endCol = viewportCappedStartRow === viewportEndRow ? end[0] : this._bufferService.cols;
|
|
373
|
-
documentFragment.appendChild(this._createSelectionElement(viewportCappedStartRow, startCol, endCol));
|
|
374
|
-
// Draw middle rows
|
|
375
|
-
const middleRowsCount = viewportCappedEndRow - viewportCappedStartRow - 1;
|
|
376
|
-
documentFragment.appendChild(this._createSelectionElement(viewportCappedStartRow + 1, 0, this._bufferService.cols, middleRowsCount));
|
|
377
|
-
// Draw final row
|
|
378
|
-
if (viewportCappedStartRow !== viewportCappedEndRow) {
|
|
379
|
-
// Only draw viewportEndRow if it's not the same as viewporttartRow
|
|
380
|
-
const endCol = viewportEndRow === viewportCappedEndRow ? end[0] : this._bufferService.cols;
|
|
381
|
-
documentFragment.appendChild(this._createSelectionElement(viewportCappedEndRow, 0, endCol));
|
|
439
|
+
// Compute minimal row range to redraw
|
|
440
|
+
let renderStartRow = Math.min(oldViewportStart, newViewportStart);
|
|
441
|
+
let renderEndRow = Math.max(oldViewportEnd, newViewportEnd);
|
|
442
|
+
|
|
443
|
+
if (renderEndRow >= 0) {
|
|
444
|
+
// Clamp to viewport
|
|
445
|
+
renderStartRow = Math.max(renderStartRow, 0);
|
|
446
|
+
renderEndRow = Math.min(renderEndRow, rows - 1);
|
|
447
|
+
|
|
448
|
+
// Ensure cursor row is included when a selection is present
|
|
449
|
+
const buffer = this._bufferService.buffer;
|
|
450
|
+
const cursorViewportRow = buffer.y;
|
|
451
|
+
if (this._selectionRenderModel.hasSelection && cursorViewportRow >= 0 && cursorViewportRow < rows) {
|
|
452
|
+
renderStartRow = Math.min(renderStartRow, cursorViewportRow);
|
|
453
|
+
renderEndRow = Math.max(renderEndRow, cursorViewportRow);
|
|
382
454
|
}
|
|
455
|
+
|
|
456
|
+
this.renderRows(renderStartRow, renderEndRow);
|
|
383
457
|
}
|
|
384
|
-
|
|
458
|
+
|
|
459
|
+
// Update last selection state
|
|
460
|
+
this._lastSelectionStart = start;
|
|
461
|
+
this._lastSelectionEnd = end;
|
|
462
|
+
this._lastSelectionColumnMode = columnSelectMode;
|
|
385
463
|
}
|
|
386
464
|
|
|
387
465
|
/**
|
|
@@ -406,7 +484,8 @@ export class DomRenderer extends Disposable implements IRenderer {
|
|
|
406
484
|
}
|
|
407
485
|
|
|
408
486
|
public handleCursorMove(): void {
|
|
409
|
-
//
|
|
487
|
+
// Reset idle timer on cursor movement (which happens on input)
|
|
488
|
+
this._cursorBlinkStateManager.restartBlinkAnimation();
|
|
410
489
|
}
|
|
411
490
|
|
|
412
491
|
private _handleOptionsChanged(): void {
|
|
@@ -436,6 +515,11 @@ export class DomRenderer extends Disposable implements IRenderer {
|
|
|
436
515
|
*/
|
|
437
516
|
e.replaceChildren();
|
|
438
517
|
}
|
|
518
|
+
if (this._rowHasBlinkingCellsCount > 0) {
|
|
519
|
+
this._rowHasBlinkingCells.fill(false);
|
|
520
|
+
this._rowHasBlinkingCellsCount = 0;
|
|
521
|
+
this._textBlinkStateManager.setNeedsBlinkInViewport(false);
|
|
522
|
+
}
|
|
439
523
|
}
|
|
440
524
|
|
|
441
525
|
public renderRows(start: number, end: number): void {
|
|
@@ -445,6 +529,7 @@ export class DomRenderer extends Disposable implements IRenderer {
|
|
|
445
529
|
const cursorBlink = this._coreService.decPrivateModes.cursorBlink ?? this._optionsService.rawOptions.cursorBlink;
|
|
446
530
|
const cursorStyle = this._coreService.decPrivateModes.cursorStyle ?? this._optionsService.rawOptions.cursorStyle;
|
|
447
531
|
const cursorInactiveStyle = this._optionsService.rawOptions.cursorInactiveStyle;
|
|
532
|
+
const rowInfo = { hasBlinkingCells: false };
|
|
448
533
|
|
|
449
534
|
for (let y = start; y <= end; y++) {
|
|
450
535
|
const row = y + buffer.ydisp;
|
|
@@ -462,13 +547,17 @@ export class DomRenderer extends Disposable implements IRenderer {
|
|
|
462
547
|
cursorInactiveStyle,
|
|
463
548
|
cursorX,
|
|
464
549
|
cursorBlink,
|
|
550
|
+
this._textBlinkStateManager.isBlinkOn,
|
|
465
551
|
this.dimensions.css.cell.width,
|
|
466
552
|
this._widthCache,
|
|
467
553
|
-1,
|
|
468
|
-
-1
|
|
554
|
+
-1,
|
|
555
|
+
rowInfo
|
|
469
556
|
)
|
|
470
557
|
);
|
|
558
|
+
this._setRowBlinkState(y, rowInfo.hasBlinkingCells);
|
|
471
559
|
}
|
|
560
|
+
this._updateTextBlinkState();
|
|
472
561
|
}
|
|
473
562
|
|
|
474
563
|
private get _terminalSelector(): string {
|
|
@@ -513,6 +602,7 @@ export class DomRenderer extends Disposable implements IRenderer {
|
|
|
513
602
|
const cursorBlink = this._optionsService.rawOptions.cursorBlink;
|
|
514
603
|
const cursorStyle = this._optionsService.rawOptions.cursorStyle;
|
|
515
604
|
const cursorInactiveStyle = this._optionsService.rawOptions.cursorInactiveStyle;
|
|
605
|
+
const rowInfo = { hasBlinkingCells: false };
|
|
516
606
|
|
|
517
607
|
// refresh rows within link range
|
|
518
608
|
for (let i = y; i <= y2; ++i) {
|
|
@@ -531,12 +621,86 @@ export class DomRenderer extends Disposable implements IRenderer {
|
|
|
531
621
|
cursorInactiveStyle,
|
|
532
622
|
cursorX,
|
|
533
623
|
cursorBlink,
|
|
624
|
+
this._textBlinkStateManager.isBlinkOn,
|
|
534
625
|
this.dimensions.css.cell.width,
|
|
535
626
|
this._widthCache,
|
|
536
627
|
enabled ? (i === y ? x : 0) : -1,
|
|
537
|
-
enabled ? ((i === y2 ? x2 : cols) - 1) : -1
|
|
628
|
+
enabled ? ((i === y2 ? x2 : cols) - 1) : -1,
|
|
629
|
+
rowInfo
|
|
538
630
|
)
|
|
539
631
|
);
|
|
632
|
+
this._setRowBlinkState(i, rowInfo.hasBlinkingCells);
|
|
633
|
+
}
|
|
634
|
+
this._updateTextBlinkState();
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
private _setRowBlinkState(row: number, hasBlinkingCells: boolean): void {
|
|
638
|
+
const previous = this._rowHasBlinkingCells[row];
|
|
639
|
+
if (previous === hasBlinkingCells) {
|
|
640
|
+
return;
|
|
641
|
+
}
|
|
642
|
+
this._rowHasBlinkingCells[row] = hasBlinkingCells;
|
|
643
|
+
this._rowHasBlinkingCellsCount += hasBlinkingCells ? 1 : -1;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
private _updateTextBlinkState(): void {
|
|
647
|
+
this._textBlinkStateManager.setNeedsBlinkInViewport(this._rowHasBlinkingCellsCount > 0);
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
class CursorBlinkStateManager {
|
|
652
|
+
private _idleTimeout: number | undefined;
|
|
653
|
+
private _isIdlePaused: boolean = false;
|
|
654
|
+
|
|
655
|
+
constructor(
|
|
656
|
+
private readonly _rowContainer: HTMLElement,
|
|
657
|
+
private readonly _coreBrowserService: ICoreBrowserService
|
|
658
|
+
) {
|
|
659
|
+
if (this._coreBrowserService.isFocused) {
|
|
660
|
+
this._resetIdleTimer();
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
public dispose(): void {
|
|
665
|
+
this._clearIdleTimer();
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
public restartBlinkAnimation(): void {
|
|
669
|
+
if (this._isIdlePaused) {
|
|
670
|
+
this._rowContainer.classList.remove(CURSOR_BLINK_IDLE_CLASS);
|
|
540
671
|
}
|
|
672
|
+
this._resetIdleTimer();
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
public pause(): void {
|
|
676
|
+
this._isIdlePaused = false;
|
|
677
|
+
this._clearIdleTimer();
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
public resume(): void {
|
|
681
|
+
this._isIdlePaused = false;
|
|
682
|
+
this._rowContainer.classList.remove(CURSOR_BLINK_IDLE_CLASS);
|
|
683
|
+
this._resetIdleTimer();
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
private _resetIdleTimer(): void {
|
|
687
|
+
this._isIdlePaused = false;
|
|
688
|
+
this._clearIdleTimer();
|
|
689
|
+
this._idleTimeout = this._coreBrowserService.window.setTimeout(() => {
|
|
690
|
+
this._stopBlinkingDueToIdle();
|
|
691
|
+
}, RendererConstants.CURSOR_BLINK_IDLE_TIMEOUT);
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
private _clearIdleTimer(): void {
|
|
695
|
+
if (this._idleTimeout) {
|
|
696
|
+
this._coreBrowserService.window.clearTimeout(this._idleTimeout);
|
|
697
|
+
this._idleTimeout = undefined;
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
private _stopBlinkingDueToIdle(): void {
|
|
702
|
+
this._rowContainer.classList.add(CURSOR_BLINK_IDLE_CLASS);
|
|
703
|
+
this._isIdlePaused = true;
|
|
704
|
+
this._idleTimeout = undefined;
|
|
541
705
|
}
|
|
542
706
|
}
|