@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
@@ -4,10 +4,14 @@
4
4
  *--------------------------------------------------------------------------------------------*/
5
5
 
6
6
  import { ColorZoneStore, IColorZone, IColorZoneStore } from 'browser/decorations/ColorZoneStore';
7
- import { ICoreBrowserService, IRenderService } from 'browser/services/Services';
8
- import { Disposable, toDisposable } from 'common/Lifecycle';
7
+ import { ICoreBrowserService, IRenderService, IThemeService } from 'browser/services/Services';
8
+ import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
9
9
  import { IBufferService, IDecorationService, IOptionsService } from 'common/services/Services';
10
10
 
11
+ const enum Constants {
12
+ OVERVIEW_RULER_BORDER_WIDTH = 1
13
+ }
14
+
11
15
  // Helper objects to avoid excessive calculation and garbage collection during rendering. These are
12
16
  // static values for each render and can be accessed using the decoration position as the key.
13
17
  const drawHeight = {
@@ -34,7 +38,7 @@ export class OverviewRulerRenderer extends Disposable {
34
38
  private readonly _ctx: CanvasRenderingContext2D;
35
39
  private readonly _colorZoneStore: IColorZoneStore = new ColorZoneStore();
36
40
  private get _width(): number {
37
- return this._optionsService.options.overviewRulerWidth || 0;
41
+ return this._optionsService.options.overviewRuler?.width || 0;
38
42
  }
39
43
  private _animationFrame: number | undefined;
40
44
 
@@ -51,6 +55,7 @@ export class OverviewRulerRenderer extends Disposable {
51
55
  @IDecorationService private readonly _decorationService: IDecorationService,
52
56
  @IRenderService private readonly _renderService: IRenderService,
53
57
  @IOptionsService private readonly _optionsService: IOptionsService,
58
+ @IThemeService private readonly _themeService: IThemeService,
54
59
  @ICoreBrowserService private readonly _coreBrowserService: ICoreBrowserService
55
60
  ) {
56
61
  super();
@@ -58,68 +63,47 @@ export class OverviewRulerRenderer extends Disposable {
58
63
  this._canvas.classList.add('xterm-decoration-overview-ruler');
59
64
  this._refreshCanvasDimensions();
60
65
  this._viewportElement.parentElement?.insertBefore(this._canvas, this._viewportElement);
66
+ this._register(toDisposable(() => this._canvas?.remove()));
67
+
61
68
  const ctx = this._canvas.getContext('2d');
62
69
  if (!ctx) {
63
70
  throw new Error('Ctx cannot be null');
64
71
  } else {
65
72
  this._ctx = ctx;
66
73
  }
67
- this._registerDecorationListeners();
68
- this._registerBufferChangeListeners();
69
- this._registerDimensionChangeListeners();
70
- this.register(toDisposable(() => {
71
- this._canvas?.remove();
72
- }));
73
- }
74
74
 
75
- /**
76
- * On decoration add or remove, redraw
77
- */
78
- private _registerDecorationListeners(): void {
79
- this.register(this._decorationService.onDecorationRegistered(() => this._queueRefresh(undefined, true)));
80
- this.register(this._decorationService.onDecorationRemoved(() => this._queueRefresh(undefined, true)));
81
- }
75
+ this._register(this._decorationService.onDecorationRegistered(() => this._queueRefresh(undefined, true)));
76
+ this._register(this._decorationService.onDecorationRemoved(() => this._queueRefresh(undefined, true)));
82
77
 
83
- /**
84
- * On buffer change, redraw
85
- * and hide the canvas if the alt buffer is active
86
- */
87
- private _registerBufferChangeListeners(): void {
88
- this.register(this._renderService.onRenderedViewportChange(() => this._queueRefresh()));
89
- this.register(this._bufferService.buffers.onBufferActivate(() => {
78
+ this._register(this._renderService.onRenderedViewportChange(() => this._queueRefresh()));
79
+ this._register(this._bufferService.buffers.onBufferActivate(() => {
90
80
  this._canvas!.style.display = this._bufferService.buffer === this._bufferService.buffers.alt ? 'none' : 'block';
91
81
  }));
92
- this.register(this._bufferService.onScroll(() => {
82
+ this._register(this._bufferService.onScroll(() => {
93
83
  if (this._lastKnownBufferLength !== this._bufferService.buffers.normal.lines.length) {
94
84
  this._refreshDrawHeightConstants();
95
85
  this._refreshColorZonePadding();
96
86
  }
97
87
  }));
98
- }
99
- /**
100
- * On dimension change, update canvas dimensions
101
- * and then redraw
102
- */
103
- private _registerDimensionChangeListeners(): void {
104
- // container height changed
105
- this.register(this._renderService.onRender((): void => {
88
+
89
+ // Container height changed
90
+ this._register(this._renderService.onRender((): void => {
106
91
  if (!this._containerHeight || this._containerHeight !== this._screenElement.clientHeight) {
107
92
  this._queueRefresh(true);
108
93
  this._containerHeight = this._screenElement.clientHeight;
109
94
  }
110
95
  }));
111
- // overview ruler width changed
112
- this.register(this._optionsService.onSpecificOptionChange('overviewRulerWidth', () => this._queueRefresh(true)));
113
- // device pixel ratio changed
114
- this.register(this._coreBrowserService.onDprChange(() => this._queueRefresh(true)));
115
- // set the canvas dimensions
96
+
97
+ this._register(this._coreBrowserService.onDprChange(() => this._queueRefresh(true)));
98
+ this._register(this._optionsService.onSpecificOptionChange('overviewRuler', () => this._queueRefresh(true)));
99
+ this._register(this._themeService.onChangeColors(() => this._queueRefresh()));
116
100
  this._queueRefresh(true);
117
101
  }
118
102
 
119
103
  private _refreshDrawConstants(): void {
120
104
  // width
121
- const outerWidth = Math.floor(this._canvas.width / 3);
122
- const innerWidth = Math.ceil(this._canvas.width / 3);
105
+ const outerWidth = Math.floor((this._canvas.width - Constants.OVERVIEW_RULER_BORDER_WIDTH) / 3);
106
+ const innerWidth = Math.ceil((this._canvas.width - Constants.OVERVIEW_RULER_BORDER_WIDTH) / 3);
123
107
  drawWidth.full = this._canvas.width;
124
108
  drawWidth.left = outerWidth;
125
109
  drawWidth.center = innerWidth;
@@ -127,10 +111,10 @@ export class OverviewRulerRenderer extends Disposable {
127
111
  // height
128
112
  this._refreshDrawHeightConstants();
129
113
  // x
130
- drawX.full = 0;
131
- drawX.left = 0;
132
- drawX.center = drawWidth.left;
133
- drawX.right = drawWidth.left + drawWidth.center;
114
+ drawX.full = Constants.OVERVIEW_RULER_BORDER_WIDTH;
115
+ drawX.left = Constants.OVERVIEW_RULER_BORDER_WIDTH;
116
+ drawX.center = Constants.OVERVIEW_RULER_BORDER_WIDTH + drawWidth.left;
117
+ drawX.right = Constants.OVERVIEW_RULER_BORDER_WIDTH + drawWidth.left + drawWidth.center;
134
118
  }
135
119
 
136
120
  private _refreshDrawHeightConstants(): void {
@@ -173,6 +157,7 @@ export class OverviewRulerRenderer extends Disposable {
173
157
  this._colorZoneStore.addDecoration(decoration);
174
158
  }
175
159
  this._ctx.lineWidth = 1;
160
+ this._renderRulerOutline();
176
161
  const zones = this._colorZoneStore.zones;
177
162
  for (const zone of zones) {
178
163
  if (zone.position !== 'full') {
@@ -188,6 +173,17 @@ export class OverviewRulerRenderer extends Disposable {
188
173
  this._shouldUpdateAnchor = false;
189
174
  }
190
175
 
176
+ private _renderRulerOutline(): void {
177
+ this._ctx.fillStyle = this._themeService.colors.overviewRulerBorder.css;
178
+ this._ctx.fillRect(0, 0, Constants.OVERVIEW_RULER_BORDER_WIDTH, this._canvas.height);
179
+ if (this._optionsService.rawOptions.overviewRuler.showTopBorder) {
180
+ this._ctx.fillRect(Constants.OVERVIEW_RULER_BORDER_WIDTH, 0, this._canvas.width - Constants.OVERVIEW_RULER_BORDER_WIDTH, Constants.OVERVIEW_RULER_BORDER_WIDTH);
181
+ }
182
+ if (this._optionsService.rawOptions.overviewRuler.showBottomBorder) {
183
+ this._ctx.fillRect(Constants.OVERVIEW_RULER_BORDER_WIDTH, this._canvas.height - Constants.OVERVIEW_RULER_BORDER_WIDTH, this._canvas.width - Constants.OVERVIEW_RULER_BORDER_WIDTH, this._canvas.height);
184
+ }
185
+ }
186
+
191
187
  private _renderColorZone(zone: IColorZone): void {
192
188
  this._ctx.fillStyle = zone.color;
193
189
  this._ctx.fillRect(
@@ -93,7 +93,8 @@ export class CompositionHelper {
93
93
  */
94
94
  public keydown(ev: KeyboardEvent): boolean {
95
95
  if (this._isComposing || this._isSendingComposition) {
96
- if (ev.keyCode === 229) {
96
+ if (ev.keyCode === 20 || ev.keyCode === 229) {
97
+ // 20 is CapsLock, 229 is Enter
97
98
  // Continue composing if the keyCode is the "composition character"
98
99
  return false;
99
100
  }
@@ -199,7 +199,9 @@ function bufferLine(
199
199
  let currentRow = startRow;
200
200
  let bufferStr = '';
201
201
 
202
- while (currentCol !== endCol || currentRow !== endRow) {
202
+ while ((currentCol !== endCol || currentRow !== endRow) &&
203
+ currentRow >= 0 &&
204
+ currentRow < bufferService.buffer.lines.length) {
203
205
  currentCol += forward ? 1 : -1;
204
206
 
205
207
  if (forward && currentCol > bufferService.cols - 1) {
@@ -4,16 +4,16 @@
4
4
  */
5
5
 
6
6
  import * as Strings from 'browser/LocalizableStrings';
7
- import { Terminal as TerminalCore } from 'browser/Terminal';
7
+ import { CoreBrowserTerminal as TerminalCore } from 'browser/CoreBrowserTerminal';
8
8
  import { IBufferRange, ITerminal } from 'browser/Types';
9
- import { IEvent } from 'common/EventEmitter';
10
- import { Disposable } from 'common/Lifecycle';
9
+ import { Disposable } from 'vs/base/common/lifecycle';
11
10
  import { ITerminalOptions } from 'common/Types';
12
11
  import { AddonManager } from 'common/public/AddonManager';
13
12
  import { BufferNamespaceApi } from 'common/public/BufferNamespaceApi';
14
13
  import { ParserApi } from 'common/public/ParserApi';
15
14
  import { UnicodeApi } from 'common/public/UnicodeApi';
16
15
  import { IBufferNamespace as IBufferNamespaceApi, IDecoration, IDecorationOptions, IDisposable, ILinkProvider, ILocalizableStrings, IMarker, IModes, IParser, ITerminalAddon, Terminal as ITerminalApi, ITerminalInitOnlyOptions, IUnicodeHandling } from '@xterm/xterm';
16
+ import type { Event } from 'vs/base/common/event';
17
17
 
18
18
  /**
19
19
  * The set of options that only have an effect when set in the Terminal constructor.
@@ -32,8 +32,8 @@ export class Terminal extends Disposable implements ITerminalApi {
32
32
  constructor(options?: ITerminalOptions & ITerminalInitOnlyOptions) {
33
33
  super();
34
34
 
35
- this._core = this.register(new TerminalCore(options));
36
- this._addonManager = this.register(new AddonManager());
35
+ this._core = this._register(new TerminalCore(options));
36
+ this._addonManager = this._register(new AddonManager());
37
37
 
38
38
  this._publicOptions = { ... this._core.options };
39
39
  const getter = (propName: string): any => {
@@ -68,18 +68,18 @@ export class Terminal extends Disposable implements ITerminalApi {
68
68
  }
69
69
  }
70
70
 
71
- public get onBell(): IEvent<void> { return this._core.onBell; }
72
- public get onBinary(): IEvent<string> { return this._core.onBinary; }
73
- public get onCursorMove(): IEvent<void> { return this._core.onCursorMove; }
74
- public get onData(): IEvent<string> { return this._core.onData; }
75
- public get onKey(): IEvent<{ key: string, domEvent: KeyboardEvent }> { return this._core.onKey; }
76
- public get onLineFeed(): IEvent<void> { return this._core.onLineFeed; }
77
- public get onRender(): IEvent<{ start: number, end: number }> { return this._core.onRender; }
78
- public get onResize(): IEvent<{ cols: number, rows: number }> { return this._core.onResize; }
79
- public get onScroll(): IEvent<number> { return this._core.onScroll; }
80
- public get onSelectionChange(): IEvent<void> { return this._core.onSelectionChange; }
81
- public get onTitleChange(): IEvent<string> { return this._core.onTitleChange; }
82
- public get onWriteParsed(): IEvent<void> { return this._core.onWriteParsed; }
71
+ public get onBell(): Event<void> { return this._core.onBell; }
72
+ public get onBinary(): Event<string> { return this._core.onBinary; }
73
+ public get onCursorMove(): Event<void> { return this._core.onCursorMove; }
74
+ public get onData(): Event<string> { return this._core.onData; }
75
+ public get onKey(): Event<{ key: string, domEvent: KeyboardEvent }> { return this._core.onKey; }
76
+ public get onLineFeed(): Event<void> { return this._core.onLineFeed; }
77
+ public get onRender(): Event<{ start: number, end: number }> { return this._core.onRender; }
78
+ public get onResize(): Event<{ cols: number, rows: number }> { return this._core.onResize; }
79
+ public get onScroll(): Event<number> { return this._core.onScroll; }
80
+ public get onSelectionChange(): Event<void> { return this._core.onSelectionChange; }
81
+ public get onTitleChange(): Event<string> { return this._core.onTitleChange; }
82
+ public get onWriteParsed(): Event<void> { return this._core.onWriteParsed; }
83
83
 
84
84
  public get element(): HTMLElement | undefined { return this._core.element; }
85
85
  public get parser(): IParser {
@@ -97,7 +97,7 @@ export class Terminal extends Disposable implements ITerminalApi {
97
97
  public get cols(): number { return this._core.cols; }
98
98
  public get buffer(): IBufferNamespaceApi {
99
99
  if (!this._buffer) {
100
- this._buffer = this.register(new BufferNamespaceApi(this._core));
100
+ this._buffer = this._register(new BufferNamespaceApi(this._core));
101
101
  }
102
102
  return this._buffer;
103
103
  }
@@ -123,6 +123,7 @@ export class Terminal extends Disposable implements ITerminalApi {
123
123
  originMode: m.origin,
124
124
  reverseWraparoundMode: m.reverseWraparound,
125
125
  sendFocusMode: m.sendFocus,
126
+ synchronizedOutputMode: m.synchronizedOutput,
126
127
  wraparoundMode: m.wraparound
127
128
  };
128
129
  }
@@ -247,7 +248,13 @@ export class Terminal extends Disposable implements ITerminalApi {
247
248
  this._addonManager.loadAddon(this, addon);
248
249
  }
249
250
  public static get strings(): ILocalizableStrings {
250
- return Strings;
251
+ // A wrapper is required here because esbuild prevents setting an `export let`
252
+ return {
253
+ get promptLabel(): string { return Strings.promptLabel.get(); },
254
+ set promptLabel(value: string) { Strings.promptLabel.set(value); },
255
+ get tooMuchOutput(): string { return Strings.tooMuchOutput.get(); },
256
+ set tooMuchOutput(value: string) { Strings.tooMuchOutput.set(value); }
257
+ };
251
258
  }
252
259
 
253
260
  private _verifyIntegers(...values: number[]): void {
@@ -12,9 +12,9 @@ import { IRenderDimensions, IRenderer, IRequestRedrawEvent, ISelectionRenderMode
12
12
  import { ICharSizeService, ICoreBrowserService, IThemeService } from 'browser/services/Services';
13
13
  import { ILinkifier2, ILinkifierEvent, ITerminal, ReadonlyColorSet } from 'browser/Types';
14
14
  import { color } from 'common/Color';
15
- import { EventEmitter } from 'common/EventEmitter';
16
- import { Disposable, toDisposable } from 'common/Lifecycle';
17
- import { IBufferService, IInstantiationService, IOptionsService } from 'common/services/Services';
15
+ import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
16
+ import { IBufferService, ICoreService, IInstantiationService, IOptionsService } from 'common/services/Services';
17
+ import { Emitter } from 'vs/base/common/event';
18
18
 
19
19
 
20
20
  const TERMINAL_CLASS_PREFIX = 'xterm-dom-renderer-owner-';
@@ -27,9 +27,9 @@ const SELECTION_CLASS = 'xterm-selection';
27
27
  let nextTerminalId = 1;
28
28
 
29
29
  /**
30
- * A fallback renderer for when canvas is slow. This is not meant to be
31
- * particularly fast or feature complete, more just stable and usable for when
32
- * canvas is not an option.
30
+ * The standard renderer and fallback for when the webgl addon is slow. This is not meant to be
31
+ * particularly fast and will even lack some features such as custom glyphs, hoever this is more
32
+ * reliable as webgl may not work on some machines.
33
33
  */
34
34
  export class DomRenderer extends Disposable implements IRenderer {
35
35
  private _rowFactory: DomRendererRowFactory;
@@ -45,7 +45,7 @@ export class DomRenderer extends Disposable implements IRenderer {
45
45
 
46
46
  public dimensions: IRenderDimensions;
47
47
 
48
- public readonly onRequestRedraw = this.register(new EventEmitter<IRequestRedrawEvent>()).event;
48
+ public readonly onRequestRedraw = this._register(new Emitter<IRequestRedrawEvent>()).event;
49
49
 
50
50
  constructor(
51
51
  private readonly _terminal: ITerminal,
@@ -59,6 +59,7 @@ export class DomRenderer extends Disposable implements IRenderer {
59
59
  @ICharSizeService private readonly _charSizeService: ICharSizeService,
60
60
  @IOptionsService private readonly _optionsService: IOptionsService,
61
61
  @IBufferService private readonly _bufferService: IBufferService,
62
+ @ICoreService private readonly _coreService: ICoreService,
62
63
  @ICoreBrowserService private readonly _coreBrowserService: ICoreBrowserService,
63
64
  @IThemeService private readonly _themeService: IThemeService
64
65
  ) {
@@ -74,9 +75,9 @@ export class DomRenderer extends Disposable implements IRenderer {
74
75
 
75
76
  this.dimensions = createRenderDimensions();
76
77
  this._updateDimensions();
77
- this.register(this._optionsService.onOptionChange(() => this._handleOptionsChanged()));
78
+ this._register(this._optionsService.onOptionChange(() => this._handleOptionsChanged()));
78
79
 
79
- this.register(this._themeService.onChangeColors(e => this._injectCss(e)));
80
+ this._register(this._themeService.onChangeColors(e => this._injectCss(e)));
80
81
  this._injectCss(this._themeService.colors);
81
82
 
82
83
  this._rowFactory = instantiationService.createInstance(DomRendererRowFactory, document);
@@ -85,10 +86,10 @@ export class DomRenderer extends Disposable implements IRenderer {
85
86
  this._screenElement.appendChild(this._rowContainer);
86
87
  this._screenElement.appendChild(this._selectionContainer);
87
88
 
88
- this.register(this._linkifier2.onShowLinkUnderline(e => this._handleLinkHover(e)));
89
- this.register(this._linkifier2.onHideLinkUnderline(e => this._handleLinkLeave(e)));
89
+ this._register(this._linkifier2.onShowLinkUnderline(e => this._handleLinkHover(e)));
90
+ this._register(this._linkifier2.onHideLinkUnderline(e => this._handleLinkLeave(e)));
90
91
 
91
- this.register(toDisposable(() => {
92
+ this._register(toDisposable(() => {
92
93
  this._element.classList.remove(TERMINAL_CLASS_PREFIX + this._terminalClass);
93
94
 
94
95
  // Outside influences such as React unmounts may manipulate the DOM before our disposal.
@@ -161,6 +162,10 @@ export class DomRenderer extends Disposable implements IRenderer {
161
162
  // Base CSS
162
163
  let styles =
163
164
  `${this._terminalSelector} .${ROW_CONTAINER_CLASS} {` +
165
+ // Disabling pointer events circumvents a browser behavior that prevents `click` events from
166
+ // being delivered if the target element is replaced during the click. This happened due to
167
+ // refresh() being called during the mousedown handler to start a selection.
168
+ ` pointer-events: none;` +
164
169
  ` color: ${colors.foreground.css};` +
165
170
  ` font-family: ${this._optionsService.rawOptions.fontFamily};` +
166
171
  ` font-size: ${this._optionsService.rawOptions.fontSize}px;` +
@@ -437,8 +442,8 @@ export class DomRenderer extends Disposable implements IRenderer {
437
442
  const buffer = this._bufferService.buffer;
438
443
  const cursorAbsoluteY = buffer.ybase + buffer.y;
439
444
  const cursorX = Math.min(buffer.x, this._bufferService.cols - 1);
440
- const cursorBlink = this._optionsService.rawOptions.cursorBlink;
441
- const cursorStyle = this._optionsService.rawOptions.cursorStyle;
445
+ const cursorBlink = this._coreService.decPrivateModes.cursorBlink ?? this._optionsService.rawOptions.cursorBlink;
446
+ const cursorStyle = this._coreService.decPrivateModes.cursorStyle ?? this._optionsService.rawOptions.cursorStyle;
442
447
  const cursorInactiveStyle = this._optionsService.rawOptions.cursorInactiveStyle;
443
448
 
444
449
  for (let y = start; y <= end; y++) {
@@ -84,6 +84,7 @@ export class DomRendererRowFactory {
84
84
  let charElement: HTMLSpanElement | undefined;
85
85
  let cellAmount = 0;
86
86
  let text = '';
87
+ let i = 0;
87
88
  let oldBg = 0;
88
89
  let oldFg = 0;
89
90
  let oldExt = 0;
@@ -91,6 +92,7 @@ export class DomRendererRowFactory {
91
92
  let oldSpacing = 0;
92
93
  let oldIsInSelection: boolean = false;
93
94
  let spacing = 0;
95
+ let skipJoinedCheckUntilX = 0;
94
96
  const classes: string[] = [];
95
97
 
96
98
  const hasHover = linkStart !== -1 && linkEnd !== -1;
@@ -106,29 +108,46 @@ export class DomRendererRowFactory {
106
108
 
107
109
  // If true, indicates that the current character(s) to draw were joined.
108
110
  let isJoined = false;
111
+
112
+ // Indicates whether this cell is part of a joined range that should be ignored as it cannot
113
+ // be rendered entirely, like the selection state differs across the range.
114
+ let isValidJoinRange = (x >= skipJoinedCheckUntilX);
115
+
109
116
  let lastCharX = x;
110
117
 
111
118
  // Process any joined character ranges as needed. Because of how the
112
119
  // ranges are produced, we know that they are valid for the characters
113
120
  // and attributes of our input.
114
121
  let cell = this._workCell;
115
- if (joinedRanges.length > 0 && x === joinedRanges[0][0]) {
116
- isJoined = true;
122
+ if (joinedRanges.length > 0 && x === joinedRanges[0][0] && isValidJoinRange) {
117
123
  const range = joinedRanges.shift()!;
124
+ // If the ligature's selection state is not consistent, don't join it. This helps the
125
+ // selection render correctly regardless whether they should be joined.
126
+ const firstSelectionState = this._isCellInSelection(range[0], row);
127
+ for (i = range[0] + 1; i < range[1]; i++) {
128
+ isValidJoinRange &&= (firstSelectionState === this._isCellInSelection(i, row));
129
+ }
130
+ // Similarly, if the cursor is in the ligature, don't join it.
131
+ isValidJoinRange &&= !isCursorRow || cursorX < range[0] || cursorX >= range[1];
132
+ if (!isValidJoinRange) {
133
+ skipJoinedCheckUntilX = range[1];
134
+ } else {
135
+ isJoined = true;
136
+
137
+ // We already know the exact start and end column of the joined range,
138
+ // so we get the string and width representing it directly
139
+ cell = new JoinedCellData(
140
+ this._workCell,
141
+ lineData.translateToString(true, range[0], range[1]),
142
+ range[1] - range[0]
143
+ );
118
144
 
119
- // We already know the exact start and end column of the joined range,
120
- // so we get the string and width representing it directly
121
- cell = new JoinedCellData(
122
- this._workCell,
123
- lineData.translateToString(true, range[0], range[1]),
124
- range[1] - range[0]
125
- );
126
-
127
- // Skip over the cells occupied by this range in the loop
128
- lastCharX = range[1] - 1;
145
+ // Skip over the cells occupied by this range in the loop
146
+ lastCharX = range[1] - 1;
129
147
 
130
- // Recalculate width
131
- width = cell.getWidth();
148
+ // Recalculate width
149
+ width = cell.getWidth();
150
+ }
132
151
  }
133
152
 
134
153
  const isInSelection = this._isCellInSelection(x, row);
@@ -178,6 +197,7 @@ export class DomRendererRowFactory {
178
197
  && !isCursorCell
179
198
  && !isJoined
180
199
  && !isDecorated
200
+ && isValidJoinRange
181
201
  ) {
182
202
  // no span alterations, thus only account chars skipping all code below
183
203
  if (cell.isInvisible()) {
@@ -435,7 +455,7 @@ export class DomRendererRowFactory {
435
455
  }
436
456
 
437
457
  // exclude conditions for cell merging - never merge these
438
- if (!isCursorCell && !isJoined && !isDecorated) {
458
+ if (!isCursorCell && !isJoined && !isDecorated && isValidJoinRange) {
439
459
  cellAmount++;
440
460
  } else {
441
461
  charElement.textContent = text;
@@ -3,12 +3,4 @@
3
3
  * @license MIT
4
4
  */
5
5
 
6
- import { isFirefox, isLegacyEdge } from 'common/Platform';
7
-
8
6
  export const INVERTED_DEFAULT_COLOR = 257;
9
-
10
- export const DIM_OPACITY = 0.5;
11
- // The text baseline is set conditionally by browser. Using 'ideographic' for Firefox or Legacy Edge
12
- // would result in truncated text (Issue 3353). Using 'bottom' for Chrome would result in slightly
13
- // unaligned Powerline fonts (PR 3356#issuecomment-850928179).
14
- export const TEXT_BASELINE: CanvasTextBaseline = isFirefox || isLegacyEdge ? 'bottom' : 'ideographic';
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Copyright (c) 2017 The xterm.js authors. All rights reserved.
3
+ * @license MIT
4
+ */
5
+
6
+ import { Terminal } from '@xterm/xterm';
7
+ import { ITerminal } from 'browser/Types';
8
+ import { IDisposable } from 'common/Types';
9
+ import type { Event } from 'vs/base/common/event';
10
+
11
+ export interface IDimensions {
12
+ width: number;
13
+ height: number;
14
+ }
15
+
16
+ export interface IOffset {
17
+ top: number;
18
+ left: number;
19
+ }
20
+
21
+ export interface IRenderDimensions {
22
+ /**
23
+ * Dimensions measured in CSS pixels (ie. device pixels / device pixel ratio).
24
+ */
25
+ css: {
26
+ canvas: IDimensions;
27
+ cell: IDimensions;
28
+ };
29
+ /**
30
+ * Dimensions measured in actual pixels as rendered to the device.
31
+ */
32
+ device: {
33
+ canvas: IDimensions;
34
+ cell: IDimensions;
35
+ char: IDimensions & IOffset;
36
+ };
37
+ }
38
+
39
+ export interface IRequestRedrawEvent {
40
+ start: number;
41
+ end: number;
42
+ }
43
+
44
+ /**
45
+ * Note that IRenderer implementations should emit the refresh event after
46
+ * rendering rows to the screen.
47
+ */
48
+ export interface IRenderer extends IDisposable {
49
+ readonly dimensions: IRenderDimensions;
50
+
51
+ /**
52
+ * Fires when the renderer is requesting to be redrawn on the next animation
53
+ * frame but is _not_ a result of content changing (eg. selection changes).
54
+ */
55
+ readonly onRequestRedraw: Event<IRequestRedrawEvent>;
56
+
57
+ dispose(): void;
58
+ handleDevicePixelRatioChange(): void;
59
+ handleResize(cols: number, rows: number): void;
60
+ handleCharSizeChanged(): void;
61
+ handleBlur(): void;
62
+ handleFocus(): void;
63
+ handleSelectionChanged(start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode: boolean): void;
64
+ handleCursorMove(): void;
65
+ clear(): void;
66
+ renderRows(start: number, end: number): void;
67
+ clearTextureAtlas?(): void;
68
+ }
69
+
70
+ export interface ISelectionRenderModel {
71
+ readonly hasSelection: boolean;
72
+ readonly columnSelectMode: boolean;
73
+ readonly viewportStartRow: number;
74
+ readonly viewportEndRow: number;
75
+ readonly viewportCappedStartRow: number;
76
+ readonly viewportCappedEndRow: number;
77
+ readonly startCol: number;
78
+ readonly endCol: number;
79
+ readonly selectionStart: [number, number] | undefined;
80
+ readonly selectionEnd: [number, number] | undefined;
81
+ clear(): void;
82
+ update(terminal: ITerminal, start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode?: boolean): void;
83
+ isCellSelected(terminal: Terminal, x: number, y: number): boolean;
84
+ }
@@ -4,9 +4,9 @@
4
4
  */
5
5
 
6
6
  import { IOptionsService } from 'common/services/Services';
7
- import { EventEmitter } from 'common/EventEmitter';
8
7
  import { ICharSizeService } from 'browser/services/Services';
9
- import { Disposable } from 'common/Lifecycle';
8
+ import { Disposable } from 'vs/base/common/lifecycle';
9
+ import { Emitter } from 'vs/base/common/event';
10
10
 
11
11
  export class CharSizeService extends Disposable implements ICharSizeService {
12
12
  public serviceBrand: undefined;
@@ -17,7 +17,7 @@ export class CharSizeService extends Disposable implements ICharSizeService {
17
17
 
18
18
  public get hasValidSize(): boolean { return this.width > 0 && this.height > 0; }
19
19
 
20
- private readonly _onCharSizeChange = this.register(new EventEmitter<void>());
20
+ private readonly _onCharSizeChange = this._register(new Emitter<void>());
21
21
  public readonly onCharSizeChange = this._onCharSizeChange.event;
22
22
 
23
23
  constructor(
@@ -27,11 +27,11 @@ export class CharSizeService extends Disposable implements ICharSizeService {
27
27
  ) {
28
28
  super();
29
29
  try {
30
- this._measureStrategy = this.register(new TextMetricsMeasureStrategy(this._optionsService));
30
+ this._measureStrategy = this._register(new TextMetricsMeasureStrategy(this._optionsService));
31
31
  } catch {
32
- this._measureStrategy = this.register(new DomMeasureStrategy(document, parentElement, this._optionsService));
32
+ this._measureStrategy = this._register(new DomMeasureStrategy(document, parentElement, this._optionsService));
33
33
  }
34
- this.register(this._optionsService.onMultipleOptionChange(['fontFamily', 'fontSize'], () => this.measure()));
34
+ this._register(this._optionsService.onMultipleOptionChange(['fontFamily', 'fontSize'], () => this.measure()));
35
35
  }
36
36
 
37
37
  public measure(): void {