@xterm/xterm 6.1.0-beta.18 → 6.1.0-beta.181
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 +60 -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 +25 -14
- package/src/browser/AccessibilityManager.ts +6 -3
- package/src/browser/Clipboard.ts +6 -3
- package/src/browser/CoreBrowserTerminal.ts +142 -62
- package/src/browser/Dom.ts +178 -0
- package/src/browser/Linkifier.ts +3 -3
- 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 +40 -17
- package/src/browser/decorations/BufferDecorationRenderer.ts +1 -1
- package/src/browser/decorations/OverviewRulerRenderer.ts +15 -16
- package/src/browser/input/CompositionHelper.ts +16 -1
- package/src/browser/public/Terminal.ts +24 -27
- package/src/browser/renderer/dom/DomRenderer.ts +128 -8
- 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 +481 -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/MouseService.ts +2 -1
- package/src/browser/services/RenderService.ts +22 -15
- package/src/browser/services/SelectionService.ts +12 -4
- package/src/browser/services/Services.ts +24 -15
- 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 +21 -11
- package/src/common/Event.ts +118 -0
- package/src/common/InputHandler.ts +244 -24
- 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 +9 -3
- package/src/common/Types.ts +29 -9
- 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 +496 -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 +75 -22
- package/src/common/parser/OscParser.ts +5 -5
- package/src/common/parser/Types.ts +34 -1
- 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/CoreMouseService.ts +2 -2
- 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/OptionsService.ts +13 -4
- package/src/common/services/Services.ts +39 -16
- package/src/common/services/UnicodeService.ts +1 -1
- package/typings/xterm.d.ts +319 -35
- 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,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 The xterm.js authors. All rights reserved.
|
|
3
|
+
* @license MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { IKeyboardService } from 'browser/services/Services';
|
|
7
|
+
import { evaluateKeyboardEvent } from 'common/input/Keyboard';
|
|
8
|
+
import { KittyKeyboard, KittyKeyboardEventType, KittyKeyboardFlags } from 'common/input/KittyKeyboard';
|
|
9
|
+
import { Win32InputMode } from 'common/input/Win32InputMode';
|
|
10
|
+
import { isMac } from 'common/Platform';
|
|
11
|
+
import { ICoreService, IOptionsService } from 'common/services/Services';
|
|
12
|
+
import { IKeyboardResult } from 'common/Types';
|
|
13
|
+
|
|
14
|
+
export class KeyboardService implements IKeyboardService {
|
|
15
|
+
public serviceBrand: undefined;
|
|
16
|
+
|
|
17
|
+
private _win32InputMode: Win32InputMode | undefined;
|
|
18
|
+
private _kittyKeyboard: KittyKeyboard | undefined;
|
|
19
|
+
|
|
20
|
+
constructor(
|
|
21
|
+
@ICoreService private readonly _coreService: ICoreService,
|
|
22
|
+
@IOptionsService private readonly _optionsService: IOptionsService
|
|
23
|
+
) {
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
private _getWin32InputMode(): Win32InputMode {
|
|
27
|
+
this._win32InputMode ??= new Win32InputMode();
|
|
28
|
+
return this._win32InputMode;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
private _getKittyKeyboard(): KittyKeyboard {
|
|
32
|
+
this._kittyKeyboard ??= new KittyKeyboard();
|
|
33
|
+
return this._kittyKeyboard;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
public evaluateKeyDown(event: KeyboardEvent): IKeyboardResult {
|
|
37
|
+
// Win32 input mode takes priority (most raw)
|
|
38
|
+
if (this.useWin32InputMode) {
|
|
39
|
+
return this._getWin32InputMode().evaluateKeyboardEvent(event, true);
|
|
40
|
+
}
|
|
41
|
+
const kittyFlags = this._coreService.kittyKeyboard.flags;
|
|
42
|
+
return this.useKitty
|
|
43
|
+
? this._getKittyKeyboard().evaluate(event, kittyFlags, event.repeat ? KittyKeyboardEventType.REPEAT : KittyKeyboardEventType.PRESS)
|
|
44
|
+
: evaluateKeyboardEvent(event, this._coreService.decPrivateModes.applicationCursorKeys, isMac, this._optionsService.rawOptions.macOptionIsMeta);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
public evaluateKeyUp(event: KeyboardEvent): IKeyboardResult | undefined {
|
|
48
|
+
// Win32 input mode sends key up events
|
|
49
|
+
if (this.useWin32InputMode) {
|
|
50
|
+
return this._getWin32InputMode().evaluateKeyboardEvent(event, false);
|
|
51
|
+
}
|
|
52
|
+
const kittyFlags = this._coreService.kittyKeyboard.flags;
|
|
53
|
+
if (this.useKitty && (kittyFlags & KittyKeyboardFlags.REPORT_EVENT_TYPES)) {
|
|
54
|
+
return this._getKittyKeyboard().evaluate(event, kittyFlags, KittyKeyboardEventType.RELEASE);
|
|
55
|
+
}
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
public get useKitty(): boolean {
|
|
60
|
+
const kittyFlags = this._coreService.kittyKeyboard.flags;
|
|
61
|
+
return !!(this._optionsService.rawOptions.vtExtensions?.kittyKeyboard && KittyKeyboard.shouldUseProtocol(kittyFlags));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
public get useWin32InputMode(): boolean {
|
|
65
|
+
return !!(this._optionsService.rawOptions.vtExtensions?.win32InputMode && this._coreService.decPrivateModes.win32InputMode);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ILinkProvider, ILinkProviderService } from 'browser/services/Services';
|
|
2
|
-
import { Disposable, toDisposable } from '
|
|
2
|
+
import { Disposable, toDisposable } from 'common/Lifecycle';
|
|
3
3
|
import { IDisposable } from 'common/Types';
|
|
4
4
|
|
|
5
5
|
export class LinkProviderService extends Disposable implements ILinkProviderService {
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* @license MIT
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import { getWindow } from 'browser/Dom';
|
|
6
7
|
import { ICharSizeService, IRenderService, IMouseService } from './Services';
|
|
7
8
|
import { getCoords, getCoordsRelativeToElement } from 'browser/input/Mouse';
|
|
8
9
|
|
|
@@ -30,7 +31,7 @@ export class MouseService implements IMouseService {
|
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
public getMouseReportCoords(event: MouseEvent, element: HTMLElement): { col: number, row: number, x: number, y: number } | undefined {
|
|
33
|
-
const coords = getCoordsRelativeToElement(
|
|
34
|
+
const coords = getCoordsRelativeToElement(getWindow(element), event, element);
|
|
34
35
|
if (!this._charSizeService.hasValidSize) {
|
|
35
36
|
return undefined;
|
|
36
37
|
}
|
|
@@ -7,10 +7,10 @@ import { RenderDebouncer } from 'browser/RenderDebouncer';
|
|
|
7
7
|
import { IRenderDebouncerWithCallback } from 'browser/Types';
|
|
8
8
|
import { IRenderDimensions, IRenderer } from 'browser/renderer/shared/Types';
|
|
9
9
|
import { ICharSizeService, ICoreBrowserService, IRenderService, IThemeService } from 'browser/services/Services';
|
|
10
|
-
import { Disposable, MutableDisposable, toDisposable } from '
|
|
10
|
+
import { Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle';
|
|
11
11
|
import { DebouncedIdleTask } from 'common/TaskQueue';
|
|
12
|
-
import { IBufferService, ICoreService, IDecorationService, IOptionsService } from 'common/services/Services';
|
|
13
|
-
import { Emitter } from '
|
|
12
|
+
import { IBufferService, ICoreService, IDecorationService, ILogService, IOptionsService } from 'common/services/Services';
|
|
13
|
+
import { Emitter } from 'common/Event';
|
|
14
14
|
|
|
15
15
|
interface ISelectionState {
|
|
16
16
|
start: [number, number] | undefined;
|
|
@@ -27,7 +27,7 @@ export class RenderService extends Disposable implements IRenderService {
|
|
|
27
27
|
|
|
28
28
|
private _renderer: MutableDisposable<IRenderer> = this._register(new MutableDisposable());
|
|
29
29
|
private _renderDebouncer: IRenderDebouncerWithCallback;
|
|
30
|
-
private _pausedResizeTask
|
|
30
|
+
private _pausedResizeTask: DebouncedIdleTask;
|
|
31
31
|
private _observerDisposable = this._register(new MutableDisposable());
|
|
32
32
|
|
|
33
33
|
private _isPaused: boolean = false;
|
|
@@ -58,6 +58,7 @@ export class RenderService extends Disposable implements IRenderService {
|
|
|
58
58
|
private _rowCount: number,
|
|
59
59
|
screenElement: HTMLElement,
|
|
60
60
|
@IOptionsService private readonly _optionsService: IOptionsService,
|
|
61
|
+
@ILogService private readonly _logService: ILogService,
|
|
61
62
|
@ICharSizeService private readonly _charSizeService: ICharSizeService,
|
|
62
63
|
@ICoreService private readonly _coreService: ICoreService,
|
|
63
64
|
@IDecorationService decorationService: IDecorationService,
|
|
@@ -67,6 +68,8 @@ export class RenderService extends Disposable implements IRenderService {
|
|
|
67
68
|
) {
|
|
68
69
|
super();
|
|
69
70
|
|
|
71
|
+
this._pausedResizeTask = new DebouncedIdleTask(this._logService);
|
|
72
|
+
|
|
70
73
|
this._renderDebouncer = new RenderDebouncer((start, end) => this._renderRows(start, end), this._coreBrowserService);
|
|
71
74
|
this._register(this._renderDebouncer);
|
|
72
75
|
|
|
@@ -111,7 +114,7 @@ export class RenderService extends Disposable implements IRenderService {
|
|
|
111
114
|
this._register(this._optionsService.onMultipleOptionChange([
|
|
112
115
|
'cursorBlink',
|
|
113
116
|
'cursorStyle'
|
|
114
|
-
], () => this.refreshRows(bufferService.buffer.y, bufferService.buffer.y, true)));
|
|
117
|
+
], () => this.refreshRows(bufferService.buffer.y, bufferService.buffer.y, undefined, true)));
|
|
115
118
|
|
|
116
119
|
this._register(themeService.onChangeColors(() => this._fullRefresh()));
|
|
117
120
|
|
|
@@ -131,6 +134,7 @@ export class RenderService extends Disposable implements IRenderService {
|
|
|
131
134
|
|
|
132
135
|
private _handleIntersectionChange(entry: IntersectionObserverEntry): void {
|
|
133
136
|
this._isPaused = entry.isIntersecting === undefined ? (entry.intersectionRatio === 0) : !entry.isIntersecting;
|
|
137
|
+
this._renderer.value?.handleViewportVisibilityChange?.(!this._isPaused);
|
|
134
138
|
|
|
135
139
|
// Terminal was hidden on open
|
|
136
140
|
if (!this._isPaused && !this._charSizeService.hasValidSize) {
|
|
@@ -144,7 +148,7 @@ export class RenderService extends Disposable implements IRenderService {
|
|
|
144
148
|
}
|
|
145
149
|
}
|
|
146
150
|
|
|
147
|
-
public refreshRows(start: number, end: number, isRedrawOnly: boolean = false): void {
|
|
151
|
+
public refreshRows(start: number, end: number, sync: boolean = false, isRedrawOnly: boolean = false): void {
|
|
148
152
|
if (this._isPaused) {
|
|
149
153
|
this._needsFullRefresh = true;
|
|
150
154
|
return;
|
|
@@ -164,7 +168,12 @@ export class RenderService extends Disposable implements IRenderService {
|
|
|
164
168
|
if (!isRedrawOnly) {
|
|
165
169
|
this._isNextRenderRedrawOnly = false;
|
|
166
170
|
}
|
|
167
|
-
|
|
171
|
+
|
|
172
|
+
if (sync) {
|
|
173
|
+
this._renderRows(start, end);
|
|
174
|
+
} else {
|
|
175
|
+
this._renderDebouncer.refresh(start, end, this._rowCount);
|
|
176
|
+
}
|
|
168
177
|
}
|
|
169
178
|
|
|
170
179
|
private _renderRows(start: number, end: number): void {
|
|
@@ -234,7 +243,7 @@ export class RenderService extends Disposable implements IRenderService {
|
|
|
234
243
|
this._renderer.value = renderer;
|
|
235
244
|
// If the value was not set, the terminal is being disposed so ignore it
|
|
236
245
|
if (this._renderer.value) {
|
|
237
|
-
this._renderer.value.onRequestRedraw(e => this.refreshRows(e.start, e.end, true));
|
|
246
|
+
this._renderer.value.onRequestRedraw(e => this.refreshRows(e.start, e.end, e.sync, true));
|
|
238
247
|
|
|
239
248
|
// Force a refresh
|
|
240
249
|
this._needsSelectionRefresh = true;
|
|
@@ -342,13 +351,11 @@ class SynchronizedOutputHandler {
|
|
|
342
351
|
this._end = Math.max(this._end, end);
|
|
343
352
|
}
|
|
344
353
|
|
|
345
|
-
|
|
346
|
-
this._timeout =
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
}, Constants.SYNCHRONIZED_OUTPUT_TIMEOUT_MS);
|
|
351
|
-
}
|
|
354
|
+
this._timeout ??= this._coreBrowserService.window.setTimeout(() => {
|
|
355
|
+
this._timeout = undefined;
|
|
356
|
+
this._coreService.decPrivateModes.synchronizedOutput = false;
|
|
357
|
+
this._onTimeout();
|
|
358
|
+
}, Constants.SYNCHRONIZED_OUTPUT_TIMEOUT_MS);
|
|
352
359
|
}
|
|
353
360
|
|
|
354
361
|
public flush(): { start: number, end: number } | undefined {
|
|
@@ -9,14 +9,14 @@ import { moveToCellSequence } from 'browser/input/MoveToCell';
|
|
|
9
9
|
import { SelectionModel } from 'browser/selection/SelectionModel';
|
|
10
10
|
import { ISelectionRedrawRequestEvent, ISelectionRequestScrollLinesEvent } from 'browser/selection/Types';
|
|
11
11
|
import { ICoreBrowserService, IMouseService, IRenderService, ISelectionService } from 'browser/services/Services';
|
|
12
|
-
import { Disposable, toDisposable } from '
|
|
12
|
+
import { Disposable, toDisposable } from 'common/Lifecycle';
|
|
13
13
|
import * as Browser from 'common/Platform';
|
|
14
|
-
import { IBufferLine, IDisposable } from 'common/Types';
|
|
14
|
+
import { IBufferLine, ICellData, IDisposable } from 'common/Types';
|
|
15
15
|
import { getRangeLength } from 'common/buffer/BufferRange';
|
|
16
16
|
import { CellData } from 'common/buffer/CellData';
|
|
17
17
|
import { IBuffer } from 'common/buffer/Types';
|
|
18
18
|
import { IBufferService, ICoreService, IOptionsService } from 'common/services/Services';
|
|
19
|
-
import { Emitter } from '
|
|
19
|
+
import { Emitter } from 'common/Event';
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* The number of pixels the mouse needs to be above or below the viewport in
|
|
@@ -532,6 +532,9 @@ export class SelectionService extends Disposable implements ISelectionService {
|
|
|
532
532
|
* @param event The mouse event.
|
|
533
533
|
*/
|
|
534
534
|
private _handleSingleClick(event: MouseEvent): void {
|
|
535
|
+
// Track if there was a selection before clearing
|
|
536
|
+
const hadSelection = this.hasSelection;
|
|
537
|
+
|
|
535
538
|
this._model.selectionStartLength = 0;
|
|
536
539
|
this._model.isSelectAllActive = false;
|
|
537
540
|
this._activeSelectionMode = this.shouldColumnSelect(event) ? SelectionMode.COLUMN : SelectionMode.NORMAL;
|
|
@@ -543,6 +546,11 @@ export class SelectionService extends Disposable implements ISelectionService {
|
|
|
543
546
|
}
|
|
544
547
|
this._model.selectionEnd = undefined;
|
|
545
548
|
|
|
549
|
+
// Fire selection change event if a selection was cleared
|
|
550
|
+
if (hadSelection) {
|
|
551
|
+
this._fireOnSelectionChange(this._model.finalSelectionStart, this._model.finalSelectionEnd, false);
|
|
552
|
+
}
|
|
553
|
+
|
|
546
554
|
// Ensure the line exists
|
|
547
555
|
const line = this._bufferService.buffer.lines.get(this._model.selectionStart[1]);
|
|
548
556
|
if (!line) {
|
|
@@ -1013,7 +1021,7 @@ export class SelectionService extends Disposable implements ISelectionService {
|
|
|
1013
1021
|
* word logic.
|
|
1014
1022
|
* @param cell The cell to check.
|
|
1015
1023
|
*/
|
|
1016
|
-
private _isCharWordSeparator(cell:
|
|
1024
|
+
private _isCharWordSeparator(cell: ICellData): boolean {
|
|
1017
1025
|
// Zero width characters are never separators as they are always to the
|
|
1018
1026
|
// right of wide characters
|
|
1019
1027
|
if (cell.getWidth() === 0) {
|
|
@@ -7,8 +7,8 @@ import { IRenderDimensions, IRenderer } from 'browser/renderer/shared/Types';
|
|
|
7
7
|
import { IColorSet, ILink, ReadonlyColorSet } from 'browser/Types';
|
|
8
8
|
import { ISelectionRedrawRequestEvent as ISelectionRequestRedrawEvent, ISelectionRequestScrollLinesEvent } from 'browser/selection/Types';
|
|
9
9
|
import { createDecorator } from 'common/services/ServiceRegistry';
|
|
10
|
-
import { AllColorIndex, IDisposable } from 'common/Types';
|
|
11
|
-
import type {
|
|
10
|
+
import { AllColorIndex, IDisposable, IKeyboardResult } from 'common/Types';
|
|
11
|
+
import type { IEvent } from 'common/Event';
|
|
12
12
|
|
|
13
13
|
export const ICharSizeService = createDecorator<ICharSizeService>('CharSizeService');
|
|
14
14
|
export interface ICharSizeService {
|
|
@@ -18,7 +18,7 @@ export interface ICharSizeService {
|
|
|
18
18
|
readonly height: number;
|
|
19
19
|
readonly hasValidSize: boolean;
|
|
20
20
|
|
|
21
|
-
readonly onCharSizeChange:
|
|
21
|
+
readonly onCharSizeChange: IEvent<void>;
|
|
22
22
|
|
|
23
23
|
measure(): void;
|
|
24
24
|
}
|
|
@@ -29,8 +29,8 @@ export interface ICoreBrowserService {
|
|
|
29
29
|
|
|
30
30
|
readonly isFocused: boolean;
|
|
31
31
|
|
|
32
|
-
readonly onDprChange:
|
|
33
|
-
readonly onWindowChange:
|
|
32
|
+
readonly onDprChange: IEvent<number>;
|
|
33
|
+
readonly onWindowChange: IEvent<Window & typeof globalThis>;
|
|
34
34
|
|
|
35
35
|
/**
|
|
36
36
|
* Gets or sets the parent window that the terminal is rendered into. DOM and rendering APIs (e.g.
|
|
@@ -61,23 +61,23 @@ export const IRenderService = createDecorator<IRenderService>('RenderService');
|
|
|
61
61
|
export interface IRenderService extends IDisposable {
|
|
62
62
|
serviceBrand: undefined;
|
|
63
63
|
|
|
64
|
-
onDimensionsChange:
|
|
64
|
+
onDimensionsChange: IEvent<IRenderDimensions>;
|
|
65
65
|
/**
|
|
66
66
|
* Fires when buffer changes are rendered. This does not fire when only cursor
|
|
67
67
|
* or selections are rendered.
|
|
68
68
|
*/
|
|
69
|
-
onRenderedViewportChange:
|
|
69
|
+
onRenderedViewportChange: IEvent<{ start: number, end: number }>;
|
|
70
70
|
/**
|
|
71
71
|
* Fires on render
|
|
72
72
|
*/
|
|
73
|
-
onRender:
|
|
74
|
-
onRefreshRequest:
|
|
73
|
+
onRender: IEvent<{ start: number, end: number }>;
|
|
74
|
+
onRefreshRequest: IEvent<{ start: number, end: number }>;
|
|
75
75
|
|
|
76
76
|
dimensions: IRenderDimensions;
|
|
77
77
|
|
|
78
78
|
addRefreshCallback(callback: FrameRequestCallback): number;
|
|
79
79
|
|
|
80
|
-
refreshRows(start: number, end: number): void;
|
|
80
|
+
refreshRows(start: number, end: number, sync?: boolean): void;
|
|
81
81
|
clearTextureAtlas(): void;
|
|
82
82
|
resize(cols: number, rows: number): void;
|
|
83
83
|
hasRenderer(): boolean;
|
|
@@ -101,10 +101,10 @@ export interface ISelectionService {
|
|
|
101
101
|
readonly selectionStart: [number, number] | undefined;
|
|
102
102
|
readonly selectionEnd: [number, number] | undefined;
|
|
103
103
|
|
|
104
|
-
readonly onLinuxMouseSelection:
|
|
105
|
-
readonly onRequestRedraw:
|
|
106
|
-
readonly onRequestScrollLines:
|
|
107
|
-
readonly onSelectionChange:
|
|
104
|
+
readonly onLinuxMouseSelection: IEvent<string>;
|
|
105
|
+
readonly onRequestRedraw: IEvent<ISelectionRequestRedrawEvent>;
|
|
106
|
+
readonly onRequestScrollLines: IEvent<ISelectionRequestScrollLinesEvent>;
|
|
107
|
+
readonly onSelectionChange: IEvent<void>;
|
|
108
108
|
|
|
109
109
|
disable(): void;
|
|
110
110
|
enable(): void;
|
|
@@ -136,7 +136,7 @@ export interface IThemeService {
|
|
|
136
136
|
|
|
137
137
|
readonly colors: ReadonlyColorSet;
|
|
138
138
|
|
|
139
|
-
readonly onChangeColors:
|
|
139
|
+
readonly onChangeColors: IEvent<ReadonlyColorSet>;
|
|
140
140
|
|
|
141
141
|
restoreColor(slot?: AllColorIndex): void;
|
|
142
142
|
/**
|
|
@@ -156,3 +156,12 @@ export interface ILinkProviderService extends IDisposable {
|
|
|
156
156
|
export interface ILinkProvider {
|
|
157
157
|
provideLinks(y: number, callback: (links: ILink[] | undefined) => void): void;
|
|
158
158
|
}
|
|
159
|
+
|
|
160
|
+
export const IKeyboardService = createDecorator<IKeyboardService>('KeyboardService');
|
|
161
|
+
export interface IKeyboardService {
|
|
162
|
+
serviceBrand: undefined;
|
|
163
|
+
evaluateKeyDown(event: KeyboardEvent): IKeyboardResult;
|
|
164
|
+
evaluateKeyUp(event: KeyboardEvent): IKeyboardResult | undefined;
|
|
165
|
+
readonly useKitty: boolean;
|
|
166
|
+
readonly useWin32InputMode: boolean;
|
|
167
|
+
}
|
|
@@ -7,10 +7,10 @@ import { ColorContrastCache } from 'browser/ColorContrastCache';
|
|
|
7
7
|
import { IThemeService } from 'browser/services/Services';
|
|
8
8
|
import { DEFAULT_ANSI_COLORS, IColorContrastCache, IColorSet, ReadonlyColorSet } from 'browser/Types';
|
|
9
9
|
import { color, css, NULL_COLOR } from 'common/Color';
|
|
10
|
-
import { Disposable } from '
|
|
10
|
+
import { Disposable } from 'common/Lifecycle';
|
|
11
11
|
import { IOptionsService, ITheme } from 'common/services/Services';
|
|
12
12
|
import { AllColorIndex, IColor, SpecialColorIndex } from 'common/Types';
|
|
13
|
-
import { Emitter } from '
|
|
13
|
+
import { Emitter } from 'common/Event';
|
|
14
14
|
|
|
15
15
|
interface IRestoreColorSet {
|
|
16
16
|
foreground: IColor;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026 The xterm.js authors. All rights reserved.
|
|
3
|
+
* @license MIT
|
|
4
|
+
*
|
|
5
|
+
* Minimal async helpers for xterm.js core.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { DisposableStore, IDisposable, toDisposable } from 'common/Lifecycle';
|
|
9
|
+
|
|
10
|
+
export function timeout(millis: number): Promise<void> {
|
|
11
|
+
return new Promise(resolve => setTimeout(resolve, millis));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Creates a timeout that can be disposed using its returned value.
|
|
16
|
+
* @param handler The timeout handler.
|
|
17
|
+
* @param timeout An optional timeout in milliseconds.
|
|
18
|
+
* @param store An optional {@link DisposableStore} that will have the timeout disposable managed
|
|
19
|
+
* automatically.
|
|
20
|
+
*/
|
|
21
|
+
export function disposableTimeout(handler: () => void, timeout = 0, store?: DisposableStore): IDisposable {
|
|
22
|
+
const timer = setTimeout(() => {
|
|
23
|
+
handler();
|
|
24
|
+
if (store) {
|
|
25
|
+
disposable.dispose();
|
|
26
|
+
}
|
|
27
|
+
}, timeout);
|
|
28
|
+
const disposable = toDisposable(() => {
|
|
29
|
+
clearTimeout(timer);
|
|
30
|
+
});
|
|
31
|
+
store?.add(disposable);
|
|
32
|
+
return disposable;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export class TimeoutTimer implements IDisposable {
|
|
36
|
+
private _token: any = -1;
|
|
37
|
+
private _isDisposed = false;
|
|
38
|
+
|
|
39
|
+
public dispose(): void {
|
|
40
|
+
this.cancel();
|
|
41
|
+
this._isDisposed = true;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public cancel(): void {
|
|
45
|
+
if (this._token !== -1) {
|
|
46
|
+
clearTimeout(this._token);
|
|
47
|
+
this._token = -1;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public cancelAndSet(runner: () => void, timeout: number): void {
|
|
52
|
+
if (this._isDisposed) {
|
|
53
|
+
throw new Error('Calling cancelAndSet on a disposed TimeoutTimer');
|
|
54
|
+
}
|
|
55
|
+
this.cancel();
|
|
56
|
+
this._token = setTimeout(() => {
|
|
57
|
+
this._token = -1;
|
|
58
|
+
runner();
|
|
59
|
+
}, timeout);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
public setIfNotSet(runner: () => void, timeout: number): void {
|
|
63
|
+
if (this._isDisposed) {
|
|
64
|
+
throw new Error('Calling setIfNotSet on a disposed TimeoutTimer');
|
|
65
|
+
}
|
|
66
|
+
if (this._token !== -1) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
this._token = setTimeout(() => {
|
|
70
|
+
this._token = -1;
|
|
71
|
+
runner();
|
|
72
|
+
}, timeout);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export class IntervalTimer implements IDisposable {
|
|
77
|
+
private _disposable: IDisposable | undefined;
|
|
78
|
+
private _isDisposed = false;
|
|
79
|
+
|
|
80
|
+
public cancel(): void {
|
|
81
|
+
this._disposable?.dispose();
|
|
82
|
+
this._disposable = undefined;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
public cancelAndSet(runner: () => void, interval: number, context: Window | typeof globalThis = globalThis): void {
|
|
86
|
+
if (this._isDisposed) {
|
|
87
|
+
throw new Error('Calling cancelAndSet on a disposed IntervalTimer');
|
|
88
|
+
}
|
|
89
|
+
this.cancel();
|
|
90
|
+
const handle = context.setInterval(() => {
|
|
91
|
+
runner();
|
|
92
|
+
}, interval);
|
|
93
|
+
this._disposable = {
|
|
94
|
+
dispose: () => {
|
|
95
|
+
context.clearInterval(handle as any);
|
|
96
|
+
this._disposable = undefined;
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
public dispose(): void {
|
|
102
|
+
this.cancel();
|
|
103
|
+
this._isDisposed = true;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { ICircularList } from 'common/Types';
|
|
7
|
-
import { Disposable } from '
|
|
8
|
-
import { Emitter } from '
|
|
7
|
+
import { Disposable } from 'common/Lifecycle';
|
|
8
|
+
import { Emitter } from 'common/Event';
|
|
9
9
|
|
|
10
10
|
export interface IInsertEvent {
|
|
11
11
|
index: number;
|
package/src/common/Color.ts
CHANGED
|
@@ -184,6 +184,14 @@ export namespace css {
|
|
|
184
184
|
return channels.toColor($r, $g, $b, $a);
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
+
// Handle the "transparent" keyword
|
|
188
|
+
if (css === 'transparent') {
|
|
189
|
+
return {
|
|
190
|
+
css: 'transparent',
|
|
191
|
+
rgba: 0x00000000
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
|
|
187
195
|
// Validate the context is available for canvas-based color parsing
|
|
188
196
|
if (!$ctx || !$litmusColor) {
|
|
189
197
|
throw new Error('css.toColor: Unsupported css format');
|
|
@@ -37,8 +37,8 @@ import { IBufferSet } from 'common/buffer/Types';
|
|
|
37
37
|
import { InputHandler } from 'common/InputHandler';
|
|
38
38
|
import { WriteBuffer } from 'common/input/WriteBuffer';
|
|
39
39
|
import { OscLinkService } from 'common/services/OscLinkService';
|
|
40
|
-
import { Emitter,
|
|
41
|
-
import { Disposable, MutableDisposable, toDisposable } from '
|
|
40
|
+
import { Emitter, EventUtils, type IEvent } from 'common/Event';
|
|
41
|
+
import { Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle';
|
|
42
42
|
|
|
43
43
|
// Only trigger this warning a single time per session
|
|
44
44
|
let hasWriteSyncWarnHappened = false;
|
|
@@ -65,6 +65,8 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
|
|
|
65
65
|
public readonly onData = this._onData.event;
|
|
66
66
|
protected _onLineFeed = this._register(new Emitter<void>());
|
|
67
67
|
public readonly onLineFeed = this._onLineFeed.event;
|
|
68
|
+
protected readonly _onRender = this._register(new Emitter<{ start: number, end: number }>());
|
|
69
|
+
public readonly onRender = this._onRender.event;
|
|
68
70
|
private readonly _onResize = this._register(new Emitter<{ cols: number, rows: number }>());
|
|
69
71
|
public readonly onResize = this._onResize.event;
|
|
70
72
|
protected readonly _onWriteParsed = this._register(new Emitter<void>());
|
|
@@ -76,7 +78,7 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
|
|
|
76
78
|
*/
|
|
77
79
|
protected _onScrollApi?: Emitter<number>;
|
|
78
80
|
protected _onScroll = this._register(new Emitter<IScrollEvent>());
|
|
79
|
-
public get onScroll():
|
|
81
|
+
public get onScroll(): IEvent<number> {
|
|
80
82
|
if (!this._onScrollApi) {
|
|
81
83
|
this._onScrollApi = this._register(new Emitter<number>());
|
|
82
84
|
this._onScroll.event(ev => {
|
|
@@ -105,10 +107,10 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
|
|
|
105
107
|
this._instantiationService = new InstantiationService();
|
|
106
108
|
this.optionsService = this._register(new OptionsService(options));
|
|
107
109
|
this._instantiationService.setService(IOptionsService, this.optionsService);
|
|
108
|
-
this._bufferService = this._register(this._instantiationService.createInstance(BufferService));
|
|
109
|
-
this._instantiationService.setService(IBufferService, this._bufferService);
|
|
110
110
|
this._logService = this._register(this._instantiationService.createInstance(LogService));
|
|
111
111
|
this._instantiationService.setService(ILogService, this._logService);
|
|
112
|
+
this._bufferService = this._register(this._instantiationService.createInstance(BufferService));
|
|
113
|
+
this._instantiationService.setService(IBufferService, this._bufferService);
|
|
112
114
|
this.coreService = this._register(this._instantiationService.createInstance(CoreService));
|
|
113
115
|
this._instantiationService.setService(ICoreService, this.coreService);
|
|
114
116
|
this.coreMouseService = this._register(this._instantiationService.createInstance(CoreMouseService));
|
|
@@ -123,13 +125,12 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
|
|
|
123
125
|
|
|
124
126
|
// Register input handler and handle/forward events
|
|
125
127
|
this._inputHandler = this._register(new InputHandler(this._bufferService, this._charsetService, this.coreService, this._logService, this.optionsService, this._oscLinkService, this.coreMouseService, this.unicodeService));
|
|
126
|
-
this._register(
|
|
127
|
-
this._register(this._inputHandler);
|
|
128
|
+
this._register(EventUtils.forward(this._inputHandler.onLineFeed, this._onLineFeed));
|
|
128
129
|
|
|
129
130
|
// Setup listeners
|
|
130
|
-
this._register(
|
|
131
|
-
this._register(
|
|
132
|
-
this._register(
|
|
131
|
+
this._register(EventUtils.forward(this._bufferService.onResize, this._onResize));
|
|
132
|
+
this._register(EventUtils.forward(this.coreService.onData, this._onData));
|
|
133
|
+
this._register(EventUtils.forward(this.coreService.onBinary, this._onBinary));
|
|
133
134
|
this._register(this.coreService.onRequestScrollToBottom(() => this.scrollToBottom(true)));
|
|
134
135
|
this._register(this.coreService.onUserInput(() => this._writeBuffer.handleUserInput()));
|
|
135
136
|
this._register(this.optionsService.onMultipleOptionChange(['windowsPty'], () => this._handleWindowsPtyOptionChange()));
|
|
@@ -139,7 +140,7 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
|
|
|
139
140
|
}));
|
|
140
141
|
// Setup WriteBuffer
|
|
141
142
|
this._writeBuffer = this._register(new WriteBuffer((data, promiseResult) => this._inputHandler.parse(data, promiseResult)));
|
|
142
|
-
this._register(
|
|
143
|
+
this._register(EventUtils.forward(this._writeBuffer.onWriteParsed, this._onWriteParsed));
|
|
143
144
|
}
|
|
144
145
|
|
|
145
146
|
public write(data: string | Uint8Array, callback?: () => void): void {
|
|
@@ -175,6 +176,10 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
|
|
|
175
176
|
x = Math.max(x, MINIMUM_COLS);
|
|
176
177
|
y = Math.max(y, MINIMUM_ROWS);
|
|
177
178
|
|
|
179
|
+
// Flush pending writes before resize to avoid race conditions where async
|
|
180
|
+
// writes are processed with incorrect dimensions
|
|
181
|
+
this._writeBuffer.flushSync();
|
|
182
|
+
|
|
178
183
|
this._bufferService.resize(x, y);
|
|
179
184
|
}
|
|
180
185
|
|
|
@@ -237,6 +242,11 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
|
|
|
237
242
|
return this._inputHandler.registerOscHandler(ident, callback);
|
|
238
243
|
}
|
|
239
244
|
|
|
245
|
+
/** Add handler for APC escape sequence. See xterm.d.ts for details. */
|
|
246
|
+
public registerApcHandler(ident: number, callback: (data: string) => boolean | Promise<boolean>): IDisposable {
|
|
247
|
+
return this._inputHandler.registerApcHandler(ident, callback);
|
|
248
|
+
}
|
|
249
|
+
|
|
240
250
|
protected _setup(): void {
|
|
241
251
|
this._handleWindowsPtyOptionChange();
|
|
242
252
|
}
|