@xterm/xterm 6.1.0-beta.28 → 6.1.0-beta.281

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 (181) hide show
  1. package/README.md +62 -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 +56 -45
  8. package/src/browser/AccessibilityManager.ts +18 -13
  9. package/src/browser/Clipboard.ts +8 -5
  10. package/src/browser/ColorContrastCache.ts +3 -3
  11. package/src/browser/CoreBrowserTerminal.ts +179 -348
  12. package/src/browser/Dom.ts +178 -0
  13. package/src/browser/Linkifier.ts +14 -14
  14. package/src/browser/OscLinkProvider.ts +86 -18
  15. package/src/browser/RenderDebouncer.ts +7 -9
  16. package/src/browser/TimeBasedDebouncer.ts +12 -5
  17. package/src/browser/Types.ts +16 -14
  18. package/src/browser/Viewport.ts +58 -23
  19. package/src/browser/decorations/BufferDecorationRenderer.ts +3 -3
  20. package/src/browser/decorations/ColorZoneStore.ts +1 -1
  21. package/src/browser/decorations/OverviewRulerRenderer.ts +36 -20
  22. package/src/browser/input/CompositionHelper.ts +47 -11
  23. package/src/browser/input/Mouse.ts +5 -9
  24. package/src/browser/input/MoveToCell.ts +3 -3
  25. package/src/browser/public/Terminal.ts +33 -36
  26. package/src/browser/renderer/dom/DomRenderer.ts +265 -89
  27. package/src/browser/renderer/dom/DomRendererRowFactory.ts +34 -27
  28. package/src/browser/renderer/dom/WidthCache.ts +57 -55
  29. package/src/browser/renderer/shared/Constants.ts +7 -0
  30. package/src/browser/renderer/shared/RendererUtils.ts +1 -1
  31. package/src/browser/renderer/shared/SelectionRenderModel.ts +2 -2
  32. package/src/browser/renderer/shared/TextBlinkStateManager.ts +97 -0
  33. package/src/browser/renderer/shared/Types.ts +10 -4
  34. package/src/browser/scrollable/abstractScrollbar.ts +300 -0
  35. package/src/browser/scrollable/fastDomNode.ts +126 -0
  36. package/src/browser/scrollable/globalPointerMoveMonitor.ts +90 -0
  37. package/src/browser/scrollable/horizontalScrollbar.ts +85 -0
  38. package/src/browser/scrollable/mouseEvent.ts +292 -0
  39. package/src/browser/scrollable/scrollable.ts +486 -0
  40. package/src/browser/scrollable/scrollableElement.ts +581 -0
  41. package/src/browser/scrollable/scrollableElementOptions.ts +161 -0
  42. package/src/browser/scrollable/scrollbarArrow.ts +110 -0
  43. package/src/browser/scrollable/scrollbarState.ts +246 -0
  44. package/src/browser/scrollable/scrollbarVisibilityController.ts +113 -0
  45. package/src/browser/scrollable/touch.ts +485 -0
  46. package/src/browser/scrollable/verticalScrollbar.ts +143 -0
  47. package/src/browser/scrollable/widget.ts +23 -0
  48. package/src/browser/selection/SelectionModel.ts +1 -1
  49. package/src/browser/services/CharSizeService.ts +4 -4
  50. package/src/browser/services/CharacterJoinerService.ts +13 -11
  51. package/src/browser/services/CoreBrowserService.ts +7 -5
  52. package/src/browser/services/KeyboardService.ts +67 -0
  53. package/src/browser/services/LinkProviderService.ts +3 -3
  54. package/src/browser/services/MouseCoordsService.ts +47 -0
  55. package/src/browser/services/MouseService.ts +619 -23
  56. package/src/browser/services/RenderService.ts +33 -21
  57. package/src/browser/services/SelectionService.ts +72 -54
  58. package/src/browser/services/Services.ts +44 -21
  59. package/src/browser/services/ThemeService.ts +9 -9
  60. package/src/common/Async.ts +141 -0
  61. package/src/common/CircularList.ts +24 -3
  62. package/src/common/Color.ts +13 -5
  63. package/src/common/CoreTerminal.ts +61 -35
  64. package/src/common/Event.ts +118 -0
  65. package/src/common/InputHandler.ts +286 -105
  66. package/src/common/Lifecycle.ts +113 -0
  67. package/src/common/Platform.ts +15 -5
  68. package/src/common/SortedList.ts +8 -4
  69. package/src/common/StringBuilder.ts +67 -0
  70. package/src/common/TaskQueue.ts +17 -8
  71. package/src/common/Types.ts +68 -206
  72. package/src/common/Version.ts +1 -1
  73. package/src/common/WindowsMode.ts +2 -2
  74. package/src/common/buffer/AttributeData.ts +3 -2
  75. package/src/common/buffer/Buffer.ts +47 -32
  76. package/src/common/buffer/BufferLine.ts +175 -100
  77. package/src/common/buffer/BufferLineStringCache.ts +69 -0
  78. package/src/common/buffer/BufferReflow.ts +7 -4
  79. package/src/common/buffer/BufferSet.ts +13 -9
  80. package/src/common/buffer/CellData.ts +61 -4
  81. package/src/common/buffer/Constants.ts +13 -13
  82. package/src/common/buffer/Marker.ts +4 -4
  83. package/src/common/buffer/Types.ts +153 -3
  84. package/src/common/data/Charsets.ts +4 -7
  85. package/src/common/data/EscapeSequences.ts +71 -70
  86. package/src/common/input/Keyboard.ts +17 -10
  87. package/src/common/input/KittyKeyboard.ts +526 -0
  88. package/src/common/input/TextDecoder.ts +3 -3
  89. package/src/common/input/UnicodeV6.ts +3 -2
  90. package/src/common/input/Win32InputMode.ts +297 -0
  91. package/src/common/input/WriteBuffer.ts +108 -39
  92. package/src/common/input/XParseColor.ts +2 -2
  93. package/src/common/parser/ApcParser.ts +196 -0
  94. package/src/common/parser/Constants.ts +14 -4
  95. package/src/common/parser/DcsParser.ts +15 -16
  96. package/src/common/parser/EscapeSequenceParser.ts +214 -72
  97. package/src/common/parser/OscParser.ts +14 -15
  98. package/src/common/parser/Params.ts +31 -12
  99. package/src/common/parser/Types.ts +40 -30
  100. package/src/common/public/BufferApiView.ts +3 -3
  101. package/src/common/public/BufferLineApiView.ts +4 -4
  102. package/src/common/public/BufferNamespaceApi.ts +5 -5
  103. package/src/common/public/ParserApi.ts +5 -2
  104. package/src/common/public/UnicodeApi.ts +1 -1
  105. package/src/common/services/BufferService.ts +17 -13
  106. package/src/common/services/CharsetService.ts +6 -2
  107. package/src/common/services/CoreService.ts +23 -10
  108. package/src/common/services/DecorationService.ts +260 -15
  109. package/src/common/services/InstantiationService.ts +2 -2
  110. package/src/common/services/LogService.ts +2 -32
  111. package/src/common/services/{CoreMouseService.ts → MouseStateService.ts} +22 -133
  112. package/src/common/services/OptionsService.ts +17 -7
  113. package/src/common/services/OscLinkService.ts +3 -2
  114. package/src/common/services/ServiceRegistry.ts +14 -8
  115. package/src/common/services/Services.ts +54 -50
  116. package/src/common/services/UnicodeService.ts +6 -11
  117. package/typings/xterm.d.ts +329 -34
  118. package/src/common/Clone.ts +0 -23
  119. package/src/common/TypedArrayUtils.ts +0 -17
  120. package/src/vs/base/browser/browser.ts +0 -141
  121. package/src/vs/base/browser/canIUse.ts +0 -49
  122. package/src/vs/base/browser/dom.ts +0 -2369
  123. package/src/vs/base/browser/fastDomNode.ts +0 -316
  124. package/src/vs/base/browser/globalPointerMoveMonitor.ts +0 -112
  125. package/src/vs/base/browser/iframe.ts +0 -135
  126. package/src/vs/base/browser/keyboardEvent.ts +0 -213
  127. package/src/vs/base/browser/mouseEvent.ts +0 -229
  128. package/src/vs/base/browser/touch.ts +0 -372
  129. package/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts +0 -303
  130. package/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts +0 -114
  131. package/src/vs/base/browser/ui/scrollbar/scrollableElement.ts +0 -720
  132. package/src/vs/base/browser/ui/scrollbar/scrollableElementOptions.ts +0 -165
  133. package/src/vs/base/browser/ui/scrollbar/scrollbarArrow.ts +0 -114
  134. package/src/vs/base/browser/ui/scrollbar/scrollbarState.ts +0 -243
  135. package/src/vs/base/browser/ui/scrollbar/scrollbarVisibilityController.ts +0 -118
  136. package/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts +0 -116
  137. package/src/vs/base/browser/ui/widget.ts +0 -57
  138. package/src/vs/base/browser/window.ts +0 -14
  139. package/src/vs/base/common/arrays.ts +0 -887
  140. package/src/vs/base/common/arraysFind.ts +0 -202
  141. package/src/vs/base/common/assert.ts +0 -71
  142. package/src/vs/base/common/async.ts +0 -1992
  143. package/src/vs/base/common/cancellation.ts +0 -148
  144. package/src/vs/base/common/charCode.ts +0 -450
  145. package/src/vs/base/common/collections.ts +0 -140
  146. package/src/vs/base/common/decorators.ts +0 -130
  147. package/src/vs/base/common/equals.ts +0 -146
  148. package/src/vs/base/common/errors.ts +0 -303
  149. package/src/vs/base/common/event.ts +0 -1778
  150. package/src/vs/base/common/functional.ts +0 -32
  151. package/src/vs/base/common/hash.ts +0 -316
  152. package/src/vs/base/common/iterator.ts +0 -159
  153. package/src/vs/base/common/keyCodes.ts +0 -526
  154. package/src/vs/base/common/keybindings.ts +0 -284
  155. package/src/vs/base/common/lazy.ts +0 -47
  156. package/src/vs/base/common/lifecycle.ts +0 -801
  157. package/src/vs/base/common/linkedList.ts +0 -142
  158. package/src/vs/base/common/map.ts +0 -202
  159. package/src/vs/base/common/numbers.ts +0 -98
  160. package/src/vs/base/common/observable.ts +0 -76
  161. package/src/vs/base/common/observableInternal/api.ts +0 -31
  162. package/src/vs/base/common/observableInternal/autorun.ts +0 -281
  163. package/src/vs/base/common/observableInternal/base.ts +0 -489
  164. package/src/vs/base/common/observableInternal/debugName.ts +0 -145
  165. package/src/vs/base/common/observableInternal/derived.ts +0 -428
  166. package/src/vs/base/common/observableInternal/lazyObservableValue.ts +0 -146
  167. package/src/vs/base/common/observableInternal/logging.ts +0 -328
  168. package/src/vs/base/common/observableInternal/promise.ts +0 -209
  169. package/src/vs/base/common/observableInternal/utils.ts +0 -610
  170. package/src/vs/base/common/platform.ts +0 -281
  171. package/src/vs/base/common/scrollable.ts +0 -522
  172. package/src/vs/base/common/sequence.ts +0 -34
  173. package/src/vs/base/common/stopwatch.ts +0 -43
  174. package/src/vs/base/common/strings.ts +0 -557
  175. package/src/vs/base/common/symbols.ts +0 -9
  176. package/src/vs/base/common/uint.ts +0 -59
  177. package/src/vs/patches/nls.ts +0 -90
  178. package/src/vs/typings/base-common.d.ts +0 -20
  179. package/src/vs/typings/require.d.ts +0 -42
  180. package/src/vs/typings/vscode-globals-nls.d.ts +0 -36
  181. package/src/vs/typings/vscode-globals-product.d.ts +0 -33
@@ -3,13 +3,15 @@
3
3
  * @license MIT
4
4
  */
5
5
 
6
- import { css } from 'common/Color';
7
- import { Disposable, DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
8
- import { IDecorationService, IInternalDecoration } from 'common/services/Services';
9
- import { SortedList } from 'common/SortedList';
10
- import { IColor } from 'common/Types';
6
+ import type { ICircularList, IDeleteEvent, IInsertEvent } from '../CircularList';
7
+ import { MicrotaskTimer } from '../Async';
8
+ import { css } from '../Color';
9
+ import { Disposable, DisposableStore, MutableDisposable, toDisposable } from '../Lifecycle';
10
+ import { IBufferService, IDecorationService, IInternalDecoration, ILogService } from './Services';
11
+ import { SortedList } from '../SortedList';
12
+ import { IColor } from '../Types';
11
13
  import { IDecoration, IDecorationOptions, IMarker } from '@xterm/xterm';
12
- import { Emitter } from 'vs/base/common/event';
14
+ import { Emitter } from '../Event';
13
15
 
14
16
  // Work variables to avoid garbage collection
15
17
  let $xmin = 0;
@@ -23,7 +25,9 @@ export class DecorationService extends Disposable implements IDecorationService
23
25
  * while marker line values do change, they should all change by the same amount so this should
24
26
  * never become out of order.
25
27
  */
26
- private readonly _decorations: SortedList<IInternalDecoration> = new SortedList(e => e?.marker.line);
28
+ private readonly _decorations: SortedList<IInternalDecoration>;
29
+
30
+ private readonly _lineCache = this._register(new DecorationLineCache());
27
31
 
28
32
  private readonly _onDecorationRegistered = this._register(new Emitter<IInternalDecoration>());
29
33
  public readonly onDecorationRegistered = this._onDecorationRegistered.event;
@@ -32,10 +36,19 @@ export class DecorationService extends Disposable implements IDecorationService
32
36
 
33
37
  public get decorations(): IterableIterator<IInternalDecoration> { return this._decorations.values(); }
34
38
 
35
- constructor() {
39
+ constructor(
40
+ @ILogService private readonly _logService: ILogService,
41
+ @IBufferService private readonly _bufferService: IBufferService
42
+ ) {
36
43
  super();
37
44
 
45
+ this._decorations = new SortedList(e => e?.marker.line, this._logService);
46
+
38
47
  this._register(toDisposable(() => this.reset()));
48
+ this._register(this._bufferService.buffers.onBufferActivate(() => {
49
+ this._lineCache.attachToBufferLines(this._bufferService.buffer.lines);
50
+ }));
51
+ this._lineCache.attachToBufferLines(this._bufferService.buffer.lines);
39
52
  }
40
53
 
41
54
  public registerDecoration(options: IDecorationOptions): IDecoration | undefined {
@@ -49,12 +62,14 @@ export class DecorationService extends Disposable implements IDecorationService
49
62
  listener.dispose();
50
63
  if (decoration) {
51
64
  if (this._decorations.delete(decoration)) {
65
+ this._lineCache.remove(decoration);
52
66
  this._onDecorationRemoved.fire(decoration);
53
67
  }
54
68
  markerDispose.dispose();
55
69
  }
56
70
  });
57
71
  this._decorations.insert(decoration);
72
+ this._lineCache.add(decoration);
58
73
  this._onDecorationRegistered.fire(decoration);
59
74
  }
60
75
  return decoration;
@@ -65,35 +80,264 @@ export class DecorationService extends Disposable implements IDecorationService
65
80
  d.dispose();
66
81
  }
67
82
  this._decorations.clear();
83
+ this._lineCache.clear();
68
84
  }
69
85
 
70
86
  public *getDecorationsAtCell(x: number, line: number, layer?: 'bottom' | 'top'): IterableIterator<IInternalDecoration> {
71
- let xmin = 0;
72
- let xmax = 0;
73
- for (const d of this._decorations.getKeyIterator(line)) {
74
- xmin = d.options.x ?? 0;
75
- xmax = xmin + (d.options.width ?? 1);
76
- if (x >= xmin && x < xmax && (!layer || (d.options.layer ?? 'bottom') === layer)) {
87
+ const bucket = this._lineCache.getDecorationsOnLine(line);
88
+ if (!bucket) {
89
+ return;
90
+ }
91
+ for (const d of bucket) {
92
+ $xmin = d.options.x ?? 0;
93
+ $xmax = $xmin + (d.options.width ?? 1);
94
+ if (x >= $xmin && x < $xmax && (!layer || (d.options.layer ?? 'bottom') === layer)) {
77
95
  yield d;
78
96
  }
79
97
  }
80
98
  }
81
99
 
82
100
  public forEachDecorationAtCell(x: number, line: number, layer: 'bottom' | 'top' | undefined, callback: (decoration: IInternalDecoration) => void): void {
83
- this._decorations.forEachByKey(line, d => {
101
+ const bucket = this._lineCache.getDecorationsOnLine(line);
102
+ if (!bucket) {
103
+ return;
104
+ }
105
+ for (const d of bucket) {
84
106
  $xmin = d.options.x ?? 0;
85
107
  $xmax = $xmin + (d.options.width ?? 1);
86
108
  if (x >= $xmin && x < $xmax && (!layer || (d.options.layer ?? 'bottom') === layer)) {
87
109
  callback(d);
88
110
  }
111
+ }
112
+ }
113
+ }
114
+
115
+ /**
116
+ * Per-logical-line index of decorations for fast cell lookup.
117
+ *
118
+ * Keys are marker.line coordinates (logical buffer lines), not CircularList ring slots.
119
+ * Multi-line decorations appear in every line bucket they span. The index is kept aligned
120
+ * with marker.line updates via buffer line trim/insert/delete events.
121
+ */
122
+ export class DecorationLineCache extends Disposable {
123
+ private readonly _decorationsByLine: Map<number, IInternalDecoration[]> = new Map();
124
+ private readonly _decorations = new Set<IInternalDecoration>();
125
+ private readonly _bufferLineListeners = this._register(new MutableDisposable<DisposableStore>());
126
+ private readonly _lineIndexSyncTimer = this._register(new MicrotaskTimer());
127
+ private _lineIndexSyncCallbacks: (() => void)[] = [];
128
+
129
+ public clear(): void {
130
+ this._lineIndexSyncCallbacks.length = 0;
131
+ this._lineIndexSyncTimer.cancel();
132
+ this._decorationsByLine.clear();
133
+ this._decorations.clear();
134
+ }
135
+
136
+ public add(decoration: IInternalDecoration): void {
137
+ this._decorations.add(decoration);
138
+ this._addToLineBuckets(decoration);
139
+ }
140
+
141
+ public remove(decoration: IInternalDecoration): void {
142
+ this._decorations.delete(decoration);
143
+ this._removeFromLineBuckets(decoration);
144
+ }
145
+
146
+ public getDecorationsOnLine(line: number): ReadonlyArray<IInternalDecoration> | undefined {
147
+ return this._decorationsByLine.get(line);
148
+ }
149
+
150
+ public attachToBufferLines(lines: ICircularList<unknown>): void {
151
+ const store = new DisposableStore();
152
+ this._bufferLineListeners.value = store;
153
+ store.add(lines.onTrim(amount => this._handleBufferLinesTrim(amount)));
154
+ store.add(lines.onInsert(event => this._handleBufferLinesInsert(event)));
155
+ store.add(lines.onDelete(event => this._handleBufferLinesDelete(event)));
156
+ }
157
+
158
+ private _getDecorationHeight(decoration: IInternalDecoration): number {
159
+ return decoration.options.height ?? 1;
160
+ }
161
+
162
+ private _addToLineBuckets(decoration: IInternalDecoration): void {
163
+ const start = decoration.marker.line;
164
+ if (start < 0) {
165
+ return;
166
+ }
167
+ decoration._indexedStartLine = start;
168
+ const height = this._getDecorationHeight(decoration);
169
+ for (let line = start; line < start + height; line++) {
170
+ let bucket = this._decorationsByLine.get(line);
171
+ if (!bucket) {
172
+ bucket = [];
173
+ this._decorationsByLine.set(line, bucket);
174
+ }
175
+ bucket.push(decoration);
176
+ }
177
+ }
178
+
179
+ private _removeFromLineBuckets(decoration: IInternalDecoration): void {
180
+ const start = decoration._indexedStartLine;
181
+ const height = this._getDecorationHeight(decoration);
182
+ for (let line = start; line < start + height; line++) {
183
+ const bucket = this._decorationsByLine.get(line);
184
+ if (!bucket) {
185
+ continue;
186
+ }
187
+ const index = bucket.indexOf(decoration);
188
+ if (index !== -1) {
189
+ bucket.splice(index, 1);
190
+ }
191
+ if (bucket.length === 0) {
192
+ this._decorationsByLine.delete(line);
193
+ }
194
+ }
195
+ }
196
+
197
+ private _reindexDecoration(decoration: IInternalDecoration): void {
198
+ this._removeFromLineBuckets(decoration);
199
+ if (!decoration.marker.isDisposed && decoration.marker.line >= 0) {
200
+ this._addToLineBuckets(decoration);
201
+ }
202
+ }
203
+
204
+ /** Re-index after marker line updates (buffer listeners may run before markers). */
205
+ private _scheduleLineIndexSync(callback: () => void): void {
206
+ this._lineIndexSyncCallbacks.push(callback);
207
+ this._lineIndexSyncTimer.set(() => {
208
+ const callbacks = this._lineIndexSyncCallbacks;
209
+ this._lineIndexSyncCallbacks = [];
210
+ for (const cb of callbacks) {
211
+ cb();
212
+ }
89
213
  });
90
214
  }
215
+
216
+ private _handleBufferLinesTrim(amount: number): void {
217
+ if (amount <= 0) {
218
+ return;
219
+ }
220
+ const newMap = new Map<number, IInternalDecoration[]>();
221
+ for (const [line, bucket] of this._decorationsByLine) {
222
+ const newLine = line - amount;
223
+ if (newLine < 0) {
224
+ continue;
225
+ }
226
+ this._mergeLineBucket(newMap, newLine, bucket);
227
+ }
228
+ this._decorationsByLine.clear();
229
+ for (const [line, bucket] of newMap) {
230
+ this._decorationsByLine.set(line, bucket);
231
+ }
232
+ for (const d of this._decorations) {
233
+ if (!d.marker.isDisposed) {
234
+ d._indexedStartLine -= amount;
235
+ }
236
+ }
237
+ }
238
+
239
+ private _handleBufferLinesInsert(event: IInsertEvent): void {
240
+ this._scheduleLineIndexSync(() => this._applyBufferLinesInsert(event));
241
+ }
242
+
243
+ private _handleBufferLinesDelete(event: IDeleteEvent): void {
244
+ this._scheduleLineIndexSync(() => this._applyBufferLinesDelete(event));
245
+ }
246
+
247
+ private _mergeLineBucket(newMap: Map<number, IInternalDecoration[]>, line: number, bucket: IInternalDecoration[]): void {
248
+ const existing = newMap.get(line);
249
+ if (existing) {
250
+ for (let i = 0, len = bucket.length; i < len; i++) {
251
+ existing.push(bucket[i]);
252
+ }
253
+ } else {
254
+ newMap.set(line, bucket.slice());
255
+ }
256
+ }
257
+
258
+ /**
259
+ * Shift indexed line keys and sync start lines. O(unique indexed lines), not O(decoration count).
260
+ * Decorations that span the insert point are re-indexed individually (rare vs single-line hits).
261
+ */
262
+ private _applyBufferLinesInsert(event: IInsertEvent): void {
263
+ const { index, amount } = event;
264
+ const spanCrossers: IInternalDecoration[] = [];
265
+ for (const d of this._decorations) {
266
+ if (d.marker.isDisposed) {
267
+ continue;
268
+ }
269
+ const start = d._indexedStartLine;
270
+ if (start < index && start + this._getDecorationHeight(d) > index) {
271
+ spanCrossers.push(d);
272
+ this._removeFromLineBuckets(d);
273
+ }
274
+ }
275
+ const newMap = new Map<number, IInternalDecoration[]>();
276
+ for (const [line, bucket] of this._decorationsByLine) {
277
+ const newLine = line >= index ? line + amount : line;
278
+ this._mergeLineBucket(newMap, newLine, bucket);
279
+ }
280
+ this._decorationsByLine.clear();
281
+ for (const [line, bucket] of newMap) {
282
+ this._decorationsByLine.set(line, bucket);
283
+ }
284
+ for (const d of this._decorations) {
285
+ if (d.marker.isDisposed) {
286
+ continue;
287
+ }
288
+ if (d._indexedStartLine >= index) {
289
+ d._indexedStartLine = d.marker.line;
290
+ }
291
+ }
292
+ for (const d of spanCrossers) {
293
+ this._addToLineBuckets(d);
294
+ }
295
+ }
296
+
297
+ /**
298
+ * Drop deleted line keys, shift keys below, sync start lines. Full re-index only when a
299
+ * multi-line decoration spans across the deleted range but survives.
300
+ */
301
+ private _applyBufferLinesDelete(event: IDeleteEvent): void {
302
+ const deleteEnd = event.index + event.amount;
303
+ const newMap = new Map<number, IInternalDecoration[]>();
304
+ for (const [line, bucket] of this._decorationsByLine) {
305
+ if (line >= event.index && line < deleteEnd) {
306
+ continue;
307
+ }
308
+ const newLine = line >= deleteEnd ? line - event.amount : line;
309
+ this._mergeLineBucket(newMap, newLine, bucket);
310
+ }
311
+ this._decorationsByLine.clear();
312
+ for (const [line, bucket] of newMap) {
313
+ this._decorationsByLine.set(line, bucket);
314
+ }
315
+ const toReindex: IInternalDecoration[] = [];
316
+ for (const d of this._decorations) {
317
+ if (d.marker.isDisposed) {
318
+ continue;
319
+ }
320
+ const start = d._indexedStartLine;
321
+ const height = this._getDecorationHeight(d);
322
+ if (start >= deleteEnd) {
323
+ d._indexedStartLine = d.marker.line;
324
+ } else if (start < event.index && start + height > deleteEnd) {
325
+ toReindex.push(d);
326
+ }
327
+ }
328
+ for (const d of toReindex) {
329
+ this._reindexDecoration(d);
330
+ }
331
+ }
91
332
  }
92
333
 
93
334
  class Decoration extends DisposableStore implements IInternalDecoration {
94
335
  public readonly marker: IMarker;
95
336
  public element: HTMLElement | undefined;
96
337
 
338
+ /** Start line used for line-index removal when marker.line is cleared on dispose. */
339
+ public _indexedStartLine: number;
340
+
97
341
  public readonly onRenderEmitter = this.add(new Emitter<HTMLElement>());
98
342
  public readonly onRender = this.onRenderEmitter.event;
99
343
  private readonly _onDispose = this.add(new Emitter<void>());
@@ -128,6 +372,7 @@ class Decoration extends DisposableStore implements IInternalDecoration {
128
372
  ) {
129
373
  super();
130
374
  this.marker = options.marker;
375
+ this._indexedStartLine = options.marker.line;
131
376
  if (this.options.overviewRulerOptions && !this.options.overviewRulerOptions.position) {
132
377
  this.options.overviewRulerOptions.position = 'full';
133
378
  }
@@ -9,8 +9,8 @@
9
9
  * Licensed under the MIT License. See License.txt in the project root for license information.
10
10
  *--------------------------------------------------------------------------------------------*/
11
11
 
12
- import { IInstantiationService, IServiceIdentifier } from 'common/services/Services';
13
- import { getServiceDependencies } from 'common/services/ServiceRegistry';
12
+ import { IInstantiationService } from './Services';
13
+ import { IServiceIdentifier, getServiceDependencies } from './ServiceRegistry';
14
14
 
15
15
  export class ServiceCollection {
16
16
 
@@ -3,8 +3,8 @@
3
3
  * @license MIT
4
4
  */
5
5
 
6
- import { Disposable } from 'vs/base/common/lifecycle';
7
- import { ILogService, IOptionsService, LogLevelEnum } from 'common/services/Services';
6
+ import { Disposable } from '../Lifecycle';
7
+ import { ILogService, IOptionsService, LogLevelEnum } from './Services';
8
8
 
9
9
  type LogType = (message?: any, ...optionalParams: any[]) => void;
10
10
 
@@ -43,9 +43,6 @@ export class LogService extends Disposable implements ILogService {
43
43
  super();
44
44
  this._updateLogLevel();
45
45
  this._register(this._optionsService.onSpecificOptionChange('logLevel', () => this._updateLogLevel()));
46
-
47
- // For trace logging, assume the latest created log service is valid
48
- traceLogger = this;
49
46
  }
50
47
 
51
48
  private _updateLogLevel(): void {
@@ -95,30 +92,3 @@ export class LogService extends Disposable implements ILogService {
95
92
  }
96
93
  }
97
94
  }
98
-
99
- let traceLogger: ILogService;
100
- export function setTraceLogger(logger: ILogService): void {
101
- traceLogger = logger;
102
- }
103
-
104
- /**
105
- * A decorator that can be used to automatically log trace calls to the decorated function.
106
- */
107
- export function traceCall(_target: any, key: string, descriptor: any): any {
108
- if (typeof descriptor.value !== 'function') {
109
- throw new Error('not supported');
110
- }
111
- const fnKey = 'value';
112
- const fn = descriptor.value;
113
- descriptor[fnKey] = function (...args: any[]) {
114
- // Early exit
115
- if (traceLogger.logLevel !== LogLevelEnum.TRACE) {
116
- return fn.apply(this, args);
117
- }
118
-
119
- traceLogger.trace(`GlyphRenderer#${fn.name}(${args.map(e => JSON.stringify(e)).join(', ')})`);
120
- const result = fn.apply(this, args);
121
- traceLogger.trace(`GlyphRenderer#${fn.name} return`, result);
122
- return result;
123
- };
124
- }
@@ -2,10 +2,10 @@
2
2
  * Copyright (c) 2019 The xterm.js authors. All rights reserved.
3
3
  * @license MIT
4
4
  */
5
- import { IBufferService, ICoreService, ICoreMouseService, IOptionsService } from 'common/services/Services';
6
- import { ICoreMouseProtocol, ICoreMouseEvent, CoreMouseEncoding, CoreMouseEventType, CoreMouseButton, CoreMouseAction } from 'common/Types';
7
- import { Disposable } from 'vs/base/common/lifecycle';
8
- import { Emitter } from 'vs/base/common/event';
5
+ import { IMouseStateService } from './Services';
6
+ import { ICoreMouseProtocol, ICoreMouseEvent, CoreMouseEncoding, CoreMouseEventType, CoreMouseButton, CoreMouseAction } from '../Types';
7
+ import { Disposable } from '../Lifecycle';
8
+ import { Emitter } from '../Event';
9
9
 
10
10
  /**
11
11
  * Supported default protocols.
@@ -151,7 +151,7 @@ const DEFAULT_ENCODINGS: { [key: string]: CoreMouseEncoding } = {
151
151
  };
152
152
 
153
153
  /**
154
- * CoreMouseService
154
+ * MouseStateService
155
155
  *
156
156
  * Provides mouse tracking reports with different protocols and encodings.
157
157
  * - protocols: NONE (default), X10, VT200, DRAG, ANY
@@ -166,25 +166,21 @@ const DEFAULT_ENCODINGS: { [key: string]: CoreMouseEncoding } = {
166
166
  * a tracking report to the backend based on protocol and encoding limitations.
167
167
  * To send a mouse event call `triggerMouseEvent`.
168
168
  */
169
- export class CoreMouseService extends Disposable implements ICoreMouseService {
169
+ export class MouseStateService extends Disposable implements IMouseStateService {
170
170
  public serviceBrand: any;
171
171
 
172
172
  private _protocols: { [name: string]: ICoreMouseProtocol } = {};
173
173
  private _encodings: { [name: string]: CoreMouseEncoding } = {};
174
174
  private _activeProtocol: string = '';
175
175
  private _activeEncoding: string = '';
176
- private _lastEvent: ICoreMouseEvent | null = null;
177
- private _wheelPartialScroll: number = 0;
176
+ private _customWheelEventHandler: ((event: WheelEvent) => boolean) | undefined;
178
177
 
179
178
  private readonly _onProtocolChange = this._register(new Emitter<CoreMouseEventType>());
180
179
  public readonly onProtocolChange = this._onProtocolChange.event;
181
180
 
182
- constructor(
183
- @IBufferService private readonly _bufferService: IBufferService,
184
- @ICoreService private readonly _coreService: ICoreService,
185
- @IOptionsService private readonly _optionsService: IOptionsService
186
- ) {
181
+ constructor() {
187
182
  super();
183
+
188
184
  // register default protocols and encodings
189
185
  for (const name of Object.keys(DEFAULT_PROTOCOLS)) this.addProtocol(name, DEFAULT_PROTOCOLS[name]);
190
186
  for (const name of Object.keys(DEFAULT_ENCODINGS)) this.addEncoding(name, DEFAULT_ENCODINGS[name]);
@@ -230,136 +226,29 @@ export class CoreMouseService extends Disposable implements ICoreMouseService {
230
226
  public reset(): void {
231
227
  this.activeProtocol = 'NONE';
232
228
  this.activeEncoding = 'DEFAULT';
233
- this._lastEvent = null;
234
- this._wheelPartialScroll = 0;
235
229
  }
236
230
 
237
- /**
238
- * Processes a wheel event, accounting for partial scrolls for trackpad, mouse scrolls.
239
- * This prevents hyper-sensitive scrolling in alt buffer.
240
- */
241
- public consumeWheelEvent(ev: WheelEvent, cellHeight?: number, dpr?: number): number {
242
- // Do nothing if it's not a vertical scroll event
243
- if (ev.deltaY === 0 || ev.shiftKey) {
244
- return 0;
245
- }
246
-
247
- if (cellHeight === undefined || dpr === undefined) {
248
- return 0;
249
- }
250
-
251
- const targetWheelEventPixels = cellHeight / dpr;
252
- let amount = this._applyScrollModifier(ev.deltaY, ev);
253
-
254
- if (ev.deltaMode === WheelEvent.DOM_DELTA_PIXEL) {
255
- amount /= (targetWheelEventPixels + 0.0); // Prevent integer division
256
-
257
- const isLikelyTrackpad = Math.abs(ev.deltaY) < 50;
258
- if (isLikelyTrackpad) {
259
- amount *= 0.3;
260
- }
261
-
262
- this._wheelPartialScroll += amount;
263
- amount = Math.floor(Math.abs(this._wheelPartialScroll)) * (this._wheelPartialScroll > 0 ? 1 : -1);
264
- this._wheelPartialScroll %= 1;
265
- } else if (ev.deltaMode === WheelEvent.DOM_DELTA_PAGE) {
266
- amount *= this._bufferService.rows;
267
- }
268
- return amount;
231
+ public setCustomWheelEventHandler(customWheelEventHandler: ((event: WheelEvent) => boolean) | undefined): void {
232
+ this._customWheelEventHandler = customWheelEventHandler;
269
233
  }
270
234
 
271
- private _applyScrollModifier(amount: number, ev: WheelEvent): number {
272
- // Multiply the scroll speed when the modifier key is pressed
273
- if (ev.altKey || ev.ctrlKey || ev.shiftKey) {
274
- return amount * this._optionsService.rawOptions.fastScrollSensitivity * this._optionsService.rawOptions.scrollSensitivity;
275
- }
276
- return amount * this._optionsService.rawOptions.scrollSensitivity;
235
+ public allowCustomWheelEvent(ev: WheelEvent): boolean {
236
+ return this._customWheelEventHandler ? this._customWheelEventHandler(ev) !== false : true;
277
237
  }
278
238
 
279
- /**
280
- * Triggers a mouse event to be sent.
281
- *
282
- * Returns true if the event passed all protocol restrictions and a report
283
- * was sent, otherwise false. The return value may be used to decide whether
284
- * the default event action in the bowser component should be omitted.
285
- *
286
- * Note: The method will change values of the given event object
287
- * to fullfill protocol and encoding restrictions.
288
- */
289
- public triggerMouseEvent(e: ICoreMouseEvent): boolean {
290
- // range check for col/row
291
- if (e.col < 0 || e.col >= this._bufferService.cols
292
- || e.row < 0 || e.row >= this._bufferService.rows) {
293
- return false;
294
- }
295
-
296
- // filter nonsense combinations of button + action
297
- if (e.button === CoreMouseButton.WHEEL && e.action === CoreMouseAction.MOVE) {
298
- return false;
299
- }
300
- if (e.button === CoreMouseButton.NONE && e.action !== CoreMouseAction.MOVE) {
301
- return false;
302
- }
303
- if (e.button !== CoreMouseButton.WHEEL && (e.action === CoreMouseAction.LEFT || e.action === CoreMouseAction.RIGHT)) {
304
- return false;
305
- }
306
-
307
- // report 1-based coords
308
- e.col++;
309
- e.row++;
310
-
311
- // debounce move events at grid or pixel level
312
- if (e.action === CoreMouseAction.MOVE
313
- && this._lastEvent
314
- && this._equalEvents(this._lastEvent, e, this._activeEncoding === 'SGR_PIXELS')
315
- ) {
316
- return false;
317
- }
318
-
319
- // apply protocol restrictions
320
- if (!this._protocols[this._activeProtocol].restrict(e)) {
321
- return false;
322
- }
323
-
324
- // encode report and send
325
- const report = this._encodings[this._activeEncoding](e);
326
- if (report) {
327
- // always send DEFAULT as binary data
328
- if (this._activeEncoding === 'DEFAULT') {
329
- this._coreService.triggerBinaryEvent(report);
330
- } else {
331
- this._coreService.triggerDataEvent(report, true);
332
- }
333
- }
334
-
335
- this._lastEvent = e;
239
+ public restrictMouseEvent(e: ICoreMouseEvent): boolean {
240
+ return this._protocols[this._activeProtocol].restrict(e);
241
+ }
336
242
 
337
- return true;
243
+ public encodeMouseEvent(e: ICoreMouseEvent): string {
244
+ return this._encodings[this._activeEncoding](e);
338
245
  }
339
246
 
340
- public explainEvents(events: CoreMouseEventType): { [event: string]: boolean } {
341
- return {
342
- down: !!(events & CoreMouseEventType.DOWN),
343
- up: !!(events & CoreMouseEventType.UP),
344
- drag: !!(events & CoreMouseEventType.DRAG),
345
- move: !!(events & CoreMouseEventType.MOVE),
346
- wheel: !!(events & CoreMouseEventType.WHEEL)
347
- };
247
+ public get isDefaultEncoding(): boolean {
248
+ return this._activeEncoding === 'DEFAULT';
348
249
  }
349
250
 
350
- private _equalEvents(e1: ICoreMouseEvent, e2: ICoreMouseEvent, pixels: boolean): boolean {
351
- if (pixels) {
352
- if (e1.x !== e2.x) return false;
353
- if (e1.y !== e2.y) return false;
354
- } else {
355
- if (e1.col !== e2.col) return false;
356
- if (e1.row !== e2.row) return false;
357
- }
358
- if (e1.button !== e2.button) return false;
359
- if (e1.action !== e2.action) return false;
360
- if (e1.ctrl !== e2.ctrl) return false;
361
- if (e1.alt !== e2.alt) return false;
362
- if (e1.shift !== e2.shift) return false;
363
- return true;
251
+ public get isPixelEncoding(): boolean {
252
+ return this._activeEncoding === 'SGR_PIXELS';
364
253
  }
365
254
  }
@@ -3,16 +3,18 @@
3
3
  * @license MIT
4
4
  */
5
5
 
6
- import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
7
- import { isMac } from 'common/Platform';
8
- import { CursorStyle, IDisposable } from 'common/Types';
9
- import { FontWeight, IOptionsService, ITerminalOptions } from 'common/services/Services';
10
- import { Emitter } from 'vs/base/common/event';
6
+ import { Disposable, toDisposable } from '../Lifecycle';
7
+ import { isMac } from '../Platform';
8
+ import { CursorStyle, IDisposable } from '../Types';
9
+ import { FontWeight, IOptionsService, ITerminalOptions } from './Services';
10
+ import { Emitter } from '../Event';
11
11
 
12
12
  export const DEFAULT_OPTIONS: Readonly<Required<ITerminalOptions>> = {
13
13
  cols: 80,
14
14
  rows: 24,
15
+ showCursorImmediately: false,
15
16
  cursorBlink: false,
17
+ blinkIntervalDuration: 0,
16
18
  cursorStyle: 'block',
17
19
  cursorWidth: 1,
18
20
  cursorInactiveStyle: 'outline',
@@ -30,6 +32,7 @@ export const DEFAULT_OPTIONS: Readonly<Required<ITerminalOptions>> = {
30
32
  logLevel: 'info',
31
33
  logger: null,
32
34
  scrollback: 1000,
35
+ scrollbar: { showScrollbar: true },
33
36
  scrollOnEraseInDisplay: false,
34
37
  scrollOnUserInput: true,
35
38
  scrollSensitivity: 1,
@@ -38,6 +41,7 @@ export const DEFAULT_OPTIONS: Readonly<Required<ITerminalOptions>> = {
38
41
  macOptionIsMeta: false,
39
42
  macOptionClickForcesSelection: false,
40
43
  minimumContrastRatio: 1,
44
+ mouseEventsRequireAlt: false,
41
45
  disableStdin: false,
42
46
  allowProposedApi: false,
43
47
  allowTransparency: false,
@@ -52,8 +56,8 @@ export const DEFAULT_OPTIONS: Readonly<Required<ITerminalOptions>> = {
52
56
  altClickMovesCursor: true,
53
57
  convertEol: false,
54
58
  termName: 'xterm',
55
- cancelEvents: false,
56
- overviewRuler: {}
59
+ quirks: {},
60
+ vtExtensions: {}
57
61
  };
58
62
 
59
63
  const FONT_WEIGHT_OPTIONS: Extract<FontWeight, string>[] = ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'];
@@ -166,6 +170,12 @@ export class OptionsService extends Disposable implements IOptionsService {
166
170
  }
167
171
  value = FONT_WEIGHT_OPTIONS.includes(value) ? value : DEFAULT_OPTIONS[key];
168
172
  break;
173
+ case 'blinkIntervalDuration':
174
+ value = Math.floor(value);
175
+ if (value < 0) {
176
+ throw new Error(`${key} cannot be less than 0, value: ${value}`);
177
+ }
178
+ break;
169
179
  case 'cursorWidth':
170
180
  value = Math.floor(value);
171
181
  // Fall through for bounds check
@@ -2,8 +2,9 @@
2
2
  * Copyright (c) 2022 The xterm.js authors. All rights reserved.
3
3
  * @license MIT
4
4
  */
5
- import { IBufferService, IOscLinkService } from 'common/services/Services';
6
- import { IMarker, IOscLinkData } from 'common/Types';
5
+ import { IBufferService, IOscLinkService } from './Services';
6
+ import { IOscLinkData } from '../Types';
7
+ import { IMarker } from '../buffer/Types';
7
8
 
8
9
  export class OscLinkService implements IOscLinkService {
9
10
  public serviceBrand: any;