@xterm/xterm 6.1.0-beta.214 → 6.1.0-beta.216
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.
- package/lib/xterm.js +1 -1
- package/lib/xterm.js.map +1 -1
- package/lib/xterm.mjs +8 -8
- package/lib/xterm.mjs.map +4 -4
- package/package.json +2 -2
- package/src/browser/AccessibilityManager.ts +5 -3
- package/src/browser/renderer/dom/DomRenderer.ts +41 -39
- package/src/browser/scrollable/scrollableElement.ts +7 -5
- package/src/browser/services/SelectionService.ts +26 -27
- package/src/common/CoreTerminal.ts +3 -3
- package/src/common/InputHandler.ts +18 -20
- package/src/common/Version.ts +1 -1
- package/src/common/buffer/Buffer.ts +14 -5
- package/src/common/buffer/BufferLine.ts +129 -60
- package/src/common/buffer/BufferLineStringCache.ts +69 -0
- package/src/common/buffer/BufferSet.ts +5 -1
- package/src/common/input/WriteBuffer.ts +30 -30
- package/src/common/parser/Params.ts +14 -8
- package/src/common/services/BufferService.ts +6 -4
- package/src/common/services/ServiceRegistry.ts +9 -7
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xterm/xterm",
|
|
3
3
|
"description": "Full xterm terminal, in your browser",
|
|
4
|
-
"version": "6.1.0-beta.
|
|
4
|
+
"version": "6.1.0-beta.216",
|
|
5
5
|
"main": "lib/xterm.js",
|
|
6
6
|
"module": "lib/xterm.mjs",
|
|
7
7
|
"style": "css/xterm.css",
|
|
@@ -119,5 +119,5 @@
|
|
|
119
119
|
"ws": "^8.2.3",
|
|
120
120
|
"xterm-benchmark": "^0.3.1"
|
|
121
121
|
},
|
|
122
|
-
"commit": "
|
|
122
|
+
"commit": "6ba731d73bfbe074e84b57abb62080bed2f4db03"
|
|
123
123
|
}
|
|
@@ -12,7 +12,9 @@ import { IBuffer } from 'common/buffer/Types';
|
|
|
12
12
|
import { IInstantiationService } from 'common/services/Services';
|
|
13
13
|
import { addDisposableListener } from 'browser/Dom';
|
|
14
14
|
|
|
15
|
-
const
|
|
15
|
+
const enum Constants {
|
|
16
|
+
MAX_ROWS_TO_READ = 20
|
|
17
|
+
}
|
|
16
18
|
|
|
17
19
|
const enum BoundaryPosition {
|
|
18
20
|
TOP,
|
|
@@ -137,7 +139,7 @@ export class AccessibilityManager extends Disposable {
|
|
|
137
139
|
}
|
|
138
140
|
|
|
139
141
|
private _handleChar(char: string): void {
|
|
140
|
-
if (this._liveRegionLineCount < MAX_ROWS_TO_READ + 1) {
|
|
142
|
+
if (this._liveRegionLineCount < Constants.MAX_ROWS_TO_READ + 1) {
|
|
141
143
|
if (this._charsToConsume.length > 0) {
|
|
142
144
|
// Have the screen reader ignore the char if it was just input
|
|
143
145
|
const shiftedChar = this._charsToConsume.shift();
|
|
@@ -150,7 +152,7 @@ export class AccessibilityManager extends Disposable {
|
|
|
150
152
|
|
|
151
153
|
if (char === '\n') {
|
|
152
154
|
this._liveRegionLineCount++;
|
|
153
|
-
if (this._liveRegionLineCount === MAX_ROWS_TO_READ + 1) {
|
|
155
|
+
if (this._liveRegionLineCount === Constants.MAX_ROWS_TO_READ + 1) {
|
|
154
156
|
this._liveRegion.textContent = Strings.tooMuchOutput.get();
|
|
155
157
|
}
|
|
156
158
|
}
|
|
@@ -19,13 +19,15 @@ import { Emitter } from 'common/Event';
|
|
|
19
19
|
import { addDisposableListener } from 'browser/Dom';
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
22
|
+
const enum Constants {
|
|
23
|
+
TERMINAL_CLASS_PREFIX = 'xterm-dom-renderer-owner-',
|
|
24
|
+
ROW_CONTAINER_CLASS = 'xterm-rows',
|
|
25
|
+
FG_CLASS_PREFIX = 'xterm-fg-',
|
|
26
|
+
BG_CLASS_PREFIX = 'xterm-bg-',
|
|
27
|
+
FOCUS_CLASS = 'xterm-focus',
|
|
28
|
+
SELECTION_CLASS = 'xterm-selection',
|
|
29
|
+
CURSOR_BLINK_IDLE_CLASS = 'xterm-cursor-blink-idle'
|
|
30
|
+
}
|
|
29
31
|
|
|
30
32
|
let nextTerminalId = 1;
|
|
31
33
|
|
|
@@ -76,12 +78,12 @@ export class DomRenderer extends Disposable implements IRenderer {
|
|
|
76
78
|
) {
|
|
77
79
|
super();
|
|
78
80
|
this._rowContainer = this._document.createElement('div');
|
|
79
|
-
this._rowContainer.classList.add(ROW_CONTAINER_CLASS);
|
|
81
|
+
this._rowContainer.classList.add(Constants.ROW_CONTAINER_CLASS);
|
|
80
82
|
this._rowContainer.style.lineHeight = 'normal';
|
|
81
83
|
this._rowContainer.setAttribute('aria-hidden', 'true');
|
|
82
84
|
this._refreshRowElements(this._bufferService.cols, this._bufferService.rows);
|
|
83
85
|
this._selectionContainer = this._document.createElement('div');
|
|
84
|
-
this._selectionContainer.classList.add(SELECTION_CLASS);
|
|
86
|
+
this._selectionContainer.classList.add(Constants.SELECTION_CLASS);
|
|
85
87
|
this._selectionContainer.setAttribute('aria-hidden', 'true');
|
|
86
88
|
|
|
87
89
|
this.dimensions = createRenderDimensions();
|
|
@@ -93,7 +95,7 @@ export class DomRenderer extends Disposable implements IRenderer {
|
|
|
93
95
|
|
|
94
96
|
this._rowFactory = instantiationService.createInstance(DomRendererRowFactory, document);
|
|
95
97
|
|
|
96
|
-
this._element.classList.add(TERMINAL_CLASS_PREFIX + this._terminalClass);
|
|
98
|
+
this._element.classList.add(Constants.TERMINAL_CLASS_PREFIX + this._terminalClass);
|
|
97
99
|
this._screenElement.appendChild(this._rowContainer);
|
|
98
100
|
this._screenElement.appendChild(this._selectionContainer);
|
|
99
101
|
|
|
@@ -110,7 +112,7 @@ export class DomRenderer extends Disposable implements IRenderer {
|
|
|
110
112
|
));
|
|
111
113
|
|
|
112
114
|
this._register(toDisposable(() => {
|
|
113
|
-
this._element.classList.remove(TERMINAL_CLASS_PREFIX + this._terminalClass);
|
|
115
|
+
this._element.classList.remove(Constants.TERMINAL_CLASS_PREFIX + this._terminalClass);
|
|
114
116
|
|
|
115
117
|
// Outside influences such as React unmounts may manipulate the DOM before our disposal.
|
|
116
118
|
// https://github.com/xtermjs/xterm.js/issues/2960
|
|
@@ -160,7 +162,7 @@ export class DomRenderer extends Disposable implements IRenderer {
|
|
|
160
162
|
}
|
|
161
163
|
|
|
162
164
|
const styles =
|
|
163
|
-
`${this._terminalSelector} .${ROW_CONTAINER_CLASS} span {` +
|
|
165
|
+
`${this._terminalSelector} .${Constants.ROW_CONTAINER_CLASS} span {` +
|
|
164
166
|
` display: inline-block;` + // TODO: find workaround for inline-block (creates ~20% render penalty)
|
|
165
167
|
` height: 100%;` +
|
|
166
168
|
` vertical-align: top;` +
|
|
@@ -181,7 +183,7 @@ export class DomRenderer extends Disposable implements IRenderer {
|
|
|
181
183
|
|
|
182
184
|
// Base CSS
|
|
183
185
|
let styles =
|
|
184
|
-
`${this._terminalSelector} .${ROW_CONTAINER_CLASS} {` +
|
|
186
|
+
`${this._terminalSelector} .${Constants.ROW_CONTAINER_CLASS} {` +
|
|
185
187
|
// Disabling pointer events circumvents a browser behavior that prevents `click` events from
|
|
186
188
|
// being delivered if the target element is replaced during the click. This happened due to
|
|
187
189
|
// refresh() being called during the mousedown handler to start a selection.
|
|
@@ -189,14 +191,14 @@ export class DomRenderer extends Disposable implements IRenderer {
|
|
|
189
191
|
` color: ${colors.foreground.css};` +
|
|
190
192
|
`}`;
|
|
191
193
|
styles +=
|
|
192
|
-
`${this._terminalSelector} .${ROW_CONTAINER_CLASS}, ${this._terminalSelector} .${ROW_CONTAINER_CLASS} span {` +
|
|
194
|
+
`${this._terminalSelector} .${Constants.ROW_CONTAINER_CLASS}, ${this._terminalSelector} .${Constants.ROW_CONTAINER_CLASS} span {` +
|
|
193
195
|
` font-family: ${this._optionsService.rawOptions.fontFamily};` +
|
|
194
196
|
` font-size: ${this._optionsService.rawOptions.fontSize}px;` +
|
|
195
197
|
` font-kerning: none;` +
|
|
196
198
|
` white-space: pre` +
|
|
197
199
|
`}`;
|
|
198
200
|
styles +=
|
|
199
|
-
`${this._terminalSelector} .${ROW_CONTAINER_CLASS} .xterm-dim {` +
|
|
201
|
+
`${this._terminalSelector} .${Constants.ROW_CONTAINER_CLASS} .xterm-dim {` +
|
|
200
202
|
` color: ${color.multiplyOpacity(colors.foreground, 0.5).css};` +
|
|
201
203
|
`}`;
|
|
202
204
|
// Text styles
|
|
@@ -242,70 +244,70 @@ export class DomRenderer extends Disposable implements IRenderer {
|
|
|
242
244
|
`}`;
|
|
243
245
|
// Cursor
|
|
244
246
|
styles +=
|
|
245
|
-
`${this._terminalSelector} .${ROW_CONTAINER_CLASS}.${FOCUS_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_BLINK_CLASS}.${RowCss.CURSOR_STYLE_UNDERLINE_CLASS} {` +
|
|
247
|
+
`${this._terminalSelector} .${Constants.ROW_CONTAINER_CLASS}.${Constants.FOCUS_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_BLINK_CLASS}.${RowCss.CURSOR_STYLE_UNDERLINE_CLASS} {` +
|
|
246
248
|
` animation: ${blinkAnimationUnderlineId} 1s step-end infinite;` +
|
|
247
249
|
`}` +
|
|
248
|
-
`${this._terminalSelector} .${ROW_CONTAINER_CLASS}.${FOCUS_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_BLINK_CLASS}.${RowCss.CURSOR_STYLE_BAR_CLASS} {` +
|
|
250
|
+
`${this._terminalSelector} .${Constants.ROW_CONTAINER_CLASS}.${Constants.FOCUS_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_BLINK_CLASS}.${RowCss.CURSOR_STYLE_BAR_CLASS} {` +
|
|
249
251
|
` animation: ${blinkAnimationBarId} 1s step-end infinite;` +
|
|
250
252
|
`}` +
|
|
251
|
-
`${this._terminalSelector} .${ROW_CONTAINER_CLASS}.${FOCUS_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_BLINK_CLASS}.${RowCss.CURSOR_STYLE_BLOCK_CLASS} {` +
|
|
253
|
+
`${this._terminalSelector} .${Constants.ROW_CONTAINER_CLASS}.${Constants.FOCUS_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_BLINK_CLASS}.${RowCss.CURSOR_STYLE_BLOCK_CLASS} {` +
|
|
252
254
|
` animation: ${blinkAnimationBlockId} 1s step-end infinite;` +
|
|
253
255
|
`}` +
|
|
254
256
|
// Disable cursor blinking when idle
|
|
255
|
-
`${this._terminalSelector} .${ROW_CONTAINER_CLASS}.${CURSOR_BLINK_IDLE_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_BLINK_CLASS} {` +
|
|
257
|
+
`${this._terminalSelector} .${Constants.ROW_CONTAINER_CLASS}.${Constants.CURSOR_BLINK_IDLE_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_BLINK_CLASS} {` +
|
|
256
258
|
` animation: none !important;` +
|
|
257
259
|
`}` +
|
|
258
260
|
// !important helps fix an issue where the cursor will not render on top of the selection,
|
|
259
261
|
// however it's very hard to fix this issue and retain the blink animation without the use of
|
|
260
262
|
// !important. So this edge case fails when cursor blink is on.
|
|
261
|
-
`${this._terminalSelector} .${ROW_CONTAINER_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_STYLE_BLOCK_CLASS} {` +
|
|
263
|
+
`${this._terminalSelector} .${Constants.ROW_CONTAINER_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_STYLE_BLOCK_CLASS} {` +
|
|
262
264
|
` background-color: ${colors.cursor.css};` +
|
|
263
265
|
` color: ${colors.cursorAccent.css};` +
|
|
264
266
|
`}` +
|
|
265
|
-
`${this._terminalSelector} .${ROW_CONTAINER_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_STYLE_BLOCK_CLASS}:not(.${RowCss.CURSOR_BLINK_CLASS}) {` +
|
|
267
|
+
`${this._terminalSelector} .${Constants.ROW_CONTAINER_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_STYLE_BLOCK_CLASS}:not(.${RowCss.CURSOR_BLINK_CLASS}) {` +
|
|
266
268
|
` background-color: ${colors.cursor.css} !important;` +
|
|
267
269
|
` color: ${colors.cursorAccent.css} !important;` +
|
|
268
270
|
`}` +
|
|
269
|
-
`${this._terminalSelector} .${ROW_CONTAINER_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_STYLE_OUTLINE_CLASS} {` +
|
|
271
|
+
`${this._terminalSelector} .${Constants.ROW_CONTAINER_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_STYLE_OUTLINE_CLASS} {` +
|
|
270
272
|
` outline: 1px solid ${colors.cursor.css};` +
|
|
271
273
|
` outline-offset: -1px;` +
|
|
272
274
|
`}` +
|
|
273
|
-
`${this._terminalSelector} .${ROW_CONTAINER_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_STYLE_BAR_CLASS} {` +
|
|
275
|
+
`${this._terminalSelector} .${Constants.ROW_CONTAINER_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_STYLE_BAR_CLASS} {` +
|
|
274
276
|
` box-shadow: ${this._optionsService.rawOptions.cursorWidth}px 0 0 ${colors.cursor.css} inset;` +
|
|
275
277
|
`}` +
|
|
276
|
-
`${this._terminalSelector} .${ROW_CONTAINER_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_STYLE_UNDERLINE_CLASS} {` +
|
|
278
|
+
`${this._terminalSelector} .${Constants.ROW_CONTAINER_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_STYLE_UNDERLINE_CLASS} {` +
|
|
277
279
|
` border-bottom: 1px ${colors.cursor.css};` +
|
|
278
280
|
` border-bottom-style: solid;` +
|
|
279
281
|
` height: calc(100% - 1px);` +
|
|
280
282
|
`}`;
|
|
281
283
|
// Selection
|
|
282
284
|
styles +=
|
|
283
|
-
`${this._terminalSelector} .${SELECTION_CLASS} {` +
|
|
285
|
+
`${this._terminalSelector} .${Constants.SELECTION_CLASS} {` +
|
|
284
286
|
` position: absolute;` +
|
|
285
287
|
` top: 0;` +
|
|
286
288
|
` left: 0;` +
|
|
287
289
|
` z-index: 1;` +
|
|
288
290
|
` pointer-events: none;` +
|
|
289
291
|
`}` +
|
|
290
|
-
`${this._terminalSelector}.focus .${SELECTION_CLASS} div {` +
|
|
292
|
+
`${this._terminalSelector}.focus .${Constants.SELECTION_CLASS} div {` +
|
|
291
293
|
` position: absolute;` +
|
|
292
294
|
` background-color: ${colors.selectionBackgroundOpaque.css};` +
|
|
293
295
|
`}` +
|
|
294
|
-
`${this._terminalSelector} .${SELECTION_CLASS} div {` +
|
|
296
|
+
`${this._terminalSelector} .${Constants.SELECTION_CLASS} div {` +
|
|
295
297
|
` position: absolute;` +
|
|
296
298
|
` background-color: ${colors.selectionInactiveBackgroundOpaque.css};` +
|
|
297
299
|
`}`;
|
|
298
300
|
// Colors
|
|
299
301
|
for (const [i, c] of colors.ansi.entries()) {
|
|
300
302
|
styles +=
|
|
301
|
-
`${this._terminalSelector} .${FG_CLASS_PREFIX}${i} { color: ${c.css}; }` +
|
|
302
|
-
`${this._terminalSelector} .${FG_CLASS_PREFIX}${i}.${RowCss.DIM_CLASS} { color: ${color.multiplyOpacity(c, 0.5).css}; }` +
|
|
303
|
-
`${this._terminalSelector} .${BG_CLASS_PREFIX}${i} { background-color: ${c.css}; }`;
|
|
303
|
+
`${this._terminalSelector} .${Constants.FG_CLASS_PREFIX}${i} { color: ${c.css}; }` +
|
|
304
|
+
`${this._terminalSelector} .${Constants.FG_CLASS_PREFIX}${i}.${RowCss.DIM_CLASS} { color: ${color.multiplyOpacity(c, 0.5).css}; }` +
|
|
305
|
+
`${this._terminalSelector} .${Constants.BG_CLASS_PREFIX}${i} { background-color: ${c.css}; }`;
|
|
304
306
|
}
|
|
305
307
|
styles +=
|
|
306
|
-
`${this._terminalSelector} .${FG_CLASS_PREFIX}${INVERTED_DEFAULT_COLOR} { color: ${color.opaque(colors.background).css}; }` +
|
|
307
|
-
`${this._terminalSelector} .${FG_CLASS_PREFIX}${INVERTED_DEFAULT_COLOR}.${RowCss.DIM_CLASS} { color: ${color.multiplyOpacity(color.opaque(colors.background), 0.5).css}; }` +
|
|
308
|
-
`${this._terminalSelector} .${BG_CLASS_PREFIX}${INVERTED_DEFAULT_COLOR} { background-color: ${colors.foreground.css}; }`;
|
|
308
|
+
`${this._terminalSelector} .${Constants.FG_CLASS_PREFIX}${INVERTED_DEFAULT_COLOR} { color: ${color.opaque(colors.background).css}; }` +
|
|
309
|
+
`${this._terminalSelector} .${Constants.FG_CLASS_PREFIX}${INVERTED_DEFAULT_COLOR}.${RowCss.DIM_CLASS} { color: ${color.multiplyOpacity(color.opaque(colors.background), 0.5).css}; }` +
|
|
310
|
+
`${this._terminalSelector} .${Constants.BG_CLASS_PREFIX}${INVERTED_DEFAULT_COLOR} { background-color: ${colors.foreground.css}; }`;
|
|
309
311
|
|
|
310
312
|
this._themeStyleElement.textContent = styles;
|
|
311
313
|
}
|
|
@@ -361,13 +363,13 @@ export class DomRenderer extends Disposable implements IRenderer {
|
|
|
361
363
|
}
|
|
362
364
|
|
|
363
365
|
public handleBlur(): void {
|
|
364
|
-
this._rowContainer.classList.remove(FOCUS_CLASS);
|
|
366
|
+
this._rowContainer.classList.remove(Constants.FOCUS_CLASS);
|
|
365
367
|
this._cursorBlinkStateManager.pause();
|
|
366
368
|
this.renderRows(0, this._bufferService.rows - 1);
|
|
367
369
|
}
|
|
368
370
|
|
|
369
371
|
public handleFocus(): void {
|
|
370
|
-
this._rowContainer.classList.add(FOCUS_CLASS);
|
|
372
|
+
this._rowContainer.classList.add(Constants.FOCUS_CLASS);
|
|
371
373
|
this._cursorBlinkStateManager.resume();
|
|
372
374
|
this.renderRows(this._bufferService.buffer.y, this._bufferService.buffer.y);
|
|
373
375
|
}
|
|
@@ -561,7 +563,7 @@ export class DomRenderer extends Disposable implements IRenderer {
|
|
|
561
563
|
}
|
|
562
564
|
|
|
563
565
|
private get _terminalSelector(): string {
|
|
564
|
-
return `.${TERMINAL_CLASS_PREFIX}${this._terminalClass}`;
|
|
566
|
+
return `.${Constants.TERMINAL_CLASS_PREFIX}${this._terminalClass}`;
|
|
565
567
|
}
|
|
566
568
|
|
|
567
569
|
private _handleLinkHover(e: ILinkifierEvent): void {
|
|
@@ -667,7 +669,7 @@ class CursorBlinkStateManager {
|
|
|
667
669
|
|
|
668
670
|
public restartBlinkAnimation(): void {
|
|
669
671
|
if (this._isIdlePaused) {
|
|
670
|
-
this._rowContainer.classList.remove(CURSOR_BLINK_IDLE_CLASS);
|
|
672
|
+
this._rowContainer.classList.remove(Constants.CURSOR_BLINK_IDLE_CLASS);
|
|
671
673
|
}
|
|
672
674
|
this._resetIdleTimer();
|
|
673
675
|
}
|
|
@@ -679,7 +681,7 @@ class CursorBlinkStateManager {
|
|
|
679
681
|
|
|
680
682
|
public resume(): void {
|
|
681
683
|
this._isIdlePaused = false;
|
|
682
|
-
this._rowContainer.classList.remove(CURSOR_BLINK_IDLE_CLASS);
|
|
684
|
+
this._rowContainer.classList.remove(Constants.CURSOR_BLINK_IDLE_CLASS);
|
|
683
685
|
this._resetIdleTimer();
|
|
684
686
|
}
|
|
685
687
|
|
|
@@ -699,7 +701,7 @@ class CursorBlinkStateManager {
|
|
|
699
701
|
}
|
|
700
702
|
|
|
701
703
|
private _stopBlinkingDueToIdle(): void {
|
|
702
|
-
this._rowContainer.classList.add(CURSOR_BLINK_IDLE_CLASS);
|
|
704
|
+
this._rowContainer.classList.add(Constants.CURSOR_BLINK_IDLE_CLASS);
|
|
703
705
|
this._isIdlePaused = true;
|
|
704
706
|
this._idleTimeout = undefined;
|
|
705
707
|
}
|
|
@@ -18,8 +18,10 @@ import * as platform from 'common/Platform';
|
|
|
18
18
|
import { INewScrollDimensions, INewScrollPosition, IScrollDimensions, IScrollPosition, IScrollEvent, Scrollable, ScrollbarVisibility } from './scrollable';
|
|
19
19
|
// import 'vs/css!./media/scrollbars';
|
|
20
20
|
|
|
21
|
-
const
|
|
22
|
-
|
|
21
|
+
const enum Constants {
|
|
22
|
+
HIDE_TIMEOUT = 500,
|
|
23
|
+
SCROLL_WHEEL_SENSITIVITY = 50
|
|
24
|
+
}
|
|
23
25
|
|
|
24
26
|
class MouseWheelClassifierItem {
|
|
25
27
|
public timestamp: number;
|
|
@@ -404,12 +406,12 @@ export class SmoothScrollableElement extends Widget {
|
|
|
404
406
|
|
|
405
407
|
let desiredScrollPosition: INewScrollPosition = {};
|
|
406
408
|
if (deltaY) {
|
|
407
|
-
const deltaScrollTop = SCROLL_WHEEL_SENSITIVITY * deltaY;
|
|
409
|
+
const deltaScrollTop = Constants.SCROLL_WHEEL_SENSITIVITY * deltaY;
|
|
408
410
|
const desiredScrollTop = futureScrollPosition.scrollTop - (deltaScrollTop < 0 ? Math.floor(deltaScrollTop) : Math.ceil(deltaScrollTop));
|
|
409
411
|
this._verticalScrollbar.writeScrollPosition(desiredScrollPosition, desiredScrollTop);
|
|
410
412
|
}
|
|
411
413
|
if (deltaX) {
|
|
412
|
-
const deltaScrollLeft = SCROLL_WHEEL_SENSITIVITY * deltaX;
|
|
414
|
+
const deltaScrollLeft = Constants.SCROLL_WHEEL_SENSITIVITY * deltaX;
|
|
413
415
|
const desiredScrollLeft = futureScrollPosition.scrollLeft - (deltaScrollLeft < 0 ? Math.floor(deltaScrollLeft) : Math.ceil(deltaScrollLeft));
|
|
414
416
|
this._horizontalScrollbar.writeScrollPosition(desiredScrollPosition, desiredScrollLeft);
|
|
415
417
|
}
|
|
@@ -533,7 +535,7 @@ export class SmoothScrollableElement extends Widget {
|
|
|
533
535
|
|
|
534
536
|
private _scheduleHide(): void {
|
|
535
537
|
if (!this._mouseIsOver && !this._isDragging) {
|
|
536
|
-
this._hideTimeout.cancelAndSet(() => this._hide(), HIDE_TIMEOUT);
|
|
538
|
+
this._hideTimeout.cancelAndSet(() => this._hide(), Constants.HIDE_TIMEOUT);
|
|
537
539
|
}
|
|
538
540
|
}
|
|
539
541
|
}
|
|
@@ -18,27 +18,26 @@ import { IBuffer } from 'common/buffer/Types';
|
|
|
18
18
|
import { IBufferService, ICoreService, IOptionsService } from 'common/services/Services';
|
|
19
19
|
import { Emitter } from 'common/Event';
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const ALT_CLICK_MOVE_CURSOR_TIME = 500;
|
|
21
|
+
const enum Constants {
|
|
22
|
+
/**
|
|
23
|
+
* The number of pixels the mouse needs to be above or below the viewport in
|
|
24
|
+
* order to scroll at the maximum speed.
|
|
25
|
+
*/
|
|
26
|
+
DRAG_SCROLL_MAX_THRESHOLD = 50,
|
|
27
|
+
/**
|
|
28
|
+
* The maximum scrolling speed
|
|
29
|
+
*/
|
|
30
|
+
DRAG_SCROLL_MAX_SPEED = 15,
|
|
31
|
+
/**
|
|
32
|
+
* The number of milliseconds between drag scroll updates.
|
|
33
|
+
*/
|
|
34
|
+
DRAG_SCROLL_INTERVAL = 50,
|
|
35
|
+
/**
|
|
36
|
+
* The maximum amount of time that can have elapsed for an alt click to move the
|
|
37
|
+
* cursor.
|
|
38
|
+
*/
|
|
39
|
+
ALT_CLICK_MOVE_CURSOR_TIME = 500
|
|
40
|
+
}
|
|
42
41
|
|
|
43
42
|
const NON_BREAKING_SPACE_CHAR = String.fromCharCode(160);
|
|
44
43
|
const ALL_NON_BREAKING_SPACE_REGEX = new RegExp(NON_BREAKING_SPACE_CHAR, 'g');
|
|
@@ -424,9 +423,9 @@ export class SelectionService extends Disposable implements ISelectionService {
|
|
|
424
423
|
offset -= terminalHeight;
|
|
425
424
|
}
|
|
426
425
|
|
|
427
|
-
offset = Math.min(Math.max(offset, -DRAG_SCROLL_MAX_THRESHOLD), DRAG_SCROLL_MAX_THRESHOLD);
|
|
428
|
-
offset /= DRAG_SCROLL_MAX_THRESHOLD;
|
|
429
|
-
return (offset / Math.abs(offset)) + Math.round(offset * (DRAG_SCROLL_MAX_SPEED - 1));
|
|
426
|
+
offset = Math.min(Math.max(offset, -Constants.DRAG_SCROLL_MAX_THRESHOLD), Constants.DRAG_SCROLL_MAX_THRESHOLD);
|
|
427
|
+
offset /= Constants.DRAG_SCROLL_MAX_THRESHOLD;
|
|
428
|
+
return (offset / Math.abs(offset)) + Math.round(offset * (Constants.DRAG_SCROLL_MAX_SPEED - 1));
|
|
430
429
|
}
|
|
431
430
|
|
|
432
431
|
/**
|
|
@@ -500,7 +499,7 @@ export class SelectionService extends Disposable implements ISelectionService {
|
|
|
500
499
|
this._screenElement.ownerDocument.addEventListener('mousemove', this._mouseMoveListener);
|
|
501
500
|
this._screenElement.ownerDocument.addEventListener('mouseup', this._mouseUpListener);
|
|
502
501
|
}
|
|
503
|
-
this._dragScrollIntervalTimer = this._coreBrowserService.window.setInterval(() => this._dragScroll(), DRAG_SCROLL_INTERVAL);
|
|
502
|
+
this._dragScrollIntervalTimer = this._coreBrowserService.window.setInterval(() => this._dragScroll(), Constants.DRAG_SCROLL_INTERVAL);
|
|
504
503
|
}
|
|
505
504
|
|
|
506
505
|
/**
|
|
@@ -675,7 +674,7 @@ export class SelectionService extends Disposable implements ISelectionService {
|
|
|
675
674
|
}
|
|
676
675
|
|
|
677
676
|
/**
|
|
678
|
-
* The callback that occurs every DRAG_SCROLL_INTERVAL ms that does the
|
|
677
|
+
* The callback that occurs every Constants.DRAG_SCROLL_INTERVAL ms that does the
|
|
679
678
|
* scrolling of the viewport.
|
|
680
679
|
*/
|
|
681
680
|
private _dragScroll(): void {
|
|
@@ -713,7 +712,7 @@ export class SelectionService extends Disposable implements ISelectionService {
|
|
|
713
712
|
|
|
714
713
|
this._removeMouseDownListeners();
|
|
715
714
|
|
|
716
|
-
if (this.selectionText.length <= 1 && timeElapsed < ALT_CLICK_MOVE_CURSOR_TIME && event.altKey && this._optionsService.rawOptions.altClickMovesCursor) {
|
|
715
|
+
if (this.selectionText.length <= 1 && timeElapsed < Constants.ALT_CLICK_MOVE_CURSOR_TIME && event.altKey && this._optionsService.rawOptions.altClickMovesCursor) {
|
|
717
716
|
if (this._bufferService.buffer.ybase === this._bufferService.buffer.ydisp) {
|
|
718
717
|
const coordinates = this._mouseCoordsService.getCoords(
|
|
719
718
|
event,
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
import { IInstantiationService, IOptionsService, IBufferService, ILogService, ICharsetService, ICoreService, IMouseStateService, IUnicodeService, LogLevelEnum, ITerminalOptions, IOscLinkService } from 'common/services/Services';
|
|
25
25
|
import { InstantiationService } from 'common/services/InstantiationService';
|
|
26
26
|
import { LogService } from 'common/services/LogService';
|
|
27
|
-
import { BufferService,
|
|
27
|
+
import { BufferService, BufferServiceConstants } from 'common/services/BufferService';
|
|
28
28
|
import { OptionsService } from 'common/services/OptionsService';
|
|
29
29
|
import { IDisposable, IAttributeData, ICoreTerminal, IScrollEvent } from 'common/Types';
|
|
30
30
|
import { CoreService } from 'common/services/CoreService';
|
|
@@ -173,8 +173,8 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
|
|
|
173
173
|
return;
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
-
x = Math.max(x, MINIMUM_COLS);
|
|
177
|
-
y = Math.max(y, MINIMUM_ROWS);
|
|
176
|
+
x = Math.max(x, BufferServiceConstants.MINIMUM_COLS);
|
|
177
|
+
y = Math.max(y, BufferServiceConstants.MINIMUM_ROWS);
|
|
178
178
|
|
|
179
179
|
// Flush pending writes before resize to avoid race conditions where async
|
|
180
180
|
// writes are processed with incorrect dimensions
|
|
@@ -41,12 +41,13 @@ const GLEVEL: { [key: string]: number } = { '(': 0, ')': 1, '*': 2, '+': 3, '-':
|
|
|
41
41
|
/**
|
|
42
42
|
* Max length of the UTF32 input buffer. Real memory consumption is 4 times higher.
|
|
43
43
|
*/
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
44
|
+
const enum Constants {
|
|
45
|
+
MAX_PARSEBUFFER_LENGTH = 131072,
|
|
46
|
+
/** Limit length of title and icon name stacks. */
|
|
47
|
+
STACK_LIMIT = 10,
|
|
48
|
+
// create a warning log if an async handler takes longer than the limit (in ms)
|
|
49
|
+
SLOW_ASYNC_LIMIT = 5000
|
|
50
|
+
}
|
|
50
51
|
|
|
51
52
|
// map params to window option
|
|
52
53
|
function paramToWindowOption(n: number, opts: IWindowOptions): boolean {
|
|
@@ -85,9 +86,6 @@ export enum WindowsOptionsReportType {
|
|
|
85
86
|
GET_CELL_SIZE_PIXELS = 1
|
|
86
87
|
}
|
|
87
88
|
|
|
88
|
-
// create a warning log if an async handler takes longer than the limit (in ms)
|
|
89
|
-
const SLOW_ASYNC_LIMIT = 5000;
|
|
90
|
-
|
|
91
89
|
// Work variables to avoid garbage collection
|
|
92
90
|
let $temp = 0;
|
|
93
91
|
|
|
@@ -393,7 +391,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
|
|
393
391
|
if (this._logService.logLevel <= LogLevelEnum.WARN) {
|
|
394
392
|
let slowTimeout: ReturnType<typeof setTimeout> | undefined;
|
|
395
393
|
const slowPromise = new Promise<never>((_res, rej) => {
|
|
396
|
-
slowTimeout = setTimeout(() => rej('#SLOW_TIMEOUT'), SLOW_ASYNC_LIMIT);
|
|
394
|
+
slowTimeout = setTimeout(() => rej('#SLOW_TIMEOUT'), Constants.SLOW_ASYNC_LIMIT);
|
|
397
395
|
});
|
|
398
396
|
Promise.race([p, slowPromise])
|
|
399
397
|
.then(() => {
|
|
@@ -407,7 +405,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
|
|
407
405
|
if (err !== '#SLOW_TIMEOUT') {
|
|
408
406
|
throw err;
|
|
409
407
|
}
|
|
410
|
-
console.warn(`async parser handler taking longer than ${SLOW_ASYNC_LIMIT} ms`);
|
|
408
|
+
console.warn(`async parser handler taking longer than ${Constants.SLOW_ASYNC_LIMIT} ms`);
|
|
411
409
|
});
|
|
412
410
|
}
|
|
413
411
|
}
|
|
@@ -445,8 +443,8 @@ export class InputHandler extends Disposable implements IInputHandler {
|
|
|
445
443
|
cursorStartX = this._parseStack.cursorStartX;
|
|
446
444
|
cursorStartY = this._parseStack.cursorStartY;
|
|
447
445
|
this._parseStack.paused = false;
|
|
448
|
-
if (data.length > MAX_PARSEBUFFER_LENGTH) {
|
|
449
|
-
start = this._parseStack.position + MAX_PARSEBUFFER_LENGTH;
|
|
446
|
+
if (data.length > Constants.MAX_PARSEBUFFER_LENGTH) {
|
|
447
|
+
start = this._parseStack.position + Constants.MAX_PARSEBUFFER_LENGTH;
|
|
450
448
|
}
|
|
451
449
|
}
|
|
452
450
|
|
|
@@ -463,8 +461,8 @@ export class InputHandler extends Disposable implements IInputHandler {
|
|
|
463
461
|
|
|
464
462
|
// resize input buffer if needed
|
|
465
463
|
if (this._parseBuffer.length < data.length) {
|
|
466
|
-
if (this._parseBuffer.length < MAX_PARSEBUFFER_LENGTH) {
|
|
467
|
-
this._parseBuffer = new Uint32Array(Math.min(data.length, MAX_PARSEBUFFER_LENGTH));
|
|
464
|
+
if (this._parseBuffer.length < Constants.MAX_PARSEBUFFER_LENGTH) {
|
|
465
|
+
this._parseBuffer = new Uint32Array(Math.min(data.length, Constants.MAX_PARSEBUFFER_LENGTH));
|
|
468
466
|
}
|
|
469
467
|
}
|
|
470
468
|
|
|
@@ -475,9 +473,9 @@ export class InputHandler extends Disposable implements IInputHandler {
|
|
|
475
473
|
}
|
|
476
474
|
|
|
477
475
|
// process big data in smaller chunks
|
|
478
|
-
if (data.length > MAX_PARSEBUFFER_LENGTH) {
|
|
479
|
-
for (let i = start; i < data.length; i += MAX_PARSEBUFFER_LENGTH) {
|
|
480
|
-
const end = i + MAX_PARSEBUFFER_LENGTH < data.length ? i + MAX_PARSEBUFFER_LENGTH : data.length;
|
|
476
|
+
if (data.length > Constants.MAX_PARSEBUFFER_LENGTH) {
|
|
477
|
+
for (let i = start; i < data.length; i += Constants.MAX_PARSEBUFFER_LENGTH) {
|
|
478
|
+
const end = i + Constants.MAX_PARSEBUFFER_LENGTH < data.length ? i + Constants.MAX_PARSEBUFFER_LENGTH : data.length;
|
|
481
479
|
const len = (typeof data === 'string')
|
|
482
480
|
? this._stringDecoder.decode(data.substring(i, end), this._parseBuffer)
|
|
483
481
|
: this._utf8Decoder.decode(data.subarray(i, end), this._parseBuffer);
|
|
@@ -2955,13 +2953,13 @@ export class InputHandler extends Disposable implements IInputHandler {
|
|
|
2955
2953
|
case 22: // PushTitle
|
|
2956
2954
|
if (second === 0 || second === 2) {
|
|
2957
2955
|
this._windowTitleStack.push(this._windowTitle);
|
|
2958
|
-
if (this._windowTitleStack.length > STACK_LIMIT) {
|
|
2956
|
+
if (this._windowTitleStack.length > Constants.STACK_LIMIT) {
|
|
2959
2957
|
this._windowTitleStack.shift();
|
|
2960
2958
|
}
|
|
2961
2959
|
}
|
|
2962
2960
|
if (second === 0 || second === 1) {
|
|
2963
2961
|
this._iconNameStack.push(this._iconName);
|
|
2964
|
-
if (this._iconNameStack.length > STACK_LIMIT) {
|
|
2962
|
+
if (this._iconNameStack.length > Constants.STACK_LIMIT) {
|
|
2965
2963
|
this._iconNameStack.shift();
|
|
2966
2964
|
}
|
|
2967
2965
|
}
|
package/src/common/Version.ts
CHANGED
|
@@ -4,10 +4,12 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { CircularList, IInsertEvent } from 'common/CircularList';
|
|
7
|
+
import { Disposable, toDisposable } from 'common/Lifecycle';
|
|
7
8
|
import { IdleTaskQueue } from 'common/TaskQueue';
|
|
8
9
|
import { IAttributeData, IBufferLine, ICellData, ICharset } from 'common/Types';
|
|
9
10
|
import { ExtendedAttrs } from 'common/buffer/AttributeData';
|
|
10
11
|
import { BufferLine, DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine';
|
|
12
|
+
import { BufferLineStringCache } from 'common/buffer/BufferLineStringCache';
|
|
11
13
|
import { getWrappedLineTrimmedLength, reflowLargerApplyNewLayout, reflowLargerCreateNewLayout, reflowLargerGetLinesToRemove, reflowSmallerGetNewLineLengths } from 'common/buffer/BufferReflow';
|
|
12
14
|
import { CellData } from 'common/buffer/CellData';
|
|
13
15
|
import { NULL_CELL_CHAR, NULL_CELL_CODE, NULL_CELL_WIDTH, WHITESPACE_CELL_CHAR, WHITESPACE_CELL_CODE, WHITESPACE_CELL_WIDTH } from 'common/buffer/Constants';
|
|
@@ -25,7 +27,7 @@ export const MAX_BUFFER_SIZE = 4294967295; // 2^32 - 1
|
|
|
25
27
|
* - cursor position
|
|
26
28
|
* - scroll position
|
|
27
29
|
*/
|
|
28
|
-
export class Buffer implements IBuffer {
|
|
30
|
+
export class Buffer extends Disposable implements IBuffer {
|
|
29
31
|
public lines: CircularList<IBufferLine>;
|
|
30
32
|
public ydisp: number = 0;
|
|
31
33
|
public ybase: number = 0;
|
|
@@ -50,6 +52,7 @@ export class Buffer implements IBuffer {
|
|
|
50
52
|
private _isClearing: boolean = false;
|
|
51
53
|
private _memoryCleanupQueue: InstanceType<typeof IdleTaskQueue>;
|
|
52
54
|
private _memoryCleanupPosition = 0;
|
|
55
|
+
private readonly _stringCache: BufferLineStringCache;
|
|
53
56
|
|
|
54
57
|
constructor(
|
|
55
58
|
private _hasScrollback: boolean,
|
|
@@ -57,6 +60,7 @@ export class Buffer implements IBuffer {
|
|
|
57
60
|
private _bufferService: IBufferService,
|
|
58
61
|
private readonly _logService: ILogService
|
|
59
62
|
) {
|
|
63
|
+
super();
|
|
60
64
|
this._cols = this._bufferService.cols;
|
|
61
65
|
this._rows = this._bufferService.rows;
|
|
62
66
|
this.lines = new CircularList<IBufferLine>(this._getCorrectBufferLength(this._rows));
|
|
@@ -64,6 +68,9 @@ export class Buffer implements IBuffer {
|
|
|
64
68
|
this.scrollBottom = this._rows - 1;
|
|
65
69
|
this.setupTabStops();
|
|
66
70
|
this._memoryCleanupQueue = new IdleTaskQueue(this._logService);
|
|
71
|
+
this._register(toDisposable(() => this._memoryCleanupQueue.clear()));
|
|
72
|
+
this._register(toDisposable(() => this.clearAllMarkers()));
|
|
73
|
+
this._stringCache = this._register(new BufferLineStringCache());
|
|
67
74
|
}
|
|
68
75
|
|
|
69
76
|
public getNullCell(attr?: IAttributeData): ICellData {
|
|
@@ -93,7 +100,7 @@ export class Buffer implements IBuffer {
|
|
|
93
100
|
}
|
|
94
101
|
|
|
95
102
|
public getBlankLine(attr: IAttributeData, isWrapped?: boolean): IBufferLine {
|
|
96
|
-
return new BufferLine(this._bufferService.cols, this.getNullCell(attr), isWrapped);
|
|
103
|
+
return new BufferLine(this._stringCache, this._bufferService.cols, this.getNullCell(attr), isWrapped);
|
|
97
104
|
}
|
|
98
105
|
|
|
99
106
|
public get hasScrollback(): boolean {
|
|
@@ -138,6 +145,7 @@ export class Buffer implements IBuffer {
|
|
|
138
145
|
* Clears the buffer to it's initial state, discarding all previous data.
|
|
139
146
|
*/
|
|
140
147
|
public clear(): void {
|
|
148
|
+
this._stringCache.clear();
|
|
141
149
|
this.ydisp = 0;
|
|
142
150
|
this.ybase = 0;
|
|
143
151
|
this.y = 0;
|
|
@@ -156,6 +164,7 @@ export class Buffer implements IBuffer {
|
|
|
156
164
|
public resize(newCols: number, newRows: number): void {
|
|
157
165
|
// store reference to null cell with default attrs
|
|
158
166
|
const nullCell = this.getNullCell(DEFAULT_ATTR_DATA);
|
|
167
|
+
this._stringCache.clear();
|
|
159
168
|
|
|
160
169
|
// count bufferlines with overly big memory to be cleaned afterwards
|
|
161
170
|
let dirtyMemoryLines = 0;
|
|
@@ -190,7 +199,7 @@ export class Buffer implements IBuffer {
|
|
|
190
199
|
if (this._optionsService.rawOptions.windowsPty.backend !== undefined || this._optionsService.rawOptions.windowsPty.buildNumber !== undefined) {
|
|
191
200
|
// Just add the new missing rows on Windows as conpty reprints the screen with it's
|
|
192
201
|
// view of the world. Once a line enters scrollback for conpty it remains there
|
|
193
|
-
this.lines.push(new BufferLine(newCols, nullCell));
|
|
202
|
+
this.lines.push(new BufferLine(this._stringCache, newCols, nullCell, false));
|
|
194
203
|
} else {
|
|
195
204
|
if (this.ybase > 0 && this.lines.length <= this.ybase + this.y + addToY + 1) {
|
|
196
205
|
// There is room above the buffer and there are no empty elements below the line,
|
|
@@ -204,7 +213,7 @@ export class Buffer implements IBuffer {
|
|
|
204
213
|
} else {
|
|
205
214
|
// Add a blank line if there is no buffer left at the top to scroll to, or if there
|
|
206
215
|
// are blank lines after the cursor
|
|
207
|
-
this.lines.push(new BufferLine(newCols, nullCell));
|
|
216
|
+
this.lines.push(new BufferLine(this._stringCache, newCols, nullCell, false));
|
|
208
217
|
}
|
|
209
218
|
}
|
|
210
219
|
}
|
|
@@ -345,7 +354,7 @@ export class Buffer implements IBuffer {
|
|
|
345
354
|
}
|
|
346
355
|
if (this.lines.length < newRows) {
|
|
347
356
|
// Add an extra row at the bottom of the viewport
|
|
348
|
-
this.lines.push(new BufferLine(newCols, nullCell));
|
|
357
|
+
this.lines.push(new BufferLine(this._stringCache, newCols, nullCell, false));
|
|
349
358
|
}
|
|
350
359
|
} else {
|
|
351
360
|
if (this.ydisp === this.ybase) {
|