@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
@@ -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');
@@ -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,16 @@ 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();
535
+ this._register(Event.any(
536
+ this._onScroll.event,
537
+ this._inputHandler.onScroll
538
+ )(() => {
539
539
  this._selectionService!.refresh();
540
+ this._viewport?.queueSync();
540
541
  }));
541
- this.register(addDisposableDomListener(this._viewportElement, 'scroll', () => this._selectionService!.refresh()));
542
542
 
543
- this.register(this._instantiationService.createInstance(BufferDecorationRenderer, this.screenElement));
544
- this.register(addDisposableDomListener(this.element, 'mousedown', (e: MouseEvent) => this._selectionService!.handleMouseDown(e)));
543
+ this._register(this._instantiationService.createInstance(BufferDecorationRenderer, this.screenElement));
544
+ this._register(addDisposableListener(this.element, 'mousedown', (e: MouseEvent) => this._selectionService!.handleMouseDown(e)));
545
545
 
546
546
  // apply mouse event classes set by escape codes before terminal was attached
547
547
  if (this.coreMouseService.areMouseEventsActive) {
@@ -556,14 +556,14 @@ export class Terminal extends CoreTerminal implements ITerminal {
556
556
  // ensure the correct order of the dprchange event
557
557
  this._accessibilityManager.value = this._instantiationService.createInstance(AccessibilityManager, this);
558
558
  }
559
- this.register(this.optionsService.onSpecificOptionChange('screenReaderMode', e => this._handleScreenReaderModeOptionChange(e)));
559
+ this._register(this.optionsService.onSpecificOptionChange('screenReaderMode', e => this._handleScreenReaderModeOptionChange(e)));
560
560
 
561
- if (this.options.overviewRulerWidth) {
562
- this._overviewRulerRenderer = this.register(this._instantiationService.createInstance(OverviewRulerRenderer, this._viewportElement, this.screenElement));
561
+ if (this.options.overviewRuler.width) {
562
+ this._overviewRulerRenderer = this._register(this._instantiationService.createInstance(OverviewRulerRenderer, this._viewportElement, this.screenElement));
563
563
  }
564
- this.optionsService.onSpecificOptionChange('overviewRulerWidth', value => {
564
+ this.optionsService.onSpecificOptionChange('overviewRuler', value => {
565
565
  if (!this._overviewRulerRenderer && value && this._viewportElement && this.screenElement) {
566
- this._overviewRulerRenderer = this.register(this._instantiationService.createInstance(OverviewRulerRenderer, this._viewportElement, this.screenElement));
566
+ this._overviewRulerRenderer = this._register(this._instantiationService.createInstance(OverviewRulerRenderer, this._viewportElement, this.screenElement));
567
567
  }
568
568
  });
569
569
  // Measure the character size
@@ -642,13 +642,19 @@ export class Terminal extends CoreTerminal implements ITerminal {
642
642
  if (self._customWheelEventHandler && self._customWheelEventHandler(ev as WheelEvent) === false) {
643
643
  return false;
644
644
  }
645
- const amount = self.viewport!.getLinesScrolled(ev as WheelEvent);
646
-
647
- if (amount === 0) {
645
+ const deltaY = (ev as WheelEvent).deltaY;
646
+ if (deltaY === 0) {
648
647
  return false;
649
648
  }
650
-
651
- action = (ev as WheelEvent).deltaY < 0 ? CoreMouseAction.UP : CoreMouseAction.DOWN;
649
+ const lines = self.coreMouseService.consumeWheelEvent(
650
+ ev as WheelEvent,
651
+ self._renderService?.dimensions?.device?.cell?.height,
652
+ self._coreBrowserService?.dpr
653
+ );
654
+ if (lines === 0) {
655
+ return false;
656
+ }
657
+ action = deltaY < 0 ? CoreMouseAction.UP : CoreMouseAction.DOWN;
652
658
  but = CoreMouseButton.WHEEL;
653
659
  break;
654
660
  default:
@@ -683,7 +689,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
683
689
  * Note: 'mousedown' currently is "always on" and not managed
684
690
  * by onProtocolChange.
685
691
  */
686
- const requestedEvents: { [key: string]: ((ev: Event) => void) | null } = {
692
+ const requestedEvents: { [key: string]: ((ev: MouseEvent | WheelEvent) => void) | null } = {
687
693
  mouseup: null,
688
694
  wheel: null,
689
695
  mousedrag: null,
@@ -718,7 +724,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
718
724
  }
719
725
  }
720
726
  };
721
- this.register(this.coreMouseService.onProtocolChange(events => {
727
+ this._register(this.coreMouseService.onProtocolChange(events => {
722
728
  // apply global changes on events
723
729
  if (events) {
724
730
  if (this.optionsService.rawOptions.logLevel === 'debug') {
@@ -770,7 +776,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
770
776
  /**
771
777
  * "Always on" event listeners.
772
778
  */
773
- this.register(addDisposableDomListener(el, 'mousedown', (ev: MouseEvent) => {
779
+ this._register(addDisposableListener(el, 'mousedown', (ev: MouseEvent) => {
774
780
  ev.preventDefault();
775
781
  this.focus();
776
782
 
@@ -797,7 +803,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
797
803
  return this.cancel(ev);
798
804
  }));
799
805
 
800
- this.register(addDisposableDomListener(el, 'wheel', (ev: WheelEvent) => {
806
+ this._register(addDisposableListener(el, 'wheel', (ev: WheelEvent) => {
801
807
  // do nothing, if app side handles wheel itself
802
808
  if (requestedEvents.wheel) return;
803
809
 
@@ -807,42 +813,32 @@ export class Terminal extends CoreTerminal implements ITerminal {
807
813
 
808
814
  if (!this.buffer.hasScrollback) {
809
815
  // 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);
816
+ // enables scrolling in apps hosted in the alt buffer such as vim or tmux even when mouse
817
+ // events are not enabled.
818
+ // This used implementation used get the actual lines/partial lines scrolled from the
819
+ // viewport but since moving to the new viewport implementation has been simplified to
820
+ // simply send a single up or down sequence.
812
821
 
813
822
  // Do nothing if there's no vertical scroll
814
- if (amount === 0) {
815
- return;
823
+ const deltaY = (ev as WheelEvent).deltaY;
824
+ if (deltaY === 0) {
825
+ return false;
826
+ }
827
+
828
+ const lines = self.coreMouseService.consumeWheelEvent(
829
+ ev as WheelEvent,
830
+ self._renderService?.dimensions?.device?.cell?.height,
831
+ self._coreBrowserService?.dpr
832
+ );
833
+ if (lines === 0) {
834
+ return this.cancel(ev, true);
816
835
  }
817
836
 
818
837
  // Construct and send sequences
819
838
  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);
839
+ this.coreService.triggerDataEvent(sequence, true);
825
840
  return this.cancel(ev, true);
826
841
  }
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
842
  }, { passive: false }));
847
843
  }
848
844
 
@@ -878,12 +874,36 @@ export class Terminal extends CoreTerminal implements ITerminal {
878
874
  }
879
875
  }
880
876
 
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);
877
+ public scrollLines(disp: number, suppressScrollEvent?: boolean): void {
878
+ // All scrollLines methods need to go via the viewport in order to support smooth scroll
879
+ if (this._viewport) {
880
+ this._viewport.scrollLines(disp);
885
881
  } else {
886
- this.viewport?.scrollLines(disp);
882
+ super.scrollLines(disp, suppressScrollEvent);
883
+ }
884
+ this.refresh(0, this.rows - 1);
885
+ }
886
+
887
+ public scrollPages(pageCount: number): void {
888
+ this.scrollLines(pageCount * (this.rows - 1));
889
+ }
890
+
891
+ public scrollToTop(): void {
892
+ this.scrollLines(-this._bufferService.buffer.ydisp);
893
+ }
894
+
895
+ public scrollToBottom(disableSmoothScroll?: boolean): void {
896
+ if (disableSmoothScroll && this._viewport) {
897
+ this._viewport.scrollToLine(this.buffer.ybase, true);
898
+ } else {
899
+ this.scrollLines(this._bufferService.buffer.ybase - this._bufferService.buffer.ydisp);
900
+ }
901
+ }
902
+
903
+ public scrollToLine(line: number): void {
904
+ const scrollAmount = line - this._bufferService.buffer.ydisp;
905
+ if (scrollAmount !== 0) {
906
+ this.scrollLines(scrollAmount);
887
907
  }
888
908
  }
889
909
 
@@ -1011,7 +1031,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
1011
1031
 
1012
1032
  if (!shouldIgnoreComposition && !this._compositionHelper!.keydown(event)) {
1013
1033
  if (this.options.scrollOnUserInput && this.buffer.ybase !== this.buffer.ydisp) {
1014
- this.scrollToBottom();
1034
+ this.scrollToBottom(true);
1015
1035
  }
1016
1036
  return false;
1017
1037
  }
@@ -1212,10 +1232,6 @@ export class Terminal extends CoreTerminal implements ITerminal {
1212
1232
 
1213
1233
  private _afterResize(x: number, y: number): void {
1214
1234
  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
1235
  }
1220
1236
 
1221
1237
  /**
@@ -1237,8 +1253,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
1237
1253
  }
1238
1254
  // IMPORTANT: Fire scroll event before viewport is reset. This ensures embedders get the clear
1239
1255
  // 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();
1256
+ this._onScroll.fire({ position: this.buffer.ydisp });
1242
1257
  this.refresh(0, this.rows - 1);
1243
1258
  }
1244
1259
 
@@ -1263,7 +1278,6 @@ export class Terminal extends CoreTerminal implements ITerminal {
1263
1278
  super.reset();
1264
1279
  this._selectionService?.reset();
1265
1280
  this._decorationService.reset();
1266
- this.viewport?.reset();
1267
1281
 
1268
1282
  // reattach
1269
1283
  this._customKeyEventHandler = customKeyEventHandler;
@@ -1304,7 +1318,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
1304
1318
  }
1305
1319
 
1306
1320
  // TODO: Remove cancel function and cancelEvents option
1307
- public cancel(ev: Event, force?: boolean): boolean | undefined {
1321
+ public cancel(ev: MouseEvent | WheelEvent | KeyboardEvent | InputEvent, force?: boolean): boolean | undefined {
1308
1322
  if (!this.options.cancelEvents && !force) {
1309
1323
  return;
1310
1324
  }