@xterm/xterm 6.1.0-beta.21 → 6.1.0-beta.211
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 +61 -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 +24 -13
- 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 +263 -43
- 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 +167 -57
- package/src/common/parser/OscParser.ts +5 -5
- package/src/common/parser/Params.ts +13 -0
- package/src/common/parser/Types.ts +36 -2
- 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
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026 The xterm.js authors. All rights reserved.
|
|
3
|
+
* @license MIT
|
|
4
|
+
*
|
|
5
|
+
* Minimal DOM helpers for xterm.js browser code.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { IntervalTimer } from 'common/Async';
|
|
9
|
+
import { IDisposable } from 'common/Lifecycle';
|
|
10
|
+
|
|
11
|
+
export function getWindow(e: Node | UIEvent | undefined | null): Window {
|
|
12
|
+
const candidateNode = e as Node | undefined | null;
|
|
13
|
+
if (candidateNode?.ownerDocument?.defaultView) {
|
|
14
|
+
return candidateNode.ownerDocument.defaultView;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const candidateEvent = e as UIEvent | undefined | null;
|
|
18
|
+
if (candidateEvent?.view) {
|
|
19
|
+
return candidateEvent.view;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return window;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
class DomListener implements IDisposable {
|
|
26
|
+
private _handler: ((e: any) => void) | null;
|
|
27
|
+
private _node: EventTarget | null;
|
|
28
|
+
private readonly _type: string;
|
|
29
|
+
private readonly _options: boolean | AddEventListenerOptions | undefined;
|
|
30
|
+
|
|
31
|
+
constructor(node: EventTarget, type: string, handler: (e: any) => void, options?: boolean | AddEventListenerOptions) {
|
|
32
|
+
this._node = node;
|
|
33
|
+
this._type = type;
|
|
34
|
+
this._handler = handler;
|
|
35
|
+
this._options = options;
|
|
36
|
+
node.addEventListener(type, handler, options);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
public dispose(): void {
|
|
40
|
+
if (!this._node || !this._handler) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
this._node.removeEventListener(this._type, this._handler, this._options);
|
|
44
|
+
this._node = null;
|
|
45
|
+
this._handler = null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function addDisposableListener<K extends keyof GlobalEventHandlersEventMap>(node: EventTarget, type: K, handler: (event: GlobalEventHandlersEventMap[K]) => void, useCapture?: boolean): IDisposable;
|
|
50
|
+
export function addDisposableListener(node: EventTarget, type: string, handler: (event: any) => void, useCapture?: boolean): IDisposable;
|
|
51
|
+
export function addDisposableListener(node: EventTarget, type: string, handler: (event: any) => void, options: AddEventListenerOptions): IDisposable;
|
|
52
|
+
export function addDisposableListener(node: EventTarget, type: string, handler: (event: any) => void, useCaptureOrOptions?: boolean | AddEventListenerOptions): IDisposable {
|
|
53
|
+
return new DomListener(node, type, handler, useCaptureOrOptions);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function addStandardDisposableListener(node: HTMLElement, type: string, handler: (event: any) => void, useCapture?: boolean): IDisposable {
|
|
57
|
+
return addDisposableListener(node, type, handler, useCapture);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export const eventType = {
|
|
61
|
+
CLICK: 'click',
|
|
62
|
+
MOUSE_DOWN: 'mousedown',
|
|
63
|
+
MOUSE_OVER: 'mouseover',
|
|
64
|
+
MOUSE_LEAVE: 'mouseleave',
|
|
65
|
+
KEY_DOWN: 'keydown',
|
|
66
|
+
KEY_UP: 'keyup',
|
|
67
|
+
INPUT: 'input',
|
|
68
|
+
BLUR: 'blur',
|
|
69
|
+
FOCUS: 'focus',
|
|
70
|
+
CHANGE: 'change',
|
|
71
|
+
POINTER_DOWN: 'pointerdown',
|
|
72
|
+
POINTER_MOVE: 'pointermove',
|
|
73
|
+
POINTER_UP: 'pointerup',
|
|
74
|
+
MOUSE_WHEEL: 'wheel',
|
|
75
|
+
WHEEL: 'wheel'
|
|
76
|
+
} as const;
|
|
77
|
+
|
|
78
|
+
export function getDomNodePagePosition(domNode: HTMLElement): { left: number, top: number, width: number, height: number } {
|
|
79
|
+
const bb = domNode.getBoundingClientRect();
|
|
80
|
+
const win = getWindow(domNode);
|
|
81
|
+
return {
|
|
82
|
+
left: bb.left + win.scrollX,
|
|
83
|
+
top: bb.top + win.scrollY,
|
|
84
|
+
width: bb.width,
|
|
85
|
+
height: bb.height
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
class AnimationFrameQueueItem implements IDisposable {
|
|
90
|
+
private _canceled = false;
|
|
91
|
+
|
|
92
|
+
constructor(private readonly _runner: () => void, public priority: number) {
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
public dispose(): void {
|
|
96
|
+
this._canceled = true;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
public execute(): void {
|
|
100
|
+
if (this._canceled) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
try {
|
|
104
|
+
this._runner();
|
|
105
|
+
} catch (e) {
|
|
106
|
+
console.error(e);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
public static sort(a: AnimationFrameQueueItem, b: AnimationFrameQueueItem): number {
|
|
111
|
+
return b.priority - a.priority;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
interface IWindowAnimationFrameState {
|
|
116
|
+
next: AnimationFrameQueueItem[];
|
|
117
|
+
current: AnimationFrameQueueItem[];
|
|
118
|
+
animFrameRequested: boolean;
|
|
119
|
+
inAnimationFrameRunner: boolean;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const animationFrameState = new Map<Window, IWindowAnimationFrameState>();
|
|
123
|
+
|
|
124
|
+
function getAnimationFrameState(targetWindow: Window): IWindowAnimationFrameState {
|
|
125
|
+
let state = animationFrameState.get(targetWindow);
|
|
126
|
+
if (!state) {
|
|
127
|
+
state = {
|
|
128
|
+
next: [],
|
|
129
|
+
current: [],
|
|
130
|
+
animFrameRequested: false,
|
|
131
|
+
inAnimationFrameRunner: false
|
|
132
|
+
};
|
|
133
|
+
animationFrameState.set(targetWindow, state);
|
|
134
|
+
}
|
|
135
|
+
return state;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function animationFrameRunner(targetWindow: Window): void {
|
|
139
|
+
const state = getAnimationFrameState(targetWindow);
|
|
140
|
+
state.animFrameRequested = false;
|
|
141
|
+
|
|
142
|
+
state.current = state.next;
|
|
143
|
+
state.next = [];
|
|
144
|
+
|
|
145
|
+
state.inAnimationFrameRunner = true;
|
|
146
|
+
while (state.current.length > 0) {
|
|
147
|
+
state.current.sort(AnimationFrameQueueItem.sort);
|
|
148
|
+
const top = state.current.shift()!;
|
|
149
|
+
top.execute();
|
|
150
|
+
}
|
|
151
|
+
state.inAnimationFrameRunner = false;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export function scheduleAtNextAnimationFrame(targetWindow: Window, runner: () => void, priority: number = 0): IDisposable {
|
|
155
|
+
const state = getAnimationFrameState(targetWindow);
|
|
156
|
+
const item = new AnimationFrameQueueItem(runner, priority);
|
|
157
|
+
state.next.push(item);
|
|
158
|
+
|
|
159
|
+
if (!state.animFrameRequested) {
|
|
160
|
+
state.animFrameRequested = true;
|
|
161
|
+
targetWindow.requestAnimationFrame(() => animationFrameRunner(targetWindow));
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return item;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export class WindowIntervalTimer extends IntervalTimer {
|
|
168
|
+
private readonly _defaultTarget?: Window;
|
|
169
|
+
|
|
170
|
+
constructor(node?: Node) {
|
|
171
|
+
super();
|
|
172
|
+
this._defaultTarget = node ? getWindow(node) : undefined;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
public cancelAndSet(runner: () => void, interval: number, targetWindow?: Window): void {
|
|
176
|
+
super.cancelAndSet(runner, interval, targetWindow ?? this._defaultTarget ?? window);
|
|
177
|
+
}
|
|
178
|
+
}
|
package/src/browser/Linkifier.ts
CHANGED
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { IBufferCellPosition, ILink, ILinkDecorations, ILinkWithState, ILinkifier2, ILinkifierEvent } from 'browser/Types';
|
|
7
|
-
import { Disposable, dispose, toDisposable } from '
|
|
7
|
+
import { Disposable, dispose, toDisposable } from 'common/Lifecycle';
|
|
8
8
|
import { IDisposable } from 'common/Types';
|
|
9
9
|
import { IBufferService } from 'common/services/Services';
|
|
10
|
-
import { ILinkProviderService,
|
|
11
|
-
import { Emitter } from '
|
|
12
|
-
import { addDisposableListener } from '
|
|
10
|
+
import { ILinkProviderService, IMouseCoordsService, IRenderService } from './services/Services';
|
|
11
|
+
import { Emitter } from 'common/Event';
|
|
12
|
+
import { addDisposableListener } from 'browser/Dom';
|
|
13
13
|
|
|
14
14
|
export class Linkifier extends Disposable implements ILinkifier2 {
|
|
15
15
|
public get currentLink(): ILinkWithState | undefined { return this._currentLink; }
|
|
@@ -30,7 +30,7 @@ export class Linkifier extends Disposable implements ILinkifier2 {
|
|
|
30
30
|
|
|
31
31
|
constructor(
|
|
32
32
|
private readonly _element: HTMLElement,
|
|
33
|
-
@
|
|
33
|
+
@IMouseCoordsService private readonly _mouseCoordsService: IMouseCoordsService,
|
|
34
34
|
@IRenderService private readonly _renderService: IRenderService,
|
|
35
35
|
@IBufferService private readonly _bufferService: IBufferService,
|
|
36
36
|
@ILinkProviderService private readonly _linkProviderService: ILinkProviderService
|
|
@@ -60,7 +60,7 @@ export class Linkifier extends Disposable implements ILinkifier2 {
|
|
|
60
60
|
private _handleMouseMove(event: MouseEvent): void {
|
|
61
61
|
this._lastMouseEvent = event;
|
|
62
62
|
|
|
63
|
-
const position = this._positionFromMouseEvent(event, this._element
|
|
63
|
+
const position = this._positionFromMouseEvent(event, this._element);
|
|
64
64
|
if (!position) {
|
|
65
65
|
return;
|
|
66
66
|
}
|
|
@@ -222,7 +222,7 @@ export class Linkifier extends Disposable implements ILinkifier2 {
|
|
|
222
222
|
return;
|
|
223
223
|
}
|
|
224
224
|
|
|
225
|
-
const position = this._positionFromMouseEvent(event, this._element
|
|
225
|
+
const position = this._positionFromMouseEvent(event, this._element);
|
|
226
226
|
if (!position) {
|
|
227
227
|
return;
|
|
228
228
|
}
|
|
@@ -251,7 +251,7 @@ export class Linkifier extends Disposable implements ILinkifier2 {
|
|
|
251
251
|
return;
|
|
252
252
|
}
|
|
253
253
|
|
|
254
|
-
const position = this._positionFromMouseEvent(this._lastMouseEvent, this._element
|
|
254
|
+
const position = this._positionFromMouseEvent(this._lastMouseEvent, this._element);
|
|
255
255
|
|
|
256
256
|
if (!position) {
|
|
257
257
|
return;
|
|
@@ -312,7 +312,7 @@ export class Linkifier extends Disposable implements ILinkifier2 {
|
|
|
312
312
|
this._clearCurrentLink(start, end);
|
|
313
313
|
if (this._lastMouseEvent) {
|
|
314
314
|
// re-eval previously active link after changes
|
|
315
|
-
const position = this._positionFromMouseEvent(this._lastMouseEvent, this._element
|
|
315
|
+
const position = this._positionFromMouseEvent(this._lastMouseEvent, this._element);
|
|
316
316
|
if (position) {
|
|
317
317
|
this._askForLink(position, false);
|
|
318
318
|
}
|
|
@@ -378,8 +378,8 @@ export class Linkifier extends Disposable implements ILinkifier2 {
|
|
|
378
378
|
* Get the buffer position from a mouse event
|
|
379
379
|
* @param event
|
|
380
380
|
*/
|
|
381
|
-
private _positionFromMouseEvent(event: MouseEvent, element: HTMLElement
|
|
382
|
-
const coords =
|
|
381
|
+
private _positionFromMouseEvent(event: MouseEvent, element: HTMLElement): IBufferCellPosition | undefined {
|
|
382
|
+
const coords = this._mouseCoordsService.getCoords(event, element, this._bufferService.cols, this._bufferService.rows);
|
|
383
383
|
if (!coords) {
|
|
384
384
|
return;
|
|
385
385
|
}
|
|
@@ -9,6 +9,8 @@ import { CellData } from 'common/buffer/CellData';
|
|
|
9
9
|
import { IBufferService, IOptionsService, IOscLinkService } from 'common/services/Services';
|
|
10
10
|
|
|
11
11
|
export class OscLinkProvider implements ILinkProvider {
|
|
12
|
+
private readonly _workCell = new CellData();
|
|
13
|
+
|
|
12
14
|
constructor(
|
|
13
15
|
@IBufferService private readonly _bufferService: IBufferService,
|
|
14
16
|
@IOptionsService private readonly _optionsService: IOptionsService,
|
|
@@ -25,7 +27,7 @@ export class OscLinkProvider implements ILinkProvider {
|
|
|
25
27
|
|
|
26
28
|
const result: ILink[] = [];
|
|
27
29
|
const linkHandler = this._optionsService.rawOptions.linkHandler;
|
|
28
|
-
const cell =
|
|
30
|
+
const cell = this._workCell;
|
|
29
31
|
const lineLength = line.getTrimmedLength();
|
|
30
32
|
let currentLinkId = -1;
|
|
31
33
|
let currentStart = -1;
|
|
@@ -40,8 +40,8 @@ export class RenderDebouncer implements IRenderDebouncerWithCallback {
|
|
|
40
40
|
public refresh(rowStart: number | undefined, rowEnd: number | undefined, rowCount: number): void {
|
|
41
41
|
this._rowCount = rowCount;
|
|
42
42
|
// Get the min/max row start/end for the arg values
|
|
43
|
-
rowStart = rowStart
|
|
44
|
-
rowEnd = rowEnd
|
|
43
|
+
rowStart = rowStart ?? 0;
|
|
44
|
+
rowEnd = rowEnd ?? this._rowCount - 1;
|
|
45
45
|
// Set the properties to the updated values
|
|
46
46
|
this._rowStart = this._rowStart !== undefined ? Math.min(this._rowStart, rowStart) : rowStart;
|
|
47
47
|
this._rowEnd = this._rowEnd !== undefined ? Math.max(this._rowEnd, rowEnd) : rowEnd;
|
|
@@ -37,8 +37,8 @@ export class TimeBasedDebouncer implements IRenderDebouncer {
|
|
|
37
37
|
public refresh(rowStart: number | undefined, rowEnd: number | undefined, rowCount: number): void {
|
|
38
38
|
this._rowCount = rowCount;
|
|
39
39
|
// Get the min/max row start/end for the arg values
|
|
40
|
-
rowStart = rowStart
|
|
41
|
-
rowEnd = rowEnd
|
|
40
|
+
rowStart = rowStart ?? 0;
|
|
41
|
+
rowEnd = rowEnd ?? this._rowCount - 1;
|
|
42
42
|
// Set the properties to the updated values
|
|
43
43
|
this._rowStart = this._rowStart !== undefined ? Math.min(this._rowStart, rowStart) : rowStart;
|
|
44
44
|
this._rowEnd = this._rowEnd !== undefined ? Math.max(this._rowEnd, rowEnd) : rowEnd;
|
package/src/browser/Types.ts
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
|
|
6
6
|
import { CharData, IColor, ICoreTerminal, ITerminalOptions } from 'common/Types';
|
|
7
7
|
import { IBuffer } from 'common/buffer/Types';
|
|
8
|
-
import { IDisposable, Terminal as ITerminalApi } from '@xterm/xterm';
|
|
8
|
+
import { IDisposable, IRenderDimensions as IRenderDimensionsApi, Terminal as ITerminalApi } from '@xterm/xterm';
|
|
9
9
|
import { channels, css } from 'common/Color';
|
|
10
|
-
import type {
|
|
10
|
+
import type { IEvent } from 'common/Event';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* A portion of the public API that are implemented identially internally and simply passed through.
|
|
@@ -21,13 +21,14 @@ export interface ITerminal extends InternalPassthroughApis, ICoreTerminal {
|
|
|
21
21
|
linkifier: ILinkifier2 | undefined;
|
|
22
22
|
options: Required<ITerminalOptions>;
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
onFocus: Event<void>;
|
|
26
|
-
onA11yChar: Event<string>;
|
|
27
|
-
onA11yTab: Event<number>;
|
|
28
|
-
onWillOpen: Event<HTMLElement>;
|
|
24
|
+
readonly dimensions: IRenderDimensionsApi | undefined;
|
|
29
25
|
|
|
30
|
-
|
|
26
|
+
onBlur: IEvent<void>;
|
|
27
|
+
onFocus: IEvent<void>;
|
|
28
|
+
onDimensionsChange: IEvent<IRenderDimensionsApi>;
|
|
29
|
+
onA11yChar: IEvent<string>;
|
|
30
|
+
onA11yTab: IEvent<number>;
|
|
31
|
+
onWillOpen: IEvent<HTMLElement>;
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
export type CustomKeyEventHandler = (event: KeyboardEvent) => boolean;
|
|
@@ -98,7 +99,7 @@ export interface IPartialColorSet {
|
|
|
98
99
|
|
|
99
100
|
export interface IViewport extends IDisposable {
|
|
100
101
|
scrollBarWidth: number;
|
|
101
|
-
readonly onRequestScrollLines:
|
|
102
|
+
readonly onRequestScrollLines: IEvent<{ amount: number, suppressScrollEvent: boolean }>;
|
|
102
103
|
syncScrollArea(immediate?: boolean, force?: boolean): void;
|
|
103
104
|
getLinesScrolled(ev: WheelEvent): number;
|
|
104
105
|
getBufferElements(startLine: number, endLine?: number): { bufferElements: HTMLElement[], cursorElement?: HTMLElement };
|
|
@@ -128,8 +129,8 @@ export interface ILinkWithState {
|
|
|
128
129
|
}
|
|
129
130
|
|
|
130
131
|
export interface ILinkifier2 extends IDisposable {
|
|
131
|
-
onShowLinkUnderline:
|
|
132
|
-
onHideLinkUnderline:
|
|
132
|
+
onShowLinkUnderline: IEvent<ILinkifierEvent>;
|
|
133
|
+
onHideLinkUnderline: IEvent<ILinkifierEvent>;
|
|
133
134
|
readonly currentLink: ILinkWithState | undefined;
|
|
134
135
|
}
|
|
135
136
|
|
package/src/browser/Viewport.ts
CHANGED
|
@@ -5,14 +5,14 @@
|
|
|
5
5
|
|
|
6
6
|
import { ICoreBrowserService, IRenderService, IThemeService } from 'browser/services/Services';
|
|
7
7
|
import { ViewportConstants } from 'browser/shared/Constants';
|
|
8
|
-
import { Disposable, toDisposable } from '
|
|
9
|
-
import { IBufferService,
|
|
8
|
+
import { Disposable, toDisposable } from 'common/Lifecycle';
|
|
9
|
+
import { IBufferService, ICoreService, IMouseStateService, IOptionsService } from 'common/services/Services';
|
|
10
10
|
import { CoreMouseEventType } from 'common/Types';
|
|
11
|
-
import { scheduleAtNextAnimationFrame } from '
|
|
12
|
-
import { SmoothScrollableElement } from '
|
|
13
|
-
import type {
|
|
14
|
-
import { Emitter,
|
|
15
|
-
import { Scrollable, ScrollbarVisibility, type
|
|
11
|
+
import { scheduleAtNextAnimationFrame } from 'browser/Dom';
|
|
12
|
+
import { SmoothScrollableElement } from 'browser/scrollable/scrollableElement';
|
|
13
|
+
import type { IScrollableElementChangeOptions } from 'browser/scrollable/scrollableElementOptions';
|
|
14
|
+
import { Emitter, EventUtils } from 'common/Event';
|
|
15
|
+
import { Scrollable, ScrollbarVisibility, type IScrollEvent } from 'browser/scrollable/scrollable';
|
|
16
16
|
|
|
17
17
|
export class Viewport extends Disposable {
|
|
18
18
|
|
|
@@ -27,13 +27,15 @@ export class Viewport extends Disposable {
|
|
|
27
27
|
private _isSyncing: boolean = false;
|
|
28
28
|
private _isHandlingScroll: boolean = false;
|
|
29
29
|
private _suppressOnScrollHandler: boolean = false;
|
|
30
|
+
private _needsSyncOnRender: boolean = false;
|
|
30
31
|
|
|
31
32
|
constructor(
|
|
32
33
|
element: HTMLElement,
|
|
33
34
|
screenElement: HTMLElement,
|
|
34
35
|
@IBufferService private readonly _bufferService: IBufferService,
|
|
35
36
|
@ICoreBrowserService coreBrowserService: ICoreBrowserService,
|
|
36
|
-
@
|
|
37
|
+
@ICoreService private readonly _coreService: ICoreService,
|
|
38
|
+
@IMouseStateService mouseStateService: IMouseStateService,
|
|
37
39
|
@IThemeService themeService: IThemeService,
|
|
38
40
|
@IOptionsService private readonly _optionsService: IOptionsService,
|
|
39
41
|
@IRenderService private readonly _renderService: IRenderService
|
|
@@ -51,26 +53,28 @@ export class Viewport extends Disposable {
|
|
|
51
53
|
}));
|
|
52
54
|
|
|
53
55
|
this._scrollableElement = this._register(new SmoothScrollableElement(screenElement, {
|
|
54
|
-
vertical: ScrollbarVisibility.
|
|
55
|
-
horizontal: ScrollbarVisibility.
|
|
56
|
+
vertical: ScrollbarVisibility.AUTO,
|
|
57
|
+
horizontal: ScrollbarVisibility.HIDDEN,
|
|
56
58
|
useShadows: false,
|
|
57
59
|
mouseWheelSmoothScroll: true,
|
|
60
|
+
verticalHasArrows: this._optionsService.rawOptions.scrollbar?.showArrows ?? false,
|
|
58
61
|
...this._getChangeOptions()
|
|
59
62
|
}, scrollable));
|
|
60
63
|
this._register(this._optionsService.onMultipleOptionChange([
|
|
61
64
|
'scrollSensitivity',
|
|
62
65
|
'fastScrollSensitivity',
|
|
63
|
-
'
|
|
66
|
+
'scrollbar'
|
|
64
67
|
], () => this._scrollableElement.updateOptions(this._getChangeOptions())));
|
|
65
68
|
// Don't handle mouse wheel if wheel events are supported by the current mouse prototcol
|
|
66
|
-
this._register(
|
|
69
|
+
this._register(mouseStateService.onProtocolChange(type => {
|
|
67
70
|
this._scrollableElement.updateOptions({
|
|
68
71
|
handleMouseWheel: !(type & CoreMouseEventType.WHEEL)
|
|
69
72
|
});
|
|
70
73
|
}));
|
|
71
74
|
|
|
72
75
|
this._scrollableElement.setScrollDimensions({ height: 0, scrollHeight: 0 });
|
|
73
|
-
this._register(
|
|
76
|
+
this._register(EventUtils.runAndSubscribe(themeService.onChangeColors, () => {
|
|
77
|
+
element.style.backgroundColor = themeService.colors.background.css;
|
|
74
78
|
this._scrollableElement.getDomNode().style.backgroundColor = themeService.colors.background.css;
|
|
75
79
|
}));
|
|
76
80
|
element.appendChild(this._scrollableElement.getDomNode());
|
|
@@ -79,15 +83,15 @@ export class Viewport extends Disposable {
|
|
|
79
83
|
this._styleElement = coreBrowserService.mainDocument.createElement('style');
|
|
80
84
|
screenElement.appendChild(this._styleElement);
|
|
81
85
|
this._register(toDisposable(() => this._styleElement.remove()));
|
|
82
|
-
this._register(
|
|
86
|
+
this._register(EventUtils.runAndSubscribe(themeService.onChangeColors, () => {
|
|
83
87
|
this._styleElement.textContent = [
|
|
84
|
-
`.xterm .xterm-scrollable-element > .scrollbar > .slider {`,
|
|
88
|
+
`.xterm .xterm-scrollable-element > .xterm-scrollbar > .xterm-slider {`,
|
|
85
89
|
` background: ${themeService.colors.scrollbarSliderBackground.css};`,
|
|
86
90
|
`}`,
|
|
87
|
-
`.xterm .xterm-scrollable-element > .scrollbar > .slider:hover {`,
|
|
91
|
+
`.xterm .xterm-scrollable-element > .xterm-scrollbar > .xterm-slider:hover {`,
|
|
88
92
|
` background: ${themeService.colors.scrollbarSliderHoverBackground.css};`,
|
|
89
93
|
`}`,
|
|
90
|
-
`.xterm .xterm-scrollable-element > .scrollbar > .slider.active {`,
|
|
94
|
+
`.xterm .xterm-scrollable-element > .xterm-scrollbar > .xterm-slider.xterm-active {`,
|
|
91
95
|
` background: ${themeService.colors.scrollbarSliderActiveBackground.css};`,
|
|
92
96
|
`}`
|
|
93
97
|
].join('\n');
|
|
@@ -102,7 +106,18 @@ export class Viewport extends Disposable {
|
|
|
102
106
|
}));
|
|
103
107
|
this._register(this._bufferService.onScroll(() => this._sync()));
|
|
104
108
|
|
|
109
|
+
// Flush deferred viewport sync after a render completes (e.g. after ESU ends
|
|
110
|
+
// synchronized output mode). This ensures DOM scroll position updates atomically
|
|
111
|
+
// with the canvas render.
|
|
112
|
+
this._register(this._renderService.onRender(() => {
|
|
113
|
+
if (this._needsSyncOnRender) {
|
|
114
|
+
this._needsSyncOnRender = false;
|
|
115
|
+
this._sync();
|
|
116
|
+
}
|
|
117
|
+
}));
|
|
118
|
+
|
|
105
119
|
this._register(this._scrollableElement.onScroll(e => this._handleScroll(e)));
|
|
120
|
+
|
|
106
121
|
}
|
|
107
122
|
|
|
108
123
|
public scrollLines(disp: number): void {
|
|
@@ -123,11 +138,18 @@ export class Viewport extends Disposable {
|
|
|
123
138
|
});
|
|
124
139
|
}
|
|
125
140
|
|
|
126
|
-
private _getChangeOptions():
|
|
141
|
+
private _getChangeOptions(): IScrollableElementChangeOptions {
|
|
142
|
+
const showScrollbar = this._optionsService.rawOptions.scrollbar?.showScrollbar ?? true;
|
|
143
|
+
const showArrows = this._optionsService.rawOptions.scrollbar?.showArrows ?? false;
|
|
144
|
+
const verticalScrollbarSize = showScrollbar
|
|
145
|
+
? (this._optionsService.rawOptions.scrollbar?.width ?? ViewportConstants.DEFAULT_SCROLL_BAR_WIDTH)
|
|
146
|
+
: 0;
|
|
127
147
|
return {
|
|
128
148
|
mouseWheelScrollSensitivity: this._optionsService.rawOptions.scrollSensitivity,
|
|
129
149
|
fastScrollSensitivity: this._optionsService.rawOptions.fastScrollSensitivity,
|
|
130
|
-
|
|
150
|
+
vertical: showScrollbar ? ScrollbarVisibility.AUTO : ScrollbarVisibility.HIDDEN,
|
|
151
|
+
verticalScrollbarSize,
|
|
152
|
+
verticalHasArrows: showArrows
|
|
131
153
|
};
|
|
132
154
|
}
|
|
133
155
|
|
|
@@ -151,6 +173,12 @@ export class Viewport extends Disposable {
|
|
|
151
173
|
if (!this._renderService || this._isSyncing) {
|
|
152
174
|
return;
|
|
153
175
|
}
|
|
176
|
+
// Defer DOM scroll updates during synchronized output to prevent visible
|
|
177
|
+
// scroll position flickering while the canvas content is frozen.
|
|
178
|
+
if (this._coreService.decPrivateModes.synchronizedOutput) {
|
|
179
|
+
this._needsSyncOnRender = true;
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
154
182
|
this._isSyncing = true;
|
|
155
183
|
|
|
156
184
|
// Ignore any onScroll event that happens as a result of dimensions changing as this should
|
|
@@ -173,7 +201,7 @@ export class Viewport extends Disposable {
|
|
|
173
201
|
this._isSyncing = false;
|
|
174
202
|
}
|
|
175
203
|
|
|
176
|
-
private _handleScroll(e:
|
|
204
|
+
private _handleScroll(e: IScrollEvent): void {
|
|
177
205
|
if (!this._renderService) {
|
|
178
206
|
return;
|
|
179
207
|
}
|
|
@@ -189,4 +217,11 @@ export class Viewport extends Disposable {
|
|
|
189
217
|
}
|
|
190
218
|
this._isHandlingScroll = false;
|
|
191
219
|
}
|
|
220
|
+
|
|
221
|
+
public handleTouchScroll(translationY: number): void {
|
|
222
|
+
const pos = this._scrollableElement.getScrollPosition();
|
|
223
|
+
this._scrollableElement.setScrollPosition({
|
|
224
|
+
scrollTop: pos.scrollTop - translationY
|
|
225
|
+
});
|
|
226
|
+
}
|
|
192
227
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*--------------------------------------------------------------------------------------------*/
|
|
5
5
|
|
|
6
6
|
import { ICoreBrowserService, IRenderService } from 'browser/services/Services';
|
|
7
|
-
import { Disposable, toDisposable } from '
|
|
7
|
+
import { Disposable, toDisposable } from 'common/Lifecycle';
|
|
8
8
|
import { IBufferService, IDecorationService, IInternalDecoration } from 'common/services/Services';
|
|
9
9
|
|
|
10
10
|
export class BufferDecorationRenderer extends Disposable {
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import { ColorZoneStore, IColorZone, IColorZoneStore } from 'browser/decorations/ColorZoneStore';
|
|
7
7
|
import { ICoreBrowserService, IRenderService, IThemeService } from 'browser/services/Services';
|
|
8
|
-
import { Disposable, toDisposable } from '
|
|
8
|
+
import { Disposable, toDisposable } from 'common/Lifecycle';
|
|
9
9
|
import { IBufferService, IDecorationService, IOptionsService } from 'common/services/Services';
|
|
10
10
|
|
|
11
11
|
const enum Constants {
|
|
@@ -38,7 +38,12 @@ export class OverviewRulerRenderer extends Disposable {
|
|
|
38
38
|
private readonly _ctx: CanvasRenderingContext2D;
|
|
39
39
|
private readonly _colorZoneStore: IColorZoneStore = new ColorZoneStore();
|
|
40
40
|
private get _width(): number {
|
|
41
|
-
|
|
41
|
+
const scrollbar = this._optionsService.rawOptions.scrollbar;
|
|
42
|
+
const showScrollbar = scrollbar?.showScrollbar ?? true;
|
|
43
|
+
if (!showScrollbar) {
|
|
44
|
+
return 0;
|
|
45
|
+
}
|
|
46
|
+
return scrollbar?.width ?? 0;
|
|
42
47
|
}
|
|
43
48
|
private _animationFrame: number | undefined;
|
|
44
49
|
|
|
@@ -46,8 +51,6 @@ export class OverviewRulerRenderer extends Disposable {
|
|
|
46
51
|
private _shouldUpdateAnchor: boolean | undefined = true;
|
|
47
52
|
private _lastKnownBufferLength: number = 0;
|
|
48
53
|
|
|
49
|
-
private _containerHeight: number | undefined;
|
|
50
|
-
|
|
51
54
|
constructor(
|
|
52
55
|
private readonly _viewportElement: HTMLElement,
|
|
53
56
|
private readonly _screenElement: HTMLElement,
|
|
@@ -86,17 +89,17 @@ export class OverviewRulerRenderer extends Disposable {
|
|
|
86
89
|
}
|
|
87
90
|
}));
|
|
88
91
|
|
|
89
|
-
|
|
90
|
-
this._register(this._renderService.onRender((): void => {
|
|
91
|
-
if (!this._containerHeight || this._containerHeight !== this._screenElement.clientHeight) {
|
|
92
|
-
this._queueRefresh(true);
|
|
93
|
-
this._containerHeight = this._screenElement.clientHeight;
|
|
94
|
-
}
|
|
95
|
-
}));
|
|
92
|
+
this._register(this._renderService.onDimensionsChange(() => this._queueRefresh(true)));
|
|
96
93
|
|
|
97
94
|
this._register(this._coreBrowserService.onDprChange(() => this._queueRefresh(true)));
|
|
98
|
-
this._register(this._optionsService.onSpecificOptionChange('
|
|
95
|
+
this._register(this._optionsService.onSpecificOptionChange('scrollbar', () => this._queueRefresh(true)));
|
|
99
96
|
this._register(this._themeService.onChangeColors(() => this._queueRefresh()));
|
|
97
|
+
this._register(toDisposable(() => {
|
|
98
|
+
if (this._animationFrame !== undefined) {
|
|
99
|
+
this._coreBrowserService.window.cancelAnimationFrame(this._animationFrame);
|
|
100
|
+
this._animationFrame = undefined;
|
|
101
|
+
}
|
|
102
|
+
}));
|
|
100
103
|
this._queueRefresh(true);
|
|
101
104
|
}
|
|
102
105
|
|
|
@@ -139,15 +142,23 @@ export class OverviewRulerRenderer extends Disposable {
|
|
|
139
142
|
}
|
|
140
143
|
|
|
141
144
|
private _refreshCanvasDimensions(): void {
|
|
145
|
+
if (this._store.isDisposed || !this._renderService.hasRenderer()) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
const cssCanvasHeight = this._renderService.dimensions.css.canvas.height;
|
|
149
|
+
const deviceCanvasHeight = this._renderService.dimensions.device.canvas.height;
|
|
142
150
|
this._canvas.style.width = `${this._width}px`;
|
|
143
151
|
this._canvas.width = Math.round(this._width * this._coreBrowserService.dpr);
|
|
144
|
-
this._canvas.style.height = `${
|
|
145
|
-
this._canvas.height =
|
|
152
|
+
this._canvas.style.height = `${cssCanvasHeight}px`;
|
|
153
|
+
this._canvas.height = deviceCanvasHeight;
|
|
146
154
|
this._refreshDrawConstants();
|
|
147
155
|
this._refreshColorZonePadding();
|
|
148
156
|
}
|
|
149
157
|
|
|
150
158
|
private _refreshDecorations(): void {
|
|
159
|
+
if (this._store.isDisposed || !this._renderService.hasRenderer()) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
151
162
|
if (this._shouldUpdateDimensions) {
|
|
152
163
|
this._refreshCanvasDimensions();
|
|
153
164
|
}
|
|
@@ -176,10 +187,10 @@ export class OverviewRulerRenderer extends Disposable {
|
|
|
176
187
|
private _renderRulerOutline(): void {
|
|
177
188
|
this._ctx.fillStyle = this._themeService.colors.overviewRulerBorder.css;
|
|
178
189
|
this._ctx.fillRect(0, 0, Constants.OVERVIEW_RULER_BORDER_WIDTH, this._canvas.height);
|
|
179
|
-
if (this._optionsService.rawOptions.overviewRuler
|
|
190
|
+
if (this._optionsService.rawOptions.scrollbar?.overviewRuler?.showTopBorder) {
|
|
180
191
|
this._ctx.fillRect(Constants.OVERVIEW_RULER_BORDER_WIDTH, 0, this._canvas.width - Constants.OVERVIEW_RULER_BORDER_WIDTH, Constants.OVERVIEW_RULER_BORDER_WIDTH);
|
|
181
192
|
}
|
|
182
|
-
if (this._optionsService.rawOptions.overviewRuler
|
|
193
|
+
if (this._optionsService.rawOptions.scrollbar?.overviewRuler?.showBottomBorder) {
|
|
183
194
|
this._ctx.fillRect(Constants.OVERVIEW_RULER_BORDER_WIDTH, this._canvas.height - Constants.OVERVIEW_RULER_BORDER_WIDTH, this._canvas.width - Constants.OVERVIEW_RULER_BORDER_WIDTH, this._canvas.height);
|
|
184
195
|
}
|
|
185
196
|
}
|
|
@@ -201,13 +212,18 @@ export class OverviewRulerRenderer extends Disposable {
|
|
|
201
212
|
}
|
|
202
213
|
|
|
203
214
|
private _queueRefresh(updateCanvasDimensions?: boolean, updateAnchor?: boolean): void {
|
|
215
|
+
if (this._store.isDisposed) {
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
204
218
|
this._shouldUpdateDimensions = updateCanvasDimensions || this._shouldUpdateDimensions;
|
|
205
219
|
this._shouldUpdateAnchor = updateAnchor || this._shouldUpdateAnchor;
|
|
206
220
|
if (this._animationFrame !== undefined) {
|
|
207
221
|
return;
|
|
208
222
|
}
|
|
209
223
|
this._animationFrame = this._coreBrowserService.window.requestAnimationFrame(() => {
|
|
210
|
-
this.
|
|
224
|
+
if (!this._store.isDisposed) {
|
|
225
|
+
this._refreshDecorations();
|
|
226
|
+
}
|
|
211
227
|
this._animationFrame = undefined;
|
|
212
228
|
});
|
|
213
229
|
}
|