@xterm/xterm 5.6.0-beta.5 → 5.6.0-beta.50

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 (112) 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 +40 -31
  8. package/src/browser/AccessibilityManager.ts +39 -11
  9. package/src/browser/{Terminal.ts → CoreBrowserTerminal.ts} +85 -97
  10. package/src/browser/Linkifier.ts +3 -3
  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 +142 -364
  14. package/src/browser/decorations/BufferDecorationRenderer.ts +6 -1
  15. package/src/browser/decorations/OverviewRulerRenderer.ts +32 -36
  16. package/src/browser/public/Terminal.ts +21 -15
  17. package/src/browser/renderer/dom/DomRenderer.ts +8 -10
  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/TextureAtlas.ts +3 -3
  21. package/src/browser/renderer/shared/{Types.d.ts → Types.ts} +4 -4
  22. package/src/browser/services/CharSizeService.ts +2 -2
  23. package/src/browser/services/CoreBrowserService.ts +13 -9
  24. package/src/browser/services/RenderService.ts +5 -5
  25. package/src/browser/services/SelectionService.ts +5 -5
  26. package/src/browser/services/Services.ts +13 -13
  27. package/src/browser/services/ThemeService.ts +14 -53
  28. package/src/browser/shared/Constants.ts +8 -0
  29. package/src/common/CircularList.ts +4 -4
  30. package/src/common/CoreTerminal.ts +22 -28
  31. package/src/common/InputHandler.ts +31 -25
  32. package/src/common/{Types.d.ts → Types.ts} +11 -17
  33. package/src/common/buffer/Buffer.ts +5 -1
  34. package/src/common/buffer/BufferSet.ts +2 -2
  35. package/src/common/buffer/Marker.ts +2 -2
  36. package/src/common/buffer/{Types.d.ts → Types.ts} +2 -2
  37. package/src/common/input/WriteBuffer.ts +2 -2
  38. package/src/common/public/BufferNamespaceApi.ts +2 -2
  39. package/src/common/services/BufferService.ts +5 -5
  40. package/src/common/services/CoreMouseService.ts +4 -2
  41. package/src/common/services/CoreService.ts +5 -5
  42. package/src/common/services/DecorationService.ts +5 -5
  43. package/src/common/services/OptionsService.ts +3 -3
  44. package/src/common/services/Services.ts +24 -17
  45. package/src/common/services/UnicodeService.ts +2 -2
  46. package/src/vs/base/browser/browser.ts +141 -0
  47. package/src/vs/base/browser/canIUse.ts +49 -0
  48. package/src/vs/base/browser/dom.ts +2369 -0
  49. package/src/vs/base/browser/fastDomNode.ts +316 -0
  50. package/src/vs/base/browser/globalPointerMoveMonitor.ts +112 -0
  51. package/src/vs/base/browser/iframe.ts +135 -0
  52. package/src/vs/base/browser/keyboardEvent.ts +213 -0
  53. package/src/vs/base/browser/mouseEvent.ts +229 -0
  54. package/src/vs/base/browser/touch.ts +372 -0
  55. package/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts +303 -0
  56. package/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts +114 -0
  57. package/src/vs/base/browser/ui/scrollbar/scrollableElement.ts +720 -0
  58. package/src/vs/base/browser/ui/scrollbar/scrollableElementOptions.ts +165 -0
  59. package/src/vs/base/browser/ui/scrollbar/scrollbarArrow.ts +114 -0
  60. package/src/vs/base/browser/ui/scrollbar/scrollbarState.ts +243 -0
  61. package/src/vs/base/browser/ui/scrollbar/scrollbarVisibilityController.ts +118 -0
  62. package/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts +116 -0
  63. package/src/vs/base/browser/ui/widget.ts +57 -0
  64. package/src/vs/base/browser/window.ts +14 -0
  65. package/src/vs/base/common/arrays.ts +887 -0
  66. package/src/vs/base/common/arraysFind.ts +202 -0
  67. package/src/vs/base/common/assert.ts +71 -0
  68. package/src/vs/base/common/async.ts +1992 -0
  69. package/src/vs/base/common/cancellation.ts +148 -0
  70. package/src/vs/base/common/charCode.ts +450 -0
  71. package/src/vs/base/common/collections.ts +140 -0
  72. package/src/vs/base/common/decorators.ts +130 -0
  73. package/src/vs/base/common/equals.ts +146 -0
  74. package/src/vs/base/common/errors.ts +303 -0
  75. package/src/vs/base/common/event.ts +1778 -0
  76. package/src/vs/base/common/functional.ts +32 -0
  77. package/src/vs/base/common/hash.ts +316 -0
  78. package/src/vs/base/common/iterator.ts +159 -0
  79. package/src/vs/base/common/keyCodes.ts +526 -0
  80. package/src/vs/base/common/keybindings.ts +284 -0
  81. package/src/vs/base/common/lazy.ts +47 -0
  82. package/src/vs/base/common/lifecycle.ts +801 -0
  83. package/src/vs/base/common/linkedList.ts +142 -0
  84. package/src/vs/base/common/map.ts +202 -0
  85. package/src/vs/base/common/numbers.ts +98 -0
  86. package/src/vs/base/common/observable.ts +76 -0
  87. package/src/vs/base/common/observableInternal/api.ts +31 -0
  88. package/src/vs/base/common/observableInternal/autorun.ts +281 -0
  89. package/src/vs/base/common/observableInternal/base.ts +489 -0
  90. package/src/vs/base/common/observableInternal/debugName.ts +145 -0
  91. package/src/vs/base/common/observableInternal/derived.ts +428 -0
  92. package/src/vs/base/common/observableInternal/lazyObservableValue.ts +146 -0
  93. package/src/vs/base/common/observableInternal/logging.ts +328 -0
  94. package/src/vs/base/common/observableInternal/promise.ts +209 -0
  95. package/src/vs/base/common/observableInternal/utils.ts +610 -0
  96. package/src/vs/base/common/platform.ts +281 -0
  97. package/src/vs/base/common/scrollable.ts +522 -0
  98. package/src/vs/base/common/sequence.ts +34 -0
  99. package/src/vs/base/common/stopwatch.ts +43 -0
  100. package/src/vs/base/common/strings.ts +557 -0
  101. package/src/vs/base/common/symbols.ts +9 -0
  102. package/src/vs/base/common/uint.ts +59 -0
  103. package/src/vs/patches/nls.ts +90 -0
  104. package/src/vs/typings/base-common.d.ts +20 -0
  105. package/src/vs/typings/require.d.ts +42 -0
  106. package/src/vs/typings/thenable.d.ts +12 -0
  107. package/src/vs/typings/vscode-globals-nls.d.ts +36 -0
  108. package/src/vs/typings/vscode-globals-product.d.ts +33 -0
  109. package/typings/xterm.d.ts +59 -15
  110. package/src/common/EventEmitter.ts +0 -78
  111. /package/src/browser/selection/{Types.d.ts → Types.ts} +0 -0
  112. /package/src/common/parser/{Types.d.ts → Types.ts} +0 -0
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "@xterm/xterm",
3
3
  "description": "Full xterm terminal, in your browser",
4
- "version": "5.6.0-beta.5",
4
+ "version": "5.6.0-beta.50",
5
5
  "main": "lib/xterm.js",
6
+ "module": "lib/xterm.mjs",
6
7
  "style": "css/xterm.css",
7
8
  "types": "typings/xterm.d.ts",
8
9
  "repository": "https://github.com/xtermjs/xterm.js",
@@ -23,44 +24,50 @@
23
24
  "xterm"
24
25
  ],
25
26
  "scripts": {
26
- "prepackage": "npm run build",
27
- "package": "webpack",
28
- "package-headless": "webpack --config ./webpack.config.headless.js",
29
- "postpackage-headless": "node ./bin/package_headless.js",
27
+ "setup": "npm run build",
28
+ "presetup": "npm run install-addons",
29
+ "install-addons": "node ./bin/install-addons.js",
30
30
  "start": "node demo/start",
31
- "start-server-only": "node demo/start-server-only",
32
- "build-demo": "webpack --config ./demo/webpack.config.js",
33
- "lint": "eslint -c .eslintrc.json --max-warnings 0 --ext .ts src/ addons/",
34
- "lint-api": "eslint --no-eslintrc -c .eslintrc.json.typings --max-warnings 0 --no-ignore --ext .d.ts typings/",
31
+ "build": "npm run tsc",
32
+ "watch": "npm run tsc-watch",
33
+ "tsc": "tsc -b ./tsconfig.all.json",
34
+ "tsc-watch": "tsc -b -w ./tsconfig.all.json --preserveWatchOutput",
35
+ "esbuild": "node bin/esbuild_all.mjs",
36
+ "esbuild-watch": "node bin/esbuild_all.mjs --watch",
37
+ "esbuild-package": "node bin/esbuild_all.mjs --prod",
38
+ "esbuild-package-watch": "node bin/esbuild_all.mjs --prod --watch",
39
+ "esbuild-package-headless-only": "node bin/esbuild.mjs --prod --headless",
40
+ "esbuild-demo": "node bin/esbuild.mjs --demo-client",
41
+ "esbuild-demo-watch": "node bin/esbuild.mjs --demo-client --watch",
35
42
  "test": "npm run test-unit",
36
43
  "posttest": "npm run lint",
37
- "test-api": "npm run test-api-chromium",
38
- "test-api-chromium": "node ./bin/test_api.js --browser=chromium --timeout=20000",
39
- "test-api-firefox": "node ./bin/test_api.js --browser=firefox --timeout=20000",
40
- "test-api-webkit": "node ./bin/test_api.js --browser=webkit --timeout=20000",
41
- "test-playwright": "node ./bin/test_playwright.js --workers=75%",
42
- "test-playwright-chromium": "node ./bin/test_playwright.js --workers=75% \"--project=Chrome Stable\"",
43
- "test-playwright-firefox": "node ./bin/test_playwright.js --workers=75% \"--project=Firefox Stable\"",
44
- "test-playwright-webkit": "node ./bin/test_playwright.js --workers=75% \"--project=WebKit\"",
45
- "test-playwright-debug": "node ./bin/test_playwright.js --workers=1 --headed --timeout=30000",
46
- "test-unit": "node ./bin/test.js",
47
- "test-unit-coverage": "node ./bin/test.js --coverage",
44
+ "lint": "eslint -c .eslintrc.json --max-warnings 0 --ext .ts src/ addons/",
45
+ "lint-api": "eslint --no-eslintrc -c .eslintrc.json.typings --max-warnings 0 --no-ignore --ext .d.ts typings/",
46
+ "test-unit": "node ./bin/test_unit.js",
47
+ "test-unit-coverage": "node ./bin/test_unit.js --coverage",
48
48
  "test-unit-dev": "cross-env NODE_PATH='./out' mocha",
49
- "build": "tsc -b ./tsconfig.all.json",
50
- "install-addons": "node ./bin/install-addons.js",
51
- "presetup": "npm run install-addons",
52
- "setup": "npm run build",
53
- "prepublishOnly": "npm run package",
54
- "watch": "tsc -b -w ./tsconfig.all.json --preserveWatchOutput",
49
+ "test-integration": "node ./bin/test_integration.js --workers=75%",
50
+ "test-integration-chromium": "node ./bin/test_integration.js --workers=75% \"--project=ChromeStable\"",
51
+ "test-integration-firefox": "node ./bin/test_integration.js --workers=75% \"--project=FirefoxStable\"",
52
+ "test-integration-webkit": "node ./bin/test_integration.js --workers=75% \"--project=WebKit\"",
53
+ "test-integration-debug": "node ./bin/test_integration.js --workers=1 --headed --timeout=30000",
55
54
  "benchmark": "NODE_PATH=./out xterm-benchmark -r 5 -c test/benchmark/benchmark.json",
56
- "benchmark-baseline": "NODE_PATH=./out xterm-benchmark -r 5 -c test/benchmark/benchmark.json --baseline out-test/benchmark/test/benchmark/*benchmark.js",
57
- "benchmark-eval": "NODE_PATH=./out xterm-benchmark -r 5 -c test/benchmark/benchmark.json --eval out-test/benchmark/test/benchmark/*benchmark.js",
55
+ "benchmark-baseline": "NODE_PATH=./out xterm-benchmark -r 5 -c test/benchmark/benchmark.json --baseline out-test/benchmark/*benchmark.js",
56
+ "benchmark-eval": "NODE_PATH=./out xterm-benchmark -r 5 -c test/benchmark/benchmark.json --eval out-test/benchmark/*benchmark.js",
58
57
  "clean": "rm -rf lib out addons/*/lib addons/*/out",
59
- "vtfeatures": "node bin/extract_vtfeatures.js src/**/*.ts src/*.ts"
58
+ "vtfeatures": "node bin/extract_vtfeatures.js src/**/*.ts src/*.ts",
59
+ "prepackage": "npm run build",
60
+ "package": "webpack",
61
+ "postpackage": "npm run esbuild-package",
62
+ "prepackage-headless": "npm run esbuild-package-headless-only",
63
+ "package-headless": "webpack --config ./webpack.config.headless.js",
64
+ "postpackage-headless": "node ./bin/package_headless.js",
65
+ "prepublishOnly": "npm run package"
60
66
  },
61
67
  "devDependencies": {
62
68
  "@lunapaint/png-codec": "^0.2.0",
63
69
  "@playwright/test": "^1.37.1",
70
+ "@stylistic/eslint-plugin": "^2.3.0",
64
71
  "@types/chai": "^4.2.22",
65
72
  "@types/debug": "^4.1.7",
66
73
  "@types/deep-equal": "^1.0.1",
@@ -70,6 +77,7 @@
70
77
  "@types/jsdom": "^16.2.13",
71
78
  "@types/mocha": "^9.0.0",
72
79
  "@types/node": "^18.16.0",
80
+ "@types/trusted-types": "^1.0.6",
73
81
  "@types/utf8": "^3.0.0",
74
82
  "@types/webpack": "^5.28.0",
75
83
  "@types/ws": "^8.2.0",
@@ -78,9 +86,10 @@
78
86
  "chai": "^4.3.4",
79
87
  "cross-env": "^7.0.3",
80
88
  "deep-equal": "^2.0.5",
89
+ "esbuild": "^0.23.0",
81
90
  "eslint": "^8.56.0",
82
91
  "eslint-plugin-jsdoc": "^46.9.1",
83
- "express": "^4.17.1",
92
+ "express": "^4.19.2",
84
93
  "express-ws": "^5.0.2",
85
94
  "glob": "^7.2.0",
86
95
  "jsdom": "^18.0.1",
@@ -91,7 +100,7 @@
91
100
  "source-map-loader": "^3.0.0",
92
101
  "source-map-support": "^0.5.20",
93
102
  "ts-loader": "^9.3.1",
94
- "typescript": "^5.1.6",
103
+ "typescript": "5.5",
95
104
  "utf8": "^3.0.0",
96
105
  "webpack": "^5.61.0",
97
106
  "webpack-cli": "^4.9.1",
@@ -58,10 +58,11 @@ export class AccessibilityManager extends Disposable {
58
58
  @IRenderService private readonly _renderService: IRenderService
59
59
  ) {
60
60
  super();
61
- this._accessibilityContainer = this._coreBrowserService.mainDocument.createElement('div');
61
+ const doc = this._coreBrowserService.mainDocument;
62
+ this._accessibilityContainer = doc.createElement('div');
62
63
  this._accessibilityContainer.classList.add('xterm-accessibility');
63
64
 
64
- this._rowContainer = this._coreBrowserService.mainDocument.createElement('div');
65
+ this._rowContainer = doc.createElement('div');
65
66
  this._rowContainer.setAttribute('role', 'list');
66
67
  this._rowContainer.classList.add('xterm-accessibility-tree');
67
68
  this._rowElements = [];
@@ -75,10 +76,9 @@ export class AccessibilityManager extends Disposable {
75
76
  this._rowElements[0].addEventListener('focus', this._topBoundaryFocusListener);
76
77
  this._rowElements[this._rowElements.length - 1].addEventListener('focus', this._bottomBoundaryFocusListener);
77
78
 
78
- this._refreshRowsDimensions();
79
79
  this._accessibilityContainer.appendChild(this._rowContainer);
80
80
 
81
- this._liveRegion = this._coreBrowserService.mainDocument.createElement('div');
81
+ this._liveRegion = doc.createElement('div');
82
82
  this._liveRegion.classList.add('live-region');
83
83
  this._liveRegion.setAttribute('aria-live', 'assertive');
84
84
  this._accessibilityContainer.appendChild(this._liveRegion);
@@ -93,12 +93,12 @@ export class AccessibilityManager extends Disposable {
93
93
  this._rowContainer.classList.add('debug');
94
94
 
95
95
  // Use a `<div class="xterm">` container so that the css will still apply.
96
- this._debugRootContainer = document.createElement('div');
96
+ this._debugRootContainer = doc.createElement('div');
97
97
  this._debugRootContainer.classList.add('xterm');
98
98
 
99
- this._debugRootContainer.appendChild(document.createTextNode('------start a11y------'));
99
+ this._debugRootContainer.appendChild(doc.createTextNode('------start a11y------'));
100
100
  this._debugRootContainer.appendChild(this._accessibilityContainer);
101
- this._debugRootContainer.appendChild(document.createTextNode('------end a11y------'));
101
+ this._debugRootContainer.appendChild(doc.createTextNode('------end a11y------'));
102
102
 
103
103
  this._terminal.element.insertAdjacentElement('afterend', this._debugRootContainer);
104
104
  } else {
@@ -115,9 +115,10 @@ export class AccessibilityManager extends Disposable {
115
115
  this.register(this._terminal.onKey(e => this._handleKey(e.key)));
116
116
  this.register(this._terminal.onBlur(() => this._clearLiveRegion()));
117
117
  this.register(this._renderService.onDimensionsChange(() => this._refreshRowsDimensions()));
118
- this.register(addDisposableDomListener(document, 'selectionchange', () => this._handleSelectionChange()));
118
+ this.register(addDisposableDomListener(doc, 'selectionchange', () => this._handleSelectionChange()));
119
119
  this.register(this._coreBrowserService.onDprChange(() => this._refreshRowsDimensions()));
120
120
 
121
+ this._refreshRowsDimensions();
121
122
  this._refreshRows();
122
123
  this.register(toDisposable(() => {
123
124
  if (DEBUG) {
@@ -150,7 +151,7 @@ export class AccessibilityManager extends Disposable {
150
151
  if (char === '\n') {
151
152
  this._liveRegionLineCount++;
152
153
  if (this._liveRegionLineCount === MAX_ROWS_TO_READ + 1) {
153
- this._liveRegion.textContent += Strings.tooMuchOutput;
154
+ this._liveRegion.textContent += Strings.tooMuchOutput.get();
154
155
  }
155
156
  }
156
157
  }
@@ -192,6 +193,7 @@ export class AccessibilityManager extends Disposable {
192
193
  }
193
194
  element.setAttribute('aria-posinset', posInSet);
194
195
  element.setAttribute('aria-setsize', setSize);
196
+ this._alignRowWidth(element);
195
197
  }
196
198
  }
197
199
  this._announceCharacters();
@@ -270,7 +272,7 @@ export class AccessibilityManager extends Disposable {
270
272
  return;
271
273
  }
272
274
 
273
- const selection = document.getSelection();
275
+ const selection = this._coreBrowserService.mainDocument.getSelection();
274
276
  if (!selection) {
275
277
  return;
276
278
  }
@@ -389,19 +391,45 @@ export class AccessibilityManager extends Disposable {
389
391
  this._refreshRowDimensions(element);
390
392
  return element;
391
393
  }
394
+
392
395
  private _refreshRowsDimensions(): void {
393
396
  if (!this._renderService.dimensions.css.cell.height) {
394
397
  return;
395
398
  }
396
- this._accessibilityContainer.style.width = `${this._renderService.dimensions.css.canvas.width}px`;
399
+ Object.assign(this._accessibilityContainer.style, {
400
+ width: `${this._renderService.dimensions.css.canvas.width}px`,
401
+ fontSize: `${this._terminal.options.fontSize}px`
402
+ });
397
403
  if (this._rowElements.length !== this._terminal.rows) {
398
404
  this._handleResize(this._terminal.rows);
399
405
  }
400
406
  for (let i = 0; i < this._terminal.rows; i++) {
401
407
  this._refreshRowDimensions(this._rowElements[i]);
408
+ this._alignRowWidth(this._rowElements[i]);
402
409
  }
403
410
  }
411
+
404
412
  private _refreshRowDimensions(element: HTMLElement): void {
405
413
  element.style.height = `${this._renderService.dimensions.css.cell.height}px`;
406
414
  }
415
+
416
+ /**
417
+ * Scale the width of a row so that each of the character is (mostly) aligned
418
+ * with the actual rendering. This will allow the screen reader to draw
419
+ * selection outline at the correct position.
420
+ *
421
+ * On top of using the "monospace" font and correct font size, the scaling
422
+ * here is necessary to handle characters that are not covered by the font
423
+ * (e.g. CJK).
424
+ */
425
+ private _alignRowWidth(element: HTMLElement): void {
426
+ element.style.transform = '';
427
+ const width = element.getBoundingClientRect().width;
428
+ const lastColumn = this._rowColumns.get(element)?.slice(-1)?.[0];
429
+ if (!lastColumn) {
430
+ return;
431
+ }
432
+ const targetWidth = lastColumn * this._renderService.dimensions.css.cell.width;
433
+ element.style.transform = `scaleX(${targetWidth / width})`;
434
+ }
407
435
  }
@@ -21,12 +21,12 @@
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
26
  import { addDisposableDomListener } from 'browser/Lifecycle';
26
- import { Linkifier } from './Linkifier';
27
27
  import * as Strings from 'browser/LocalizableStrings';
28
28
  import { OscLinkProvider } from 'browser/OscLinkProvider';
29
- import { CharacterJoinerHandler, CustomKeyEventHandler, CustomWheelEventHandler, IBrowser, IBufferRange, ICompositionHelper, ILinkifier2, ITerminal, IViewport } from 'browser/Types';
29
+ import { CharacterJoinerHandler, CustomKeyEventHandler, CustomWheelEventHandler, IBrowser, IBufferRange, ICompositionHelper, ILinkifier2, ITerminal } from 'browser/Types';
30
30
  import { Viewport } from 'browser/Viewport';
31
31
  import { BufferDecorationRenderer } from 'browser/decorations/BufferDecorationRenderer';
32
32
  import { OverviewRulerRenderer } from 'browser/decorations/OverviewRulerRenderer';
@@ -36,6 +36,7 @@ import { IRenderer } from 'browser/renderer/shared/Types';
36
36
  import { CharSizeService } from 'browser/services/CharSizeService';
37
37
  import { CharacterJoinerService } from 'browser/services/CharacterJoinerService';
38
38
  import { CoreBrowserService } from 'browser/services/CoreBrowserService';
39
+ import { LinkProviderService } from 'browser/services/LinkProviderService';
39
40
  import { MouseService } from 'browser/services/MouseService';
40
41
  import { RenderService } from 'browser/services/RenderService';
41
42
  import { SelectionService } from 'browser/services/SelectionService';
@@ -43,10 +44,9 @@ import { ICharSizeService, ICharacterJoinerService, ICoreBrowserService, ILinkPr
43
44
  import { ThemeService } from 'browser/services/ThemeService';
44
45
  import { channels, color } from 'common/Color';
45
46
  import { CoreTerminal } from 'common/CoreTerminal';
46
- import { EventEmitter, IEvent, forwardEvent } from 'common/EventEmitter';
47
47
  import { MutableDisposable, toDisposable } from 'common/Lifecycle';
48
48
  import * as Browser from 'common/Platform';
49
- import { ColorRequestType, CoreMouseAction, CoreMouseButton, CoreMouseEventType, IColorEvent, ITerminalOptions, KeyboardResultType, ScrollSource, SpecialColorIndex } from 'common/Types';
49
+ import { ColorRequestType, CoreMouseAction, CoreMouseButton, CoreMouseEventType, IColorEvent, ITerminalOptions, KeyboardResultType, SpecialColorIndex } from 'common/Types';
50
50
  import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine';
51
51
  import { IBuffer } from 'common/buffer/Types';
52
52
  import { C0, C1_ESCAPED } from 'common/data/EscapeSequences';
@@ -54,24 +54,24 @@ import { evaluateKeyboardEvent } from 'common/input/Keyboard';
54
54
  import { toRgbString } from 'common/input/XParseColor';
55
55
  import { DecorationService } from 'common/services/DecorationService';
56
56
  import { IDecorationService } from 'common/services/Services';
57
- import { IDecoration, IDecorationOptions, IDisposable, ILinkProvider, IMarker } from '@xterm/xterm';
58
57
  import { WindowsOptionsReportType } from '../common/InputHandler';
59
58
  import { AccessibilityManager } from './AccessibilityManager';
60
- import { LinkProviderService } from 'browser/services/LinkProviderService';
59
+ import { Linkifier } from './Linkifier';
60
+ import { Emitter, Event } from 'vs/base/common/event';
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
72
  public linkifier: ILinkifier2 | undefined;
74
73
  private _overviewRulerRenderer: OverviewRulerRenderer | undefined;
74
+ private _viewport: Viewport | undefined;
75
75
 
76
76
  public browser: IBrowser = Browser as any;
77
77
 
@@ -118,33 +118,32 @@ export class Terminal extends CoreTerminal implements ITerminal {
118
118
  */
119
119
  private _unprocessedDeadKey: boolean = false;
120
120
 
121
- public viewport: IViewport | undefined;
122
121
  private _compositionHelper: ICompositionHelper | undefined;
123
122
  private _accessibilityManager: MutableDisposable<AccessibilityManager> = this.register(new MutableDisposable());
124
123
 
125
- private readonly _onCursorMove = this.register(new EventEmitter<void>());
124
+ private readonly _onCursorMove = this.register(new Emitter<void>());
126
125
  public readonly onCursorMove = this._onCursorMove.event;
127
- private readonly _onKey = this.register(new EventEmitter<{ key: string, domEvent: KeyboardEvent }>());
126
+ private readonly _onKey = this.register(new Emitter<{ key: string, domEvent: KeyboardEvent }>());
128
127
  public readonly onKey = this._onKey.event;
129
- private readonly _onRender = this.register(new EventEmitter<{ start: number, end: number }>());
128
+ private readonly _onRender = this.register(new Emitter<{ start: number, end: number }>());
130
129
  public readonly onRender = this._onRender.event;
131
- private readonly _onSelectionChange = this.register(new EventEmitter<void>());
130
+ private readonly _onSelectionChange = this.register(new Emitter<void>());
132
131
  public readonly onSelectionChange = this._onSelectionChange.event;
133
- private readonly _onTitleChange = this.register(new EventEmitter<string>());
132
+ private readonly _onTitleChange = this.register(new Emitter<string>());
134
133
  public readonly onTitleChange = this._onTitleChange.event;
135
- private readonly _onBell = this.register(new EventEmitter<void>());
134
+ private readonly _onBell = this.register(new Emitter<void>());
136
135
  public readonly onBell = this._onBell.event;
137
136
 
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; }
137
+ private _onFocus = this.register(new Emitter<void>());
138
+ public get onFocus(): Event<void> { return this._onFocus.event; }
139
+ private _onBlur = this.register(new Emitter<void>());
140
+ public get onBlur(): Event<void> { return this._onBlur.event; }
141
+ private _onA11yCharEmitter = this.register(new Emitter<string>());
142
+ public get onA11yChar(): Event<string> { return this._onA11yCharEmitter.event; }
143
+ private _onA11yTabEmitter = this.register(new Emitter<number>());
144
+ public get onA11yTab(): Event<number> { return this._onA11yTabEmitter.event; }
145
+ private _onWillOpen = this.register(new Emitter<HTMLElement>());
146
+ public get onWillOpen(): Event<HTMLElement> { return this._onWillOpen.event; }
148
147
 
149
148
  constructor(
150
149
  options: Partial<ITerminalOptions> = {}
@@ -161,15 +160,15 @@ export class Terminal extends CoreTerminal implements ITerminal {
161
160
 
162
161
  // Setup InputHandler listeners
163
162
  this.register(this._inputHandler.onRequestBell(() => this._onBell.fire()));
164
- this.register(this._inputHandler.onRequestRefreshRows((start, end) => this.refresh(start, end)));
163
+ this.register(this._inputHandler.onRequestRefreshRows((e) => this.refresh(e?.start ?? 0, e?.end ?? (this.rows - 1))));
165
164
  this.register(this._inputHandler.onRequestSendFocus(() => this._reportFocus()));
166
165
  this.register(this._inputHandler.onRequestReset(() => this.reset()));
167
166
  this.register(this._inputHandler.onRequestWindowsOptionsReport(type => this._reportWindowsOptions(type)));
168
167
  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));
168
+ this.register(Event.forward(this._inputHandler.onCursorMove, this._onCursorMove));
169
+ this.register(Event.forward(this._inputHandler.onTitleChange, this._onTitleChange));
170
+ this.register(Event.forward(this._inputHandler.onA11yChar, this._onA11yCharEmitter));
171
+ this.register(Event.forward(this._inputHandler.onA11yTab, this._onA11yTabEmitter));
173
172
 
174
173
  // Setup listeners
175
174
  this.register(this._bufferService.onResize(e => this._afterResize(e.cols, e.rows)));
@@ -427,10 +426,6 @@ export class Terminal extends CoreTerminal implements ITerminal {
427
426
  this._viewportElement.classList.add('xterm-viewport');
428
427
  fragment.appendChild(this._viewportElement);
429
428
 
430
- this._viewportScrollArea = this._document.createElement('div');
431
- this._viewportScrollArea.classList.add('xterm-scroll-area');
432
- this._viewportElement.appendChild(this._viewportScrollArea);
433
-
434
429
  this.screenElement = this._document.createElement('div');
435
430
  this.screenElement.classList.add('xterm-screen');
436
431
  this.register(addDisposableDomListener(this.screenElement, 'mousemove', (ev: MouseEvent) => this.updateCursorStyle(ev)));
@@ -443,7 +438,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
443
438
 
444
439
  this.textarea = this._document.createElement('textarea');
445
440
  this.textarea.classList.add('xterm-helper-textarea');
446
- this.textarea.setAttribute('aria-label', Strings.promptLabel);
441
+ this.textarea.setAttribute('aria-label', Strings.promptLabel.get());
447
442
  if (!Browser.isChromeOS) {
448
443
  // ChromeVox on ChromeOS does not like this. See
449
444
  // https://issuetracker.google.com/issues/260170397
@@ -503,11 +498,6 @@ export class Terminal extends CoreTerminal implements ITerminal {
503
498
  this._renderService.setRenderer(this._createRenderer());
504
499
  }
505
500
 
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
501
  this.register(this.onCursorMove(() => {
512
502
  this._renderService!.handleCursorMove();
513
503
  this._syncTextArea();
@@ -515,7 +505,12 @@ export class Terminal extends CoreTerminal implements ITerminal {
515
505
  this.register(this.onResize(() => this._renderService!.handleResize(this.cols, this.rows)));
516
506
  this.register(this.onBlur(() => this._renderService!.handleBlur()));
517
507
  this.register(this.onFocus(() => this._renderService!.handleFocus()));
518
- this.register(this._renderService.onDimensionsChange(() => this.viewport!.syncScrollArea()));
508
+
509
+ this._viewport = this.register(this._instantiationService.createInstance(Viewport, this.element, this.screenElement));
510
+ this.register(this._viewport.onRequestScrollLines(e => {
511
+ super.scrollLines(e, false);
512
+ this.refresh(0, this.rows - 1);
513
+ }));
519
514
 
520
515
  this._selectionService = this.register(this._instantiationService.createInstance(SelectionService,
521
516
  this.element,
@@ -534,11 +529,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
534
529
  this.textarea!.focus();
535
530
  this.textarea!.select();
536
531
  }));
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()));
532
+ this.register(this._onScroll.event(() => this._selectionService!.refresh()));
542
533
 
543
534
  this.register(this._instantiationService.createInstance(BufferDecorationRenderer, this.screenElement));
544
535
  this.register(addDisposableDomListener(this.element, 'mousedown', (e: MouseEvent) => this._selectionService!.handleMouseDown(e)));
@@ -558,11 +549,11 @@ export class Terminal extends CoreTerminal implements ITerminal {
558
549
  }
559
550
  this.register(this.optionsService.onSpecificOptionChange('screenReaderMode', e => this._handleScreenReaderModeOptionChange(e)));
560
551
 
561
- if (this.options.overviewRulerWidth) {
552
+ if (this.options.overviewRuler.width) {
562
553
  this._overviewRulerRenderer = this.register(this._instantiationService.createInstance(OverviewRulerRenderer, this._viewportElement, this.screenElement));
563
554
  }
564
- this.optionsService.onSpecificOptionChange('overviewRulerWidth', value => {
565
- if (!this._overviewRulerRenderer && value && this._viewportElement && this.screenElement) {
555
+ this.optionsService.onSpecificOptionChange('overviewRuler', value => {
556
+ if (!this._overviewRulerRenderer && value.width && this._viewportElement && this.screenElement) {
566
557
  this._overviewRulerRenderer = this.register(this._instantiationService.createInstance(OverviewRulerRenderer, this._viewportElement, this.screenElement));
567
558
  }
568
559
  });
@@ -642,13 +633,11 @@ export class Terminal extends CoreTerminal implements ITerminal {
642
633
  if (self._customWheelEventHandler && self._customWheelEventHandler(ev as WheelEvent) === false) {
643
634
  return false;
644
635
  }
645
- const amount = self.viewport!.getLinesScrolled(ev as WheelEvent);
646
-
647
- if (amount === 0) {
636
+ const deltaY = (ev as WheelEvent).deltaY;
637
+ if (deltaY === 0) {
648
638
  return false;
649
639
  }
650
-
651
- action = (ev as WheelEvent).deltaY < 0 ? CoreMouseAction.UP : CoreMouseAction.DOWN;
640
+ action = deltaY < 0 ? CoreMouseAction.UP : CoreMouseAction.DOWN;
652
641
  but = CoreMouseButton.WHEEL;
653
642
  break;
654
643
  default:
@@ -683,7 +672,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
683
672
  * Note: 'mousedown' currently is "always on" and not managed
684
673
  * by onProtocolChange.
685
674
  */
686
- const requestedEvents: { [key: string]: ((ev: Event) => void) | null } = {
675
+ const requestedEvents: { [key: string]: ((ev: MouseEvent | WheelEvent) => void) | null } = {
687
676
  mouseup: null,
688
677
  wheel: null,
689
678
  mousedrag: null,
@@ -807,42 +796,23 @@ export class Terminal extends CoreTerminal implements ITerminal {
807
796
 
808
797
  if (!this.buffer.hasScrollback) {
809
798
  // 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);
799
+ // enables scrolling in apps hosted in the alt buffer such as vim or tmux even when mouse
800
+ // events are not enabled.
801
+ // This used implementation used get the actual lines/partial lines scrolled from the
802
+ // viewport but since moving to the new viewport implementation has been simplified to
803
+ // simply send a single up or down sequence.
812
804
 
813
805
  // Do nothing if there's no vertical scroll
814
- if (amount === 0) {
815
- return;
806
+ const deltaY = (ev as WheelEvent).deltaY;
807
+ if (deltaY === 0) {
808
+ return false;
816
809
  }
817
810
 
818
811
  // Construct and send sequences
819
812
  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);
813
+ this.coreService.triggerDataEvent(sequence, true);
825
814
  return this.cancel(ev, true);
826
815
  }
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
816
  }, { passive: false }));
847
817
  }
848
818
 
@@ -878,12 +848,36 @@ export class Terminal extends CoreTerminal implements ITerminal {
878
848
  }
879
849
  }
880
850
 
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);
851
+ public scrollLines(disp: number, suppressScrollEvent?: boolean): void {
852
+ // All scrollLines methods need to go via the viewport in order to support smooth scroll
853
+ if (this._viewport) {
854
+ this._viewport.scrollLines(disp);
885
855
  } else {
886
- this.viewport?.scrollLines(disp);
856
+ super.scrollLines(disp, suppressScrollEvent);
857
+ }
858
+ this.refresh(0, this.rows - 1);
859
+ }
860
+
861
+ public scrollPages(pageCount: number): void {
862
+ this.scrollLines(pageCount * (this.rows - 1));
863
+ }
864
+
865
+ public scrollToTop(): void {
866
+ this.scrollLines(-this._bufferService.buffer.ydisp);
867
+ }
868
+
869
+ public scrollToBottom(disableSmoothScroll?: boolean): void {
870
+ if (disableSmoothScroll && this._viewport) {
871
+ this._viewport.scrollToLine(this.buffer.ybase, true);
872
+ } else {
873
+ this.scrollLines(this._bufferService.buffer.ybase - this._bufferService.buffer.ydisp);
874
+ }
875
+ }
876
+
877
+ public scrollToLine(line: number): void {
878
+ const scrollAmount = line - this._bufferService.buffer.ydisp;
879
+ if (scrollAmount !== 0) {
880
+ this.scrollLines(scrollAmount);
887
881
  }
888
882
  }
889
883
 
@@ -1011,7 +1005,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
1011
1005
 
1012
1006
  if (!shouldIgnoreComposition && !this._compositionHelper!.keydown(event)) {
1013
1007
  if (this.options.scrollOnUserInput && this.buffer.ybase !== this.buffer.ydisp) {
1014
- this.scrollToBottom();
1008
+ this.scrollToBottom(true);
1015
1009
  }
1016
1010
  return false;
1017
1011
  }
@@ -1212,10 +1206,6 @@ export class Terminal extends CoreTerminal implements ITerminal {
1212
1206
 
1213
1207
  private _afterResize(x: number, y: number): void {
1214
1208
  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
1209
  }
1220
1210
 
1221
1211
  /**
@@ -1237,8 +1227,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
1237
1227
  }
1238
1228
  // IMPORTANT: Fire scroll event before viewport is reset. This ensures embedders get the clear
1239
1229
  // 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();
1230
+ this._onScroll.fire({ position: this.buffer.ydisp });
1242
1231
  this.refresh(0, this.rows - 1);
1243
1232
  }
1244
1233
 
@@ -1263,7 +1252,6 @@ export class Terminal extends CoreTerminal implements ITerminal {
1263
1252
  super.reset();
1264
1253
  this._selectionService?.reset();
1265
1254
  this._decorationService.reset();
1266
- this.viewport?.reset();
1267
1255
 
1268
1256
  // reattach
1269
1257
  this._customKeyEventHandler = customKeyEventHandler;
@@ -1304,7 +1292,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
1304
1292
  }
1305
1293
 
1306
1294
  // TODO: Remove cancel function and cancelEvents option
1307
- public cancel(ev: Event, force?: boolean): boolean | undefined {
1295
+ public cancel(ev: MouseEvent | WheelEvent | KeyboardEvent | InputEvent, force?: boolean): boolean | undefined {
1308
1296
  if (!this.options.cancelEvents && !force) {
1309
1297
  return;
1310
1298
  }
@@ -5,11 +5,11 @@
5
5
 
6
6
  import { addDisposableDomListener } from 'browser/Lifecycle';
7
7
  import { IBufferCellPosition, ILink, ILinkDecorations, ILinkWithState, ILinkifier2, ILinkifierEvent } from 'browser/Types';
8
- import { EventEmitter } from 'common/EventEmitter';
9
8
  import { Disposable, disposeArray, getDisposeArrayDisposable, toDisposable } from 'common/Lifecycle';
10
9
  import { IDisposable } from 'common/Types';
11
10
  import { IBufferService } from 'common/services/Services';
12
11
  import { ILinkProviderService, IMouseService, IRenderService } from './services/Services';
12
+ import { Emitter } from 'vs/base/common/event';
13
13
 
14
14
  export class Linkifier extends Disposable implements ILinkifier2 {
15
15
  public get currentLink(): ILinkWithState | undefined { return this._currentLink; }
@@ -23,9 +23,9 @@ export class Linkifier extends Disposable implements ILinkifier2 {
23
23
  private _activeProviderReplies: Map<Number, ILinkWithState[] | undefined> | undefined;
24
24
  private _activeLine: number = -1;
25
25
 
26
- private readonly _onShowLinkUnderline = this.register(new EventEmitter<ILinkifierEvent>());
26
+ private readonly _onShowLinkUnderline = this.register(new Emitter<ILinkifierEvent>());
27
27
  public readonly onShowLinkUnderline = this._onShowLinkUnderline.event;
28
- private readonly _onHideLinkUnderline = this.register(new EventEmitter<ILinkifierEvent>());
28
+ private readonly _onHideLinkUnderline = this.register(new Emitter<ILinkifierEvent>());
29
29
  public readonly onHideLinkUnderline = this._onHideLinkUnderline.event;
30
30
 
31
31
  constructor(