@xterm/xterm 5.6.0-beta.14 → 5.6.0-beta.141

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 (131) hide show
  1. package/README.md +10 -3
  2. package/css/xterm.css +71 -4
  3. package/lib/xterm.js +1 -1
  4. package/lib/xterm.js.map +1 -1
  5. package/lib/xterm.mjs +53 -0
  6. package/lib/xterm.mjs.map +7 -0
  7. package/package.json +46 -35
  8. package/src/browser/AccessibilityManager.ts +54 -26
  9. package/src/browser/{Terminal.ts → CoreBrowserTerminal.ts} +159 -145
  10. package/src/browser/Linkifier.ts +26 -14
  11. package/src/browser/LocalizableStrings.ts +15 -4
  12. package/src/browser/TimeBasedDebouncer.ts +2 -2
  13. package/src/browser/{Types.d.ts → Types.ts} +67 -15
  14. package/src/browser/Viewport.ts +148 -370
  15. package/src/browser/decorations/BufferDecorationRenderer.ts +14 -9
  16. package/src/browser/decorations/OverviewRulerRenderer.ts +40 -44
  17. package/src/browser/input/CompositionHelper.ts +2 -1
  18. package/src/browser/input/MoveToCell.ts +3 -1
  19. package/src/browser/public/Terminal.ts +26 -19
  20. package/src/browser/renderer/dom/DomRenderer.ts +19 -14
  21. package/src/browser/renderer/dom/DomRendererRowFactory.ts +35 -15
  22. package/src/browser/renderer/shared/Constants.ts +0 -8
  23. package/src/browser/renderer/shared/Types.ts +84 -0
  24. package/src/browser/services/CharSizeService.ts +6 -6
  25. package/src/browser/services/CoreBrowserService.ts +16 -20
  26. package/src/browser/services/LinkProviderService.ts +2 -2
  27. package/src/browser/services/RenderService.ts +116 -25
  28. package/src/browser/services/SelectionService.ts +16 -8
  29. package/src/browser/services/Services.ts +13 -13
  30. package/src/browser/services/ThemeService.ts +19 -58
  31. package/src/browser/shared/Constants.ts +8 -0
  32. package/src/common/CircularList.ts +5 -5
  33. package/src/common/CoreTerminal.ts +35 -41
  34. package/src/common/InputHandler.ts +97 -59
  35. package/src/common/TaskQueue.ts +7 -7
  36. package/src/common/{Types.d.ts → Types.ts} +14 -17
  37. package/src/common/buffer/Buffer.ts +15 -7
  38. package/src/common/buffer/BufferReflow.ts +9 -6
  39. package/src/common/buffer/BufferSet.ts +5 -5
  40. package/src/common/buffer/Marker.ts +4 -4
  41. package/src/common/buffer/{Types.d.ts → Types.ts} +2 -2
  42. package/src/common/input/Keyboard.ts +0 -24
  43. package/src/common/input/WriteBuffer.ts +9 -8
  44. package/src/common/parser/EscapeSequenceParser.ts +4 -4
  45. package/src/common/public/BufferNamespaceApi.ts +3 -3
  46. package/src/common/services/BufferService.ts +14 -11
  47. package/src/common/services/CoreMouseService.ts +53 -6
  48. package/src/common/services/CoreService.ts +13 -8
  49. package/src/common/services/DecorationService.ts +8 -9
  50. package/src/common/services/InstantiationService.ts +1 -1
  51. package/src/common/services/LogService.ts +2 -2
  52. package/src/common/services/OptionsService.ts +8 -6
  53. package/src/common/services/ServiceRegistry.ts +1 -1
  54. package/src/common/services/Services.ts +39 -17
  55. package/src/common/services/UnicodeService.ts +2 -2
  56. package/src/vs/base/browser/browser.ts +141 -0
  57. package/src/vs/base/browser/canIUse.ts +49 -0
  58. package/src/vs/base/browser/dom.ts +2369 -0
  59. package/src/vs/base/browser/fastDomNode.ts +316 -0
  60. package/src/vs/base/browser/globalPointerMoveMonitor.ts +112 -0
  61. package/src/vs/base/browser/iframe.ts +135 -0
  62. package/src/vs/base/browser/keyboardEvent.ts +213 -0
  63. package/src/vs/base/browser/mouseEvent.ts +229 -0
  64. package/src/vs/base/browser/touch.ts +372 -0
  65. package/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts +303 -0
  66. package/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts +114 -0
  67. package/src/vs/base/browser/ui/scrollbar/scrollableElement.ts +720 -0
  68. package/src/vs/base/browser/ui/scrollbar/scrollableElementOptions.ts +165 -0
  69. package/src/vs/base/browser/ui/scrollbar/scrollbarArrow.ts +114 -0
  70. package/src/vs/base/browser/ui/scrollbar/scrollbarState.ts +243 -0
  71. package/src/vs/base/browser/ui/scrollbar/scrollbarVisibilityController.ts +118 -0
  72. package/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts +116 -0
  73. package/src/vs/base/browser/ui/widget.ts +57 -0
  74. package/src/vs/base/browser/window.ts +14 -0
  75. package/src/vs/base/common/arrays.ts +887 -0
  76. package/src/vs/base/common/arraysFind.ts +202 -0
  77. package/src/vs/base/common/assert.ts +71 -0
  78. package/src/vs/base/common/async.ts +1992 -0
  79. package/src/vs/base/common/cancellation.ts +148 -0
  80. package/src/vs/base/common/charCode.ts +450 -0
  81. package/src/vs/base/common/collections.ts +140 -0
  82. package/src/vs/base/common/decorators.ts +130 -0
  83. package/src/vs/base/common/equals.ts +146 -0
  84. package/src/vs/base/common/errors.ts +303 -0
  85. package/src/vs/base/common/event.ts +1778 -0
  86. package/src/vs/base/common/functional.ts +32 -0
  87. package/src/vs/base/common/hash.ts +316 -0
  88. package/src/vs/base/common/iterator.ts +159 -0
  89. package/src/vs/base/common/keyCodes.ts +526 -0
  90. package/src/vs/base/common/keybindings.ts +284 -0
  91. package/src/vs/base/common/lazy.ts +47 -0
  92. package/src/vs/base/common/lifecycle.ts +801 -0
  93. package/src/vs/base/common/linkedList.ts +142 -0
  94. package/src/vs/base/common/map.ts +202 -0
  95. package/src/vs/base/common/numbers.ts +98 -0
  96. package/src/vs/base/common/observable.ts +76 -0
  97. package/src/vs/base/common/observableInternal/api.ts +31 -0
  98. package/src/vs/base/common/observableInternal/autorun.ts +281 -0
  99. package/src/vs/base/common/observableInternal/base.ts +489 -0
  100. package/src/vs/base/common/observableInternal/debugName.ts +145 -0
  101. package/src/vs/base/common/observableInternal/derived.ts +428 -0
  102. package/src/vs/base/common/observableInternal/lazyObservableValue.ts +146 -0
  103. package/src/vs/base/common/observableInternal/logging.ts +328 -0
  104. package/src/vs/base/common/observableInternal/promise.ts +209 -0
  105. package/src/vs/base/common/observableInternal/utils.ts +610 -0
  106. package/src/vs/base/common/platform.ts +281 -0
  107. package/src/vs/base/common/scrollable.ts +522 -0
  108. package/src/vs/base/common/sequence.ts +34 -0
  109. package/src/vs/base/common/stopwatch.ts +43 -0
  110. package/src/vs/base/common/strings.ts +557 -0
  111. package/src/vs/base/common/symbols.ts +9 -0
  112. package/src/vs/base/common/uint.ts +59 -0
  113. package/src/vs/patches/nls.ts +90 -0
  114. package/src/vs/typings/base-common.d.ts +20 -0
  115. package/src/vs/typings/require.d.ts +42 -0
  116. package/src/vs/typings/vscode-globals-nls.d.ts +36 -0
  117. package/src/vs/typings/vscode-globals-product.d.ts +33 -0
  118. package/typings/xterm.d.ts +87 -14
  119. package/src/browser/Lifecycle.ts +0 -33
  120. package/src/browser/renderer/shared/CellColorResolver.ts +0 -236
  121. package/src/browser/renderer/shared/CharAtlasCache.ts +0 -96
  122. package/src/browser/renderer/shared/CharAtlasUtils.ts +0 -75
  123. package/src/browser/renderer/shared/CursorBlinkStateManager.ts +0 -146
  124. package/src/browser/renderer/shared/CustomGlyphs.ts +0 -687
  125. package/src/browser/renderer/shared/DevicePixelObserver.ts +0 -41
  126. package/src/browser/renderer/shared/TextureAtlas.ts +0 -1100
  127. package/src/browser/renderer/shared/Types.d.ts +0 -173
  128. package/src/common/EventEmitter.ts +0 -78
  129. package/src/common/Lifecycle.ts +0 -108
  130. /package/src/browser/selection/{Types.d.ts → Types.ts} +0 -0
  131. /package/src/common/parser/{Types.d.ts → Types.ts} +0 -0
@@ -3,21 +3,21 @@
3
3
  * @license MIT
4
4
  */
5
5
 
6
- import { Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle';
7
6
  import { ICoreBrowserService } from './Services';
8
- import { EventEmitter, forwardEvent } from 'common/EventEmitter';
9
- import { addDisposableDomListener } from 'browser/Lifecycle';
7
+ import { Emitter, Event } from 'vs/base/common/event';
8
+ import { addDisposableListener } from 'vs/base/browser/dom';
9
+ import { Disposable, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
10
10
 
11
11
  export class CoreBrowserService extends Disposable implements ICoreBrowserService {
12
12
  public serviceBrand: undefined;
13
13
 
14
14
  private _isFocused = false;
15
15
  private _cachedIsFocused: boolean | undefined = undefined;
16
- private _screenDprMonitor = this.register(new ScreenDprMonitor(this._window));
16
+ private _screenDprMonitor = this._register(new ScreenDprMonitor(this._window));
17
17
 
18
- private readonly _onDprChange = this.register(new EventEmitter<number>());
18
+ private readonly _onDprChange = this._register(new Emitter<number>());
19
19
  public readonly onDprChange = this._onDprChange.event;
20
- private readonly _onWindowChange = this.register(new EventEmitter<Window & typeof globalThis>());
20
+ private readonly _onWindowChange = this._register(new Emitter<Window & typeof globalThis>());
21
21
  public readonly onWindowChange = this._onWindowChange.event;
22
22
 
23
23
  constructor(
@@ -28,15 +28,11 @@ export class CoreBrowserService extends Disposable implements ICoreBrowserServic
28
28
  super();
29
29
 
30
30
  // Monitor device pixel ratio
31
- this.register(this.onWindowChange(w => this._screenDprMonitor.setWindow(w)));
32
- this.register(forwardEvent(this._screenDprMonitor.onDprChange, this._onDprChange));
33
-
34
- this.register(
35
- addDisposableDomListener(this._textarea, 'focus', () => (this._isFocused = true))
36
- );
37
- this.register(
38
- addDisposableDomListener(this._textarea, 'blur', () => (this._isFocused = false))
39
- );
31
+ this._register(this.onWindowChange(w => this._screenDprMonitor.setWindow(w)));
32
+ this._register(Event.forward(this._screenDprMonitor.onDprChange, this._onDprChange));
33
+
34
+ this._register(addDisposableListener(this._textarea, 'focus', () => this._isFocused = true));
35
+ this._register(addDisposableListener(this._textarea, 'blur', () => this._isFocused = false));
40
36
  }
41
37
 
42
38
  public get window(): Window & typeof globalThis {
@@ -69,7 +65,7 @@ export class CoreBrowserService extends Disposable implements ICoreBrowserServic
69
65
  * window.devicePixelRatio value changes. This is done not with polling but with
70
66
  * the use of window.matchMedia to watch media queries. When the event fires,
71
67
  * the listener will be reattached using a different media query to ensure that
72
- * any further changes will register.
68
+ * any further changes will _register.
73
69
  *
74
70
  * The listener should fire on both window zoom changes and switching to a
75
71
  * monitor with a different DPI.
@@ -78,9 +74,9 @@ class ScreenDprMonitor extends Disposable {
78
74
  private _currentDevicePixelRatio: number;
79
75
  private _outerListener: ((this: MediaQueryList, ev: MediaQueryListEvent) => any) | undefined;
80
76
  private _resolutionMediaMatchList: MediaQueryList | undefined;
81
- private _windowResizeListener = this.register(new MutableDisposable());
77
+ private _windowResizeListener = this._register(new MutableDisposable());
82
78
 
83
- private readonly _onDprChange = this.register(new EventEmitter<number>());
79
+ private readonly _onDprChange = this._register(new Emitter<number>());
84
80
  public readonly onDprChange = this._onDprChange.event;
85
81
 
86
82
  constructor(private _parentWindow: Window) {
@@ -95,7 +91,7 @@ class ScreenDprMonitor extends Disposable {
95
91
  this._setWindowResizeListener();
96
92
 
97
93
  // Setup additional disposables
98
- this.register(toDisposable(() => this.clearListener()));
94
+ this._register(toDisposable(() => this.clearListener()));
99
95
  }
100
96
 
101
97
 
@@ -106,7 +102,7 @@ class ScreenDprMonitor extends Disposable {
106
102
  }
107
103
 
108
104
  private _setWindowResizeListener(): void {
109
- this._windowResizeListener.value = addDisposableDomListener(this._parentWindow, 'resize', () => this._setDprAndFireIfDiffers());
105
+ this._windowResizeListener.value = addDisposableListener(this._parentWindow, 'resize', () => this._setDprAndFireIfDiffers());
110
106
  }
111
107
 
112
108
  private _setDprAndFireIfDiffers(): void {
@@ -1,5 +1,5 @@
1
1
  import { ILinkProvider, ILinkProviderService } from 'browser/services/Services';
2
- import { Disposable, toDisposable } from 'common/Lifecycle';
2
+ import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
3
3
  import { IDisposable } from 'common/Types';
4
4
 
5
5
  export class LinkProviderService extends Disposable implements ILinkProviderService {
@@ -9,7 +9,7 @@ export class LinkProviderService extends Disposable implements ILinkProviderServ
9
9
 
10
10
  constructor() {
11
11
  super();
12
- this.register(toDisposable(() => this.linkProviders.length = 0));
12
+ this._register(toDisposable(() => this.linkProviders.length = 0));
13
13
  }
14
14
 
15
15
  public registerLinkProvider(linkProvider: ILinkProvider): IDisposable {
@@ -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 { EventEmitter } from 'common/EventEmitter';
11
- import { Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle';
10
+ import { Disposable, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
12
11
  import { DebouncedIdleTask } from 'common/TaskQueue';
13
- import { IBufferService, IDecorationService, IOptionsService } from 'common/services/Services';
12
+ import { IBufferService, ICoreService, IDecorationService, IOptionsService } from 'common/services/Services';
13
+ import { Emitter } from 'vs/base/common/event';
14
14
 
15
15
  interface ISelectionState {
16
16
  start: [number, number] | undefined;
@@ -18,13 +18,17 @@ interface ISelectionState {
18
18
  columnSelectMode: boolean;
19
19
  }
20
20
 
21
+ const enum Constants {
22
+ SYNCHRONIZED_OUTPUT_TIMEOUT_MS = 1000
23
+ }
24
+
21
25
  export class RenderService extends Disposable implements IRenderService {
22
26
  public serviceBrand: undefined;
23
27
 
24
- private _renderer: MutableDisposable<IRenderer> = this.register(new MutableDisposable());
28
+ private _renderer: MutableDisposable<IRenderer> = this._register(new MutableDisposable());
25
29
  private _renderDebouncer: IRenderDebouncerWithCallback;
26
30
  private _pausedResizeTask = new DebouncedIdleTask();
27
- private _observerDisposable = this.register(new MutableDisposable());
31
+ private _observerDisposable = this._register(new MutableDisposable());
28
32
 
29
33
  private _isPaused: boolean = false;
30
34
  private _needsFullRefresh: boolean = false;
@@ -32,19 +36,20 @@ export class RenderService extends Disposable implements IRenderService {
32
36
  private _needsSelectionRefresh: boolean = false;
33
37
  private _canvasWidth: number = 0;
34
38
  private _canvasHeight: number = 0;
39
+ private _syncOutputHandler: SynchronizedOutputHandler;
35
40
  private _selectionState: ISelectionState = {
36
41
  start: undefined,
37
42
  end: undefined,
38
43
  columnSelectMode: false
39
44
  };
40
45
 
41
- private readonly _onDimensionsChange = this.register(new EventEmitter<IRenderDimensions>());
46
+ private readonly _onDimensionsChange = this._register(new Emitter<IRenderDimensions>());
42
47
  public readonly onDimensionsChange = this._onDimensionsChange.event;
43
- private readonly _onRenderedViewportChange = this.register(new EventEmitter<{ start: number, end: number }>());
48
+ private readonly _onRenderedViewportChange = this._register(new Emitter<{ start: number, end: number }>());
44
49
  public readonly onRenderedViewportChange = this._onRenderedViewportChange.event;
45
- private readonly _onRender = this.register(new EventEmitter<{ start: number, end: number }>());
50
+ private readonly _onRender = this._register(new Emitter<{ start: number, end: number }>());
46
51
  public readonly onRender = this._onRender.event;
47
- private readonly _onRefreshRequest = this.register(new EventEmitter<{ start: number, end: number }>());
52
+ private readonly _onRefreshRequest = this._register(new Emitter<{ start: number, end: number }>());
48
53
  public readonly onRefreshRequest = this._onRefreshRequest.event;
49
54
 
50
55
  public get dimensions(): IRenderDimensions { return this._renderer.value!.dimensions; }
@@ -52,33 +57,41 @@ export class RenderService extends Disposable implements IRenderService {
52
57
  constructor(
53
58
  private _rowCount: number,
54
59
  screenElement: HTMLElement,
55
- @IOptionsService optionsService: IOptionsService,
60
+ @IOptionsService private readonly _optionsService: IOptionsService,
56
61
  @ICharSizeService private readonly _charSizeService: ICharSizeService,
62
+ @ICoreService private readonly _coreService: ICoreService,
57
63
  @IDecorationService decorationService: IDecorationService,
58
64
  @IBufferService bufferService: IBufferService,
59
- @ICoreBrowserService coreBrowserService: ICoreBrowserService,
65
+ @ICoreBrowserService private readonly _coreBrowserService: ICoreBrowserService,
60
66
  @IThemeService themeService: IThemeService
61
67
  ) {
62
68
  super();
63
69
 
64
- this._renderDebouncer = new RenderDebouncer((start, end) => this._renderRows(start, end), coreBrowserService);
65
- this.register(this._renderDebouncer);
70
+ this._renderDebouncer = new RenderDebouncer((start, end) => this._renderRows(start, end), this._coreBrowserService);
71
+ this._register(this._renderDebouncer);
66
72
 
67
- this.register(coreBrowserService.onDprChange(() => this.handleDevicePixelRatioChange()));
73
+ this._syncOutputHandler = new SynchronizedOutputHandler(
74
+ this._coreBrowserService,
75
+ this._coreService,
76
+ () => this._fullRefresh()
77
+ );
78
+ this._register(toDisposable(() => this._syncOutputHandler.dispose()));
68
79
 
69
- this.register(bufferService.onResize(() => this._fullRefresh()));
70
- this.register(bufferService.buffers.onBufferActivate(() => this._renderer.value?.clear()));
71
- this.register(optionsService.onOptionChange(() => this._handleOptionsChanged()));
72
- this.register(this._charSizeService.onCharSizeChange(() => this.handleCharSizeChanged()));
80
+ this._register(this._coreBrowserService.onDprChange(() => this.handleDevicePixelRatioChange()));
81
+
82
+ this._register(bufferService.onResize(() => this._fullRefresh()));
83
+ this._register(bufferService.buffers.onBufferActivate(() => this._renderer.value?.clear()));
84
+ this._register(this._optionsService.onOptionChange(() => this._handleOptionsChanged()));
85
+ this._register(this._charSizeService.onCharSizeChange(() => this.handleCharSizeChanged()));
73
86
 
74
87
  // Do a full refresh whenever any decoration is added or removed. This may not actually result
75
88
  // in changes but since decorations should be used sparingly or added/removed all in the same
76
89
  // frame this should have minimal performance impact.
77
- this.register(decorationService.onDecorationRegistered(() => this._fullRefresh()));
78
- this.register(decorationService.onDecorationRemoved(() => this._fullRefresh()));
90
+ this._register(decorationService.onDecorationRegistered(() => this._fullRefresh()));
91
+ this._register(decorationService.onDecorationRemoved(() => this._fullRefresh()));
79
92
 
80
93
  // Clear the renderer when the a change that could affect glyphs occurs
81
- this.register(optionsService.onMultipleOptionChange([
94
+ this._register(this._optionsService.onMultipleOptionChange([
82
95
  'customGlyphs',
83
96
  'drawBoldTextInBrightColors',
84
97
  'letterSpacing',
@@ -96,15 +109,15 @@ export class RenderService extends Disposable implements IRenderService {
96
109
  }));
97
110
 
98
111
  // Refresh the cursor line when the cursor changes
99
- this.register(optionsService.onMultipleOptionChange([
112
+ this._register(this._optionsService.onMultipleOptionChange([
100
113
  'cursorBlink',
101
114
  'cursorStyle'
102
115
  ], () => this.refreshRows(bufferService.buffer.y, bufferService.buffer.y, true)));
103
116
 
104
- this.register(themeService.onChangeColors(() => this._fullRefresh()));
117
+ this._register(themeService.onChangeColors(() => this._fullRefresh()));
105
118
 
106
- this._registerIntersectionObserver(coreBrowserService.window, screenElement);
107
- this.register(coreBrowserService.onWindowChange((w) => this._registerIntersectionObserver(w, screenElement)));
119
+ this._registerIntersectionObserver(this._coreBrowserService.window, screenElement);
120
+ this._register(this._coreBrowserService.onWindowChange((w) => this._registerIntersectionObserver(w, screenElement)));
108
121
  }
109
122
 
110
123
  private _registerIntersectionObserver(w: Window & typeof globalThis, screenElement: HTMLElement): void {
@@ -137,6 +150,18 @@ export class RenderService extends Disposable implements IRenderService {
137
150
  this._needsFullRefresh = true;
138
151
  return;
139
152
  }
153
+
154
+ if (this._coreService.decPrivateModes.synchronizedOutput) {
155
+ this._syncOutputHandler.bufferRows(start, end);
156
+ return;
157
+ }
158
+
159
+ const buffered = this._syncOutputHandler.flush();
160
+ if (buffered) {
161
+ start = Math.min(start, buffered.start);
162
+ end = Math.max(end, buffered.end);
163
+ }
164
+
140
165
  if (!isRedrawOnly) {
141
166
  this._isNextRenderRedrawOnly = false;
142
167
  }
@@ -148,6 +173,13 @@ export class RenderService extends Disposable implements IRenderService {
148
173
  return;
149
174
  }
150
175
 
176
+ // Skip rendering if synchronized output mode is enabled. This check must happen here
177
+ // (in addition to refreshRows) to handle renders that were queued before the mode was enabled.
178
+ if (this._coreService.decPrivateModes.synchronizedOutput) {
179
+ this._syncOutputHandler.bufferRows(start, end);
180
+ return;
181
+ }
182
+
151
183
  // Since this is debounced, a resize event could have happened between the time a refresh was
152
184
  // requested and when this triggers. Clamp the values of start and end to ensure they're valid
153
185
  // given the current viewport state.
@@ -283,3 +315,62 @@ export class RenderService extends Disposable implements IRenderService {
283
315
  this._renderer.value?.clear();
284
316
  }
285
317
  }
318
+
319
+ /**
320
+ * Buffers row refresh requests during synchronized output mode (DEC mode 2026).
321
+ * When the mode is disabled, the accumulated row range is flushed for rendering.
322
+ * A safety timeout ensures rendering occurs even if the end sequence is not received.
323
+ */
324
+ class SynchronizedOutputHandler {
325
+ private _start: number = 0;
326
+ private _end: number = 0;
327
+ private _timeout: number | undefined;
328
+ private _isBuffering: boolean = false;
329
+
330
+ constructor(
331
+ private readonly _coreBrowserService: ICoreBrowserService,
332
+ private readonly _coreService: ICoreService,
333
+ private readonly _onTimeout: () => void
334
+ ) {}
335
+
336
+ public bufferRows(start: number, end: number): void {
337
+ if (!this._isBuffering) {
338
+ this._start = start;
339
+ this._end = end;
340
+ this._isBuffering = true;
341
+ } else {
342
+ this._start = Math.min(this._start, start);
343
+ this._end = Math.max(this._end, end);
344
+ }
345
+
346
+ if (this._timeout === undefined) {
347
+ this._timeout = this._coreBrowserService.window.setTimeout(() => {
348
+ this._timeout = undefined;
349
+ this._coreService.decPrivateModes.synchronizedOutput = false;
350
+ this._onTimeout();
351
+ }, Constants.SYNCHRONIZED_OUTPUT_TIMEOUT_MS);
352
+ }
353
+ }
354
+
355
+ public flush(): { start: number, end: number } | undefined {
356
+ if (this._timeout !== undefined) {
357
+ this._coreBrowserService.window.clearTimeout(this._timeout);
358
+ this._timeout = undefined;
359
+ }
360
+
361
+ if (!this._isBuffering) {
362
+ return undefined;
363
+ }
364
+
365
+ const result = { start: this._start, end: this._end };
366
+ this._isBuffering = false;
367
+ return result;
368
+ }
369
+
370
+ public dispose(): void {
371
+ if (this._timeout !== undefined) {
372
+ this._coreBrowserService.window.clearTimeout(this._timeout);
373
+ this._timeout = undefined;
374
+ }
375
+ }
376
+ }
@@ -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 { EventEmitter } from 'common/EventEmitter';
13
- import { Disposable, toDisposable } from 'common/Lifecycle';
12
+ import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
14
13
  import * as Browser from 'common/Platform';
15
14
  import { IBufferLine, IDisposable } from 'common/Types';
16
15
  import { getRangeLength } from 'common/buffer/BufferRange';
17
16
  import { CellData } from 'common/buffer/CellData';
18
17
  import { IBuffer } from 'common/buffer/Types';
19
18
  import { IBufferService, ICoreService, IOptionsService } from 'common/services/Services';
19
+ import { Emitter } from 'vs/base/common/event';
20
20
 
21
21
  /**
22
22
  * The number of pixels the mouse needs to be above or below the viewport in
@@ -111,13 +111,13 @@ export class SelectionService extends Disposable implements ISelectionService {
111
111
  private _oldSelectionStart: [number, number] | undefined = undefined;
112
112
  private _oldSelectionEnd: [number, number] | undefined = undefined;
113
113
 
114
- private readonly _onLinuxMouseSelection = this.register(new EventEmitter<string>());
114
+ private readonly _onLinuxMouseSelection = this._register(new Emitter<string>());
115
115
  public readonly onLinuxMouseSelection = this._onLinuxMouseSelection.event;
116
- private readonly _onRedrawRequest = this.register(new EventEmitter<ISelectionRedrawRequestEvent>());
116
+ private readonly _onRedrawRequest = this._register(new Emitter<ISelectionRedrawRequestEvent>());
117
117
  public readonly onRequestRedraw = this._onRedrawRequest.event;
118
- private readonly _onSelectionChange = this.register(new EventEmitter<void>());
118
+ private readonly _onSelectionChange = this._register(new Emitter<void>());
119
119
  public readonly onSelectionChange = this._onSelectionChange.event;
120
- private readonly _onRequestScrollLines = this.register(new EventEmitter<ISelectionRequestScrollLinesEvent>());
120
+ private readonly _onRequestScrollLines = this._register(new Emitter<ISelectionRequestScrollLinesEvent>());
121
121
  public readonly onRequestScrollLines = this._onRequestScrollLines.event;
122
122
 
123
123
  constructor(
@@ -142,16 +142,24 @@ export class SelectionService extends Disposable implements ISelectionService {
142
142
  }
143
143
  });
144
144
  this._trimListener = this._bufferService.buffer.lines.onTrim(amount => this._handleTrim(amount));
145
- this.register(this._bufferService.buffers.onBufferActivate(e => this._handleBufferActivate(e)));
145
+ this._register(this._bufferService.buffers.onBufferActivate(e => this._handleBufferActivate(e)));
146
146
 
147
147
  this.enable();
148
148
 
149
149
  this._model = new SelectionModel(this._bufferService);
150
150
  this._activeSelectionMode = SelectionMode.NORMAL;
151
151
 
152
- this.register(toDisposable(() => {
152
+ this._register(toDisposable(() => {
153
153
  this._removeMouseDownListeners();
154
154
  }));
155
+
156
+ // Clear selection when resizing vertically. This experience could be improved, this is the
157
+ // simple option to fix the buggy behavior. https://github.com/xtermjs/xterm.js/issues/5300
158
+ this._register(this._bufferService.onResize(e => {
159
+ if (e.rowsChanged) {
160
+ this.clearSelection();
161
+ }
162
+ }));
155
163
  }
156
164
 
157
165
  public reset(): void {
@@ -3,12 +3,12 @@
3
3
  * @license MIT
4
4
  */
5
5
 
6
- import { IEvent } from 'common/EventEmitter';
7
6
  import { IRenderDimensions, IRenderer } from 'browser/renderer/shared/Types';
8
7
  import { IColorSet, ILink, ReadonlyColorSet } from 'browser/Types';
9
8
  import { ISelectionRedrawRequestEvent as ISelectionRequestRedrawEvent, ISelectionRequestScrollLinesEvent } from 'browser/selection/Types';
10
9
  import { createDecorator } from 'common/services/ServiceRegistry';
11
10
  import { AllColorIndex, IDisposable } from 'common/Types';
11
+ import type { Event } from 'vs/base/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: IEvent<void>;
21
+ readonly onCharSizeChange: Event<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: IEvent<number>;
33
- readonly onWindowChange: IEvent<Window & typeof globalThis>;
32
+ readonly onDprChange: Event<number>;
33
+ readonly onWindowChange: Event<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,17 +61,17 @@ export const IRenderService = createDecorator<IRenderService>('RenderService');
61
61
  export interface IRenderService extends IDisposable {
62
62
  serviceBrand: undefined;
63
63
 
64
- onDimensionsChange: IEvent<IRenderDimensions>;
64
+ onDimensionsChange: Event<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: IEvent<{ start: number, end: number }>;
69
+ onRenderedViewportChange: Event<{ start: number, end: number }>;
70
70
  /**
71
71
  * Fires on render
72
72
  */
73
- onRender: IEvent<{ start: number, end: number }>;
74
- onRefreshRequest: IEvent<{ start: number, end: number }>;
73
+ onRender: Event<{ start: number, end: number }>;
74
+ onRefreshRequest: Event<{ start: number, end: number }>;
75
75
 
76
76
  dimensions: IRenderDimensions;
77
77
 
@@ -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: IEvent<string>;
105
- readonly onRequestRedraw: IEvent<ISelectionRequestRedrawEvent>;
106
- readonly onRequestScrollLines: IEvent<ISelectionRequestScrollLinesEvent>;
107
- readonly onSelectionChange: IEvent<void>;
104
+ readonly onLinuxMouseSelection: Event<string>;
105
+ readonly onRequestRedraw: Event<ISelectionRequestRedrawEvent>;
106
+ readonly onRequestScrollLines: Event<ISelectionRequestScrollLinesEvent>;
107
+ readonly onSelectionChange: Event<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: IEvent<ReadonlyColorSet>;
139
+ readonly onChangeColors: Event<ReadonlyColorSet>;
140
140
 
141
141
  restoreColor(slot?: AllColorIndex): void;
142
142
  /**
@@ -5,12 +5,12 @@
5
5
 
6
6
  import { ColorContrastCache } from 'browser/ColorContrastCache';
7
7
  import { IThemeService } from 'browser/services/Services';
8
- import { IColorContrastCache, IColorSet, ReadonlyColorSet } from 'browser/Types';
9
- import { channels, color, css, NULL_COLOR } from 'common/Color';
10
- import { EventEmitter } from 'common/EventEmitter';
11
- import { Disposable } from 'common/Lifecycle';
8
+ import { DEFAULT_ANSI_COLORS, IColorContrastCache, IColorSet, ReadonlyColorSet } from 'browser/Types';
9
+ import { color, css, NULL_COLOR } from 'common/Color';
10
+ import { Disposable } from 'vs/base/common/lifecycle';
12
11
  import { IOptionsService, ITheme } from 'common/services/Services';
13
12
  import { AllColorIndex, IColor, SpecialColorIndex } from 'common/Types';
13
+ import { Emitter } from 'vs/base/common/event';
14
14
 
15
15
  interface IRestoreColorSet {
16
16
  foreground: IColor;
@@ -23,59 +23,12 @@ interface IRestoreColorSet {
23
23
  const DEFAULT_FOREGROUND = css.toColor('#ffffff');
24
24
  const DEFAULT_BACKGROUND = css.toColor('#000000');
25
25
  const DEFAULT_CURSOR = css.toColor('#ffffff');
26
- const DEFAULT_CURSOR_ACCENT = css.toColor('#000000');
26
+ const DEFAULT_CURSOR_ACCENT = DEFAULT_BACKGROUND;
27
27
  const DEFAULT_SELECTION = {
28
28
  css: 'rgba(255, 255, 255, 0.3)',
29
29
  rgba: 0xFFFFFF4D
30
30
  };
31
-
32
- // An IIFE to generate DEFAULT_ANSI_COLORS.
33
- export const DEFAULT_ANSI_COLORS = Object.freeze((() => {
34
- const colors = [
35
- // dark:
36
- css.toColor('#2e3436'),
37
- css.toColor('#cc0000'),
38
- css.toColor('#4e9a06'),
39
- css.toColor('#c4a000'),
40
- css.toColor('#3465a4'),
41
- css.toColor('#75507b'),
42
- css.toColor('#06989a'),
43
- css.toColor('#d3d7cf'),
44
- // bright:
45
- css.toColor('#555753'),
46
- css.toColor('#ef2929'),
47
- css.toColor('#8ae234'),
48
- css.toColor('#fce94f'),
49
- css.toColor('#729fcf'),
50
- css.toColor('#ad7fa8'),
51
- css.toColor('#34e2e2'),
52
- css.toColor('#eeeeec')
53
- ];
54
-
55
- // Fill in the remaining 240 ANSI colors.
56
- // Generate colors (16-231)
57
- const v = [0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff];
58
- for (let i = 0; i < 216; i++) {
59
- const r = v[(i / 36) % 6 | 0];
60
- const g = v[(i / 6) % 6 | 0];
61
- const b = v[i % 6];
62
- colors.push({
63
- css: channels.toCss(r, g, b),
64
- rgba: channels.toRgba(r, g, b)
65
- });
66
- }
67
-
68
- // Generate greys (232-255)
69
- for (let i = 0; i < 24; i++) {
70
- const c = 8 + i * 10;
71
- colors.push({
72
- css: channels.toCss(c, c, c),
73
- rgba: channels.toRgba(c, c, c)
74
- });
75
- }
76
-
77
- return colors;
78
- })());
31
+ const DEFAULT_OVERVIEW_RULER_BORDER = DEFAULT_FOREGROUND;
79
32
 
80
33
  export class ThemeService extends Disposable implements IThemeService {
81
34
  public serviceBrand: undefined;
@@ -87,7 +40,7 @@ export class ThemeService extends Disposable implements IThemeService {
87
40
 
88
41
  public get colors(): ReadonlyColorSet { return this._colors; }
89
42
 
90
- private readonly _onChangeColors = this.register(new EventEmitter<ReadonlyColorSet>());
43
+ private readonly _onChangeColors = this._register(new Emitter<ReadonlyColorSet>());
91
44
  public readonly onChangeColors = this._onChangeColors.event;
92
45
 
93
46
  constructor(
@@ -105,6 +58,10 @@ export class ThemeService extends Disposable implements IThemeService {
105
58
  selectionBackgroundOpaque: color.blend(DEFAULT_BACKGROUND, DEFAULT_SELECTION),
106
59
  selectionInactiveBackgroundTransparent: DEFAULT_SELECTION,
107
60
  selectionInactiveBackgroundOpaque: color.blend(DEFAULT_BACKGROUND, DEFAULT_SELECTION),
61
+ scrollbarSliderBackground: color.opacity(DEFAULT_FOREGROUND, 0.2),
62
+ scrollbarSliderHoverBackground: color.opacity(DEFAULT_FOREGROUND, 0.4),
63
+ scrollbarSliderActiveBackground: color.opacity(DEFAULT_FOREGROUND, 0.5),
64
+ overviewRulerBorder: DEFAULT_FOREGROUND,
108
65
  ansi: DEFAULT_ANSI_COLORS.slice(),
109
66
  contrastCache: this._contrastCache,
110
67
  halfContrastCache: this._halfContrastCache
@@ -112,8 +69,8 @@ export class ThemeService extends Disposable implements IThemeService {
112
69
  this._updateRestoreColors();
113
70
  this._setTheme(this._optionsService.rawOptions.theme);
114
71
 
115
- this.register(this._optionsService.onSpecificOptionChange('minimumContrastRatio', () => this._contrastCache.clear()));
116
- this.register(this._optionsService.onSpecificOptionChange('theme', () => this._setTheme(this._optionsService.rawOptions.theme)));
72
+ this._register(this._optionsService.onSpecificOptionChange('minimumContrastRatio', () => this._contrastCache.clear()));
73
+ this._register(this._optionsService.onSpecificOptionChange('theme', () => this._setTheme(this._optionsService.rawOptions.theme)));
117
74
  }
118
75
 
119
76
  /**
@@ -125,8 +82,8 @@ export class ThemeService extends Disposable implements IThemeService {
125
82
  const colors = this._colors;
126
83
  colors.foreground = parseColor(theme.foreground, DEFAULT_FOREGROUND);
127
84
  colors.background = parseColor(theme.background, DEFAULT_BACKGROUND);
128
- colors.cursor = parseColor(theme.cursor, DEFAULT_CURSOR);
129
- colors.cursorAccent = parseColor(theme.cursorAccent, DEFAULT_CURSOR_ACCENT);
85
+ colors.cursor = color.blend(colors.background, parseColor(theme.cursor, DEFAULT_CURSOR));
86
+ colors.cursorAccent = color.blend(colors.background, parseColor(theme.cursorAccent, DEFAULT_CURSOR_ACCENT));
130
87
  colors.selectionBackgroundTransparent = parseColor(theme.selectionBackground, DEFAULT_SELECTION);
131
88
  colors.selectionBackgroundOpaque = color.blend(colors.background, colors.selectionBackgroundTransparent);
132
89
  colors.selectionInactiveBackgroundTransparent = parseColor(theme.selectionInactiveBackground, colors.selectionBackgroundTransparent);
@@ -148,6 +105,10 @@ export class ThemeService extends Disposable implements IThemeService {
148
105
  const opacity = 0.3;
149
106
  colors.selectionInactiveBackgroundTransparent = color.opacity(colors.selectionInactiveBackgroundTransparent, opacity);
150
107
  }
108
+ colors.scrollbarSliderBackground = parseColor(theme.scrollbarSliderBackground, color.opacity(colors.foreground, 0.2));
109
+ colors.scrollbarSliderHoverBackground = parseColor(theme.scrollbarSliderHoverBackground, color.opacity(colors.foreground, 0.4));
110
+ colors.scrollbarSliderActiveBackground = parseColor(theme.scrollbarSliderActiveBackground, color.opacity(colors.foreground, 0.5));
111
+ colors.overviewRulerBorder = parseColor(theme.overviewRulerBorder, DEFAULT_OVERVIEW_RULER_BORDER);
151
112
  colors.ansi = DEFAULT_ANSI_COLORS.slice();
152
113
  colors.ansi[0] = parseColor(theme.black, DEFAULT_ANSI_COLORS[0]);
153
114
  colors.ansi[1] = parseColor(theme.red, DEFAULT_ANSI_COLORS[1]);
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Copyright (c) 2024 The xterm.js authors. All rights reserved.
3
+ * @license MIT
4
+ */
5
+
6
+ export const enum ViewportConstants {
7
+ DEFAULT_SCROLL_BAR_WIDTH = 14
8
+ }
@@ -4,8 +4,8 @@
4
4
  */
5
5
 
6
6
  import { ICircularList } from 'common/Types';
7
- import { EventEmitter } from 'common/EventEmitter';
8
- import { Disposable } from 'common/Lifecycle';
7
+ import { Disposable } from 'vs/base/common/lifecycle';
8
+ import { Emitter } from 'vs/base/common/event';
9
9
 
10
10
  export interface IInsertEvent {
11
11
  index: number;
@@ -26,11 +26,11 @@ export class CircularList<T> extends Disposable implements ICircularList<T> {
26
26
  private _startIndex: number;
27
27
  private _length: number;
28
28
 
29
- public readonly onDeleteEmitter = this.register(new EventEmitter<IDeleteEvent>());
29
+ public readonly onDeleteEmitter = this._register(new Emitter<IDeleteEvent>());
30
30
  public readonly onDelete = this.onDeleteEmitter.event;
31
- public readonly onInsertEmitter = this.register(new EventEmitter<IInsertEvent>());
31
+ public readonly onInsertEmitter = this._register(new Emitter<IInsertEvent>());
32
32
  public readonly onInsert = this.onInsertEmitter.event;
33
- public readonly onTrimEmitter = this.register(new EventEmitter<number>());
33
+ public readonly onTrimEmitter = this._register(new Emitter<number>());
34
34
  public readonly onTrim = this.onTrimEmitter.event;
35
35
 
36
36
  constructor(