@xterm/xterm 5.6.0-beta.9 → 5.6.0-beta.90

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 (124) hide show
  1. package/README.md +9 -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} +139 -148
  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/input/CompositionHelper.ts +2 -1
  17. package/src/browser/public/Terminal.ts +25 -19
  18. package/src/browser/renderer/dom/DomRenderer.ts +19 -14
  19. package/src/browser/renderer/dom/DomRendererRowFactory.ts +35 -15
  20. package/src/browser/renderer/shared/CharAtlasCache.ts +3 -2
  21. package/src/browser/renderer/shared/CharAtlasUtils.ts +6 -1
  22. package/src/browser/renderer/shared/CustomGlyphs.ts +6 -0
  23. package/src/browser/renderer/shared/DevicePixelObserver.ts +1 -2
  24. package/src/browser/renderer/shared/TextureAtlas.ts +45 -12
  25. package/src/browser/renderer/shared/{Types.d.ts → Types.ts} +7 -6
  26. package/src/browser/services/CharSizeService.ts +6 -6
  27. package/src/browser/services/CoreBrowserService.ts +15 -15
  28. package/src/browser/services/LinkProviderService.ts +2 -2
  29. package/src/browser/services/RenderService.ts +20 -20
  30. package/src/browser/services/SelectionService.ts +8 -8
  31. package/src/browser/services/Services.ts +13 -13
  32. package/src/browser/services/ThemeService.ts +19 -58
  33. package/src/browser/shared/Constants.ts +8 -0
  34. package/src/common/CircularList.ts +5 -5
  35. package/src/common/CoreTerminal.ts +35 -41
  36. package/src/common/InputHandler.ts +63 -51
  37. package/src/common/{Types.d.ts → Types.ts} +13 -17
  38. package/src/common/buffer/Buffer.ts +15 -7
  39. package/src/common/buffer/BufferReflow.ts +9 -6
  40. package/src/common/buffer/BufferSet.ts +5 -5
  41. package/src/common/buffer/Marker.ts +4 -4
  42. package/src/common/buffer/{Types.d.ts → Types.ts} +2 -2
  43. package/src/common/input/WriteBuffer.ts +3 -3
  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 +7 -7
  47. package/src/common/services/CoreMouseService.ts +5 -3
  48. package/src/common/services/CoreService.ts +8 -6
  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 +7 -6
  53. package/src/common/services/ServiceRegistry.ts +1 -1
  54. package/src/common/services/Services.ts +26 -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/thenable.d.ts +12 -0
  117. package/src/vs/typings/vscode-globals-nls.d.ts +36 -0
  118. package/src/vs/typings/vscode-globals-product.d.ts +33 -0
  119. package/typings/xterm.d.ts +66 -15
  120. package/src/browser/Lifecycle.ts +0 -33
  121. package/src/common/EventEmitter.ts +0 -78
  122. package/src/common/Lifecycle.ts +0 -108
  123. /package/src/browser/selection/{Types.d.ts → Types.ts} +0 -0
  124. /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
  /**
@@ -400,7 +400,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
400
400
  }
401
401
 
402
402
  // If the terminal is already opened
403
- if (this.element?.ownerDocument.defaultView && this._coreBrowserService) {
403
+ if (this.element?.ownerDocument.defaultView && this._coreBrowserService && this.element?.isConnected) {
404
404
  // Adjust the window if needed
405
405
  if (this.element.ownerDocument.defaultView !== this._coreBrowserService.window) {
406
406
  this._coreBrowserService.window = this.element.ownerDocument.defaultView;
@@ -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');
@@ -441,9 +437,9 @@ export class Terminal extends CoreTerminal implements ITerminal {
441
437
  this.screenElement.appendChild(this._helperContainer);
442
438
  fragment.appendChild(this.screenElement);
443
439
 
444
- this.textarea = this._document.createElement('textarea');
440
+ const textarea = 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
@@ -453,10 +449,12 @@ export class Terminal extends CoreTerminal implements ITerminal {
453
449
  this.textarea.setAttribute('autocapitalize', 'off');
454
450
  this.textarea.setAttribute('spellcheck', 'false');
455
451
  this.textarea.tabIndex = 0;
452
+ this._register(this.optionsService.onSpecificOptionChange('disableStdin', () => textarea.readOnly = this.optionsService.rawOptions.disableStdin));
453
+ this.textarea.readOnly = this.optionsService.rawOptions.disableStdin;
456
454
 
457
455
  // Register the core browser service before the generic textarea handlers are registered so it
458
456
  // handles them first. Otherwise the renderers may use the wrong focus state.
459
- this._coreBrowserService = this.register(this._instantiationService.createInstance(CoreBrowserService,
457
+ this._coreBrowserService = this._register(this._instantiationService.createInstance(CoreBrowserService,
460
458
  this.textarea,
461
459
  parent.ownerDocument.defaultView ?? window,
462
460
  // Force unsafe null in node.js environment for tests
@@ -464,8 +462,8 @@ export class Terminal extends CoreTerminal implements ITerminal {
464
462
  ));
465
463
  this._instantiationService.setService(ICoreBrowserService, this._coreBrowserService);
466
464
 
467
- this.register(addDisposableDomListener(this.textarea, 'focus', (ev: FocusEvent) => this._handleTextAreaFocus(ev)));
468
- this.register(addDisposableDomListener(this.textarea, 'blur', () => this._handleTextAreaBlur()));
465
+ this._register(addDisposableListener(this.textarea, 'focus', (ev: FocusEvent) => this._handleTextAreaFocus(ev)));
466
+ this._register(addDisposableListener(this.textarea, 'blur', () => this._handleTextAreaBlur()));
469
467
  this._helperContainer.appendChild(this.textarea);
470
468
 
471
469
  this._charSizeService = this._instantiationService.createInstance(CharSizeService, this._document, this._helperContainer);
@@ -477,9 +475,9 @@ export class Terminal extends CoreTerminal implements ITerminal {
477
475
  this._characterJoinerService = this._instantiationService.createInstance(CharacterJoinerService);
478
476
  this._instantiationService.setService(ICharacterJoinerService, this._characterJoinerService);
479
477
 
480
- this._renderService = this.register(this._instantiationService.createInstance(RenderService, this.rows, this.screenElement));
478
+ this._renderService = this._register(this._instantiationService.createInstance(RenderService, this.rows, this.screenElement));
481
479
  this._instantiationService.setService(IRenderService, this._renderService);
482
- this.register(this._renderService.onRenderedViewportChange(e => this._onRender.fire(e)));
480
+ this._register(this._renderService.onRenderedViewportChange(e => this._onRender.fire(e)));
483
481
  this.onResize(e => this._renderService!.resize(e.cols, e.rows));
484
482
 
485
483
  this._compositionView = this._document.createElement('div');
@@ -490,7 +488,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
490
488
  this._mouseService = this._instantiationService.createInstance(MouseService);
491
489
  this._instantiationService.setService(IMouseService, this._mouseService);
492
490
 
493
- this.linkifier = this.register(this._instantiationService.createInstance(Linkifier, this.screenElement));
491
+ const linkifier = this._linkifier.value = this._register(this._instantiationService.createInstance(Linkifier, this.screenElement));
494
492
 
495
493
  // Performance: Add viewport and helper elements from the fragment
496
494
  this.element.appendChild(fragment);
@@ -503,30 +501,30 @@ export class Terminal extends CoreTerminal implements ITerminal {
503
501
  this._renderService.setRenderer(this._createRenderer());
504
502
  }
505
503
 
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(() => {
504
+ this._register(this.onCursorMove(() => {
512
505
  this._renderService!.handleCursorMove();
513
506
  this._syncTextArea();
514
507
  }));
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()));
508
+ this._register(this.onResize(() => this._renderService!.handleResize(this.cols, this.rows)));
509
+ this._register(this.onBlur(() => this._renderService!.handleBlur()));
510
+ this._register(this.onFocus(() => this._renderService!.handleFocus()));
511
+
512
+ this._viewport = this._register(this._instantiationService.createInstance(Viewport, this.element, this.screenElement));
513
+ this._register(this._viewport.onRequestScrollLines(e => {
514
+ super.scrollLines(e, false);
515
+ this.refresh(0, this.rows - 1);
516
+ }));
519
517
 
520
- this._selectionService = this.register(this._instantiationService.createInstance(SelectionService,
518
+ this._selectionService = this._register(this._instantiationService.createInstance(SelectionService,
521
519
  this.element,
522
520
  this.screenElement,
523
- this.linkifier
521
+ linkifier
524
522
  ));
525
523
  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 => {
524
+ this._register(this._selectionService.onRequestScrollLines(e => this.scrollLines(e.amount, e.suppressScrollEvent)));
525
+ this._register(this._selectionService.onSelectionChange(() => this._onSelectionChange.fire()));
526
+ this._register(this._selectionService.onRequestRedraw(e => this._renderService!.handleSelectionChanged(e.start, e.end, e.columnSelectMode)));
527
+ this._register(this._selectionService.onLinuxMouseSelection(text => {
530
528
  // If there's a new selection, put it into the textarea, focus and select it
531
529
  // in order to register it as a selection on the OS. This event is fired
532
530
  // only on Linux to enable middle click to paste selection.
@@ -534,14 +532,10 @@ export class Terminal extends CoreTerminal implements ITerminal {
534
532
  this.textarea!.focus();
535
533
  this.textarea!.select();
536
534
  }));
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()));
535
+ this._register(this._onScroll.event(() => this._selectionService!.refresh()));
542
536
 
543
- this.register(this._instantiationService.createInstance(BufferDecorationRenderer, this.screenElement));
544
- this.register(addDisposableDomListener(this.element, 'mousedown', (e: MouseEvent) => this._selectionService!.handleMouseDown(e)));
537
+ this._register(this._instantiationService.createInstance(BufferDecorationRenderer, this.screenElement));
538
+ this._register(addDisposableListener(this.element, 'mousedown', (e: MouseEvent) => this._selectionService!.handleMouseDown(e)));
545
539
 
546
540
  // apply mouse event classes set by escape codes before terminal was attached
547
541
  if (this.coreMouseService.areMouseEventsActive) {
@@ -556,14 +550,14 @@ export class Terminal extends CoreTerminal implements ITerminal {
556
550
  // ensure the correct order of the dprchange event
557
551
  this._accessibilityManager.value = this._instantiationService.createInstance(AccessibilityManager, this);
558
552
  }
559
- this.register(this.optionsService.onSpecificOptionChange('screenReaderMode', e => this._handleScreenReaderModeOptionChange(e)));
553
+ this._register(this.optionsService.onSpecificOptionChange('screenReaderMode', e => this._handleScreenReaderModeOptionChange(e)));
560
554
 
561
- if (this.options.overviewRulerWidth) {
562
- this._overviewRulerRenderer = this.register(this._instantiationService.createInstance(OverviewRulerRenderer, this._viewportElement, this.screenElement));
555
+ if (this.options.overviewRuler.width) {
556
+ this._overviewRulerRenderer = this._register(this._instantiationService.createInstance(OverviewRulerRenderer, this._viewportElement, this.screenElement));
563
557
  }
564
- this.optionsService.onSpecificOptionChange('overviewRulerWidth', value => {
558
+ this.optionsService.onSpecificOptionChange('overviewRuler', value => {
565
559
  if (!this._overviewRulerRenderer && value && this._viewportElement && this.screenElement) {
566
- this._overviewRulerRenderer = this.register(this._instantiationService.createInstance(OverviewRulerRenderer, this._viewportElement, this.screenElement));
560
+ this._overviewRulerRenderer = this._register(this._instantiationService.createInstance(OverviewRulerRenderer, this._viewportElement, this.screenElement));
567
561
  }
568
562
  });
569
563
  // Measure the character size
@@ -642,13 +636,11 @@ export class Terminal extends CoreTerminal implements ITerminal {
642
636
  if (self._customWheelEventHandler && self._customWheelEventHandler(ev as WheelEvent) === false) {
643
637
  return false;
644
638
  }
645
- const amount = self.viewport!.getLinesScrolled(ev as WheelEvent);
646
-
647
- if (amount === 0) {
639
+ const deltaY = (ev as WheelEvent).deltaY;
640
+ if (deltaY === 0) {
648
641
  return false;
649
642
  }
650
-
651
- action = (ev as WheelEvent).deltaY < 0 ? CoreMouseAction.UP : CoreMouseAction.DOWN;
643
+ action = deltaY < 0 ? CoreMouseAction.UP : CoreMouseAction.DOWN;
652
644
  but = CoreMouseButton.WHEEL;
653
645
  break;
654
646
  default:
@@ -683,7 +675,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
683
675
  * Note: 'mousedown' currently is "always on" and not managed
684
676
  * by onProtocolChange.
685
677
  */
686
- const requestedEvents: { [key: string]: ((ev: Event) => void) | null } = {
678
+ const requestedEvents: { [key: string]: ((ev: MouseEvent | WheelEvent) => void) | null } = {
687
679
  mouseup: null,
688
680
  wheel: null,
689
681
  mousedrag: null,
@@ -718,7 +710,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
718
710
  }
719
711
  }
720
712
  };
721
- this.register(this.coreMouseService.onProtocolChange(events => {
713
+ this._register(this.coreMouseService.onProtocolChange(events => {
722
714
  // apply global changes on events
723
715
  if (events) {
724
716
  if (this.optionsService.rawOptions.logLevel === 'debug') {
@@ -770,7 +762,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
770
762
  /**
771
763
  * "Always on" event listeners.
772
764
  */
773
- this.register(addDisposableDomListener(el, 'mousedown', (ev: MouseEvent) => {
765
+ this._register(addDisposableListener(el, 'mousedown', (ev: MouseEvent) => {
774
766
  ev.preventDefault();
775
767
  this.focus();
776
768
 
@@ -797,7 +789,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
797
789
  return this.cancel(ev);
798
790
  }));
799
791
 
800
- this.register(addDisposableDomListener(el, 'wheel', (ev: WheelEvent) => {
792
+ this._register(addDisposableListener(el, 'wheel', (ev: WheelEvent) => {
801
793
  // do nothing, if app side handles wheel itself
802
794
  if (requestedEvents.wheel) return;
803
795
 
@@ -807,42 +799,23 @@ export class Terminal extends CoreTerminal implements ITerminal {
807
799
 
808
800
  if (!this.buffer.hasScrollback) {
809
801
  // 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);
802
+ // enables scrolling in apps hosted in the alt buffer such as vim or tmux even when mouse
803
+ // events are not enabled.
804
+ // This used implementation used get the actual lines/partial lines scrolled from the
805
+ // viewport but since moving to the new viewport implementation has been simplified to
806
+ // simply send a single up or down sequence.
812
807
 
813
808
  // Do nothing if there's no vertical scroll
814
- if (amount === 0) {
815
- return;
809
+ const deltaY = (ev as WheelEvent).deltaY;
810
+ if (deltaY === 0) {
811
+ return false;
816
812
  }
817
813
 
818
814
  // Construct and send sequences
819
815
  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);
816
+ this.coreService.triggerDataEvent(sequence, true);
825
817
  return this.cancel(ev, true);
826
818
  }
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
819
  }, { passive: false }));
847
820
  }
848
821
 
@@ -878,12 +851,36 @@ export class Terminal extends CoreTerminal implements ITerminal {
878
851
  }
879
852
  }
880
853
 
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);
854
+ public scrollLines(disp: number, suppressScrollEvent?: boolean): void {
855
+ // All scrollLines methods need to go via the viewport in order to support smooth scroll
856
+ if (this._viewport) {
857
+ this._viewport.scrollLines(disp);
885
858
  } else {
886
- this.viewport?.scrollLines(disp);
859
+ super.scrollLines(disp, suppressScrollEvent);
860
+ }
861
+ this.refresh(0, this.rows - 1);
862
+ }
863
+
864
+ public scrollPages(pageCount: number): void {
865
+ this.scrollLines(pageCount * (this.rows - 1));
866
+ }
867
+
868
+ public scrollToTop(): void {
869
+ this.scrollLines(-this._bufferService.buffer.ydisp);
870
+ }
871
+
872
+ public scrollToBottom(disableSmoothScroll?: boolean): void {
873
+ if (disableSmoothScroll && this._viewport) {
874
+ this._viewport.scrollToLine(this.buffer.ybase, true);
875
+ } else {
876
+ this.scrollLines(this._bufferService.buffer.ybase - this._bufferService.buffer.ydisp);
877
+ }
878
+ }
879
+
880
+ public scrollToLine(line: number): void {
881
+ const scrollAmount = line - this._bufferService.buffer.ydisp;
882
+ if (scrollAmount !== 0) {
883
+ this.scrollLines(scrollAmount);
887
884
  }
888
885
  }
889
886
 
@@ -1011,7 +1008,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
1011
1008
 
1012
1009
  if (!shouldIgnoreComposition && !this._compositionHelper!.keydown(event)) {
1013
1010
  if (this.options.scrollOnUserInput && this.buffer.ybase !== this.buffer.ydisp) {
1014
- this.scrollToBottom();
1011
+ this.scrollToBottom(true);
1015
1012
  }
1016
1013
  return false;
1017
1014
  }
@@ -1212,10 +1209,6 @@ export class Terminal extends CoreTerminal implements ITerminal {
1212
1209
 
1213
1210
  private _afterResize(x: number, y: number): void {
1214
1211
  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
1212
  }
1220
1213
 
1221
1214
  /**
@@ -1237,8 +1230,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
1237
1230
  }
1238
1231
  // IMPORTANT: Fire scroll event before viewport is reset. This ensures embedders get the clear
1239
1232
  // 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();
1233
+ this._onScroll.fire({ position: this.buffer.ydisp });
1242
1234
  this.refresh(0, this.rows - 1);
1243
1235
  }
1244
1236
 
@@ -1263,7 +1255,6 @@ export class Terminal extends CoreTerminal implements ITerminal {
1263
1255
  super.reset();
1264
1256
  this._selectionService?.reset();
1265
1257
  this._decorationService.reset();
1266
- this.viewport?.reset();
1267
1258
 
1268
1259
  // reattach
1269
1260
  this._customKeyEventHandler = customKeyEventHandler;
@@ -1304,7 +1295,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
1304
1295
  }
1305
1296
 
1306
1297
  // TODO: Remove cancel function and cancelEvents option
1307
- public cancel(ev: Event, force?: boolean): boolean | undefined {
1298
+ public cancel(ev: MouseEvent | WheelEvent | KeyboardEvent | InputEvent, force?: boolean): boolean | undefined {
1308
1299
  if (!this.options.cancelEvents && !force) {
1309
1300
  return;
1310
1301
  }