@xterm/xterm 6.1.0-beta.17 → 6.1.0-beta.170

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 (156) hide show
  1. package/README.md +27 -28
  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 +26 -15
  8. package/src/browser/AccessibilityManager.ts +6 -3
  9. package/src/browser/Clipboard.ts +6 -3
  10. package/src/browser/CoreBrowserTerminal.ts +142 -62
  11. package/src/browser/Dom.ts +178 -0
  12. package/src/browser/Linkifier.ts +3 -3
  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 +40 -17
  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 +10 -1
  21. package/src/browser/public/Terminal.ts +24 -27
  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 +481 -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/MouseService.ts +2 -1
  47. package/src/browser/services/RenderService.ts +22 -15
  48. package/src/browser/services/SelectionService.ts +12 -4
  49. package/src/browser/services/Services.ts +24 -15
  50. package/src/browser/services/ThemeService.ts +2 -2
  51. package/src/common/Async.ts +105 -0
  52. package/src/common/CircularList.ts +2 -2
  53. package/src/common/Color.ts +8 -0
  54. package/src/common/CoreTerminal.ts +21 -11
  55. package/src/common/Event.ts +118 -0
  56. package/src/common/InputHandler.ts +244 -24
  57. package/src/common/Lifecycle.ts +113 -0
  58. package/src/common/Platform.ts +13 -3
  59. package/src/common/SortedList.ts +7 -3
  60. package/src/common/TaskQueue.ts +9 -3
  61. package/src/common/Types.ts +27 -7
  62. package/src/common/Version.ts +9 -0
  63. package/src/common/buffer/Buffer.ts +20 -14
  64. package/src/common/buffer/BufferLine.ts +4 -5
  65. package/src/common/buffer/BufferSet.ts +7 -6
  66. package/src/common/buffer/CellData.ts +57 -0
  67. package/src/common/buffer/Marker.ts +2 -2
  68. package/src/common/buffer/Types.ts +6 -2
  69. package/src/common/data/EscapeSequences.ts +71 -70
  70. package/src/common/input/Keyboard.ts +7 -6
  71. package/src/common/input/KittyKeyboard.ts +491 -0
  72. package/src/common/input/Win32InputMode.ts +297 -0
  73. package/src/common/input/WriteBuffer.ts +34 -2
  74. package/src/common/input/XParseColor.ts +2 -2
  75. package/src/common/parser/ApcParser.ts +245 -0
  76. package/src/common/parser/Constants.ts +22 -4
  77. package/src/common/parser/DcsParser.ts +5 -5
  78. package/src/common/parser/EscapeSequenceParser.ts +75 -22
  79. package/src/common/parser/OscParser.ts +5 -5
  80. package/src/common/parser/Types.ts +34 -1
  81. package/src/common/public/BufferLineApiView.ts +2 -2
  82. package/src/common/public/BufferNamespaceApi.ts +2 -2
  83. package/src/common/public/ParserApi.ts +3 -0
  84. package/src/common/services/BufferService.ts +8 -5
  85. package/src/common/services/CharsetService.ts +4 -0
  86. package/src/common/services/CoreMouseService.ts +2 -2
  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/OptionsService.ts +13 -4
  91. package/src/common/services/Services.ts +39 -16
  92. package/src/common/services/UnicodeService.ts +1 -1
  93. package/typings/xterm.d.ts +319 -35
  94. package/src/common/TypedArrayUtils.ts +0 -17
  95. package/src/vs/base/browser/browser.ts +0 -141
  96. package/src/vs/base/browser/canIUse.ts +0 -49
  97. package/src/vs/base/browser/dom.ts +0 -2369
  98. package/src/vs/base/browser/fastDomNode.ts +0 -316
  99. package/src/vs/base/browser/globalPointerMoveMonitor.ts +0 -112
  100. package/src/vs/base/browser/iframe.ts +0 -135
  101. package/src/vs/base/browser/keyboardEvent.ts +0 -213
  102. package/src/vs/base/browser/mouseEvent.ts +0 -229
  103. package/src/vs/base/browser/touch.ts +0 -372
  104. package/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts +0 -303
  105. package/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts +0 -114
  106. package/src/vs/base/browser/ui/scrollbar/scrollableElement.ts +0 -720
  107. package/src/vs/base/browser/ui/scrollbar/scrollableElementOptions.ts +0 -165
  108. package/src/vs/base/browser/ui/scrollbar/scrollbarArrow.ts +0 -114
  109. package/src/vs/base/browser/ui/scrollbar/scrollbarState.ts +0 -243
  110. package/src/vs/base/browser/ui/scrollbar/scrollbarVisibilityController.ts +0 -118
  111. package/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts +0 -116
  112. package/src/vs/base/browser/ui/widget.ts +0 -57
  113. package/src/vs/base/browser/window.ts +0 -14
  114. package/src/vs/base/common/arrays.ts +0 -887
  115. package/src/vs/base/common/arraysFind.ts +0 -202
  116. package/src/vs/base/common/assert.ts +0 -71
  117. package/src/vs/base/common/async.ts +0 -1992
  118. package/src/vs/base/common/cancellation.ts +0 -148
  119. package/src/vs/base/common/charCode.ts +0 -450
  120. package/src/vs/base/common/collections.ts +0 -140
  121. package/src/vs/base/common/decorators.ts +0 -130
  122. package/src/vs/base/common/equals.ts +0 -146
  123. package/src/vs/base/common/errors.ts +0 -303
  124. package/src/vs/base/common/event.ts +0 -1778
  125. package/src/vs/base/common/functional.ts +0 -32
  126. package/src/vs/base/common/hash.ts +0 -316
  127. package/src/vs/base/common/iterator.ts +0 -159
  128. package/src/vs/base/common/keyCodes.ts +0 -526
  129. package/src/vs/base/common/keybindings.ts +0 -284
  130. package/src/vs/base/common/lazy.ts +0 -47
  131. package/src/vs/base/common/lifecycle.ts +0 -801
  132. package/src/vs/base/common/linkedList.ts +0 -142
  133. package/src/vs/base/common/map.ts +0 -202
  134. package/src/vs/base/common/numbers.ts +0 -98
  135. package/src/vs/base/common/observable.ts +0 -76
  136. package/src/vs/base/common/observableInternal/api.ts +0 -31
  137. package/src/vs/base/common/observableInternal/autorun.ts +0 -281
  138. package/src/vs/base/common/observableInternal/base.ts +0 -489
  139. package/src/vs/base/common/observableInternal/debugName.ts +0 -145
  140. package/src/vs/base/common/observableInternal/derived.ts +0 -428
  141. package/src/vs/base/common/observableInternal/lazyObservableValue.ts +0 -146
  142. package/src/vs/base/common/observableInternal/logging.ts +0 -328
  143. package/src/vs/base/common/observableInternal/promise.ts +0 -209
  144. package/src/vs/base/common/observableInternal/utils.ts +0 -610
  145. package/src/vs/base/common/platform.ts +0 -281
  146. package/src/vs/base/common/scrollable.ts +0 -522
  147. package/src/vs/base/common/sequence.ts +0 -34
  148. package/src/vs/base/common/stopwatch.ts +0 -43
  149. package/src/vs/base/common/strings.ts +0 -557
  150. package/src/vs/base/common/symbols.ts +0 -9
  151. package/src/vs/base/common/uint.ts +0 -59
  152. package/src/vs/patches/nls.ts +0 -90
  153. package/src/vs/typings/base-common.d.ts +0 -20
  154. package/src/vs/typings/require.d.ts +0 -42
  155. package/src/vs/typings/vscode-globals-nls.d.ts +0 -36
  156. package/src/vs/typings/vscode-globals-product.d.ts +0 -33
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Copyright (c) 2025 The xterm.js authors. All rights reserved.
3
+ * @license MIT
4
+ */
5
+
6
+ import { IKeyboardService } from 'browser/services/Services';
7
+ import { evaluateKeyboardEvent } from 'common/input/Keyboard';
8
+ import { KittyKeyboard, KittyKeyboardEventType, KittyKeyboardFlags } from 'common/input/KittyKeyboard';
9
+ import { Win32InputMode } from 'common/input/Win32InputMode';
10
+ import { isMac } from 'common/Platform';
11
+ import { ICoreService, IOptionsService } from 'common/services/Services';
12
+ import { IKeyboardResult } from 'common/Types';
13
+
14
+ export class KeyboardService implements IKeyboardService {
15
+ public serviceBrand: undefined;
16
+
17
+ private _win32InputMode: Win32InputMode | undefined;
18
+ private _kittyKeyboard: KittyKeyboard | undefined;
19
+
20
+ constructor(
21
+ @ICoreService private readonly _coreService: ICoreService,
22
+ @IOptionsService private readonly _optionsService: IOptionsService
23
+ ) {
24
+ }
25
+
26
+ private _getWin32InputMode(): Win32InputMode {
27
+ this._win32InputMode ??= new Win32InputMode();
28
+ return this._win32InputMode;
29
+ }
30
+
31
+ private _getKittyKeyboard(): KittyKeyboard {
32
+ this._kittyKeyboard ??= new KittyKeyboard();
33
+ return this._kittyKeyboard;
34
+ }
35
+
36
+ public evaluateKeyDown(event: KeyboardEvent): IKeyboardResult {
37
+ // Win32 input mode takes priority (most raw)
38
+ if (this.useWin32InputMode) {
39
+ return this._getWin32InputMode().evaluateKeyboardEvent(event, true);
40
+ }
41
+ const kittyFlags = this._coreService.kittyKeyboard.flags;
42
+ return this.useKitty
43
+ ? this._getKittyKeyboard().evaluate(event, kittyFlags, event.repeat ? KittyKeyboardEventType.REPEAT : KittyKeyboardEventType.PRESS)
44
+ : evaluateKeyboardEvent(event, this._coreService.decPrivateModes.applicationCursorKeys, isMac, this._optionsService.rawOptions.macOptionIsMeta);
45
+ }
46
+
47
+ public evaluateKeyUp(event: KeyboardEvent): IKeyboardResult | undefined {
48
+ // Win32 input mode sends key up events
49
+ if (this.useWin32InputMode) {
50
+ return this._getWin32InputMode().evaluateKeyboardEvent(event, false);
51
+ }
52
+ const kittyFlags = this._coreService.kittyKeyboard.flags;
53
+ if (this.useKitty && (kittyFlags & KittyKeyboardFlags.REPORT_EVENT_TYPES)) {
54
+ return this._getKittyKeyboard().evaluate(event, kittyFlags, KittyKeyboardEventType.RELEASE);
55
+ }
56
+ return undefined;
57
+ }
58
+
59
+ public get useKitty(): boolean {
60
+ const kittyFlags = this._coreService.kittyKeyboard.flags;
61
+ return !!(this._optionsService.rawOptions.vtExtensions?.kittyKeyboard && KittyKeyboard.shouldUseProtocol(kittyFlags));
62
+ }
63
+
64
+ public get useWin32InputMode(): boolean {
65
+ return !!(this._optionsService.rawOptions.vtExtensions?.win32InputMode && this._coreService.decPrivateModes.win32InputMode);
66
+ }
67
+ }
@@ -1,5 +1,5 @@
1
1
  import { ILinkProvider, ILinkProviderService } from 'browser/services/Services';
2
- import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
2
+ import { Disposable, toDisposable } from 'common/Lifecycle';
3
3
  import { IDisposable } from 'common/Types';
4
4
 
5
5
  export class LinkProviderService extends Disposable implements ILinkProviderService {
@@ -3,6 +3,7 @@
3
3
  * @license MIT
4
4
  */
5
5
 
6
+ import { getWindow } from 'browser/Dom';
6
7
  import { ICharSizeService, IRenderService, IMouseService } from './Services';
7
8
  import { getCoords, getCoordsRelativeToElement } from 'browser/input/Mouse';
8
9
 
@@ -30,7 +31,7 @@ export class MouseService implements IMouseService {
30
31
  }
31
32
 
32
33
  public getMouseReportCoords(event: MouseEvent, element: HTMLElement): { col: number, row: number, x: number, y: number } | undefined {
33
- const coords = getCoordsRelativeToElement(window, event, element);
34
+ const coords = getCoordsRelativeToElement(getWindow(element), event, element);
34
35
  if (!this._charSizeService.hasValidSize) {
35
36
  return undefined;
36
37
  }
@@ -7,10 +7,10 @@ import { RenderDebouncer } from 'browser/RenderDebouncer';
7
7
  import { IRenderDebouncerWithCallback } from 'browser/Types';
8
8
  import { IRenderDimensions, IRenderer } from 'browser/renderer/shared/Types';
9
9
  import { ICharSizeService, ICoreBrowserService, IRenderService, IThemeService } from 'browser/services/Services';
10
- import { Disposable, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
10
+ import { Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle';
11
11
  import { DebouncedIdleTask } from 'common/TaskQueue';
12
- import { IBufferService, ICoreService, IDecorationService, IOptionsService } from 'common/services/Services';
13
- import { Emitter } from 'vs/base/common/event';
12
+ import { IBufferService, ICoreService, IDecorationService, ILogService, IOptionsService } from 'common/services/Services';
13
+ import { Emitter } from 'common/Event';
14
14
 
15
15
  interface ISelectionState {
16
16
  start: [number, number] | undefined;
@@ -27,7 +27,7 @@ export class RenderService extends Disposable implements IRenderService {
27
27
 
28
28
  private _renderer: MutableDisposable<IRenderer> = this._register(new MutableDisposable());
29
29
  private _renderDebouncer: IRenderDebouncerWithCallback;
30
- private _pausedResizeTask = new DebouncedIdleTask();
30
+ private _pausedResizeTask: DebouncedIdleTask;
31
31
  private _observerDisposable = this._register(new MutableDisposable());
32
32
 
33
33
  private _isPaused: boolean = false;
@@ -58,6 +58,7 @@ export class RenderService extends Disposable implements IRenderService {
58
58
  private _rowCount: number,
59
59
  screenElement: HTMLElement,
60
60
  @IOptionsService private readonly _optionsService: IOptionsService,
61
+ @ILogService private readonly _logService: ILogService,
61
62
  @ICharSizeService private readonly _charSizeService: ICharSizeService,
62
63
  @ICoreService private readonly _coreService: ICoreService,
63
64
  @IDecorationService decorationService: IDecorationService,
@@ -67,6 +68,8 @@ export class RenderService extends Disposable implements IRenderService {
67
68
  ) {
68
69
  super();
69
70
 
71
+ this._pausedResizeTask = new DebouncedIdleTask(this._logService);
72
+
70
73
  this._renderDebouncer = new RenderDebouncer((start, end) => this._renderRows(start, end), this._coreBrowserService);
71
74
  this._register(this._renderDebouncer);
72
75
 
@@ -111,7 +114,7 @@ export class RenderService extends Disposable implements IRenderService {
111
114
  this._register(this._optionsService.onMultipleOptionChange([
112
115
  'cursorBlink',
113
116
  'cursorStyle'
114
- ], () => this.refreshRows(bufferService.buffer.y, bufferService.buffer.y, true)));
117
+ ], () => this.refreshRows(bufferService.buffer.y, bufferService.buffer.y, undefined, true)));
115
118
 
116
119
  this._register(themeService.onChangeColors(() => this._fullRefresh()));
117
120
 
@@ -131,6 +134,7 @@ export class RenderService extends Disposable implements IRenderService {
131
134
 
132
135
  private _handleIntersectionChange(entry: IntersectionObserverEntry): void {
133
136
  this._isPaused = entry.isIntersecting === undefined ? (entry.intersectionRatio === 0) : !entry.isIntersecting;
137
+ this._renderer.value?.handleViewportVisibilityChange?.(!this._isPaused);
134
138
 
135
139
  // Terminal was hidden on open
136
140
  if (!this._isPaused && !this._charSizeService.hasValidSize) {
@@ -144,7 +148,7 @@ export class RenderService extends Disposable implements IRenderService {
144
148
  }
145
149
  }
146
150
 
147
- public refreshRows(start: number, end: number, isRedrawOnly: boolean = false): void {
151
+ public refreshRows(start: number, end: number, sync: boolean = false, isRedrawOnly: boolean = false): void {
148
152
  if (this._isPaused) {
149
153
  this._needsFullRefresh = true;
150
154
  return;
@@ -164,7 +168,12 @@ export class RenderService extends Disposable implements IRenderService {
164
168
  if (!isRedrawOnly) {
165
169
  this._isNextRenderRedrawOnly = false;
166
170
  }
167
- this._renderDebouncer.refresh(start, end, this._rowCount);
171
+
172
+ if (sync) {
173
+ this._renderRows(start, end);
174
+ } else {
175
+ this._renderDebouncer.refresh(start, end, this._rowCount);
176
+ }
168
177
  }
169
178
 
170
179
  private _renderRows(start: number, end: number): void {
@@ -234,7 +243,7 @@ export class RenderService extends Disposable implements IRenderService {
234
243
  this._renderer.value = renderer;
235
244
  // If the value was not set, the terminal is being disposed so ignore it
236
245
  if (this._renderer.value) {
237
- this._renderer.value.onRequestRedraw(e => this.refreshRows(e.start, e.end, true));
246
+ this._renderer.value.onRequestRedraw(e => this.refreshRows(e.start, e.end, e.sync, true));
238
247
 
239
248
  // Force a refresh
240
249
  this._needsSelectionRefresh = true;
@@ -342,13 +351,11 @@ class SynchronizedOutputHandler {
342
351
  this._end = Math.max(this._end, end);
343
352
  }
344
353
 
345
- if (this._timeout === undefined) {
346
- this._timeout = this._coreBrowserService.window.setTimeout(() => {
347
- this._timeout = undefined;
348
- this._coreService.decPrivateModes.synchronizedOutput = false;
349
- this._onTimeout();
350
- }, Constants.SYNCHRONIZED_OUTPUT_TIMEOUT_MS);
351
- }
354
+ this._timeout ??= this._coreBrowserService.window.setTimeout(() => {
355
+ this._timeout = undefined;
356
+ this._coreService.decPrivateModes.synchronizedOutput = false;
357
+ this._onTimeout();
358
+ }, Constants.SYNCHRONIZED_OUTPUT_TIMEOUT_MS);
352
359
  }
353
360
 
354
361
  public flush(): { start: number, end: number } | undefined {
@@ -9,14 +9,14 @@ import { moveToCellSequence } from 'browser/input/MoveToCell';
9
9
  import { SelectionModel } from 'browser/selection/SelectionModel';
10
10
  import { ISelectionRedrawRequestEvent, ISelectionRequestScrollLinesEvent } from 'browser/selection/Types';
11
11
  import { ICoreBrowserService, IMouseService, IRenderService, ISelectionService } from 'browser/services/Services';
12
- import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
12
+ import { Disposable, toDisposable } from 'common/Lifecycle';
13
13
  import * as Browser from 'common/Platform';
14
- import { IBufferLine, IDisposable } from 'common/Types';
14
+ import { IBufferLine, ICellData, IDisposable } from 'common/Types';
15
15
  import { getRangeLength } from 'common/buffer/BufferRange';
16
16
  import { CellData } from 'common/buffer/CellData';
17
17
  import { IBuffer } from 'common/buffer/Types';
18
18
  import { IBufferService, ICoreService, IOptionsService } from 'common/services/Services';
19
- import { Emitter } from 'vs/base/common/event';
19
+ import { Emitter } from 'common/Event';
20
20
 
21
21
  /**
22
22
  * The number of pixels the mouse needs to be above or below the viewport in
@@ -532,6 +532,9 @@ export class SelectionService extends Disposable implements ISelectionService {
532
532
  * @param event The mouse event.
533
533
  */
534
534
  private _handleSingleClick(event: MouseEvent): void {
535
+ // Track if there was a selection before clearing
536
+ const hadSelection = this.hasSelection;
537
+
535
538
  this._model.selectionStartLength = 0;
536
539
  this._model.isSelectAllActive = false;
537
540
  this._activeSelectionMode = this.shouldColumnSelect(event) ? SelectionMode.COLUMN : SelectionMode.NORMAL;
@@ -543,6 +546,11 @@ export class SelectionService extends Disposable implements ISelectionService {
543
546
  }
544
547
  this._model.selectionEnd = undefined;
545
548
 
549
+ // Fire selection change event if a selection was cleared
550
+ if (hadSelection) {
551
+ this._fireOnSelectionChange(this._model.finalSelectionStart, this._model.finalSelectionEnd, false);
552
+ }
553
+
546
554
  // Ensure the line exists
547
555
  const line = this._bufferService.buffer.lines.get(this._model.selectionStart[1]);
548
556
  if (!line) {
@@ -1013,7 +1021,7 @@ export class SelectionService extends Disposable implements ISelectionService {
1013
1021
  * word logic.
1014
1022
  * @param cell The cell to check.
1015
1023
  */
1016
- private _isCharWordSeparator(cell: CellData): boolean {
1024
+ private _isCharWordSeparator(cell: ICellData): boolean {
1017
1025
  // Zero width characters are never separators as they are always to the
1018
1026
  // right of wide characters
1019
1027
  if (cell.getWidth() === 0) {
@@ -7,8 +7,8 @@ import { IRenderDimensions, IRenderer } from 'browser/renderer/shared/Types';
7
7
  import { IColorSet, ILink, ReadonlyColorSet } from 'browser/Types';
8
8
  import { ISelectionRedrawRequestEvent as ISelectionRequestRedrawEvent, ISelectionRequestScrollLinesEvent } from 'browser/selection/Types';
9
9
  import { createDecorator } from 'common/services/ServiceRegistry';
10
- import { AllColorIndex, IDisposable } from 'common/Types';
11
- import type { Event } from 'vs/base/common/event';
10
+ import { AllColorIndex, IDisposable, IKeyboardResult } from 'common/Types';
11
+ import type { IEvent } from 'common/Event';
12
12
 
13
13
  export const ICharSizeService = createDecorator<ICharSizeService>('CharSizeService');
14
14
  export interface ICharSizeService {
@@ -18,7 +18,7 @@ export interface ICharSizeService {
18
18
  readonly height: number;
19
19
  readonly hasValidSize: boolean;
20
20
 
21
- readonly onCharSizeChange: Event<void>;
21
+ readonly onCharSizeChange: IEvent<void>;
22
22
 
23
23
  measure(): void;
24
24
  }
@@ -29,8 +29,8 @@ export interface ICoreBrowserService {
29
29
 
30
30
  readonly isFocused: boolean;
31
31
 
32
- readonly onDprChange: Event<number>;
33
- readonly onWindowChange: Event<Window & typeof globalThis>;
32
+ readonly onDprChange: IEvent<number>;
33
+ readonly onWindowChange: IEvent<Window & typeof globalThis>;
34
34
 
35
35
  /**
36
36
  * Gets or sets the parent window that the terminal is rendered into. DOM and rendering APIs (e.g.
@@ -61,23 +61,23 @@ export const IRenderService = createDecorator<IRenderService>('RenderService');
61
61
  export interface IRenderService extends IDisposable {
62
62
  serviceBrand: undefined;
63
63
 
64
- onDimensionsChange: Event<IRenderDimensions>;
64
+ onDimensionsChange: IEvent<IRenderDimensions>;
65
65
  /**
66
66
  * Fires when buffer changes are rendered. This does not fire when only cursor
67
67
  * or selections are rendered.
68
68
  */
69
- onRenderedViewportChange: Event<{ start: number, end: number }>;
69
+ onRenderedViewportChange: IEvent<{ start: number, end: number }>;
70
70
  /**
71
71
  * Fires on render
72
72
  */
73
- onRender: Event<{ start: number, end: number }>;
74
- onRefreshRequest: Event<{ start: number, end: number }>;
73
+ onRender: IEvent<{ start: number, end: number }>;
74
+ onRefreshRequest: IEvent<{ start: number, end: number }>;
75
75
 
76
76
  dimensions: IRenderDimensions;
77
77
 
78
78
  addRefreshCallback(callback: FrameRequestCallback): number;
79
79
 
80
- refreshRows(start: number, end: number): void;
80
+ refreshRows(start: number, end: number, sync?: boolean): void;
81
81
  clearTextureAtlas(): void;
82
82
  resize(cols: number, rows: number): void;
83
83
  hasRenderer(): boolean;
@@ -101,10 +101,10 @@ export interface ISelectionService {
101
101
  readonly selectionStart: [number, number] | undefined;
102
102
  readonly selectionEnd: [number, number] | undefined;
103
103
 
104
- readonly onLinuxMouseSelection: Event<string>;
105
- readonly onRequestRedraw: Event<ISelectionRequestRedrawEvent>;
106
- readonly onRequestScrollLines: Event<ISelectionRequestScrollLinesEvent>;
107
- readonly onSelectionChange: Event<void>;
104
+ readonly onLinuxMouseSelection: IEvent<string>;
105
+ readonly onRequestRedraw: IEvent<ISelectionRequestRedrawEvent>;
106
+ readonly onRequestScrollLines: IEvent<ISelectionRequestScrollLinesEvent>;
107
+ readonly onSelectionChange: IEvent<void>;
108
108
 
109
109
  disable(): void;
110
110
  enable(): void;
@@ -136,7 +136,7 @@ export interface IThemeService {
136
136
 
137
137
  readonly colors: ReadonlyColorSet;
138
138
 
139
- readonly onChangeColors: Event<ReadonlyColorSet>;
139
+ readonly onChangeColors: IEvent<ReadonlyColorSet>;
140
140
 
141
141
  restoreColor(slot?: AllColorIndex): void;
142
142
  /**
@@ -156,3 +156,12 @@ export interface ILinkProviderService extends IDisposable {
156
156
  export interface ILinkProvider {
157
157
  provideLinks(y: number, callback: (links: ILink[] | undefined) => void): void;
158
158
  }
159
+
160
+ export const IKeyboardService = createDecorator<IKeyboardService>('KeyboardService');
161
+ export interface IKeyboardService {
162
+ serviceBrand: undefined;
163
+ evaluateKeyDown(event: KeyboardEvent): IKeyboardResult;
164
+ evaluateKeyUp(event: KeyboardEvent): IKeyboardResult | undefined;
165
+ readonly useKitty: boolean;
166
+ readonly useWin32InputMode: boolean;
167
+ }
@@ -7,10 +7,10 @@ import { ColorContrastCache } from 'browser/ColorContrastCache';
7
7
  import { IThemeService } from 'browser/services/Services';
8
8
  import { DEFAULT_ANSI_COLORS, IColorContrastCache, IColorSet, ReadonlyColorSet } from 'browser/Types';
9
9
  import { color, css, NULL_COLOR } from 'common/Color';
10
- import { Disposable } from 'vs/base/common/lifecycle';
10
+ import { Disposable } from 'common/Lifecycle';
11
11
  import { IOptionsService, ITheme } from 'common/services/Services';
12
12
  import { AllColorIndex, IColor, SpecialColorIndex } from 'common/Types';
13
- import { Emitter } from 'vs/base/common/event';
13
+ import { Emitter } from 'common/Event';
14
14
 
15
15
  interface IRestoreColorSet {
16
16
  foreground: IColor;
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Copyright (c) 2026 The xterm.js authors. All rights reserved.
3
+ * @license MIT
4
+ *
5
+ * Minimal async helpers for xterm.js core.
6
+ */
7
+
8
+ import { DisposableStore, IDisposable, toDisposable } from 'common/Lifecycle';
9
+
10
+ export function timeout(millis: number): Promise<void> {
11
+ return new Promise(resolve => setTimeout(resolve, millis));
12
+ }
13
+
14
+ /**
15
+ * Creates a timeout that can be disposed using its returned value.
16
+ * @param handler The timeout handler.
17
+ * @param timeout An optional timeout in milliseconds.
18
+ * @param store An optional {@link DisposableStore} that will have the timeout disposable managed
19
+ * automatically.
20
+ */
21
+ export function disposableTimeout(handler: () => void, timeout = 0, store?: DisposableStore): IDisposable {
22
+ const timer = setTimeout(() => {
23
+ handler();
24
+ if (store) {
25
+ disposable.dispose();
26
+ }
27
+ }, timeout);
28
+ const disposable = toDisposable(() => {
29
+ clearTimeout(timer);
30
+ });
31
+ store?.add(disposable);
32
+ return disposable;
33
+ }
34
+
35
+ export class TimeoutTimer implements IDisposable {
36
+ private _token: any = -1;
37
+ private _isDisposed = false;
38
+
39
+ public dispose(): void {
40
+ this.cancel();
41
+ this._isDisposed = true;
42
+ }
43
+
44
+ public cancel(): void {
45
+ if (this._token !== -1) {
46
+ clearTimeout(this._token);
47
+ this._token = -1;
48
+ }
49
+ }
50
+
51
+ public cancelAndSet(runner: () => void, timeout: number): void {
52
+ if (this._isDisposed) {
53
+ throw new Error('Calling cancelAndSet on a disposed TimeoutTimer');
54
+ }
55
+ this.cancel();
56
+ this._token = setTimeout(() => {
57
+ this._token = -1;
58
+ runner();
59
+ }, timeout);
60
+ }
61
+
62
+ public setIfNotSet(runner: () => void, timeout: number): void {
63
+ if (this._isDisposed) {
64
+ throw new Error('Calling setIfNotSet on a disposed TimeoutTimer');
65
+ }
66
+ if (this._token !== -1) {
67
+ return;
68
+ }
69
+ this._token = setTimeout(() => {
70
+ this._token = -1;
71
+ runner();
72
+ }, timeout);
73
+ }
74
+ }
75
+
76
+ export class IntervalTimer implements IDisposable {
77
+ private _disposable: IDisposable | undefined;
78
+ private _isDisposed = false;
79
+
80
+ public cancel(): void {
81
+ this._disposable?.dispose();
82
+ this._disposable = undefined;
83
+ }
84
+
85
+ public cancelAndSet(runner: () => void, interval: number, context: Window | typeof globalThis = globalThis): void {
86
+ if (this._isDisposed) {
87
+ throw new Error('Calling cancelAndSet on a disposed IntervalTimer');
88
+ }
89
+ this.cancel();
90
+ const handle = context.setInterval(() => {
91
+ runner();
92
+ }, interval);
93
+ this._disposable = {
94
+ dispose: () => {
95
+ context.clearInterval(handle as any);
96
+ this._disposable = undefined;
97
+ }
98
+ };
99
+ }
100
+
101
+ public dispose(): void {
102
+ this.cancel();
103
+ this._isDisposed = true;
104
+ }
105
+ }
@@ -4,8 +4,8 @@
4
4
  */
5
5
 
6
6
  import { ICircularList } from 'common/Types';
7
- import { Disposable } from 'vs/base/common/lifecycle';
8
- import { Emitter } from 'vs/base/common/event';
7
+ import { Disposable } from 'common/Lifecycle';
8
+ import { Emitter } from 'common/Event';
9
9
 
10
10
  export interface IInsertEvent {
11
11
  index: number;
@@ -184,6 +184,14 @@ export namespace css {
184
184
  return channels.toColor($r, $g, $b, $a);
185
185
  }
186
186
 
187
+ // Handle the "transparent" keyword
188
+ if (css === 'transparent') {
189
+ return {
190
+ css: 'transparent',
191
+ rgba: 0x00000000
192
+ };
193
+ }
194
+
187
195
  // Validate the context is available for canvas-based color parsing
188
196
  if (!$ctx || !$litmusColor) {
189
197
  throw new Error('css.toColor: Unsupported css format');
@@ -37,8 +37,8 @@ import { IBufferSet } from 'common/buffer/Types';
37
37
  import { InputHandler } from 'common/InputHandler';
38
38
  import { WriteBuffer } from 'common/input/WriteBuffer';
39
39
  import { OscLinkService } from 'common/services/OscLinkService';
40
- import { Emitter, Event } from 'vs/base/common/event';
41
- import { Disposable, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
40
+ import { Emitter, EventUtils, type IEvent } from 'common/Event';
41
+ import { Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle';
42
42
 
43
43
  // Only trigger this warning a single time per session
44
44
  let hasWriteSyncWarnHappened = false;
@@ -65,6 +65,8 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
65
65
  public readonly onData = this._onData.event;
66
66
  protected _onLineFeed = this._register(new Emitter<void>());
67
67
  public readonly onLineFeed = this._onLineFeed.event;
68
+ protected readonly _onRender = this._register(new Emitter<{ start: number, end: number }>());
69
+ public readonly onRender = this._onRender.event;
68
70
  private readonly _onResize = this._register(new Emitter<{ cols: number, rows: number }>());
69
71
  public readonly onResize = this._onResize.event;
70
72
  protected readonly _onWriteParsed = this._register(new Emitter<void>());
@@ -76,7 +78,7 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
76
78
  */
77
79
  protected _onScrollApi?: Emitter<number>;
78
80
  protected _onScroll = this._register(new Emitter<IScrollEvent>());
79
- public get onScroll(): Event<number> {
81
+ public get onScroll(): IEvent<number> {
80
82
  if (!this._onScrollApi) {
81
83
  this._onScrollApi = this._register(new Emitter<number>());
82
84
  this._onScroll.event(ev => {
@@ -105,10 +107,10 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
105
107
  this._instantiationService = new InstantiationService();
106
108
  this.optionsService = this._register(new OptionsService(options));
107
109
  this._instantiationService.setService(IOptionsService, this.optionsService);
108
- this._bufferService = this._register(this._instantiationService.createInstance(BufferService));
109
- this._instantiationService.setService(IBufferService, this._bufferService);
110
110
  this._logService = this._register(this._instantiationService.createInstance(LogService));
111
111
  this._instantiationService.setService(ILogService, this._logService);
112
+ this._bufferService = this._register(this._instantiationService.createInstance(BufferService));
113
+ this._instantiationService.setService(IBufferService, this._bufferService);
112
114
  this.coreService = this._register(this._instantiationService.createInstance(CoreService));
113
115
  this._instantiationService.setService(ICoreService, this.coreService);
114
116
  this.coreMouseService = this._register(this._instantiationService.createInstance(CoreMouseService));
@@ -123,13 +125,12 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
123
125
 
124
126
  // Register input handler and handle/forward events
125
127
  this._inputHandler = this._register(new InputHandler(this._bufferService, this._charsetService, this.coreService, this._logService, this.optionsService, this._oscLinkService, this.coreMouseService, this.unicodeService));
126
- this._register(Event.forward(this._inputHandler.onLineFeed, this._onLineFeed));
127
- this._register(this._inputHandler);
128
+ this._register(EventUtils.forward(this._inputHandler.onLineFeed, this._onLineFeed));
128
129
 
129
130
  // Setup listeners
130
- this._register(Event.forward(this._bufferService.onResize, this._onResize));
131
- this._register(Event.forward(this.coreService.onData, this._onData));
132
- this._register(Event.forward(this.coreService.onBinary, this._onBinary));
131
+ this._register(EventUtils.forward(this._bufferService.onResize, this._onResize));
132
+ this._register(EventUtils.forward(this.coreService.onData, this._onData));
133
+ this._register(EventUtils.forward(this.coreService.onBinary, this._onBinary));
133
134
  this._register(this.coreService.onRequestScrollToBottom(() => this.scrollToBottom(true)));
134
135
  this._register(this.coreService.onUserInput(() => this._writeBuffer.handleUserInput()));
135
136
  this._register(this.optionsService.onMultipleOptionChange(['windowsPty'], () => this._handleWindowsPtyOptionChange()));
@@ -139,7 +140,7 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
139
140
  }));
140
141
  // Setup WriteBuffer
141
142
  this._writeBuffer = this._register(new WriteBuffer((data, promiseResult) => this._inputHandler.parse(data, promiseResult)));
142
- this._register(Event.forward(this._writeBuffer.onWriteParsed, this._onWriteParsed));
143
+ this._register(EventUtils.forward(this._writeBuffer.onWriteParsed, this._onWriteParsed));
143
144
  }
144
145
 
145
146
  public write(data: string | Uint8Array, callback?: () => void): void {
@@ -175,6 +176,10 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
175
176
  x = Math.max(x, MINIMUM_COLS);
176
177
  y = Math.max(y, MINIMUM_ROWS);
177
178
 
179
+ // Flush pending writes before resize to avoid race conditions where async
180
+ // writes are processed with incorrect dimensions
181
+ this._writeBuffer.flushSync();
182
+
178
183
  this._bufferService.resize(x, y);
179
184
  }
180
185
 
@@ -237,6 +242,11 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
237
242
  return this._inputHandler.registerOscHandler(ident, callback);
238
243
  }
239
244
 
245
+ /** Add handler for APC escape sequence. See xterm.d.ts for details. */
246
+ public registerApcHandler(ident: number, callback: (data: string) => boolean | Promise<boolean>): IDisposable {
247
+ return this._inputHandler.registerApcHandler(ident, callback);
248
+ }
249
+
240
250
  protected _setup(): void {
241
251
  this._handleWindowsPtyOptionChange();
242
252
  }