@xterm/xterm 6.1.0-beta.19 → 6.1.0-beta.190

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.
Files changed (157) hide show
  1. package/README.md +60 -38
  2. package/css/xterm.css +29 -22
  3. package/lib/xterm.js +1 -1
  4. package/lib/xterm.js.map +1 -1
  5. package/lib/xterm.mjs +8 -34
  6. package/lib/xterm.mjs.map +4 -4
  7. package/package.json +25 -14
  8. package/src/browser/AccessibilityManager.ts +6 -3
  9. package/src/browser/Clipboard.ts +6 -3
  10. package/src/browser/CoreBrowserTerminal.ts +147 -318
  11. package/src/browser/Dom.ts +178 -0
  12. package/src/browser/Linkifier.ts +11 -11
  13. package/src/browser/OscLinkProvider.ts +3 -1
  14. package/src/browser/RenderDebouncer.ts +2 -2
  15. package/src/browser/TimeBasedDebouncer.ts +2 -2
  16. package/src/browser/Types.ts +12 -11
  17. package/src/browser/Viewport.ts +37 -20
  18. package/src/browser/decorations/BufferDecorationRenderer.ts +1 -1
  19. package/src/browser/decorations/OverviewRulerRenderer.ts +15 -16
  20. package/src/browser/input/CompositionHelper.ts +44 -8
  21. package/src/browser/public/Terminal.ts +25 -28
  22. package/src/browser/renderer/dom/DomRenderer.ts +128 -8
  23. package/src/browser/renderer/dom/DomRendererRowFactory.ts +19 -13
  24. package/src/browser/renderer/dom/WidthCache.ts +54 -52
  25. package/src/browser/renderer/shared/Constants.ts +7 -0
  26. package/src/browser/renderer/shared/TextBlinkStateManager.ts +97 -0
  27. package/src/browser/renderer/shared/Types.ts +8 -2
  28. package/src/browser/scrollable/abstractScrollbar.ts +300 -0
  29. package/src/browser/scrollable/fastDomNode.ts +126 -0
  30. package/src/browser/scrollable/globalPointerMoveMonitor.ts +90 -0
  31. package/src/browser/scrollable/horizontalScrollbar.ts +85 -0
  32. package/src/browser/scrollable/mouseEvent.ts +292 -0
  33. package/src/browser/scrollable/scrollable.ts +486 -0
  34. package/src/browser/scrollable/scrollableElement.ts +579 -0
  35. package/src/browser/scrollable/scrollableElementOptions.ts +161 -0
  36. package/src/browser/scrollable/scrollbarArrow.ts +110 -0
  37. package/src/browser/scrollable/scrollbarState.ts +246 -0
  38. package/src/browser/scrollable/scrollbarVisibilityController.ts +113 -0
  39. package/src/browser/scrollable/touch.ts +485 -0
  40. package/src/browser/scrollable/verticalScrollbar.ts +143 -0
  41. package/src/browser/scrollable/widget.ts +23 -0
  42. package/src/browser/services/CharSizeService.ts +2 -2
  43. package/src/browser/services/CoreBrowserService.ts +7 -5
  44. package/src/browser/services/KeyboardService.ts +67 -0
  45. package/src/browser/services/LinkProviderService.ts +1 -1
  46. package/src/browser/services/MouseCoordsService.ts +47 -0
  47. package/src/browser/services/MouseService.ts +518 -25
  48. package/src/browser/services/RenderService.ts +22 -15
  49. package/src/browser/services/SelectionService.ts +16 -8
  50. package/src/browser/services/Services.ts +40 -17
  51. package/src/browser/services/ThemeService.ts +2 -2
  52. package/src/common/Async.ts +105 -0
  53. package/src/common/CircularList.ts +2 -2
  54. package/src/common/Color.ts +8 -0
  55. package/src/common/CoreTerminal.ts +28 -18
  56. package/src/common/Event.ts +118 -0
  57. package/src/common/InputHandler.ts +256 -36
  58. package/src/common/Lifecycle.ts +113 -0
  59. package/src/common/Platform.ts +13 -3
  60. package/src/common/SortedList.ts +7 -3
  61. package/src/common/TaskQueue.ts +9 -3
  62. package/src/common/Types.ts +35 -15
  63. package/src/common/Version.ts +9 -0
  64. package/src/common/buffer/Buffer.ts +20 -14
  65. package/src/common/buffer/BufferLine.ts +4 -5
  66. package/src/common/buffer/BufferSet.ts +7 -6
  67. package/src/common/buffer/CellData.ts +57 -0
  68. package/src/common/buffer/Marker.ts +2 -2
  69. package/src/common/buffer/Types.ts +6 -2
  70. package/src/common/data/EscapeSequences.ts +71 -70
  71. package/src/common/input/Keyboard.ts +14 -7
  72. package/src/common/input/KittyKeyboard.ts +496 -0
  73. package/src/common/input/Win32InputMode.ts +297 -0
  74. package/src/common/input/WriteBuffer.ts +34 -2
  75. package/src/common/input/XParseColor.ts +2 -2
  76. package/src/common/parser/ApcParser.ts +245 -0
  77. package/src/common/parser/Constants.ts +22 -4
  78. package/src/common/parser/DcsParser.ts +5 -5
  79. package/src/common/parser/EscapeSequenceParser.ts +75 -22
  80. package/src/common/parser/OscParser.ts +5 -5
  81. package/src/common/parser/Types.ts +34 -1
  82. package/src/common/public/BufferLineApiView.ts +2 -2
  83. package/src/common/public/BufferNamespaceApi.ts +2 -2
  84. package/src/common/public/ParserApi.ts +3 -0
  85. package/src/common/services/BufferService.ts +8 -5
  86. package/src/common/services/CharsetService.ts +4 -0
  87. package/src/common/services/CoreService.ts +18 -4
  88. package/src/common/services/DecorationService.ts +24 -8
  89. package/src/common/services/LogService.ts +1 -31
  90. package/src/common/services/{CoreMouseService.ts → MouseStateService.ts} +21 -132
  91. package/src/common/services/OptionsService.ts +13 -4
  92. package/src/common/services/Services.ts +47 -40
  93. package/src/common/services/UnicodeService.ts +1 -1
  94. package/typings/xterm.d.ts +319 -35
  95. package/src/common/TypedArrayUtils.ts +0 -17
  96. package/src/vs/base/browser/browser.ts +0 -141
  97. package/src/vs/base/browser/canIUse.ts +0 -49
  98. package/src/vs/base/browser/dom.ts +0 -2369
  99. package/src/vs/base/browser/fastDomNode.ts +0 -316
  100. package/src/vs/base/browser/globalPointerMoveMonitor.ts +0 -112
  101. package/src/vs/base/browser/iframe.ts +0 -135
  102. package/src/vs/base/browser/keyboardEvent.ts +0 -213
  103. package/src/vs/base/browser/mouseEvent.ts +0 -229
  104. package/src/vs/base/browser/touch.ts +0 -372
  105. package/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts +0 -303
  106. package/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts +0 -114
  107. package/src/vs/base/browser/ui/scrollbar/scrollableElement.ts +0 -720
  108. package/src/vs/base/browser/ui/scrollbar/scrollableElementOptions.ts +0 -165
  109. package/src/vs/base/browser/ui/scrollbar/scrollbarArrow.ts +0 -114
  110. package/src/vs/base/browser/ui/scrollbar/scrollbarState.ts +0 -243
  111. package/src/vs/base/browser/ui/scrollbar/scrollbarVisibilityController.ts +0 -118
  112. package/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts +0 -116
  113. package/src/vs/base/browser/ui/widget.ts +0 -57
  114. package/src/vs/base/browser/window.ts +0 -14
  115. package/src/vs/base/common/arrays.ts +0 -887
  116. package/src/vs/base/common/arraysFind.ts +0 -202
  117. package/src/vs/base/common/assert.ts +0 -71
  118. package/src/vs/base/common/async.ts +0 -1992
  119. package/src/vs/base/common/cancellation.ts +0 -148
  120. package/src/vs/base/common/charCode.ts +0 -450
  121. package/src/vs/base/common/collections.ts +0 -140
  122. package/src/vs/base/common/decorators.ts +0 -130
  123. package/src/vs/base/common/equals.ts +0 -146
  124. package/src/vs/base/common/errors.ts +0 -303
  125. package/src/vs/base/common/event.ts +0 -1778
  126. package/src/vs/base/common/functional.ts +0 -32
  127. package/src/vs/base/common/hash.ts +0 -316
  128. package/src/vs/base/common/iterator.ts +0 -159
  129. package/src/vs/base/common/keyCodes.ts +0 -526
  130. package/src/vs/base/common/keybindings.ts +0 -284
  131. package/src/vs/base/common/lazy.ts +0 -47
  132. package/src/vs/base/common/lifecycle.ts +0 -801
  133. package/src/vs/base/common/linkedList.ts +0 -142
  134. package/src/vs/base/common/map.ts +0 -202
  135. package/src/vs/base/common/numbers.ts +0 -98
  136. package/src/vs/base/common/observable.ts +0 -76
  137. package/src/vs/base/common/observableInternal/api.ts +0 -31
  138. package/src/vs/base/common/observableInternal/autorun.ts +0 -281
  139. package/src/vs/base/common/observableInternal/base.ts +0 -489
  140. package/src/vs/base/common/observableInternal/debugName.ts +0 -145
  141. package/src/vs/base/common/observableInternal/derived.ts +0 -428
  142. package/src/vs/base/common/observableInternal/lazyObservableValue.ts +0 -146
  143. package/src/vs/base/common/observableInternal/logging.ts +0 -328
  144. package/src/vs/base/common/observableInternal/promise.ts +0 -209
  145. package/src/vs/base/common/observableInternal/utils.ts +0 -610
  146. package/src/vs/base/common/platform.ts +0 -281
  147. package/src/vs/base/common/scrollable.ts +0 -522
  148. package/src/vs/base/common/sequence.ts +0 -34
  149. package/src/vs/base/common/stopwatch.ts +0 -43
  150. package/src/vs/base/common/strings.ts +0 -557
  151. package/src/vs/base/common/symbols.ts +0 -9
  152. package/src/vs/base/common/uint.ts +0 -59
  153. package/src/vs/patches/nls.ts +0 -90
  154. package/src/vs/typings/base-common.d.ts +0 -20
  155. package/src/vs/typings/require.d.ts +0 -42
  156. package/src/vs/typings/vscode-globals-nls.d.ts +0 -36
  157. package/src/vs/typings/vscode-globals-product.d.ts +0 -33
@@ -3,6 +3,7 @@
3
3
  * @license MIT
4
4
  */
5
5
 
6
+ import { throwIfFalsy } from 'browser/renderer/shared/RendererUtils';
6
7
  import { IDisposable } from 'common/Types';
7
8
  import { FontWeight } from 'common/services/Services';
8
9
 
@@ -24,6 +25,10 @@ const enum FontVariant {
24
25
  BOLD_ITALIC = 3
25
26
  }
26
27
 
28
+ export interface IWidthCacheFontVariantCanvas {
29
+ setFont(fontFamily: string, fontSize: number, fontWeight: FontWeight, italic: boolean): void;
30
+ measure(c: string): number;
31
+ }
27
32
 
28
33
  export class WidthCache implements IDisposable {
29
34
  // flat cache for regular variant up to CacheSettings.FLAT_SIZE
@@ -42,50 +47,24 @@ export class WidthCache implements IDisposable {
42
47
  private _fontSize = 0;
43
48
  private _weight: FontWeight = 'normal';
44
49
  private _weightBold: FontWeight = 'bold';
45
- private _container: HTMLDivElement;
46
- private _measureElements: HTMLSpanElement[] = [];
47
-
48
- constructor(_document: Document, _helperContainer: HTMLElement) {
49
- this._container = _document.createElement('div');
50
- this._container.classList.add('xterm-width-cache-measure-container');
51
- this._container.setAttribute('aria-hidden', 'true');
52
- // SP should stack in spans
53
- this._container.style.whiteSpace = 'pre';
54
- // avoid undercuts in non-monospace fonts from kerning
55
- this._container.style.fontKerning = 'none';
56
-
57
- const regular = _document.createElement('span');
58
- regular.classList.add('xterm-char-measure-element');
59
-
60
- const bold = _document.createElement('span');
61
- bold.classList.add('xterm-char-measure-element');
62
- bold.style.fontWeight = 'bold';
63
-
64
- const italic = _document.createElement('span');
65
- italic.classList.add('xterm-char-measure-element');
66
- italic.style.fontStyle = 'italic';
67
-
68
- const boldItalic = _document.createElement('span');
69
- boldItalic.classList.add('xterm-char-measure-element');
70
- boldItalic.style.fontWeight = 'bold';
71
- boldItalic.style.fontStyle = 'italic';
72
-
73
- // NOTE: must be in order of FontVariant
74
- this._measureElements = [regular, bold, italic, boldItalic];
75
- this._container.appendChild(regular);
76
- this._container.appendChild(bold);
77
- this._container.appendChild(italic);
78
- this._container.appendChild(boldItalic);
79
-
80
- _helperContainer.appendChild(this._container);
50
+ private _canvasElements: IWidthCacheFontVariantCanvas[] = [];
51
+
52
+ constructor(
53
+ canvasFactory: () => IWidthCacheFontVariantCanvas = () => new WidthCacheFontVariantCanvas()
54
+ ) {
55
+ this._canvasElements = [
56
+ canvasFactory(),
57
+ canvasFactory(),
58
+ canvasFactory(),
59
+ canvasFactory()
60
+ ];
81
61
 
82
62
  this.clear();
83
63
  }
84
64
 
85
65
  public dispose(): void {
86
- this._container.remove(); // remove elements from DOM
87
- this._measureElements.length = 0; // release element refs
88
- this._holey = undefined; // free cache memory via GC
66
+ this._canvasElements.length = 0;
67
+ this._holey = undefined; // free cache memory via GC
89
68
  }
90
69
 
91
70
  /**
@@ -104,10 +83,11 @@ export class WidthCache implements IDisposable {
104
83
  */
105
84
  public setFont(font: string, fontSize: number, weight: FontWeight, weightBold: FontWeight): void {
106
85
  // skip if nothing changed
107
- if (font === this._font
108
- && fontSize === this._fontSize
109
- && weight === this._weight
110
- && weightBold === this._weightBold
86
+ if (
87
+ font === this._font &&
88
+ fontSize === this._fontSize &&
89
+ weight === this._weight &&
90
+ weightBold === this._weightBold
111
91
  ) {
112
92
  return;
113
93
  }
@@ -117,12 +97,10 @@ export class WidthCache implements IDisposable {
117
97
  this._weight = weight;
118
98
  this._weightBold = weightBold;
119
99
 
120
- this._container.style.fontFamily = this._font;
121
- this._container.style.fontSize = `${this._fontSize}px`;
122
- this._measureElements[FontVariant.REGULAR].style.fontWeight = `${weight}`;
123
- this._measureElements[FontVariant.BOLD].style.fontWeight = `${weightBold}`;
124
- this._measureElements[FontVariant.ITALIC].style.fontWeight = `${weight}`;
125
- this._measureElements[FontVariant.BOLD_ITALIC].style.fontWeight = `${weightBold}`;
100
+ this._canvasElements[FontVariant.REGULAR].setFont(font, fontSize, weight, false);
101
+ this._canvasElements[FontVariant.BOLD].setFont(font, fontSize, weightBold, false);
102
+ this._canvasElements[FontVariant.ITALIC].setFont(font, fontSize, weight, true);
103
+ this._canvasElements[FontVariant.BOLD_ITALIC].setFont(font, fontSize, weightBold, true);
126
104
 
127
105
  this.clear();
128
106
  }
@@ -160,8 +138,32 @@ export class WidthCache implements IDisposable {
160
138
  }
161
139
 
162
140
  protected _measure(c: string, variant: FontVariant): number {
163
- const el = this._measureElements[variant];
164
- el.textContent = c.repeat(WidthCacheSettings.REPEAT);
165
- return el.offsetWidth / WidthCacheSettings.REPEAT;
141
+ return this._canvasElements[variant].measure(c);
142
+ }
143
+ }
144
+
145
+ class WidthCacheFontVariantCanvas implements IWidthCacheFontVariantCanvas {
146
+ private _canvas: OffscreenCanvas | HTMLCanvasElement;
147
+ private _ctx: OffscreenCanvasRenderingContext2D | CanvasRenderingContext2D;
148
+
149
+ constructor() {
150
+ if (typeof OffscreenCanvas !== 'undefined') {
151
+ this._canvas = new OffscreenCanvas(1, 1);
152
+ this._ctx = throwIfFalsy(this._canvas.getContext('2d'));
153
+ } else {
154
+ this._canvas = document.createElement('canvas');
155
+ this._canvas.width = 1;
156
+ this._canvas.height = 1;
157
+ this._ctx = throwIfFalsy(this._canvas.getContext('2d'));
158
+ }
159
+ }
160
+
161
+ public setFont(fontFamily: string, fontSize: number, fontWeight: FontWeight, italic: boolean): void {
162
+ const fontStyle = italic ? 'italic' : '';
163
+ this._ctx.font = `${fontStyle} ${fontWeight} ${fontSize}px ${fontFamily}`.trim();
164
+ }
165
+
166
+ public measure(c: string): number {
167
+ return this._ctx.measureText(c).width;
166
168
  }
167
169
  }
@@ -4,3 +4,10 @@
4
4
  */
5
5
 
6
6
  export const INVERTED_DEFAULT_COLOR = 257;
7
+
8
+ export const enum RendererConstants {
9
+ /**
10
+ * The idle time after which cursor blinking stops.
11
+ */
12
+ CURSOR_BLINK_IDLE_TIMEOUT = 5 * 60 * 1000
13
+ }
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Copyright (c) 2026 The xterm.js authors. All rights reserved.
3
+ * @license MIT
4
+ */
5
+
6
+ import { ICoreBrowserService } from 'browser/services/Services';
7
+ import { Disposable, toDisposable } from 'common/Lifecycle';
8
+ import { IOptionsService } from 'common/services/Services';
9
+
10
+ export class TextBlinkStateManager extends Disposable {
11
+ private _intervalDuration: number = 0;
12
+ private _interval: number | undefined;
13
+ private _blinkOn: boolean = true;
14
+ private _needsBlinkInViewport: boolean = false;
15
+ private _isViewportVisible: boolean = true;
16
+
17
+ constructor(
18
+ private readonly _renderCallback: () => void,
19
+ private readonly _coreBrowserService: ICoreBrowserService,
20
+ private readonly _optionsService: IOptionsService
21
+ ) {
22
+ super();
23
+ this._register(this._optionsService.onSpecificOptionChange('blinkIntervalDuration', duration => {
24
+ this.setIntervalDuration(duration);
25
+ }));
26
+ this.setIntervalDuration(this._optionsService.rawOptions.blinkIntervalDuration);
27
+ this._register(toDisposable(() => this._clearInterval()));
28
+ }
29
+
30
+ public get isBlinkOn(): boolean {
31
+ return this._blinkOn;
32
+ }
33
+
34
+ public get isEnabled(): boolean {
35
+ return this._intervalDuration > 0;
36
+ }
37
+
38
+ public setNeedsBlinkInViewport(needsBlinkInViewport: boolean): void {
39
+ if (this._needsBlinkInViewport === needsBlinkInViewport) {
40
+ return;
41
+ }
42
+
43
+ this._needsBlinkInViewport = needsBlinkInViewport;
44
+ this._updateIntervalState();
45
+ }
46
+
47
+ public setViewportVisible(isVisible: boolean): void {
48
+ if (this._isViewportVisible === isVisible) {
49
+ return;
50
+ }
51
+
52
+ this._isViewportVisible = isVisible;
53
+ this._updateIntervalState();
54
+ }
55
+
56
+ public setIntervalDuration(duration: number): void {
57
+ if (duration === this._intervalDuration) {
58
+ return;
59
+ }
60
+
61
+ this._intervalDuration = duration;
62
+ this._clearInterval();
63
+ this._updateIntervalState();
64
+ }
65
+
66
+ private _updateIntervalState(): void {
67
+ const shouldBlink = this._intervalDuration > 0 && this._needsBlinkInViewport && this._isViewportVisible;
68
+ if (shouldBlink) {
69
+ if (this._interval !== undefined) {
70
+ return;
71
+ }
72
+ const wasBlinkOn = this._blinkOn;
73
+ this._blinkOn = true;
74
+ this._interval = this._coreBrowserService.window.setInterval(() => {
75
+ this._blinkOn = !this._blinkOn;
76
+ this._renderCallback();
77
+ }, this._intervalDuration);
78
+ if (!wasBlinkOn) {
79
+ this._renderCallback();
80
+ }
81
+ return;
82
+ }
83
+
84
+ this._clearInterval();
85
+ if (!this._blinkOn) {
86
+ this._blinkOn = true;
87
+ this._renderCallback();
88
+ }
89
+ }
90
+
91
+ private _clearInterval(): void {
92
+ if (this._interval !== undefined) {
93
+ this._coreBrowserService.window.clearInterval(this._interval);
94
+ this._interval = undefined;
95
+ }
96
+ }
97
+ }
@@ -6,7 +6,7 @@
6
6
  import { Terminal } from '@xterm/xterm';
7
7
  import { ITerminal } from 'browser/Types';
8
8
  import { IDisposable } from 'common/Types';
9
- import type { Event } from 'vs/base/common/event';
9
+ import type { IEvent } from 'common/Event';
10
10
 
11
11
  export interface IDimensions {
12
12
  width: number;
@@ -39,6 +39,11 @@ export interface IRenderDimensions {
39
39
  export interface IRequestRedrawEvent {
40
40
  start: number;
41
41
  end: number;
42
+ /**
43
+ * Whether the redraw should happen synchronously. This is used to avoid
44
+ * flicker when the canvas is resized.
45
+ */
46
+ sync?: boolean;
42
47
  }
43
48
 
44
49
  /**
@@ -52,7 +57,7 @@ export interface IRenderer extends IDisposable {
52
57
  * Fires when the renderer is requesting to be redrawn on the next animation
53
58
  * frame but is _not_ a result of content changing (eg. selection changes).
54
59
  */
55
- readonly onRequestRedraw: Event<IRequestRedrawEvent>;
60
+ readonly onRequestRedraw: IEvent<IRequestRedrawEvent>;
56
61
 
57
62
  dispose(): void;
58
63
  handleDevicePixelRatioChange(): void;
@@ -60,6 +65,7 @@ export interface IRenderer extends IDisposable {
60
65
  handleCharSizeChanged(): void;
61
66
  handleBlur(): void;
62
67
  handleFocus(): void;
68
+ handleViewportVisibilityChange?(isVisible: boolean): void;
63
69
  handleSelectionChanged(start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode: boolean): void;
64
70
  handleCursorMove(): void;
65
71
  clear(): void;
@@ -0,0 +1,300 @@
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Microsoft Corporation. All rights reserved.
3
+ * Licensed under the MIT License. See License.txt in the project root for license information.
4
+ *--------------------------------------------------------------------------------------------*/
5
+
6
+ import * as dom from '../Dom';
7
+ import { FastDomNode } from './fastDomNode';
8
+ import { GlobalPointerMoveMonitor } from './globalPointerMoveMonitor';
9
+ import { StandardWheelEvent } from './mouseEvent';
10
+ import { ScrollbarArrow, IScrollbarArrowOptions } from './scrollbarArrow';
11
+ import { ScrollbarState } from './scrollbarState';
12
+ import { ScrollbarVisibilityController } from './scrollbarVisibilityController';
13
+ import { Widget } from './widget';
14
+ import * as platform from 'common/Platform';
15
+ import { INewScrollPosition, Scrollable, ScrollbarVisibility } from './scrollable';
16
+
17
+ /**
18
+ * The orthogonal distance to the slider at which dragging "resets". This implements "snapping"
19
+ */
20
+ const POINTER_DRAG_RESET_DISTANCE = 140;
21
+
22
+ export interface ISimplifiedPointerEvent {
23
+ buttons: number;
24
+ pageX: number;
25
+ pageY: number;
26
+ }
27
+
28
+ export interface IScrollbarHost {
29
+ handleMouseWheel(mouseWheelEvent: StandardWheelEvent): void;
30
+ handleDragStart(): void;
31
+ handleDragEnd(): void;
32
+ }
33
+
34
+ interface IAbstractScrollbarOptions {
35
+ lazyRender: boolean;
36
+ host: IScrollbarHost;
37
+ scrollbarState: ScrollbarState;
38
+ visibility: ScrollbarVisibility;
39
+ extraScrollbarClassName: string;
40
+ scrollable: Scrollable;
41
+ scrollByPage: boolean;
42
+ }
43
+
44
+ export abstract class AbstractScrollbar extends Widget {
45
+
46
+ protected _host: IScrollbarHost;
47
+ protected _scrollable: Scrollable;
48
+ protected _scrollByPage: boolean;
49
+ private _lazyRender: boolean;
50
+ protected _scrollbarState: ScrollbarState;
51
+ protected _visibilityController: ScrollbarVisibilityController;
52
+ private _pointerMoveMonitor: GlobalPointerMoveMonitor;
53
+
54
+ public domNode: FastDomNode<HTMLElement>;
55
+ public slider!: FastDomNode<HTMLElement>;
56
+
57
+ protected _shouldRender: boolean;
58
+
59
+ constructor(opts: IAbstractScrollbarOptions) {
60
+ super();
61
+ this._lazyRender = opts.lazyRender;
62
+ this._host = opts.host;
63
+ this._scrollable = opts.scrollable;
64
+ this._scrollByPage = opts.scrollByPage;
65
+ this._scrollbarState = opts.scrollbarState;
66
+ this._visibilityController = this._register(new ScrollbarVisibilityController(opts.visibility, 'xterm-visible xterm-scrollbar ' + opts.extraScrollbarClassName, 'xterm-invisible xterm-scrollbar ' + opts.extraScrollbarClassName));
67
+ this._visibilityController.setIsNeeded(this._scrollbarState.isNeeded());
68
+ this._pointerMoveMonitor = this._register(new GlobalPointerMoveMonitor());
69
+ this._shouldRender = true;
70
+ this.domNode = new FastDomNode(document.createElement('div'));
71
+ this.domNode.setAttribute('role', 'presentation');
72
+ this.domNode.setAttribute('aria-hidden', 'true');
73
+
74
+ this._visibilityController.setDomNode(this.domNode);
75
+ this.domNode.setPosition('absolute');
76
+
77
+ this._register(dom.addDisposableListener(this.domNode.domNode, dom.eventType.POINTER_DOWN, (e: PointerEvent) => this._domNodePointerDown(e)));
78
+ }
79
+
80
+ // ----------------- creation
81
+
82
+ /**
83
+ * Creates the dom node for an arrow & adds it to the container
84
+ */
85
+ protected _createArrow(opts: IScrollbarArrowOptions): ScrollbarArrow {
86
+ const arrow = this._register(new ScrollbarArrow(opts));
87
+ this.domNode.domNode.appendChild(arrow.bgDomNode);
88
+ this.domNode.domNode.appendChild(arrow.domNode);
89
+ return arrow;
90
+ }
91
+
92
+ /**
93
+ * Creates the slider dom node, adds it to the container & hooks up the events
94
+ */
95
+ protected _createSlider(top: number, left: number, width: number | undefined, height: number | undefined): void {
96
+ this.slider = new FastDomNode(document.createElement('div'));
97
+ this.slider.setClassName('xterm-slider');
98
+ this.slider.setPosition('absolute');
99
+ this.slider.setTop(top);
100
+ this.slider.setLeft(left);
101
+ if (typeof width === 'number') {
102
+ this.slider.setWidth(width);
103
+ }
104
+ if (typeof height === 'number') {
105
+ this.slider.setHeight(height);
106
+ }
107
+ this.slider.setLayerHinting(true);
108
+ this.slider.setContain('strict');
109
+
110
+ this.domNode.domNode.appendChild(this.slider.domNode);
111
+
112
+ this._register(dom.addDisposableListener(
113
+ this.slider.domNode,
114
+ dom.eventType.POINTER_DOWN,
115
+ (e: PointerEvent) => {
116
+ if (e.button === 0) {
117
+ e.preventDefault();
118
+ this._sliderPointerDown(e);
119
+ }
120
+ }
121
+ ));
122
+
123
+ this._onclick(this.slider.domNode, e => {
124
+ if (e.leftButton) {
125
+ e.stopPropagation();
126
+ }
127
+ });
128
+ }
129
+
130
+ // ----------------- Update state
131
+
132
+ protected _handleElementSize(visibleSize: number): boolean {
133
+ if (this._scrollbarState.setVisibleSize(visibleSize)) {
134
+ this._visibilityController.setIsNeeded(this._scrollbarState.isNeeded());
135
+ this._shouldRender = true;
136
+ if (!this._lazyRender) {
137
+ this.render();
138
+ }
139
+ }
140
+ return this._shouldRender;
141
+ }
142
+
143
+ protected _handleElementScrollSize(elementScrollSize: number): boolean {
144
+ if (this._scrollbarState.setScrollSize(elementScrollSize)) {
145
+ this._visibilityController.setIsNeeded(this._scrollbarState.isNeeded());
146
+ this._shouldRender = true;
147
+ if (!this._lazyRender) {
148
+ this.render();
149
+ }
150
+ }
151
+ return this._shouldRender;
152
+ }
153
+
154
+ protected _handleElementScrollPosition(elementScrollPosition: number): boolean {
155
+ if (this._scrollbarState.setScrollPosition(elementScrollPosition)) {
156
+ this._visibilityController.setIsNeeded(this._scrollbarState.isNeeded());
157
+ this._shouldRender = true;
158
+ if (!this._lazyRender) {
159
+ this.render();
160
+ }
161
+ }
162
+ return this._shouldRender;
163
+ }
164
+
165
+ // ----------------- rendering
166
+
167
+ public beginReveal(): void {
168
+ this._visibilityController.setShouldBeVisible(true);
169
+ }
170
+
171
+ public beginHide(): void {
172
+ this._visibilityController.setShouldBeVisible(false);
173
+ }
174
+
175
+ public render(): void {
176
+ if (!this._shouldRender) {
177
+ return;
178
+ }
179
+ this._shouldRender = false;
180
+
181
+ this._renderDomNode(this._scrollbarState.getRectangleLargeSize(), this._scrollbarState.getRectangleSmallSize());
182
+ this._updateSlider(this._scrollbarState.getSliderSize(), this._scrollbarState.getArrowSize() + this._scrollbarState.getSliderPosition());
183
+ }
184
+ // ----------------- DOM events
185
+
186
+ private _domNodePointerDown(e: PointerEvent): void {
187
+ if (e.target !== this.domNode.domNode) {
188
+ return;
189
+ }
190
+ this._handlePointerDown(e);
191
+ }
192
+
193
+ public delegatePointerDown(e: PointerEvent): void {
194
+ const domTop = this.domNode.domNode.getClientRects()[0].top;
195
+ const sliderStart = domTop + this._scrollbarState.getSliderPosition();
196
+ const sliderStop = domTop + this._scrollbarState.getSliderPosition() + this._scrollbarState.getSliderSize();
197
+ const pointerPos = this._sliderPointerPosition(e);
198
+ if (sliderStart <= pointerPos && pointerPos <= sliderStop) {
199
+ if (e.button === 0) {
200
+ e.preventDefault();
201
+ this._sliderPointerDown(e);
202
+ }
203
+ } else {
204
+ this._handlePointerDown(e);
205
+ }
206
+ }
207
+
208
+ private _handlePointerDown(e: PointerEvent): void {
209
+ let offsetX: number;
210
+ let offsetY: number;
211
+ if (e.target === this.domNode.domNode && typeof e.offsetX === 'number' && typeof e.offsetY === 'number') {
212
+ offsetX = e.offsetX;
213
+ offsetY = e.offsetY;
214
+ } else {
215
+ const domNodePosition = dom.getDomNodePagePosition(this.domNode.domNode);
216
+ offsetX = e.pageX - domNodePosition.left;
217
+ offsetY = e.pageY - domNodePosition.top;
218
+ }
219
+
220
+ const offset = this._pointerDownRelativePosition(offsetX, offsetY);
221
+ this._setDesiredScrollPositionNow(
222
+ this._scrollByPage
223
+ ? this._scrollbarState.getDesiredScrollPositionFromOffsetPaged(offset)
224
+ : this._scrollbarState.getDesiredScrollPositionFromOffset(offset)
225
+ );
226
+
227
+ if (e.button === 0) {
228
+ e.preventDefault();
229
+ this._sliderPointerDown(e);
230
+ }
231
+ }
232
+
233
+ private _sliderPointerDown(e: PointerEvent): void {
234
+ if (!e.target || !(e.target instanceof Element)) {
235
+ return;
236
+ }
237
+ const initialPointerPosition = this._sliderPointerPosition(e);
238
+ const initialPointerOrthogonalPosition = this._sliderOrthogonalPointerPosition(e);
239
+ const initialScrollbarState = this._scrollbarState.clone();
240
+ this.slider.toggleClassName('xterm-active', true);
241
+
242
+ this._pointerMoveMonitor.startMonitoring(
243
+ e.target,
244
+ e.pointerId,
245
+ e.buttons,
246
+ (pointerMoveData: PointerEvent) => {
247
+ const pointerOrthogonalPosition = this._sliderOrthogonalPointerPosition(pointerMoveData);
248
+ const pointerOrthogonalDelta = Math.abs(pointerOrthogonalPosition - initialPointerOrthogonalPosition);
249
+
250
+ if (platform.isWindows && pointerOrthogonalDelta > POINTER_DRAG_RESET_DISTANCE) {
251
+ this._setDesiredScrollPositionNow(initialScrollbarState.getScrollPosition());
252
+ return;
253
+ }
254
+
255
+ const pointerPosition = this._sliderPointerPosition(pointerMoveData);
256
+ const pointerDelta = pointerPosition - initialPointerPosition;
257
+ this._setDesiredScrollPositionNow(initialScrollbarState.getDesiredScrollPositionFromDelta(pointerDelta));
258
+ },
259
+ () => {
260
+ this.slider.toggleClassName('xterm-active', false);
261
+ this._host.handleDragEnd();
262
+ }
263
+ );
264
+
265
+ this._host.handleDragStart();
266
+ }
267
+
268
+ private _setDesiredScrollPositionNow(_desiredScrollPosition: number): void {
269
+
270
+ const desiredScrollPosition: INewScrollPosition = {};
271
+ this.writeScrollPosition(desiredScrollPosition, _desiredScrollPosition);
272
+
273
+ this._scrollable.setScrollPositionNow(desiredScrollPosition);
274
+ }
275
+
276
+ public updateScrollbarSize(scrollbarSize: number): void {
277
+ this._updateScrollbarSize(scrollbarSize);
278
+ this._scrollbarState.setScrollbarSize(scrollbarSize);
279
+ this._shouldRender = true;
280
+ if (!this._lazyRender) {
281
+ this.render();
282
+ }
283
+ }
284
+
285
+ public isNeeded(): boolean {
286
+ return this._scrollbarState.isNeeded();
287
+ }
288
+
289
+ // ----------------- Overwrite these
290
+
291
+ protected abstract _renderDomNode(largeSize: number, smallSize: number): void;
292
+ protected abstract _updateSlider(sliderSize: number, sliderPosition: number): void;
293
+
294
+ protected abstract _pointerDownRelativePosition(offsetX: number, offsetY: number): number;
295
+ protected abstract _sliderPointerPosition(e: ISimplifiedPointerEvent): number;
296
+ protected abstract _sliderOrthogonalPointerPosition(e: ISimplifiedPointerEvent): number;
297
+ protected abstract _updateScrollbarSize(size: number): void;
298
+
299
+ public abstract writeScrollPosition(target: INewScrollPosition, scrollPosition: number): void;
300
+ }