@xterm/xterm 5.6.0-beta.7 → 5.6.0-beta.70

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 (118) hide show
  1. package/README.md +6 -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 +43 -33
  8. package/src/browser/AccessibilityManager.ts +53 -25
  9. package/src/browser/{Terminal.ts → CoreBrowserTerminal.ts} +135 -146
  10. package/src/browser/Linkifier.ts +26 -14
  11. package/src/browser/LocalizableStrings.ts +15 -4
  12. package/src/browser/{Types.d.ts → Types.ts} +67 -15
  13. package/src/browser/Viewport.ts +143 -370
  14. package/src/browser/decorations/BufferDecorationRenderer.ts +14 -9
  15. package/src/browser/decorations/OverviewRulerRenderer.ts +40 -44
  16. package/src/browser/public/Terminal.ts +25 -19
  17. package/src/browser/renderer/dom/DomRenderer.ts +14 -16
  18. package/src/browser/renderer/shared/CharAtlasUtils.ts +4 -0
  19. package/src/browser/renderer/shared/CustomGlyphs.ts +6 -0
  20. package/src/browser/renderer/shared/DevicePixelObserver.ts +1 -2
  21. package/src/browser/renderer/shared/TextureAtlas.ts +3 -3
  22. package/src/browser/renderer/shared/{Types.d.ts → Types.ts} +4 -4
  23. package/src/browser/services/CharSizeService.ts +6 -6
  24. package/src/browser/services/CoreBrowserService.ts +15 -15
  25. package/src/browser/services/LinkProviderService.ts +2 -2
  26. package/src/browser/services/RenderService.ts +20 -20
  27. package/src/browser/services/SelectionService.ts +8 -8
  28. package/src/browser/services/Services.ts +13 -13
  29. package/src/browser/services/ThemeService.ts +17 -56
  30. package/src/browser/shared/Constants.ts +8 -0
  31. package/src/common/CircularList.ts +5 -5
  32. package/src/common/CoreTerminal.ts +35 -41
  33. package/src/common/InputHandler.ts +34 -28
  34. package/src/common/{Types.d.ts → Types.ts} +11 -17
  35. package/src/common/buffer/Buffer.ts +5 -1
  36. package/src/common/buffer/BufferSet.ts +5 -5
  37. package/src/common/buffer/Marker.ts +4 -4
  38. package/src/common/buffer/{Types.d.ts → Types.ts} +2 -2
  39. package/src/common/input/WriteBuffer.ts +3 -3
  40. package/src/common/parser/EscapeSequenceParser.ts +4 -4
  41. package/src/common/public/BufferNamespaceApi.ts +3 -3
  42. package/src/common/services/BufferService.ts +7 -7
  43. package/src/common/services/CoreMouseService.ts +5 -3
  44. package/src/common/services/CoreService.ts +6 -6
  45. package/src/common/services/DecorationService.ts +8 -9
  46. package/src/common/services/LogService.ts +2 -2
  47. package/src/common/services/OptionsService.ts +5 -5
  48. package/src/common/services/Services.ts +24 -17
  49. package/src/common/services/UnicodeService.ts +2 -2
  50. package/src/vs/base/browser/browser.ts +141 -0
  51. package/src/vs/base/browser/canIUse.ts +49 -0
  52. package/src/vs/base/browser/dom.ts +2369 -0
  53. package/src/vs/base/browser/fastDomNode.ts +316 -0
  54. package/src/vs/base/browser/globalPointerMoveMonitor.ts +112 -0
  55. package/src/vs/base/browser/iframe.ts +135 -0
  56. package/src/vs/base/browser/keyboardEvent.ts +213 -0
  57. package/src/vs/base/browser/mouseEvent.ts +229 -0
  58. package/src/vs/base/browser/touch.ts +372 -0
  59. package/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts +303 -0
  60. package/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts +114 -0
  61. package/src/vs/base/browser/ui/scrollbar/scrollableElement.ts +720 -0
  62. package/src/vs/base/browser/ui/scrollbar/scrollableElementOptions.ts +165 -0
  63. package/src/vs/base/browser/ui/scrollbar/scrollbarArrow.ts +114 -0
  64. package/src/vs/base/browser/ui/scrollbar/scrollbarState.ts +243 -0
  65. package/src/vs/base/browser/ui/scrollbar/scrollbarVisibilityController.ts +118 -0
  66. package/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts +116 -0
  67. package/src/vs/base/browser/ui/widget.ts +57 -0
  68. package/src/vs/base/browser/window.ts +14 -0
  69. package/src/vs/base/common/arrays.ts +887 -0
  70. package/src/vs/base/common/arraysFind.ts +202 -0
  71. package/src/vs/base/common/assert.ts +71 -0
  72. package/src/vs/base/common/async.ts +1992 -0
  73. package/src/vs/base/common/cancellation.ts +148 -0
  74. package/src/vs/base/common/charCode.ts +450 -0
  75. package/src/vs/base/common/collections.ts +140 -0
  76. package/src/vs/base/common/decorators.ts +130 -0
  77. package/src/vs/base/common/equals.ts +146 -0
  78. package/src/vs/base/common/errors.ts +303 -0
  79. package/src/vs/base/common/event.ts +1778 -0
  80. package/src/vs/base/common/functional.ts +32 -0
  81. package/src/vs/base/common/hash.ts +316 -0
  82. package/src/vs/base/common/iterator.ts +159 -0
  83. package/src/vs/base/common/keyCodes.ts +526 -0
  84. package/src/vs/base/common/keybindings.ts +284 -0
  85. package/src/vs/base/common/lazy.ts +47 -0
  86. package/src/vs/base/common/lifecycle.ts +801 -0
  87. package/src/vs/base/common/linkedList.ts +142 -0
  88. package/src/vs/base/common/map.ts +202 -0
  89. package/src/vs/base/common/numbers.ts +98 -0
  90. package/src/vs/base/common/observable.ts +76 -0
  91. package/src/vs/base/common/observableInternal/api.ts +31 -0
  92. package/src/vs/base/common/observableInternal/autorun.ts +281 -0
  93. package/src/vs/base/common/observableInternal/base.ts +489 -0
  94. package/src/vs/base/common/observableInternal/debugName.ts +145 -0
  95. package/src/vs/base/common/observableInternal/derived.ts +428 -0
  96. package/src/vs/base/common/observableInternal/lazyObservableValue.ts +146 -0
  97. package/src/vs/base/common/observableInternal/logging.ts +328 -0
  98. package/src/vs/base/common/observableInternal/promise.ts +209 -0
  99. package/src/vs/base/common/observableInternal/utils.ts +610 -0
  100. package/src/vs/base/common/platform.ts +281 -0
  101. package/src/vs/base/common/scrollable.ts +522 -0
  102. package/src/vs/base/common/sequence.ts +34 -0
  103. package/src/vs/base/common/stopwatch.ts +43 -0
  104. package/src/vs/base/common/strings.ts +557 -0
  105. package/src/vs/base/common/symbols.ts +9 -0
  106. package/src/vs/base/common/uint.ts +59 -0
  107. package/src/vs/patches/nls.ts +90 -0
  108. package/src/vs/typings/base-common.d.ts +20 -0
  109. package/src/vs/typings/require.d.ts +42 -0
  110. package/src/vs/typings/thenable.d.ts +12 -0
  111. package/src/vs/typings/vscode-globals-nls.d.ts +36 -0
  112. package/src/vs/typings/vscode-globals-product.d.ts +33 -0
  113. package/typings/xterm.d.ts +59 -15
  114. package/src/browser/Lifecycle.ts +0 -33
  115. package/src/common/EventEmitter.ts +0 -78
  116. package/src/common/Lifecycle.ts +0 -108
  117. /package/src/browser/selection/{Types.d.ts → Types.ts} +0 -0
  118. /package/src/common/parser/{Types.d.ts → Types.ts} +0 -0
@@ -21,12 +21,11 @@
21
21
  * http://linux.die.net/man/7/urxvt
22
22
  */
23
23
 
24
+ import { IDecoration, IDecorationOptions, IDisposable, ILinkProvider, IMarker } from '@xterm/xterm';
24
25
  import { copyHandler, handlePasteEvent, moveTextAreaUnderMouseCursor, paste, rightClickHandler } from 'browser/Clipboard';
25
- import { addDisposableDomListener } from 'browser/Lifecycle';
26
- import { Linkifier } from './Linkifier';
27
26
  import * as Strings from 'browser/LocalizableStrings';
28
27
  import { OscLinkProvider } from 'browser/OscLinkProvider';
29
- import { CharacterJoinerHandler, CustomKeyEventHandler, CustomWheelEventHandler, IBrowser, IBufferRange, ICompositionHelper, ILinkifier2, ITerminal, IViewport } from 'browser/Types';
28
+ import { CharacterJoinerHandler, CustomKeyEventHandler, CustomWheelEventHandler, IBrowser, IBufferRange, ICompositionHelper, ILinkifier2, ITerminal } from 'browser/Types';
30
29
  import { Viewport } from 'browser/Viewport';
31
30
  import { BufferDecorationRenderer } from 'browser/decorations/BufferDecorationRenderer';
32
31
  import { OverviewRulerRenderer } from 'browser/decorations/OverviewRulerRenderer';
@@ -36,6 +35,7 @@ import { IRenderer } from 'browser/renderer/shared/Types';
36
35
  import { CharSizeService } from 'browser/services/CharSizeService';
37
36
  import { CharacterJoinerService } from 'browser/services/CharacterJoinerService';
38
37
  import { CoreBrowserService } from 'browser/services/CoreBrowserService';
38
+ import { LinkProviderService } from 'browser/services/LinkProviderService';
39
39
  import { MouseService } from 'browser/services/MouseService';
40
40
  import { RenderService } from 'browser/services/RenderService';
41
41
  import { SelectionService } from 'browser/services/SelectionService';
@@ -43,10 +43,8 @@ import { ICharSizeService, ICharacterJoinerService, ICoreBrowserService, ILinkPr
43
43
  import { ThemeService } from 'browser/services/ThemeService';
44
44
  import { channels, color } from 'common/Color';
45
45
  import { CoreTerminal } from 'common/CoreTerminal';
46
- import { EventEmitter, IEvent, forwardEvent } from 'common/EventEmitter';
47
- import { MutableDisposable, toDisposable } from 'common/Lifecycle';
48
46
  import * as Browser from 'common/Platform';
49
- import { ColorRequestType, CoreMouseAction, CoreMouseButton, CoreMouseEventType, IColorEvent, ITerminalOptions, KeyboardResultType, ScrollSource, SpecialColorIndex } from 'common/Types';
47
+ import { ColorRequestType, CoreMouseAction, CoreMouseButton, CoreMouseEventType, IColorEvent, ITerminalOptions, KeyboardResultType, SpecialColorIndex } from 'common/Types';
50
48
  import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine';
51
49
  import { IBuffer } from 'common/buffer/Types';
52
50
  import { C0, C1_ESCAPED } from 'common/data/EscapeSequences';
@@ -54,24 +52,27 @@ import { evaluateKeyboardEvent } from 'common/input/Keyboard';
54
52
  import { toRgbString } from 'common/input/XParseColor';
55
53
  import { DecorationService } from 'common/services/DecorationService';
56
54
  import { IDecorationService } from 'common/services/Services';
57
- import { IDecoration, IDecorationOptions, IDisposable, ILinkProvider, IMarker } from '@xterm/xterm';
58
55
  import { WindowsOptionsReportType } from '../common/InputHandler';
59
56
  import { AccessibilityManager } from './AccessibilityManager';
60
- import { LinkProviderService } from 'browser/services/LinkProviderService';
57
+ import { Linkifier } from './Linkifier';
58
+ import { Emitter, Event } from 'vs/base/common/event';
59
+ import { addDisposableListener } from 'vs/base/browser/dom';
60
+ import { MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
61
61
 
62
- export class Terminal extends CoreTerminal implements ITerminal {
62
+ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
63
63
  public textarea: HTMLTextAreaElement | undefined;
64
64
  public element: HTMLElement | undefined;
65
65
  public screenElement: HTMLElement | undefined;
66
66
 
67
67
  private _document: Document | undefined;
68
- private _viewportScrollArea: HTMLElement | undefined;
69
68
  private _viewportElement: HTMLElement | undefined;
70
69
  private _helperContainer: HTMLElement | undefined;
71
70
  private _compositionView: HTMLElement | undefined;
72
71
 
73
- public linkifier: ILinkifier2 | undefined;
72
+ private readonly _linkifier: MutableDisposable<ILinkifier2> = this._register(new MutableDisposable());
73
+ public get linkifier(): ILinkifier2 | undefined { return this._linkifier.value; }
74
74
  private _overviewRulerRenderer: OverviewRulerRenderer | undefined;
75
+ private _viewport: Viewport | undefined;
75
76
 
76
77
  public browser: IBrowser = Browser as any;
77
78
 
@@ -118,33 +119,32 @@ export class Terminal extends CoreTerminal implements ITerminal {
118
119
  */
119
120
  private _unprocessedDeadKey: boolean = false;
120
121
 
121
- public viewport: IViewport | undefined;
122
122
  private _compositionHelper: ICompositionHelper | undefined;
123
- private _accessibilityManager: MutableDisposable<AccessibilityManager> = this.register(new MutableDisposable());
123
+ private _accessibilityManager: MutableDisposable<AccessibilityManager> = this._register(new MutableDisposable());
124
124
 
125
- private readonly _onCursorMove = this.register(new EventEmitter<void>());
125
+ private readonly _onCursorMove = this._register(new Emitter<void>());
126
126
  public readonly onCursorMove = this._onCursorMove.event;
127
- private readonly _onKey = this.register(new EventEmitter<{ key: string, domEvent: KeyboardEvent }>());
127
+ private readonly _onKey = this._register(new Emitter<{ key: string, domEvent: KeyboardEvent }>());
128
128
  public readonly onKey = this._onKey.event;
129
- private readonly _onRender = this.register(new EventEmitter<{ start: number, end: number }>());
129
+ private readonly _onRender = this._register(new Emitter<{ start: number, end: number }>());
130
130
  public readonly onRender = this._onRender.event;
131
- private readonly _onSelectionChange = this.register(new EventEmitter<void>());
131
+ private readonly _onSelectionChange = this._register(new Emitter<void>());
132
132
  public readonly onSelectionChange = this._onSelectionChange.event;
133
- private readonly _onTitleChange = this.register(new EventEmitter<string>());
133
+ private readonly _onTitleChange = this._register(new Emitter<string>());
134
134
  public readonly onTitleChange = this._onTitleChange.event;
135
- private readonly _onBell = this.register(new EventEmitter<void>());
135
+ private readonly _onBell = this._register(new Emitter<void>());
136
136
  public readonly onBell = this._onBell.event;
137
137
 
138
- private _onFocus = this.register(new EventEmitter<void>());
139
- public get onFocus(): IEvent<void> { return this._onFocus.event; }
140
- private _onBlur = this.register(new EventEmitter<void>());
141
- public get onBlur(): IEvent<void> { return this._onBlur.event; }
142
- private _onA11yCharEmitter = this.register(new EventEmitter<string>());
143
- public get onA11yChar(): IEvent<string> { return this._onA11yCharEmitter.event; }
144
- private _onA11yTabEmitter = this.register(new EventEmitter<number>());
145
- public get onA11yTab(): IEvent<number> { return this._onA11yTabEmitter.event; }
146
- private _onWillOpen = this.register(new EventEmitter<HTMLElement>());
147
- public get onWillOpen(): IEvent<HTMLElement> { return this._onWillOpen.event; }
138
+ private _onFocus = this._register(new Emitter<void>());
139
+ public get onFocus(): Event<void> { return this._onFocus.event; }
140
+ private _onBlur = this._register(new Emitter<void>());
141
+ public get onBlur(): Event<void> { return this._onBlur.event; }
142
+ private _onA11yCharEmitter = this._register(new Emitter<string>());
143
+ public get onA11yChar(): Event<string> { return this._onA11yCharEmitter.event; }
144
+ private _onA11yTabEmitter = this._register(new Emitter<number>());
145
+ public get onA11yTab(): Event<number> { return this._onA11yTabEmitter.event; }
146
+ private _onWillOpen = this._register(new Emitter<HTMLElement>());
147
+ public get onWillOpen(): Event<HTMLElement> { return this._onWillOpen.event; }
148
148
 
149
149
  constructor(
150
150
  options: Partial<ITerminalOptions> = {}
@@ -160,21 +160,21 @@ export class Terminal extends CoreTerminal implements ITerminal {
160
160
  this._linkProviderService.registerLinkProvider(this._instantiationService.createInstance(OscLinkProvider));
161
161
 
162
162
  // Setup InputHandler listeners
163
- this.register(this._inputHandler.onRequestBell(() => this._onBell.fire()));
164
- this.register(this._inputHandler.onRequestRefreshRows((start, end) => this.refresh(start, end)));
165
- this.register(this._inputHandler.onRequestSendFocus(() => this._reportFocus()));
166
- this.register(this._inputHandler.onRequestReset(() => this.reset()));
167
- this.register(this._inputHandler.onRequestWindowsOptionsReport(type => this._reportWindowsOptions(type)));
168
- this.register(this._inputHandler.onColor((event) => this._handleColorEvent(event)));
169
- this.register(forwardEvent(this._inputHandler.onCursorMove, this._onCursorMove));
170
- this.register(forwardEvent(this._inputHandler.onTitleChange, this._onTitleChange));
171
- this.register(forwardEvent(this._inputHandler.onA11yChar, this._onA11yCharEmitter));
172
- this.register(forwardEvent(this._inputHandler.onA11yTab, this._onA11yTabEmitter));
163
+ this._register(this._inputHandler.onRequestBell(() => this._onBell.fire()));
164
+ this._register(this._inputHandler.onRequestRefreshRows((e) => this.refresh(e?.start ?? 0, e?.end ?? (this.rows - 1))));
165
+ this._register(this._inputHandler.onRequestSendFocus(() => this._reportFocus()));
166
+ this._register(this._inputHandler.onRequestReset(() => this.reset()));
167
+ this._register(this._inputHandler.onRequestWindowsOptionsReport(type => this._reportWindowsOptions(type)));
168
+ this._register(this._inputHandler.onColor((event) => this._handleColorEvent(event)));
169
+ this._register(Event.forward(this._inputHandler.onCursorMove, this._onCursorMove));
170
+ this._register(Event.forward(this._inputHandler.onTitleChange, this._onTitleChange));
171
+ this._register(Event.forward(this._inputHandler.onA11yChar, this._onA11yCharEmitter));
172
+ this._register(Event.forward(this._inputHandler.onA11yTab, this._onA11yTabEmitter));
173
173
 
174
174
  // Setup listeners
175
- this.register(this._bufferService.onResize(e => this._afterResize(e.cols, e.rows)));
175
+ this._register(this._bufferService.onResize(e => this._afterResize(e.cols, e.rows)));
176
176
 
177
- this.register(toDisposable(() => {
177
+ this._register(toDisposable(() => {
178
178
  this._customKeyEventHandler = undefined;
179
179
  this.element?.parentNode?.removeChild(this.element);
180
180
  }));
@@ -331,7 +331,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
331
331
  this._bindKeys();
332
332
 
333
333
  // Bind clipboard functionality
334
- this.register(addDisposableDomListener(this.element!, 'copy', (event: ClipboardEvent) => {
334
+ this._register(addDisposableListener(this.element!, 'copy', (event: ClipboardEvent) => {
335
335
  // If mouse events are active it means the selection manager is disabled and
336
336
  // copy should be handled by the host program.
337
337
  if (!this.hasSelection()) {
@@ -340,19 +340,19 @@ export class Terminal extends CoreTerminal implements ITerminal {
340
340
  copyHandler(event, this._selectionService!);
341
341
  }));
342
342
  const pasteHandlerWrapper = (event: ClipboardEvent): void => handlePasteEvent(event, this.textarea!, this.coreService, this.optionsService);
343
- this.register(addDisposableDomListener(this.textarea!, 'paste', pasteHandlerWrapper));
344
- this.register(addDisposableDomListener(this.element!, 'paste', pasteHandlerWrapper));
343
+ this._register(addDisposableListener(this.textarea!, 'paste', pasteHandlerWrapper));
344
+ this._register(addDisposableListener(this.element!, 'paste', pasteHandlerWrapper));
345
345
 
346
346
  // Handle right click context menus
347
347
  if (Browser.isFirefox) {
348
348
  // Firefox doesn't appear to fire the contextmenu event on right click
349
- this.register(addDisposableDomListener(this.element!, 'mousedown', (event: MouseEvent) => {
349
+ this._register(addDisposableListener(this.element!, 'mousedown', (event: MouseEvent) => {
350
350
  if (event.button === 2) {
351
351
  rightClickHandler(event, this.textarea!, this.screenElement!, this._selectionService!, this.options.rightClickSelectsWord);
352
352
  }
353
353
  }));
354
354
  } else {
355
- this.register(addDisposableDomListener(this.element!, 'contextmenu', (event: MouseEvent) => {
355
+ this._register(addDisposableListener(this.element!, 'contextmenu', (event: MouseEvent) => {
356
356
  rightClickHandler(event, this.textarea!, this.screenElement!, this._selectionService!, this.options.rightClickSelectsWord);
357
357
  }));
358
358
  }
@@ -363,7 +363,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
363
363
  if (Browser.isLinux) {
364
364
  // Use auxclick event over mousedown the latter doesn't seem to work. Note
365
365
  // that the regular click event doesn't fire for the middle mouse button.
366
- this.register(addDisposableDomListener(this.element!, 'auxclick', (event: MouseEvent) => {
366
+ this._register(addDisposableListener(this.element!, 'auxclick', (event: MouseEvent) => {
367
367
  if (event.button === 1) {
368
368
  moveTextAreaUnderMouseCursor(event, this.textarea!, this.screenElement!);
369
369
  }
@@ -375,14 +375,14 @@ export class Terminal extends CoreTerminal implements ITerminal {
375
375
  * Apply key handling to the terminal
376
376
  */
377
377
  private _bindKeys(): void {
378
- this.register(addDisposableDomListener(this.textarea!, 'keyup', (ev: KeyboardEvent) => this._keyUp(ev), true));
379
- this.register(addDisposableDomListener(this.textarea!, 'keydown', (ev: KeyboardEvent) => this._keyDown(ev), true));
380
- this.register(addDisposableDomListener(this.textarea!, 'keypress', (ev: KeyboardEvent) => this._keyPress(ev), true));
381
- this.register(addDisposableDomListener(this.textarea!, 'compositionstart', () => this._compositionHelper!.compositionstart()));
382
- this.register(addDisposableDomListener(this.textarea!, 'compositionupdate', (e: CompositionEvent) => this._compositionHelper!.compositionupdate(e)));
383
- this.register(addDisposableDomListener(this.textarea!, 'compositionend', () => this._compositionHelper!.compositionend()));
384
- this.register(addDisposableDomListener(this.textarea!, 'input', (ev: InputEvent) => this._inputEvent(ev), true));
385
- this.register(this.onRender(() => this._compositionHelper!.updateCompositionElements()));
378
+ this._register(addDisposableListener(this.textarea!, 'keyup', (ev: KeyboardEvent) => this._keyUp(ev), true));
379
+ this._register(addDisposableListener(this.textarea!, 'keydown', (ev: KeyboardEvent) => this._keyDown(ev), true));
380
+ this._register(addDisposableListener(this.textarea!, 'keypress', (ev: KeyboardEvent) => this._keyPress(ev), true));
381
+ this._register(addDisposableListener(this.textarea!, 'compositionstart', () => this._compositionHelper!.compositionstart()));
382
+ this._register(addDisposableListener(this.textarea!, 'compositionupdate', (e: CompositionEvent) => this._compositionHelper!.compositionupdate(e)));
383
+ this._register(addDisposableListener(this.textarea!, 'compositionend', () => this._compositionHelper!.compositionend()));
384
+ this._register(addDisposableListener(this.textarea!, 'input', (ev: InputEvent) => this._inputEvent(ev), true));
385
+ this._register(this.onRender(() => this._compositionHelper!.updateCompositionElements()));
386
386
  }
387
387
 
388
388
  /**
@@ -427,13 +427,9 @@ export class Terminal extends CoreTerminal implements ITerminal {
427
427
  this._viewportElement.classList.add('xterm-viewport');
428
428
  fragment.appendChild(this._viewportElement);
429
429
 
430
- this._viewportScrollArea = this._document.createElement('div');
431
- this._viewportScrollArea.classList.add('xterm-scroll-area');
432
- this._viewportElement.appendChild(this._viewportScrollArea);
433
-
434
430
  this.screenElement = this._document.createElement('div');
435
431
  this.screenElement.classList.add('xterm-screen');
436
- this.register(addDisposableDomListener(this.screenElement, 'mousemove', (ev: MouseEvent) => this.updateCursorStyle(ev)));
432
+ this._register(addDisposableListener(this.screenElement, 'mousemove', (ev: MouseEvent) => this.updateCursorStyle(ev)));
437
433
  // Create the container that will hold helpers like the textarea for
438
434
  // capturing DOM Events. Then produce the helpers.
439
435
  this._helperContainer = this._document.createElement('div');
@@ -443,7 +439,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
443
439
 
444
440
  this.textarea = this._document.createElement('textarea');
445
441
  this.textarea.classList.add('xterm-helper-textarea');
446
- this.textarea.setAttribute('aria-label', Strings.promptLabel);
442
+ this.textarea.setAttribute('aria-label', Strings.promptLabel.get());
447
443
  if (!Browser.isChromeOS) {
448
444
  // ChromeVox on ChromeOS does not like this. See
449
445
  // https://issuetracker.google.com/issues/260170397
@@ -456,7 +452,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
456
452
 
457
453
  // Register the core browser service before the generic textarea handlers are registered so it
458
454
  // handles them first. Otherwise the renderers may use the wrong focus state.
459
- this._coreBrowserService = this.register(this._instantiationService.createInstance(CoreBrowserService,
455
+ this._coreBrowserService = this._register(this._instantiationService.createInstance(CoreBrowserService,
460
456
  this.textarea,
461
457
  parent.ownerDocument.defaultView ?? window,
462
458
  // Force unsafe null in node.js environment for tests
@@ -464,8 +460,8 @@ export class Terminal extends CoreTerminal implements ITerminal {
464
460
  ));
465
461
  this._instantiationService.setService(ICoreBrowserService, this._coreBrowserService);
466
462
 
467
- this.register(addDisposableDomListener(this.textarea, 'focus', (ev: FocusEvent) => this._handleTextAreaFocus(ev)));
468
- this.register(addDisposableDomListener(this.textarea, 'blur', () => this._handleTextAreaBlur()));
463
+ this._register(addDisposableListener(this.textarea, 'focus', (ev: FocusEvent) => this._handleTextAreaFocus(ev)));
464
+ this._register(addDisposableListener(this.textarea, 'blur', () => this._handleTextAreaBlur()));
469
465
  this._helperContainer.appendChild(this.textarea);
470
466
 
471
467
  this._charSizeService = this._instantiationService.createInstance(CharSizeService, this._document, this._helperContainer);
@@ -477,9 +473,9 @@ export class Terminal extends CoreTerminal implements ITerminal {
477
473
  this._characterJoinerService = this._instantiationService.createInstance(CharacterJoinerService);
478
474
  this._instantiationService.setService(ICharacterJoinerService, this._characterJoinerService);
479
475
 
480
- this._renderService = this.register(this._instantiationService.createInstance(RenderService, this.rows, this.screenElement));
476
+ this._renderService = this._register(this._instantiationService.createInstance(RenderService, this.rows, this.screenElement));
481
477
  this._instantiationService.setService(IRenderService, this._renderService);
482
- this.register(this._renderService.onRenderedViewportChange(e => this._onRender.fire(e)));
478
+ this._register(this._renderService.onRenderedViewportChange(e => this._onRender.fire(e)));
483
479
  this.onResize(e => this._renderService!.resize(e.cols, e.rows));
484
480
 
485
481
  this._compositionView = this._document.createElement('div');
@@ -490,7 +486,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
490
486
  this._mouseService = this._instantiationService.createInstance(MouseService);
491
487
  this._instantiationService.setService(IMouseService, this._mouseService);
492
488
 
493
- this.linkifier = this.register(this._instantiationService.createInstance(Linkifier, this.screenElement));
489
+ const linkifier = this._linkifier.value = this._register(this._instantiationService.createInstance(Linkifier, this.screenElement));
494
490
 
495
491
  // Performance: Add viewport and helper elements from the fragment
496
492
  this.element.appendChild(fragment);
@@ -503,30 +499,30 @@ export class Terminal extends CoreTerminal implements ITerminal {
503
499
  this._renderService.setRenderer(this._createRenderer());
504
500
  }
505
501
 
506
- this.viewport = this._instantiationService.createInstance(Viewport, this._viewportElement, this._viewportScrollArea);
507
- this.viewport.onRequestScrollLines(e => this.scrollLines(e.amount, e.suppressScrollEvent, ScrollSource.VIEWPORT)),
508
- this.register(this._inputHandler.onRequestSyncScrollBar(() => this.viewport!.syncScrollArea()));
509
- this.register(this.viewport);
510
-
511
- this.register(this.onCursorMove(() => {
502
+ this._register(this.onCursorMove(() => {
512
503
  this._renderService!.handleCursorMove();
513
504
  this._syncTextArea();
514
505
  }));
515
- this.register(this.onResize(() => this._renderService!.handleResize(this.cols, this.rows)));
516
- this.register(this.onBlur(() => this._renderService!.handleBlur()));
517
- this.register(this.onFocus(() => this._renderService!.handleFocus()));
518
- this.register(this._renderService.onDimensionsChange(() => this.viewport!.syncScrollArea()));
506
+ this._register(this.onResize(() => this._renderService!.handleResize(this.cols, this.rows)));
507
+ this._register(this.onBlur(() => this._renderService!.handleBlur()));
508
+ this._register(this.onFocus(() => this._renderService!.handleFocus()));
509
+
510
+ this._viewport = this._register(this._instantiationService.createInstance(Viewport, this.element, this.screenElement));
511
+ this._register(this._viewport.onRequestScrollLines(e => {
512
+ super.scrollLines(e, false);
513
+ this.refresh(0, this.rows - 1);
514
+ }));
519
515
 
520
- this._selectionService = this.register(this._instantiationService.createInstance(SelectionService,
516
+ this._selectionService = this._register(this._instantiationService.createInstance(SelectionService,
521
517
  this.element,
522
518
  this.screenElement,
523
- this.linkifier
519
+ linkifier
524
520
  ));
525
521
  this._instantiationService.setService(ISelectionService, this._selectionService);
526
- this.register(this._selectionService.onRequestScrollLines(e => this.scrollLines(e.amount, e.suppressScrollEvent)));
527
- this.register(this._selectionService.onSelectionChange(() => this._onSelectionChange.fire()));
528
- this.register(this._selectionService.onRequestRedraw(e => this._renderService!.handleSelectionChanged(e.start, e.end, e.columnSelectMode)));
529
- this.register(this._selectionService.onLinuxMouseSelection(text => {
522
+ this._register(this._selectionService.onRequestScrollLines(e => this.scrollLines(e.amount, e.suppressScrollEvent)));
523
+ this._register(this._selectionService.onSelectionChange(() => this._onSelectionChange.fire()));
524
+ this._register(this._selectionService.onRequestRedraw(e => this._renderService!.handleSelectionChanged(e.start, e.end, e.columnSelectMode)));
525
+ this._register(this._selectionService.onLinuxMouseSelection(text => {
530
526
  // If there's a new selection, put it into the textarea, focus and select it
531
527
  // in order to register it as a selection on the OS. This event is fired
532
528
  // only on Linux to enable middle click to paste selection.
@@ -534,14 +530,10 @@ export class Terminal extends CoreTerminal implements ITerminal {
534
530
  this.textarea!.focus();
535
531
  this.textarea!.select();
536
532
  }));
537
- this.register(this._onScroll.event(ev => {
538
- this.viewport!.syncScrollArea();
539
- this._selectionService!.refresh();
540
- }));
541
- this.register(addDisposableDomListener(this._viewportElement, 'scroll', () => this._selectionService!.refresh()));
533
+ this._register(this._onScroll.event(() => this._selectionService!.refresh()));
542
534
 
543
- this.register(this._instantiationService.createInstance(BufferDecorationRenderer, this.screenElement));
544
- this.register(addDisposableDomListener(this.element, 'mousedown', (e: MouseEvent) => this._selectionService!.handleMouseDown(e)));
535
+ this._register(this._instantiationService.createInstance(BufferDecorationRenderer, this.screenElement));
536
+ this._register(addDisposableListener(this.element, 'mousedown', (e: MouseEvent) => this._selectionService!.handleMouseDown(e)));
545
537
 
546
538
  // apply mouse event classes set by escape codes before terminal was attached
547
539
  if (this.coreMouseService.areMouseEventsActive) {
@@ -556,14 +548,14 @@ export class Terminal extends CoreTerminal implements ITerminal {
556
548
  // ensure the correct order of the dprchange event
557
549
  this._accessibilityManager.value = this._instantiationService.createInstance(AccessibilityManager, this);
558
550
  }
559
- this.register(this.optionsService.onSpecificOptionChange('screenReaderMode', e => this._handleScreenReaderModeOptionChange(e)));
551
+ this._register(this.optionsService.onSpecificOptionChange('screenReaderMode', e => this._handleScreenReaderModeOptionChange(e)));
560
552
 
561
- if (this.options.overviewRulerWidth) {
562
- this._overviewRulerRenderer = this.register(this._instantiationService.createInstance(OverviewRulerRenderer, this._viewportElement, this.screenElement));
553
+ if (this.options.overviewRuler.width) {
554
+ this._overviewRulerRenderer = this._register(this._instantiationService.createInstance(OverviewRulerRenderer, this._viewportElement, this.screenElement));
563
555
  }
564
- this.optionsService.onSpecificOptionChange('overviewRulerWidth', value => {
556
+ this.optionsService.onSpecificOptionChange('overviewRuler', value => {
565
557
  if (!this._overviewRulerRenderer && value && this._viewportElement && this.screenElement) {
566
- this._overviewRulerRenderer = this.register(this._instantiationService.createInstance(OverviewRulerRenderer, this._viewportElement, this.screenElement));
558
+ this._overviewRulerRenderer = this._register(this._instantiationService.createInstance(OverviewRulerRenderer, this._viewportElement, this.screenElement));
567
559
  }
568
560
  });
569
561
  // Measure the character size
@@ -642,13 +634,11 @@ export class Terminal extends CoreTerminal implements ITerminal {
642
634
  if (self._customWheelEventHandler && self._customWheelEventHandler(ev as WheelEvent) === false) {
643
635
  return false;
644
636
  }
645
- const amount = self.viewport!.getLinesScrolled(ev as WheelEvent);
646
-
647
- if (amount === 0) {
637
+ const deltaY = (ev as WheelEvent).deltaY;
638
+ if (deltaY === 0) {
648
639
  return false;
649
640
  }
650
-
651
- action = (ev as WheelEvent).deltaY < 0 ? CoreMouseAction.UP : CoreMouseAction.DOWN;
641
+ action = deltaY < 0 ? CoreMouseAction.UP : CoreMouseAction.DOWN;
652
642
  but = CoreMouseButton.WHEEL;
653
643
  break;
654
644
  default:
@@ -683,7 +673,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
683
673
  * Note: 'mousedown' currently is "always on" and not managed
684
674
  * by onProtocolChange.
685
675
  */
686
- const requestedEvents: { [key: string]: ((ev: Event) => void) | null } = {
676
+ const requestedEvents: { [key: string]: ((ev: MouseEvent | WheelEvent) => void) | null } = {
687
677
  mouseup: null,
688
678
  wheel: null,
689
679
  mousedrag: null,
@@ -718,7 +708,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
718
708
  }
719
709
  }
720
710
  };
721
- this.register(this.coreMouseService.onProtocolChange(events => {
711
+ this._register(this.coreMouseService.onProtocolChange(events => {
722
712
  // apply global changes on events
723
713
  if (events) {
724
714
  if (this.optionsService.rawOptions.logLevel === 'debug') {
@@ -770,7 +760,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
770
760
  /**
771
761
  * "Always on" event listeners.
772
762
  */
773
- this.register(addDisposableDomListener(el, 'mousedown', (ev: MouseEvent) => {
763
+ this._register(addDisposableListener(el, 'mousedown', (ev: MouseEvent) => {
774
764
  ev.preventDefault();
775
765
  this.focus();
776
766
 
@@ -797,7 +787,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
797
787
  return this.cancel(ev);
798
788
  }));
799
789
 
800
- this.register(addDisposableDomListener(el, 'wheel', (ev: WheelEvent) => {
790
+ this._register(addDisposableListener(el, 'wheel', (ev: WheelEvent) => {
801
791
  // do nothing, if app side handles wheel itself
802
792
  if (requestedEvents.wheel) return;
803
793
 
@@ -807,42 +797,23 @@ export class Terminal extends CoreTerminal implements ITerminal {
807
797
 
808
798
  if (!this.buffer.hasScrollback) {
809
799
  // Convert wheel events into up/down events when the buffer does not have scrollback, this
810
- // enables scrolling in apps hosted in the alt buffer such as vim or tmux.
811
- const amount = this.viewport!.getLinesScrolled(ev);
800
+ // enables scrolling in apps hosted in the alt buffer such as vim or tmux even when mouse
801
+ // events are not enabled.
802
+ // This used implementation used get the actual lines/partial lines scrolled from the
803
+ // viewport but since moving to the new viewport implementation has been simplified to
804
+ // simply send a single up or down sequence.
812
805
 
813
806
  // Do nothing if there's no vertical scroll
814
- if (amount === 0) {
815
- return;
807
+ const deltaY = (ev as WheelEvent).deltaY;
808
+ if (deltaY === 0) {
809
+ return false;
816
810
  }
817
811
 
818
812
  // Construct and send sequences
819
813
  const sequence = C0.ESC + (this.coreService.decPrivateModes.applicationCursorKeys ? 'O' : '[') + (ev.deltaY < 0 ? 'A' : 'B');
820
- let data = '';
821
- for (let i = 0; i < Math.abs(amount); i++) {
822
- data += sequence;
823
- }
824
- this.coreService.triggerDataEvent(data, true);
814
+ this.coreService.triggerDataEvent(sequence, true);
825
815
  return this.cancel(ev, true);
826
816
  }
827
-
828
- // normal viewport scrolling
829
- // conditionally stop event, if the viewport still had rows to scroll within
830
- if (this.viewport!.handleWheel(ev)) {
831
- return this.cancel(ev);
832
- }
833
- }, { passive: false }));
834
-
835
- this.register(addDisposableDomListener(el, 'touchstart', (ev: TouchEvent) => {
836
- if (this.coreMouseService.areMouseEventsActive) return;
837
- this.viewport!.handleTouchStart(ev);
838
- return this.cancel(ev);
839
- }, { passive: true }));
840
-
841
- this.register(addDisposableDomListener(el, 'touchmove', (ev: TouchEvent) => {
842
- if (this.coreMouseService.areMouseEventsActive) return;
843
- if (!this.viewport!.handleTouchMove(ev)) {
844
- return this.cancel(ev);
845
- }
846
817
  }, { passive: false }));
847
818
  }
848
819
 
@@ -878,12 +849,36 @@ export class Terminal extends CoreTerminal implements ITerminal {
878
849
  }
879
850
  }
880
851
 
881
- public scrollLines(disp: number, suppressScrollEvent?: boolean, source = ScrollSource.TERMINAL): void {
882
- if (source === ScrollSource.VIEWPORT) {
883
- super.scrollLines(disp, suppressScrollEvent, source);
884
- this.refresh(0, this.rows - 1);
852
+ public scrollLines(disp: number, suppressScrollEvent?: boolean): void {
853
+ // All scrollLines methods need to go via the viewport in order to support smooth scroll
854
+ if (this._viewport) {
855
+ this._viewport.scrollLines(disp);
885
856
  } else {
886
- this.viewport?.scrollLines(disp);
857
+ super.scrollLines(disp, suppressScrollEvent);
858
+ }
859
+ this.refresh(0, this.rows - 1);
860
+ }
861
+
862
+ public scrollPages(pageCount: number): void {
863
+ this.scrollLines(pageCount * (this.rows - 1));
864
+ }
865
+
866
+ public scrollToTop(): void {
867
+ this.scrollLines(-this._bufferService.buffer.ydisp);
868
+ }
869
+
870
+ public scrollToBottom(disableSmoothScroll?: boolean): void {
871
+ if (disableSmoothScroll && this._viewport) {
872
+ this._viewport.scrollToLine(this.buffer.ybase, true);
873
+ } else {
874
+ this.scrollLines(this._bufferService.buffer.ybase - this._bufferService.buffer.ydisp);
875
+ }
876
+ }
877
+
878
+ public scrollToLine(line: number): void {
879
+ const scrollAmount = line - this._bufferService.buffer.ydisp;
880
+ if (scrollAmount !== 0) {
881
+ this.scrollLines(scrollAmount);
887
882
  }
888
883
  }
889
884
 
@@ -1011,7 +1006,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
1011
1006
 
1012
1007
  if (!shouldIgnoreComposition && !this._compositionHelper!.keydown(event)) {
1013
1008
  if (this.options.scrollOnUserInput && this.buffer.ybase !== this.buffer.ydisp) {
1014
- this.scrollToBottom();
1009
+ this.scrollToBottom(true);
1015
1010
  }
1016
1011
  return false;
1017
1012
  }
@@ -1212,10 +1207,6 @@ export class Terminal extends CoreTerminal implements ITerminal {
1212
1207
 
1213
1208
  private _afterResize(x: number, y: number): void {
1214
1209
  this._charSizeService?.measure();
1215
-
1216
- // Sync the scroll area to make sure scroll events don't fire and scroll the viewport to an
1217
- // invalid location
1218
- this.viewport?.syncScrollArea(true);
1219
1210
  }
1220
1211
 
1221
1212
  /**
@@ -1237,8 +1228,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
1237
1228
  }
1238
1229
  // IMPORTANT: Fire scroll event before viewport is reset. This ensures embedders get the clear
1239
1230
  // scroll event and that the viewport's state will be valid for immediate writes.
1240
- this._onScroll.fire({ position: this.buffer.ydisp, source: ScrollSource.TERMINAL });
1241
- this.viewport?.reset();
1231
+ this._onScroll.fire({ position: this.buffer.ydisp });
1242
1232
  this.refresh(0, this.rows - 1);
1243
1233
  }
1244
1234
 
@@ -1263,7 +1253,6 @@ export class Terminal extends CoreTerminal implements ITerminal {
1263
1253
  super.reset();
1264
1254
  this._selectionService?.reset();
1265
1255
  this._decorationService.reset();
1266
- this.viewport?.reset();
1267
1256
 
1268
1257
  // reattach
1269
1258
  this._customKeyEventHandler = customKeyEventHandler;
@@ -1304,7 +1293,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
1304
1293
  }
1305
1294
 
1306
1295
  // TODO: Remove cancel function and cancelEvents option
1307
- public cancel(ev: Event, force?: boolean): boolean | undefined {
1296
+ public cancel(ev: MouseEvent | WheelEvent | KeyboardEvent | InputEvent, force?: boolean): boolean | undefined {
1308
1297
  if (!this.options.cancelEvents && !force) {
1309
1298
  return;
1310
1299
  }