@xterm/xterm 6.1.0-beta.21 → 6.1.0-beta.210
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/README.md +61 -38
- package/css/xterm.css +29 -22
- package/lib/xterm.js +1 -1
- package/lib/xterm.js.map +1 -1
- package/lib/xterm.mjs +8 -34
- package/lib/xterm.mjs.map +4 -4
- package/package.json +24 -13
- package/src/browser/AccessibilityManager.ts +6 -3
- package/src/browser/Clipboard.ts +6 -3
- package/src/browser/CoreBrowserTerminal.ts +147 -318
- package/src/browser/Dom.ts +178 -0
- package/src/browser/Linkifier.ts +11 -11
- package/src/browser/OscLinkProvider.ts +3 -1
- package/src/browser/RenderDebouncer.ts +2 -2
- package/src/browser/TimeBasedDebouncer.ts +2 -2
- package/src/browser/Types.ts +12 -11
- package/src/browser/Viewport.ts +55 -20
- package/src/browser/decorations/BufferDecorationRenderer.ts +1 -1
- package/src/browser/decorations/OverviewRulerRenderer.ts +33 -17
- package/src/browser/input/CompositionHelper.ts +44 -8
- package/src/browser/public/Terminal.ts +25 -28
- package/src/browser/renderer/dom/DomRenderer.ts +205 -41
- package/src/browser/renderer/dom/DomRendererRowFactory.ts +19 -13
- package/src/browser/renderer/dom/WidthCache.ts +54 -52
- package/src/browser/renderer/shared/Constants.ts +7 -0
- package/src/browser/renderer/shared/TextBlinkStateManager.ts +97 -0
- package/src/browser/renderer/shared/Types.ts +8 -2
- package/src/browser/scrollable/abstractScrollbar.ts +300 -0
- package/src/browser/scrollable/fastDomNode.ts +126 -0
- package/src/browser/scrollable/globalPointerMoveMonitor.ts +90 -0
- package/src/browser/scrollable/horizontalScrollbar.ts +85 -0
- package/src/browser/scrollable/mouseEvent.ts +292 -0
- package/src/browser/scrollable/scrollable.ts +486 -0
- package/src/browser/scrollable/scrollableElement.ts +579 -0
- package/src/browser/scrollable/scrollableElementOptions.ts +161 -0
- package/src/browser/scrollable/scrollbarArrow.ts +110 -0
- package/src/browser/scrollable/scrollbarState.ts +246 -0
- package/src/browser/scrollable/scrollbarVisibilityController.ts +113 -0
- package/src/browser/scrollable/touch.ts +485 -0
- package/src/browser/scrollable/verticalScrollbar.ts +143 -0
- package/src/browser/scrollable/widget.ts +23 -0
- package/src/browser/services/CharSizeService.ts +2 -2
- package/src/browser/services/CoreBrowserService.ts +7 -5
- package/src/browser/services/KeyboardService.ts +67 -0
- package/src/browser/services/LinkProviderService.ts +1 -1
- package/src/browser/services/MouseCoordsService.ts +47 -0
- package/src/browser/services/MouseService.ts +518 -25
- package/src/browser/services/RenderService.ts +22 -15
- package/src/browser/services/SelectionService.ts +16 -8
- package/src/browser/services/Services.ts +40 -17
- package/src/browser/services/ThemeService.ts +2 -2
- package/src/common/Async.ts +105 -0
- package/src/common/CircularList.ts +2 -2
- package/src/common/Color.ts +8 -0
- package/src/common/CoreTerminal.ts +28 -18
- package/src/common/Event.ts +118 -0
- package/src/common/InputHandler.ts +263 -43
- package/src/common/Lifecycle.ts +113 -0
- package/src/common/Platform.ts +13 -3
- package/src/common/SortedList.ts +7 -3
- package/src/common/TaskQueue.ts +14 -5
- package/src/common/Types.ts +35 -15
- package/src/common/Version.ts +9 -0
- package/src/common/buffer/Buffer.ts +20 -14
- package/src/common/buffer/BufferLine.ts +4 -5
- package/src/common/buffer/BufferSet.ts +7 -6
- package/src/common/buffer/CellData.ts +57 -0
- package/src/common/buffer/Marker.ts +2 -2
- package/src/common/buffer/Types.ts +6 -2
- package/src/common/data/EscapeSequences.ts +71 -70
- package/src/common/input/Keyboard.ts +14 -7
- package/src/common/input/KittyKeyboard.ts +519 -0
- package/src/common/input/Win32InputMode.ts +297 -0
- package/src/common/input/WriteBuffer.ts +34 -2
- package/src/common/input/XParseColor.ts +2 -2
- package/src/common/parser/ApcParser.ts +245 -0
- package/src/common/parser/Constants.ts +22 -4
- package/src/common/parser/DcsParser.ts +5 -5
- package/src/common/parser/EscapeSequenceParser.ts +167 -57
- package/src/common/parser/OscParser.ts +5 -5
- package/src/common/parser/Params.ts +13 -0
- package/src/common/parser/Types.ts +36 -2
- package/src/common/public/BufferLineApiView.ts +2 -2
- package/src/common/public/BufferNamespaceApi.ts +2 -2
- package/src/common/public/ParserApi.ts +3 -0
- package/src/common/services/BufferService.ts +8 -5
- package/src/common/services/CharsetService.ts +4 -0
- package/src/common/services/CoreService.ts +18 -4
- package/src/common/services/DecorationService.ts +24 -8
- package/src/common/services/LogService.ts +1 -31
- package/src/common/services/{CoreMouseService.ts → MouseStateService.ts} +21 -132
- package/src/common/services/OptionsService.ts +13 -4
- package/src/common/services/Services.ts +47 -40
- package/src/common/services/UnicodeService.ts +1 -1
- package/typings/xterm.d.ts +316 -32
- package/src/common/TypedArrayUtils.ts +0 -17
- package/src/vs/base/browser/browser.ts +0 -141
- package/src/vs/base/browser/canIUse.ts +0 -49
- package/src/vs/base/browser/dom.ts +0 -2369
- package/src/vs/base/browser/fastDomNode.ts +0 -316
- package/src/vs/base/browser/globalPointerMoveMonitor.ts +0 -112
- package/src/vs/base/browser/iframe.ts +0 -135
- package/src/vs/base/browser/keyboardEvent.ts +0 -213
- package/src/vs/base/browser/mouseEvent.ts +0 -229
- package/src/vs/base/browser/touch.ts +0 -372
- package/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts +0 -303
- package/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts +0 -114
- package/src/vs/base/browser/ui/scrollbar/scrollableElement.ts +0 -720
- package/src/vs/base/browser/ui/scrollbar/scrollableElementOptions.ts +0 -165
- package/src/vs/base/browser/ui/scrollbar/scrollbarArrow.ts +0 -114
- package/src/vs/base/browser/ui/scrollbar/scrollbarState.ts +0 -243
- package/src/vs/base/browser/ui/scrollbar/scrollbarVisibilityController.ts +0 -118
- package/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts +0 -116
- package/src/vs/base/browser/ui/widget.ts +0 -57
- package/src/vs/base/browser/window.ts +0 -14
- package/src/vs/base/common/arrays.ts +0 -887
- package/src/vs/base/common/arraysFind.ts +0 -202
- package/src/vs/base/common/assert.ts +0 -71
- package/src/vs/base/common/async.ts +0 -1992
- package/src/vs/base/common/cancellation.ts +0 -148
- package/src/vs/base/common/charCode.ts +0 -450
- package/src/vs/base/common/collections.ts +0 -140
- package/src/vs/base/common/decorators.ts +0 -130
- package/src/vs/base/common/equals.ts +0 -146
- package/src/vs/base/common/errors.ts +0 -303
- package/src/vs/base/common/event.ts +0 -1778
- package/src/vs/base/common/functional.ts +0 -32
- package/src/vs/base/common/hash.ts +0 -316
- package/src/vs/base/common/iterator.ts +0 -159
- package/src/vs/base/common/keyCodes.ts +0 -526
- package/src/vs/base/common/keybindings.ts +0 -284
- package/src/vs/base/common/lazy.ts +0 -47
- package/src/vs/base/common/lifecycle.ts +0 -801
- package/src/vs/base/common/linkedList.ts +0 -142
- package/src/vs/base/common/map.ts +0 -202
- package/src/vs/base/common/numbers.ts +0 -98
- package/src/vs/base/common/observable.ts +0 -76
- package/src/vs/base/common/observableInternal/api.ts +0 -31
- package/src/vs/base/common/observableInternal/autorun.ts +0 -281
- package/src/vs/base/common/observableInternal/base.ts +0 -489
- package/src/vs/base/common/observableInternal/debugName.ts +0 -145
- package/src/vs/base/common/observableInternal/derived.ts +0 -428
- package/src/vs/base/common/observableInternal/lazyObservableValue.ts +0 -146
- package/src/vs/base/common/observableInternal/logging.ts +0 -328
- package/src/vs/base/common/observableInternal/promise.ts +0 -209
- package/src/vs/base/common/observableInternal/utils.ts +0 -610
- package/src/vs/base/common/platform.ts +0 -281
- package/src/vs/base/common/scrollable.ts +0 -522
- package/src/vs/base/common/sequence.ts +0 -34
- package/src/vs/base/common/stopwatch.ts +0 -43
- package/src/vs/base/common/strings.ts +0 -557
- package/src/vs/base/common/symbols.ts +0 -9
- package/src/vs/base/common/uint.ts +0 -59
- package/src/vs/patches/nls.ts +0 -90
- package/src/vs/typings/base-common.d.ts +0 -20
- package/src/vs/typings/require.d.ts +0 -42
- package/src/vs/typings/vscode-globals-nls.d.ts +0 -36
- package/src/vs/typings/vscode-globals-product.d.ts +0 -33
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2024-2026 The xterm.js authors. All rights reserved.
|
|
3
|
+
* @license MIT
|
|
4
|
+
*
|
|
5
|
+
* Minimal lifecycle utilities for xterm.js core.
|
|
6
|
+
* Simplified from VS Code's lifecycle.ts - no tracking/leak detection.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export interface IDisposable {
|
|
10
|
+
dispose(): void;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function toDisposable(fn: () => void): IDisposable {
|
|
14
|
+
return { dispose: fn };
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function dispose<T extends IDisposable>(disposable: T): T;
|
|
18
|
+
export function dispose<T extends IDisposable>(disposable: T | undefined): T | undefined;
|
|
19
|
+
export function dispose<T extends IDisposable>(disposables: T[]): T[];
|
|
20
|
+
export function dispose<T extends IDisposable>(arg: T | T[] | undefined): T | T[] | undefined {
|
|
21
|
+
if (!arg) {
|
|
22
|
+
return arg;
|
|
23
|
+
}
|
|
24
|
+
if (Array.isArray(arg)) {
|
|
25
|
+
for (const d of arg) {
|
|
26
|
+
d.dispose();
|
|
27
|
+
}
|
|
28
|
+
return [];
|
|
29
|
+
}
|
|
30
|
+
arg.dispose();
|
|
31
|
+
return arg;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function combinedDisposable(...disposables: IDisposable[]): IDisposable {
|
|
35
|
+
return toDisposable(() => dispose(disposables));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export class DisposableStore implements IDisposable {
|
|
39
|
+
private readonly _disposables = new Set<IDisposable>();
|
|
40
|
+
private _isDisposed = false;
|
|
41
|
+
|
|
42
|
+
public get isDisposed(): boolean {
|
|
43
|
+
return this._isDisposed;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public add<T extends IDisposable>(o: T): T {
|
|
47
|
+
if (this._isDisposed) {
|
|
48
|
+
o.dispose();
|
|
49
|
+
} else {
|
|
50
|
+
this._disposables.add(o);
|
|
51
|
+
}
|
|
52
|
+
return o;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
public dispose(): void {
|
|
56
|
+
if (this._isDisposed) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
this._isDisposed = true;
|
|
60
|
+
for (const d of this._disposables) {
|
|
61
|
+
d.dispose();
|
|
62
|
+
}
|
|
63
|
+
this._disposables.clear();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
public clear(): void {
|
|
67
|
+
for (const d of this._disposables) {
|
|
68
|
+
d.dispose();
|
|
69
|
+
}
|
|
70
|
+
this._disposables.clear();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export abstract class Disposable implements IDisposable {
|
|
75
|
+
public static readonly None: IDisposable = Object.freeze({ dispose() { } });
|
|
76
|
+
|
|
77
|
+
protected readonly _store = new DisposableStore();
|
|
78
|
+
|
|
79
|
+
public dispose(): void {
|
|
80
|
+
this._store.dispose();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
protected _register<T extends IDisposable>(o: T): T {
|
|
84
|
+
return this._store.add(o);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export class MutableDisposable<T extends IDisposable> implements IDisposable {
|
|
89
|
+
private _value: T | undefined;
|
|
90
|
+
private _isDisposed = false;
|
|
91
|
+
|
|
92
|
+
public get value(): T | undefined {
|
|
93
|
+
return this._isDisposed ? undefined : this._value;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
public set value(value: T | undefined) {
|
|
97
|
+
if (this._isDisposed || value === this._value) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
this._value?.dispose();
|
|
101
|
+
this._value = value;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
public clear(): void {
|
|
105
|
+
this.value = undefined;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
public dispose(): void {
|
|
109
|
+
this._isDisposed = true;
|
|
110
|
+
this._value?.dispose();
|
|
111
|
+
this._value = undefined;
|
|
112
|
+
}
|
|
113
|
+
}
|
package/src/common/Platform.ts
CHANGED
|
@@ -14,13 +14,25 @@ interface INavigator {
|
|
|
14
14
|
declare const navigator: INavigator;
|
|
15
15
|
declare const process: unknown;
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
// navigator.userAgent is also checked here because bundling with the process module can cause
|
|
18
|
+
// issues otherwise. Note that navigator exists in Node.js 21+ but the userAgent is
|
|
19
|
+
// "Node.js/<version>".
|
|
20
|
+
export const isNode = (typeof process !== 'undefined' && 'title' in (process as any) && (typeof navigator === 'undefined' || navigator.userAgent.startsWith('Node.js/'))) ? true : false;
|
|
18
21
|
const userAgent = (isNode) ? 'node' : navigator.userAgent;
|
|
19
22
|
const platform = (isNode) ? 'node' : navigator.platform;
|
|
20
23
|
|
|
21
24
|
export const isFirefox = userAgent.includes('Firefox');
|
|
25
|
+
export const isChrome = userAgent.includes('Chrome');
|
|
22
26
|
export const isLegacyEdge = userAgent.includes('Edge');
|
|
23
27
|
export const isSafari = /^((?!chrome|android).)*safari/i.test(userAgent);
|
|
28
|
+
|
|
29
|
+
interface IZoomWindow {
|
|
30
|
+
devicePixelRatio?: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function getZoomFactor(_targetWindow: IZoomWindow): number {
|
|
34
|
+
return 1;
|
|
35
|
+
}
|
|
24
36
|
export function getSafariVersion(): number {
|
|
25
37
|
if (!isSafari) {
|
|
26
38
|
return 0;
|
|
@@ -36,8 +48,6 @@ export function getSafariVersion(): number {
|
|
|
36
48
|
// and ISO third level shifts.
|
|
37
49
|
// http://stackoverflow.com/q/19877924/577598
|
|
38
50
|
export const isMac = ['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K'].includes(platform);
|
|
39
|
-
export const isIpad = platform === 'iPad';
|
|
40
|
-
export const isIphone = platform === 'iPhone';
|
|
41
51
|
export const isWindows = ['Windows', 'Win16', 'Win32', 'WinCE'].includes(platform);
|
|
42
52
|
export const isLinux = platform.indexOf('Linux') >= 0;
|
|
43
53
|
// Note that when this is true, isLinux will also be true.
|
package/src/common/SortedList.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { IdleTaskQueue } from 'common/TaskQueue';
|
|
7
|
+
import type { ILogService } from 'common/services/Services';
|
|
7
8
|
|
|
8
9
|
// Work variables to avoid garbage collection.
|
|
9
10
|
let i = 0;
|
|
@@ -18,16 +19,19 @@ export class SortedList<T> {
|
|
|
18
19
|
private _array: T[] = [];
|
|
19
20
|
|
|
20
21
|
private readonly _insertedValues: T[] = [];
|
|
21
|
-
private readonly _flushInsertedTask
|
|
22
|
+
private readonly _flushInsertedTask: InstanceType<typeof IdleTaskQueue>;
|
|
22
23
|
private _isFlushingInserted = false;
|
|
23
24
|
|
|
24
25
|
private readonly _deletedIndices: number[] = [];
|
|
25
|
-
private readonly _flushDeletedTask
|
|
26
|
+
private readonly _flushDeletedTask: InstanceType<typeof IdleTaskQueue>;
|
|
26
27
|
private _isFlushingDeleted = false;
|
|
27
28
|
|
|
28
29
|
constructor(
|
|
29
|
-
private readonly _getKey: (value: T) => number
|
|
30
|
+
private readonly _getKey: (value: T) => number,
|
|
31
|
+
logService: ILogService
|
|
30
32
|
) {
|
|
33
|
+
this._flushInsertedTask = new IdleTaskQueue(logService);
|
|
34
|
+
this._flushDeletedTask = new IdleTaskQueue(logService);
|
|
31
35
|
}
|
|
32
36
|
|
|
33
37
|
public clear(): void {
|
package/src/common/TaskQueue.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @license MIT
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import type { ILogService } from 'common/services/Services';
|
|
7
7
|
|
|
8
8
|
interface ITaskQueue {
|
|
9
9
|
/**
|
|
@@ -34,6 +34,11 @@ abstract class TaskQueue implements ITaskQueue {
|
|
|
34
34
|
private _tasks: (() => boolean | void)[] = [];
|
|
35
35
|
private _idleCallback?: number;
|
|
36
36
|
private _i = 0;
|
|
37
|
+
protected readonly _logService: ILogService;
|
|
38
|
+
|
|
39
|
+
constructor(logService: ILogService) {
|
|
40
|
+
this._logService = logService;
|
|
41
|
+
}
|
|
37
42
|
|
|
38
43
|
protected abstract _requestCallback(callback: CallbackWithDeadline): number;
|
|
39
44
|
protected abstract _cancelCallback(identifier: number): void;
|
|
@@ -90,7 +95,7 @@ abstract class TaskQueue implements ITaskQueue {
|
|
|
90
95
|
// Warn when the time exceeding the deadline is over 20ms, if this happens in practice the
|
|
91
96
|
// task should be split into sub-tasks to ensure the UI remains responsive.
|
|
92
97
|
if (lastDeadlineRemaining - taskDuration < -20) {
|
|
93
|
-
|
|
98
|
+
this._logService.warn(`task queue exceeded allotted deadline by ${Math.abs(Math.round(lastDeadlineRemaining - taskDuration))}ms`);
|
|
94
99
|
}
|
|
95
100
|
this._start();
|
|
96
101
|
return;
|
|
@@ -142,7 +147,7 @@ class IdleTaskQueueInternal extends TaskQueue {
|
|
|
142
147
|
* This reverts to a {@link PriorityTaskQueue} if the environment does not support idle callbacks.
|
|
143
148
|
*/
|
|
144
149
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
145
|
-
export const IdleTaskQueue = (
|
|
150
|
+
export const IdleTaskQueue = ('requestIdleCallback' in globalThis) ? IdleTaskQueueInternal : PriorityTaskQueue;
|
|
146
151
|
|
|
147
152
|
/**
|
|
148
153
|
* An object that tracks a single debounced task that will run on the next idle frame. When called
|
|
@@ -151,8 +156,8 @@ export const IdleTaskQueue = (!isNode && 'requestIdleCallback' in window) ? Idle
|
|
|
151
156
|
export class DebouncedIdleTask {
|
|
152
157
|
private _queue: ITaskQueue;
|
|
153
158
|
|
|
154
|
-
constructor() {
|
|
155
|
-
this._queue = new IdleTaskQueue();
|
|
159
|
+
constructor(logService: ILogService) {
|
|
160
|
+
this._queue = new IdleTaskQueue(logService);
|
|
156
161
|
}
|
|
157
162
|
|
|
158
163
|
public set(task: () => boolean | void): void {
|
|
@@ -163,4 +168,8 @@ export class DebouncedIdleTask {
|
|
|
163
168
|
public flush(): void {
|
|
164
169
|
this._queue.flush();
|
|
165
170
|
}
|
|
171
|
+
|
|
172
|
+
public dispose(): void {
|
|
173
|
+
this._queue.clear();
|
|
174
|
+
}
|
|
166
175
|
}
|
package/src/common/Types.ts
CHANGED
|
@@ -7,12 +7,12 @@ import { IDeleteEvent, IInsertEvent } from 'common/CircularList';
|
|
|
7
7
|
import { UnderlineStyle } from 'common/buffer/Constants';
|
|
8
8
|
import { IBufferSet } from 'common/buffer/Types';
|
|
9
9
|
import { IParams } from 'common/parser/Types';
|
|
10
|
-
import {
|
|
10
|
+
import { IMouseStateService, ICoreService, IOptionsService, IUnicodeService } from 'common/services/Services';
|
|
11
11
|
import { IFunctionIdentifier, ITerminalOptions as IPublicTerminalOptions } from '@xterm/xterm';
|
|
12
|
-
import type { Emitter,
|
|
12
|
+
import type { Emitter, IEvent } from 'common/Event';
|
|
13
13
|
|
|
14
14
|
export interface ICoreTerminal {
|
|
15
|
-
|
|
15
|
+
mouseStateService: IMouseStateService;
|
|
16
16
|
coreService: ICoreService;
|
|
17
17
|
optionsService: IOptionsService;
|
|
18
18
|
unicodeService: IUnicodeService;
|
|
@@ -22,6 +22,7 @@ export interface ICoreTerminal {
|
|
|
22
22
|
registerDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: IParams) => boolean | Promise<boolean>): IDisposable;
|
|
23
23
|
registerEscHandler(id: IFunctionIdentifier, callback: () => boolean | Promise<boolean>): IDisposable;
|
|
24
24
|
registerOscHandler(ident: number, callback: (data: string) => boolean | Promise<boolean>): IDisposable;
|
|
25
|
+
registerApcHandler(ident: number, callback: (data: string) => boolean | Promise<boolean>): IDisposable;
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
export interface IDisposable {
|
|
@@ -31,7 +32,6 @@ export interface IDisposable {
|
|
|
31
32
|
// TODO: The options that are not in the public API should be reviewed
|
|
32
33
|
export interface ITerminalOptions extends IPublicTerminalOptions {
|
|
33
34
|
[key: string]: any;
|
|
34
|
-
cancelEvents?: boolean;
|
|
35
35
|
convertEol?: boolean;
|
|
36
36
|
termName?: string;
|
|
37
37
|
}
|
|
@@ -68,11 +68,11 @@ export interface ICircularList<T> {
|
|
|
68
68
|
isFull: boolean;
|
|
69
69
|
|
|
70
70
|
onDeleteEmitter: Emitter<IDeleteEvent>;
|
|
71
|
-
onDelete:
|
|
71
|
+
onDelete: IEvent<IDeleteEvent>;
|
|
72
72
|
onInsertEmitter: Emitter<IInsertEvent>;
|
|
73
|
-
onInsert:
|
|
73
|
+
onInsert: IEvent<IInsertEvent>;
|
|
74
74
|
onTrimEmitter: Emitter<number>;
|
|
75
|
-
onTrim:
|
|
75
|
+
onTrim: IEvent<number>;
|
|
76
76
|
|
|
77
77
|
get(index: number): T | undefined;
|
|
78
78
|
set(index: number, value: T): void;
|
|
@@ -101,13 +101,13 @@ export interface ICharset {
|
|
|
101
101
|
[key: string]: string | undefined;
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
export type CharData = [number, string, number, number];
|
|
104
|
+
export type CharData = [attr: number, char: string, width: number, code: number];
|
|
105
105
|
|
|
106
106
|
export interface IColor {
|
|
107
107
|
readonly css: string;
|
|
108
108
|
readonly rgba: number; // 32-bit int with rgba in each byte
|
|
109
109
|
}
|
|
110
|
-
export type IColorRGB = [number, number, number];
|
|
110
|
+
export type IColorRGB = [red: number, green: number, blue: number];
|
|
111
111
|
|
|
112
112
|
export interface IExtendedAttrs {
|
|
113
113
|
ext: number;
|
|
@@ -258,7 +258,7 @@ export interface IMarker extends IDisposable {
|
|
|
258
258
|
readonly id: number;
|
|
259
259
|
readonly isDisposed: boolean;
|
|
260
260
|
readonly line: number;
|
|
261
|
-
onDispose:
|
|
261
|
+
onDispose: IEvent<void>;
|
|
262
262
|
}
|
|
263
263
|
export interface IModes {
|
|
264
264
|
insertMode: boolean;
|
|
@@ -268,15 +268,34 @@ export interface IDecPrivateModes {
|
|
|
268
268
|
applicationCursorKeys: boolean;
|
|
269
269
|
applicationKeypad: boolean;
|
|
270
270
|
bracketedPasteMode: boolean;
|
|
271
|
+
colorSchemeUpdates: boolean;
|
|
271
272
|
cursorBlink: boolean | undefined;
|
|
272
273
|
cursorStyle: CursorStyle | undefined;
|
|
273
274
|
origin: boolean;
|
|
274
275
|
reverseWraparound: boolean;
|
|
275
276
|
sendFocus: boolean;
|
|
276
277
|
synchronizedOutput: boolean;
|
|
278
|
+
win32InputMode: boolean;
|
|
277
279
|
wraparound: boolean; // defaults: xterm - true, vt100 - false
|
|
278
280
|
}
|
|
279
281
|
|
|
282
|
+
/**
|
|
283
|
+
* Kitty keyboard protocol state.
|
|
284
|
+
* Maintains per-screen stacks of enhancement flags.
|
|
285
|
+
*/
|
|
286
|
+
export interface IKittyKeyboardState {
|
|
287
|
+
/** Current active enhancement flags (for current screen) */
|
|
288
|
+
flags: number;
|
|
289
|
+
/** Saved flags for main screen when alt is active */
|
|
290
|
+
mainFlags: number;
|
|
291
|
+
/** Saved flags for alternate screen when main is active */
|
|
292
|
+
altFlags: number;
|
|
293
|
+
/** Stack of flags for main screen */
|
|
294
|
+
mainStack: number[];
|
|
295
|
+
/** Stack of flags for alternate screen */
|
|
296
|
+
altStack: number[];
|
|
297
|
+
}
|
|
298
|
+
|
|
280
299
|
export interface IRowRange {
|
|
281
300
|
start: number;
|
|
282
301
|
end: number;
|
|
@@ -324,7 +343,7 @@ export interface ICoreMouseEvent {
|
|
|
324
343
|
* it is not possible to report multiple buttons at once.
|
|
325
344
|
* Wheel is treated as a button.
|
|
326
345
|
* There are invalid combinations of buttons and actions possible
|
|
327
|
-
* (like move + wheel), those are silently ignored by the
|
|
346
|
+
* (like move + wheel), those are silently ignored by the MouseStateService.
|
|
328
347
|
*/
|
|
329
348
|
button: CoreMouseButton;
|
|
330
349
|
action: CoreMouseAction;
|
|
@@ -341,7 +360,7 @@ export interface ICoreMouseEvent {
|
|
|
341
360
|
* CoreMouseEventType
|
|
342
361
|
* To be reported to the browser component which events a mouse
|
|
343
362
|
* protocol wants to be catched and forwarded as an ICoreMouseEvent
|
|
344
|
-
* to
|
|
363
|
+
* to MouseStateService.
|
|
345
364
|
*/
|
|
346
365
|
export const enum CoreMouseEventType {
|
|
347
366
|
NONE = 0,
|
|
@@ -359,7 +378,7 @@ export const enum CoreMouseEventType {
|
|
|
359
378
|
|
|
360
379
|
/**
|
|
361
380
|
* Mouse protocol interface.
|
|
362
|
-
* A mouse protocol can be registered and activated at the
|
|
381
|
+
* A mouse protocol can be registered and activated at the MouseStateService.
|
|
363
382
|
* `events` should contain a list of needed events as a hint for the browser component
|
|
364
383
|
* to install/remove the appropriate event handlers.
|
|
365
384
|
* `restrict` applies further protocol specific restrictions like not allowed
|
|
@@ -372,7 +391,7 @@ export interface ICoreMouseProtocol {
|
|
|
372
391
|
|
|
373
392
|
/**
|
|
374
393
|
* CoreMouseEncoding
|
|
375
|
-
* The tracking encoding can be registered and activated at the
|
|
394
|
+
* The tracking encoding can be registered and activated at the MouseStateService.
|
|
376
395
|
* If a ICoreMouseEvent passes all procotol restrictions it will be encoded
|
|
377
396
|
* with the active encoding and sent out.
|
|
378
397
|
* Note: Returning an empty string will supress sending a mouse report,
|
|
@@ -449,7 +468,7 @@ export type IColorEvent = (IColorReportRequest | IColorSetRequest | IColorRestor
|
|
|
449
468
|
* Calls the parser and handles actions generated by the parser.
|
|
450
469
|
*/
|
|
451
470
|
export interface IInputHandler {
|
|
452
|
-
onTitleChange:
|
|
471
|
+
onTitleChange: IEvent<string>;
|
|
453
472
|
|
|
454
473
|
parse(data: string | Uint8Array, promiseResult?: boolean): void | Promise<boolean>;
|
|
455
474
|
print(data: Uint32Array, start: number, end: number): void;
|
|
@@ -457,6 +476,7 @@ export interface IInputHandler {
|
|
|
457
476
|
registerDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: IParams) => boolean | Promise<boolean>): IDisposable;
|
|
458
477
|
registerEscHandler(id: IFunctionIdentifier, callback: () => boolean | Promise<boolean>): IDisposable;
|
|
459
478
|
registerOscHandler(ident: number, callback: (data: string) => boolean | Promise<boolean>): IDisposable;
|
|
479
|
+
registerApcHandler(ident: number, callback: (data: string) => boolean | Promise<boolean>): IDisposable;
|
|
460
480
|
|
|
461
481
|
/** C0 BEL */ bell(): boolean;
|
|
462
482
|
/** C0 LF */ lineFeed(): boolean;
|
|
@@ -14,7 +14,7 @@ import { NULL_CELL_CHAR, NULL_CELL_CODE, NULL_CELL_WIDTH, WHITESPACE_CELL_CHAR,
|
|
|
14
14
|
import { Marker } from 'common/buffer/Marker';
|
|
15
15
|
import { IBuffer } from 'common/buffer/Types';
|
|
16
16
|
import { DEFAULT_CHARSET } from 'common/data/Charsets';
|
|
17
|
-
import { IBufferService, IOptionsService } from 'common/services/Services';
|
|
17
|
+
import { IBufferService, ILogService, IOptionsService } from 'common/services/Services';
|
|
18
18
|
|
|
19
19
|
export const MAX_BUFFER_SIZE = 4294967295; // 2^32 - 1
|
|
20
20
|
|
|
@@ -38,17 +38,24 @@ export class Buffer implements IBuffer {
|
|
|
38
38
|
public savedX: number = 0;
|
|
39
39
|
public savedCurAttrData = DEFAULT_ATTR_DATA.clone();
|
|
40
40
|
public savedCharset: ICharset | undefined = DEFAULT_CHARSET;
|
|
41
|
+
public savedCharsets: (ICharset | undefined)[] = [];
|
|
42
|
+
public savedGlevel: number = 0;
|
|
43
|
+
public savedOriginMode: boolean = false;
|
|
44
|
+
public savedWraparoundMode: boolean = true;
|
|
41
45
|
public markers: Marker[] = [];
|
|
42
46
|
private _nullCell: ICellData = CellData.fromCharData([0, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]);
|
|
43
47
|
private _whitespaceCell: ICellData = CellData.fromCharData([0, WHITESPACE_CELL_CHAR, WHITESPACE_CELL_WIDTH, WHITESPACE_CELL_CODE]);
|
|
44
48
|
private _cols: number;
|
|
45
49
|
private _rows: number;
|
|
46
50
|
private _isClearing: boolean = false;
|
|
51
|
+
private _memoryCleanupQueue: InstanceType<typeof IdleTaskQueue>;
|
|
52
|
+
private _memoryCleanupPosition = 0;
|
|
47
53
|
|
|
48
54
|
constructor(
|
|
49
55
|
private _hasScrollback: boolean,
|
|
50
56
|
private _optionsService: IOptionsService,
|
|
51
|
-
private _bufferService: IBufferService
|
|
57
|
+
private _bufferService: IBufferService,
|
|
58
|
+
private readonly _logService: ILogService
|
|
52
59
|
) {
|
|
53
60
|
this._cols = this._bufferService.cols;
|
|
54
61
|
this._rows = this._bufferService.rows;
|
|
@@ -56,6 +63,7 @@ export class Buffer implements IBuffer {
|
|
|
56
63
|
this.scrollTop = 0;
|
|
57
64
|
this.scrollBottom = this._rows - 1;
|
|
58
65
|
this.setupTabStops();
|
|
66
|
+
this._memoryCleanupQueue = new IdleTaskQueue(this._logService);
|
|
59
67
|
}
|
|
60
68
|
|
|
61
69
|
public getNullCell(attr?: IAttributeData): ICellData {
|
|
@@ -118,9 +126,7 @@ export class Buffer implements IBuffer {
|
|
|
118
126
|
*/
|
|
119
127
|
public fillViewportRows(fillAttr?: IAttributeData): void {
|
|
120
128
|
if (this.lines.length === 0) {
|
|
121
|
-
|
|
122
|
-
fillAttr = DEFAULT_ATTR_DATA;
|
|
123
|
-
}
|
|
129
|
+
fillAttr ??= DEFAULT_ATTR_DATA;
|
|
124
130
|
let i = this._rows;
|
|
125
131
|
while (i--) {
|
|
126
132
|
this.lines.push(this.getBlankLine(fillAttr));
|
|
@@ -260,6 +266,13 @@ export class Buffer implements IBuffer {
|
|
|
260
266
|
this._cols = newCols;
|
|
261
267
|
this._rows = newRows;
|
|
262
268
|
|
|
269
|
+
// Ensure the cursor position invariant: ybase + y must be within buffer bounds
|
|
270
|
+
// This can be violated during reflow or when shrinking rows
|
|
271
|
+
if (this.lines.length > 0) {
|
|
272
|
+
const maxY = Math.max(0, this.lines.length - this.ybase - 1);
|
|
273
|
+
this.y = Math.min(this.y, maxY);
|
|
274
|
+
}
|
|
275
|
+
|
|
263
276
|
this._memoryCleanupQueue.clear();
|
|
264
277
|
// schedule memory cleanup only, if more than 10% of the lines are affected
|
|
265
278
|
if (dirtyMemoryLines > 0.1 * this.lines.length) {
|
|
@@ -268,9 +281,6 @@ export class Buffer implements IBuffer {
|
|
|
268
281
|
}
|
|
269
282
|
}
|
|
270
283
|
|
|
271
|
-
private _memoryCleanupQueue = new IdleTaskQueue();
|
|
272
|
-
private _memoryCleanupPosition = 0;
|
|
273
|
-
|
|
274
284
|
private _batchedMemoryCleanup(): boolean {
|
|
275
285
|
let normalRun = true;
|
|
276
286
|
if (this._memoryCleanupPosition >= this.lines.length) {
|
|
@@ -578,9 +588,7 @@ export class Buffer implements IBuffer {
|
|
|
578
588
|
* @param x The position to move the cursor to the previous tab stop.
|
|
579
589
|
*/
|
|
580
590
|
public prevStop(x?: number): number {
|
|
581
|
-
|
|
582
|
-
x = this.x;
|
|
583
|
-
}
|
|
591
|
+
x ??= this.x;
|
|
584
592
|
while (!this.tabs[--x] && x > 0);
|
|
585
593
|
return x >= this._cols ? this._cols - 1 : x < 0 ? 0 : x;
|
|
586
594
|
}
|
|
@@ -590,9 +598,7 @@ export class Buffer implements IBuffer {
|
|
|
590
598
|
* @param x The position to move the cursor one tab stop forward.
|
|
591
599
|
*/
|
|
592
600
|
public nextStop(x?: number): number {
|
|
593
|
-
|
|
594
|
-
x = this.x;
|
|
595
|
-
}
|
|
601
|
+
x ??= this.x;
|
|
596
602
|
while (!this.tabs[++x] && x < this._cols);
|
|
597
603
|
return x >= this._cols ? this._cols - 1 : x < 0 ? 0 : x;
|
|
598
604
|
}
|
|
@@ -39,6 +39,7 @@ export const DEFAULT_ATTR_DATA = Object.freeze(new AttributeData());
|
|
|
39
39
|
|
|
40
40
|
// Work variables to avoid garbage collection
|
|
41
41
|
let $startIndex = 0;
|
|
42
|
+
const $workCell = new CellData();
|
|
42
43
|
|
|
43
44
|
/** Factor when to cleanup underlying array buffer after shrinking. */
|
|
44
45
|
const CLEANUP_THRESHOLD = 2;
|
|
@@ -66,7 +67,7 @@ export class BufferLine implements IBufferLine {
|
|
|
66
67
|
|
|
67
68
|
constructor(cols: number, fillCellData?: ICellData, public isWrapped: boolean = false) {
|
|
68
69
|
this._data = new Uint32Array(cols * CELL_SIZE);
|
|
69
|
-
const cell = fillCellData
|
|
70
|
+
const cell = fillCellData ?? CellData.fromCharData([0, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]);
|
|
70
71
|
for (let i = 0; i < cols; ++i) {
|
|
71
72
|
this.setCell(i, cell);
|
|
72
73
|
}
|
|
@@ -262,9 +263,8 @@ export class BufferLine implements IBufferLine {
|
|
|
262
263
|
}
|
|
263
264
|
|
|
264
265
|
if (n < this.length - pos) {
|
|
265
|
-
const cell = new CellData();
|
|
266
266
|
for (let i = this.length - pos - n - 1; i >= 0; --i) {
|
|
267
|
-
this.setCell(pos + n + i, this.loadCell(pos + i,
|
|
267
|
+
this.setCell(pos + n + i, this.loadCell(pos + i, $workCell));
|
|
268
268
|
}
|
|
269
269
|
for (let i = 0; i < n; ++i) {
|
|
270
270
|
this.setCell(pos + i, fillCellData);
|
|
@@ -284,9 +284,8 @@ export class BufferLine implements IBufferLine {
|
|
|
284
284
|
public deleteCells(pos: number, n: number, fillCellData: ICellData): void {
|
|
285
285
|
pos %= this.length;
|
|
286
286
|
if (n < this.length - pos) {
|
|
287
|
-
const cell = new CellData();
|
|
288
287
|
for (let i = 0; i < this.length - pos - n; ++i) {
|
|
289
|
-
this.setCell(pos + i, this.loadCell(pos + n + i,
|
|
288
|
+
this.setCell(pos + i, this.loadCell(pos + n + i, $workCell));
|
|
290
289
|
}
|
|
291
290
|
for (let i = this.length - n; i < this.length; ++i) {
|
|
292
291
|
this.setCell(i, fillCellData);
|
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
* @license MIT
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { Disposable } from '
|
|
6
|
+
import { Disposable } from 'common/Lifecycle';
|
|
7
7
|
import { IAttributeData } from 'common/Types';
|
|
8
8
|
import { Buffer } from 'common/buffer/Buffer';
|
|
9
9
|
import { IBuffer, IBufferSet } from 'common/buffer/Types';
|
|
10
|
-
import { IBufferService, IOptionsService } from 'common/services/Services';
|
|
11
|
-
import { Emitter } from '
|
|
10
|
+
import { IBufferService, ILogService, IOptionsService } from 'common/services/Services';
|
|
11
|
+
import { Emitter } from 'common/Event';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* The BufferSet represents the set of two buffers used by xterm terminals (normal and alt) and
|
|
@@ -27,7 +27,8 @@ export class BufferSet extends Disposable implements IBufferSet {
|
|
|
27
27
|
*/
|
|
28
28
|
constructor(
|
|
29
29
|
private readonly _optionsService: IOptionsService,
|
|
30
|
-
private readonly _bufferService: IBufferService
|
|
30
|
+
private readonly _bufferService: IBufferService,
|
|
31
|
+
private readonly _logService: ILogService
|
|
31
32
|
) {
|
|
32
33
|
super();
|
|
33
34
|
this.reset();
|
|
@@ -36,12 +37,12 @@ export class BufferSet extends Disposable implements IBufferSet {
|
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
public reset(): void {
|
|
39
|
-
this._normal = new Buffer(true, this._optionsService, this._bufferService);
|
|
40
|
+
this._normal = new Buffer(true, this._optionsService, this._bufferService, this._logService);
|
|
40
41
|
this._normal.fillViewportRows();
|
|
41
42
|
|
|
42
43
|
// The alt buffer should never have scrollback.
|
|
43
44
|
// See http://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-The-Alternate-Screen-Buffer
|
|
44
|
-
this._alt = new Buffer(false, this._optionsService, this._bufferService);
|
|
45
|
+
this._alt = new Buffer(false, this._optionsService, this._bufferService, this._logService);
|
|
45
46
|
this._activeBuffer = this._normal;
|
|
46
47
|
this._onBufferActivate.fire({
|
|
47
48
|
activeBuffer: this._normal,
|
|
@@ -7,6 +7,7 @@ import { CharData, ICellData, IExtendedAttrs } from 'common/Types';
|
|
|
7
7
|
import { stringFromCodePoint } from 'common/input/TextDecoder';
|
|
8
8
|
import { CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX, CHAR_DATA_ATTR_INDEX, Content } from 'common/buffer/Constants';
|
|
9
9
|
import { AttributeData, ExtendedAttrs } from 'common/buffer/AttributeData';
|
|
10
|
+
import type { IBufferCell as IBufferCellApi } from '@xterm/xterm';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* CellData - represents a single Cell in the terminal buffer.
|
|
@@ -91,4 +92,60 @@ export class CellData extends AttributeData implements ICellData {
|
|
|
91
92
|
public getAsCharData(): CharData {
|
|
92
93
|
return [this.fg, this.getChars(), this.getWidth(), this.getCode()];
|
|
93
94
|
}
|
|
95
|
+
|
|
96
|
+
public attributesEquals(other: IBufferCellApi): boolean {
|
|
97
|
+
if (this.getFgColorMode() !== other.getFgColorMode() || this.getFgColor() !== other.getFgColor()) {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
if (this.getBgColorMode() !== other.getBgColorMode() || this.getBgColor() !== other.getBgColor()) {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
if (this.isInverse() !== other.isInverse()) {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
if (this.isBold() !== other.isBold()) {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
if (this.isUnderline() !== other.isUnderline()) {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
if (this.isUnderline()) {
|
|
113
|
+
if (this.getUnderlineStyle() !== other.getUnderlineStyle()) {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
const thisDefault = this.isUnderlineColorDefault();
|
|
117
|
+
const otherDefault = other.isUnderlineColorDefault();
|
|
118
|
+
if (!(thisDefault && otherDefault)) {
|
|
119
|
+
if (thisDefault !== otherDefault) {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
if (this.getUnderlineColor() !== other.getUnderlineColor()) {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
if (this.getUnderlineColorMode() !== other.getUnderlineColorMode()) {
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (this.isOverline() !== other.isOverline()) {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
if (this.isBlink() !== other.isBlink()) {
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
if (this.isInvisible() !== other.isInvisible()) {
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
if (this.isItalic() !== other.isItalic()) {
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
if (this.isDim() !== other.isDim()) {
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
if (this.isStrikethrough() !== other.isStrikethrough()) {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
|
|
94
151
|
}
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { IDisposable, IMarker } from 'common/Types';
|
|
7
|
-
import { Emitter } from '
|
|
8
|
-
import { dispose } from '
|
|
7
|
+
import { Emitter } from 'common/Event';
|
|
8
|
+
import { dispose } from 'common/Lifecycle';
|
|
9
9
|
|
|
10
10
|
export class Marker implements IMarker {
|
|
11
11
|
private static _nextId = 1;
|