@floegence/floeterm-terminal-web 0.9.0 → 0.10.0
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 +22 -1
- package/dist/core/TerminalCore.d.ts +5 -1
- package/dist/core/TerminalCore.d.ts.map +1 -1
- package/dist/core/TerminalCore.js +58 -36
- package/dist/core/TerminalCore.js.map +1 -1
- package/dist/core/TerminalScrollbarOverlay.d.ts +63 -0
- package/dist/core/TerminalScrollbarOverlay.d.ts.map +1 -0
- package/dist/core/TerminalScrollbarOverlay.js +493 -0
- package/dist/core/TerminalScrollbarOverlay.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/internal/GhosttyScrollbarCompat.d.ts +10 -0
- package/dist/internal/GhosttyScrollbarCompat.d.ts.map +1 -0
- package/dist/internal/GhosttyScrollbarCompat.js +94 -0
- package/dist/internal/GhosttyScrollbarCompat.js.map +1 -0
- package/dist/types.d.ts +8 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/themeColor.d.ts +12 -0
- package/dist/utils/themeColor.d.ts.map +1 -0
- package/dist/utils/themeColor.js +88 -0
- package/dist/utils/themeColor.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -53,6 +53,27 @@ const core = new TerminalCore(
|
|
|
53
53
|
await core.initialize();
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
+
Floeterm projects one renderer-neutral DOM scrollbar for both canvas and WebGL terminals while Ghostty remains the only scrollback and viewport owner:
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
const core = new TerminalCore(container, {
|
|
60
|
+
rendererType: 'webgl',
|
|
61
|
+
fit: { scrollbarReservePx: 15 },
|
|
62
|
+
scrollbar: {
|
|
63
|
+
visibility: 'persistent', // "auto" by default, or "hidden"
|
|
64
|
+
minThumbPx: 24,
|
|
65
|
+
ariaLabel: 'Terminal history',
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// Keep a long-lived Core aligned with a runtime locale change.
|
|
70
|
+
core.setScrollbarOptions({ ariaLabel: localizedTerminalHistoryLabel });
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The scrollbar uses a 12px visual and fine-pointer rail. Reserve at least 12px when the last terminal column must remain fully unobstructed; the default 15px reserve provides a stable gutter. An explicit `scrollbarReservePx: 0` remains supported as an overlay mode and may cover the rightmost 12px. The visual overlay itself never owns pointer hit testing: Floeterm captures fine-pointer track and thumb gestures at the viewport boundary, while wheel and touch events continue to target Ghostty's terminal surface exactly once. `persistent` automatically behaves as `auto` on coarse-pointer-only devices. Mixed-pointer devices keep mouse and pen interaction without creating a dead touch strip.
|
|
74
|
+
|
|
75
|
+
`auto` reveals on terminal wheel activity, keyboard focus, or fine-pointer movement into the right-edge rail, then fades after 1,200ms of inactivity. `persistent` remains visible on fine-pointer layouts and `hidden` removes the control from pointer, tab, and accessibility access. Alternate-screen programs and empty buffers also hide it. Theme-derived idle and hover/focus colors meet 3:1 and 4.5:1 contrast targets. Drag color targets 7:1; when that ratio is mathematically impossible against the configured background, Floeterm chooses whichever of black or white provides the highest available contrast. Forced-colors and reduced-motion preferences are honored.
|
|
76
|
+
|
|
56
77
|
After a host-owned layout transition or history recovery, request an explicit
|
|
57
78
|
presentation fence before declaring the terminal surface ready:
|
|
58
79
|
|
|
@@ -132,7 +153,7 @@ the foreground revision that was active at that exact byte boundary.
|
|
|
132
153
|
- Each `TerminalCore` owns an isolated `ghostty-web` WASM runtime; consumers must not provide or share a Ghostty runtime.
|
|
133
154
|
- `scrollback` is measured in terminal buffer rows, including separately wrapped rows, and accepts integers from 1 through 10,000. Within the supported geometry, Floeterm preserves at least the requested number of buffer rows; it does not trim to an exact physical row count. Floeterm maps that contract to a bounded byte budget for the exact pinned `ghostty-web@0.4.0-next.14.g6a1a50d` release, which currently interprets the value as bytes. The 81,920,000-byte cap limits Ghostty's scrollback arena, not the total memory of a WASM runtime. The mapping is temporary and must be reviewed and removed or updated with any Ghostty upgrade.
|
|
134
155
|
- Supported terminal geometry is limited to 500 columns. Explicit dimensions above that limit fail, while automatic fitting reports at most 500 columns.
|
|
135
|
-
- Consumer dependency overrides for `ghostty-web` are unsupported. Floeterm's compatibility guard requires the exact package pin so an upstream behavior change cannot silently apply the row-to-byte mapping twice.
|
|
156
|
+
- Consumer dependency overrides for `ghostty-web` are unsupported. Floeterm's compatibility guard requires the exact package pin so an upstream behavior change cannot silently apply the row-to-byte mapping twice or reactivate the native canvas scrollbar beneath the renderer-neutral DOM control.
|
|
136
157
|
- `TerminalCore` bridges the hidden textarea used by `ghostty-web`, so soft-keyboard and composition input continue to work on touch devices.
|
|
137
158
|
- The hidden terminal input is mounted in the document viewport plane and anchored from rendered cursor geometry, so native IME candidate windows stay aligned without expanding transformed terminal hosts.
|
|
138
159
|
- Programmatic terminal focus uses no-scroll focus by default, keeping embedded terminals stable inside scaled, projected, or otherwise transformed host surfaces.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TerminalState, type Logger, type TerminalConfig, type TerminalCopySelectionResult, type TerminalCopySelectionSource, type TerminalDimensions, type TerminalEventHandlers, type TerminalFocusOptions, type TerminalAppearance, type TerminalLinkProvider, type TerminalRuntimeLineSnapshot, type TerminalRestorableSnapshot, type TerminalRestorableSnapshotOptions, type TerminalResourceEstimate, type TerminalTouchScrollRuntime, type TerminalInitializationOptions, type TerminalVisualSuspendHandle, type TerminalVisualSuspendOptions } from '../types.js';
|
|
1
|
+
import { TerminalState, type Logger, type TerminalConfig, type TerminalCopySelectionResult, type TerminalCopySelectionSource, type TerminalDimensions, type TerminalEventHandlers, type TerminalFocusOptions, type TerminalAppearance, type TerminalLinkProvider, type TerminalScrollbarOptions, type TerminalRuntimeLineSnapshot, type TerminalRestorableSnapshot, type TerminalRestorableSnapshotOptions, type TerminalResourceEstimate, type TerminalTouchScrollRuntime, type TerminalInitializationOptions, type TerminalVisualSuspendHandle, type TerminalVisualSuspendOptions } from '../types.js';
|
|
2
2
|
export { preloadTerminalResources } from '../internal/TerminalResourceLoader.js';
|
|
3
3
|
export declare class TerminalCore {
|
|
4
4
|
private container;
|
|
@@ -24,6 +24,7 @@ export declare class TerminalCore {
|
|
|
24
24
|
private inputElement;
|
|
25
25
|
private viewportHost;
|
|
26
26
|
private renderHost;
|
|
27
|
+
private scrollbarOverlay;
|
|
27
28
|
private resizeObserver;
|
|
28
29
|
private resizeDebounceTimer;
|
|
29
30
|
private resizeRaf;
|
|
@@ -51,6 +52,7 @@ export declare class TerminalCore {
|
|
|
51
52
|
private suppressResizeNotifications;
|
|
52
53
|
private clearResizeSuppressionRaf;
|
|
53
54
|
private readonly scrollbackRows;
|
|
55
|
+
private scrollbarOptions;
|
|
54
56
|
private hasFocus;
|
|
55
57
|
private resizeNotifySeq;
|
|
56
58
|
private lastNotifiedSize;
|
|
@@ -79,6 +81,7 @@ export declare class TerminalCore {
|
|
|
79
81
|
private loadAddons;
|
|
80
82
|
private openTerminal;
|
|
81
83
|
private mountInputElement;
|
|
84
|
+
private mountScrollbarOverlay;
|
|
82
85
|
private installLinkDetector;
|
|
83
86
|
private installFitAddonGeometryPatch;
|
|
84
87
|
private proposeFitDimensions;
|
|
@@ -216,6 +219,7 @@ export declare class TerminalCore {
|
|
|
216
219
|
private forceResizeAndWaitForCommittedFrame;
|
|
217
220
|
setFixedDimensions(dimensions: TerminalDimensions | null): void;
|
|
218
221
|
setAppearance(appearance: TerminalAppearance): void;
|
|
222
|
+
setScrollbarOptions(options: Partial<TerminalScrollbarOptions>): void;
|
|
219
223
|
setTheme(theme: Record<string, unknown>): void;
|
|
220
224
|
setFontSize(size: number): void;
|
|
221
225
|
setPresentationScale(scale: number): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TerminalCore.d.ts","sourceRoot":"","sources":["../../src/core/TerminalCore.ts"],"names":[],"mappings":"AAYA,OAAO,EACL,aAAa,EACb,KAAK,MAAM,EAEX,KAAK,cAAc,EACnB,KAAK,2BAA2B,EAChC,KAAK,2BAA2B,EAChC,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAE1B,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,
|
|
1
|
+
{"version":3,"file":"TerminalCore.d.ts","sourceRoot":"","sources":["../../src/core/TerminalCore.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,10 +6,13 @@ import { TerminalState, } from '../types.js';
|
|
|
6
6
|
import { terminalInitializationScheduler, } from '../internal/TerminalInitializationScheduler.js';
|
|
7
7
|
import { acquireGhosttyRuntime, getGhosttyFitAddonConstructor, getGhosttyLinkConstructors, getGhosttyTerminalConstructor, inspectGhosttyRuntimeMemory, loadGhosttyModules, waitWithAbort, } from '../internal/TerminalResourceLoader.js';
|
|
8
8
|
import { capAutoFitTerminalColumns, mapGhosttyScrollbackRowsForPinnedVersion, validateTerminalColumns, validateTerminalScrollbackRows, } from '../internal/GhosttyScrollbackCompat.js';
|
|
9
|
+
import { installPinnedGhosttyAlternateScreenProjection, suppressPinnedGhosttyScrollbarBeforeOpen, suppressPinnedGhosttyScrollbarRenderer, } from '../internal/GhosttyScrollbarCompat.js';
|
|
9
10
|
import { createUnicodeSafeUrlProviderTerminal, } from '../internal/UnicodeSafeUrlProvider.js';
|
|
10
11
|
import { resolveTerminalInputElement, TerminalInputBridge } from './TerminalInputBridge.js';
|
|
11
12
|
import { terminalRenderScheduler } from './TerminalRenderScheduler.js';
|
|
12
13
|
import { scheduleUiTurn } from '../internal/scheduleUiTurn.js';
|
|
14
|
+
import { parseThemeColor } from '../utils/themeColor.js';
|
|
15
|
+
import { normalizeTerminalScrollbarOptions, TerminalScrollbarOverlay, } from './TerminalScrollbarOverlay.js';
|
|
13
16
|
const TERMINAL_SNAPSHOT_VERSION = 1;
|
|
14
17
|
const DEFAULT_TERMINAL_SNAPSHOT_MAX_BYTES = 2 * 1024 * 1024;
|
|
15
18
|
const ESTIMATED_RENDERER_BYTES = 4 * 1024 * 1024;
|
|
@@ -131,41 +134,6 @@ const mapThemeToGhostty = (theme) => {
|
|
|
131
134
|
}
|
|
132
135
|
return mapped;
|
|
133
136
|
};
|
|
134
|
-
function normalizeThemeColor(value) {
|
|
135
|
-
if (!value) {
|
|
136
|
-
return null;
|
|
137
|
-
}
|
|
138
|
-
const trimmed = value.trim();
|
|
139
|
-
const shortHex = /^#([0-9a-fA-F]{3})$/.exec(trimmed);
|
|
140
|
-
if (shortHex) {
|
|
141
|
-
const [r, g, b] = shortHex[1].split('');
|
|
142
|
-
return `#${r}${r}${g}${g}${b}${b}`.toLowerCase();
|
|
143
|
-
}
|
|
144
|
-
if (/^#[0-9a-fA-F]{6}$/.test(trimmed)) {
|
|
145
|
-
return trimmed.toLowerCase();
|
|
146
|
-
}
|
|
147
|
-
const rgb = /^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/.exec(trimmed);
|
|
148
|
-
if (!rgb) {
|
|
149
|
-
return null;
|
|
150
|
-
}
|
|
151
|
-
const channels = rgb.slice(1).map(channel => Number(channel));
|
|
152
|
-
if (channels.some(channel => !Number.isInteger(channel) || channel < 0 || channel > 255)) {
|
|
153
|
-
return null;
|
|
154
|
-
}
|
|
155
|
-
return `#${channels.map(channel => channel.toString(16).padStart(2, '0')).join('')}`;
|
|
156
|
-
}
|
|
157
|
-
function parseThemeColor(value) {
|
|
158
|
-
const normalized = normalizeThemeColor(value);
|
|
159
|
-
if (!normalized) {
|
|
160
|
-
return null;
|
|
161
|
-
}
|
|
162
|
-
const hex = normalized.slice(1);
|
|
163
|
-
return {
|
|
164
|
-
r: Number.parseInt(hex.slice(0, 2), 16),
|
|
165
|
-
g: Number.parseInt(hex.slice(2, 4), 16),
|
|
166
|
-
b: Number.parseInt(hex.slice(4, 6), 16),
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
137
|
function colorKey(color) {
|
|
170
138
|
return `${color.r},${color.g},${color.b}`;
|
|
171
139
|
}
|
|
@@ -359,6 +327,7 @@ export class TerminalCore {
|
|
|
359
327
|
this.inputElement = null;
|
|
360
328
|
this.viewportHost = null;
|
|
361
329
|
this.renderHost = null;
|
|
330
|
+
this.scrollbarOverlay = null;
|
|
362
331
|
this.resizeObserver = null;
|
|
363
332
|
this.resizeDebounceTimer = null;
|
|
364
333
|
this.resizeRaf = null;
|
|
@@ -416,6 +385,7 @@ export class TerminalCore {
|
|
|
416
385
|
this.eventHandlers = eventHandlers;
|
|
417
386
|
this.clipboard = TerminalCore.normalizeClipboardConfig(config?.clipboard);
|
|
418
387
|
this.fit = TerminalCore.normalizeFitConfig(config?.fit);
|
|
388
|
+
this.scrollbarOptions = normalizeTerminalScrollbarOptions(config?.scrollbar);
|
|
419
389
|
this.logger = logger ?? noopLogger;
|
|
420
390
|
this.responsive = TerminalCore.normalizeResponsiveConfig(config?.responsive);
|
|
421
391
|
this.logicalFontSize = TerminalCore.normalizeFontSize(config?.fontSize);
|
|
@@ -426,6 +396,7 @@ export class TerminalCore {
|
|
|
426
396
|
...(explicitCols === undefined ? {} : { cols: explicitCols }),
|
|
427
397
|
fixedDimensions: this.fixedDimensions,
|
|
428
398
|
scrollback: this.scrollbackRows,
|
|
399
|
+
scrollbar: this.scrollbarOptions,
|
|
429
400
|
};
|
|
430
401
|
this.renderTask = {
|
|
431
402
|
id: TerminalCore.nextRenderTaskId,
|
|
@@ -567,6 +538,8 @@ export class TerminalCore {
|
|
|
567
538
|
this.resizeObserver = null;
|
|
568
539
|
this.disposeInputBridge();
|
|
569
540
|
this.disposeTerminalEventListeners();
|
|
541
|
+
this.scrollbarOverlay?.dispose();
|
|
542
|
+
this.scrollbarOverlay = null;
|
|
570
543
|
this.fabricView?.dispose();
|
|
571
544
|
this.fabricView = null;
|
|
572
545
|
this.terminal?.dispose();
|
|
@@ -653,7 +626,11 @@ export class TerminalCore {
|
|
|
653
626
|
const renderHost = this.ensurePresentationHosts();
|
|
654
627
|
this.applyPresentationScaleStyles();
|
|
655
628
|
this.installDemandRenderPatchBeforeOpen();
|
|
629
|
+
suppressPinnedGhosttyScrollbarBeforeOpen(this.terminal);
|
|
656
630
|
this.terminal.open(renderHost);
|
|
631
|
+
installPinnedGhosttyAlternateScreenProjection(this.terminal);
|
|
632
|
+
const renderer = this.terminal.renderer;
|
|
633
|
+
suppressPinnedGhosttyScrollbarRenderer(renderer ?? {});
|
|
657
634
|
this.installLinkDetector();
|
|
658
635
|
if (this.config.rendererType === 'webgl') {
|
|
659
636
|
const canvas = this.terminal
|
|
@@ -667,6 +644,7 @@ export class TerminalCore {
|
|
|
667
644
|
this.patchSelectionManagerClipboardBehavior();
|
|
668
645
|
this.patchSelectionManagerRenderingBehavior();
|
|
669
646
|
this.setupInputBridge(renderHost);
|
|
647
|
+
this.mountScrollbarOverlay();
|
|
670
648
|
this.applyRegisteredLinkProviders();
|
|
671
649
|
void this.refreshFontMetricsAfterLoad('open');
|
|
672
650
|
}
|
|
@@ -682,6 +660,30 @@ export class TerminalCore {
|
|
|
682
660
|
body.appendChild(input);
|
|
683
661
|
this.inputElement = input;
|
|
684
662
|
}
|
|
663
|
+
mountScrollbarOverlay() {
|
|
664
|
+
if (!this.terminal || !this.viewportHost || !this.renderHost) {
|
|
665
|
+
throw new Error('Terminal scrollbar requires an initialized presentation host');
|
|
666
|
+
}
|
|
667
|
+
this.scrollbarOverlay?.dispose();
|
|
668
|
+
const terminal = this.terminal;
|
|
669
|
+
const surfaceId = `${this.fabricViewId}-surface`;
|
|
670
|
+
this.renderHost.id = surfaceId;
|
|
671
|
+
this.scrollbarOverlay = new TerminalScrollbarOverlay(this.viewportHost, {
|
|
672
|
+
get rows() {
|
|
673
|
+
return terminal.rows;
|
|
674
|
+
},
|
|
675
|
+
getScrollbackLength: () => terminal.getScrollbackLength(),
|
|
676
|
+
getViewportY: () => terminal.getViewportY(),
|
|
677
|
+
isAlternateScreen: () => terminal.isAlternateScreen(),
|
|
678
|
+
scrollToLine: line => terminal.scrollToLine(line),
|
|
679
|
+
scrollToTop: () => terminal.scrollToTop(),
|
|
680
|
+
scrollToBottom: () => terminal.scrollToBottom(),
|
|
681
|
+
scrollLines: amount => terminal.scrollLines(amount),
|
|
682
|
+
scrollPages: amount => terminal.scrollPages(amount),
|
|
683
|
+
focusTerminal: () => this.scheduleInputSurfaceRefocus({ preventScroll: true }),
|
|
684
|
+
}, this.scrollbarOptions, surfaceId);
|
|
685
|
+
this.scrollbarOverlay.setBackgroundColor(this.terminalThemeSource.background);
|
|
686
|
+
}
|
|
685
687
|
installLinkDetector() {
|
|
686
688
|
if (!this.terminal) {
|
|
687
689
|
throw new Error('Terminal instance not created');
|
|
@@ -742,7 +744,13 @@ export class TerminalCore {
|
|
|
742
744
|
if (!geometry) {
|
|
743
745
|
return null;
|
|
744
746
|
}
|
|
745
|
-
const
|
|
747
|
+
const cellWidth = Number(geometry.cellWidth);
|
|
748
|
+
const hostWidth = Number(this.viewportHost?.clientWidth ?? this.container.clientWidth);
|
|
749
|
+
const visibleCellWidth = cellWidth / this.presentationScale;
|
|
750
|
+
const cols = Number.isFinite(hostWidth) && hostWidth > 0
|
|
751
|
+
&& Number.isFinite(visibleCellWidth) && visibleCellWidth > 0
|
|
752
|
+
? Math.floor(Math.max(0, hostWidth - this.fit.scrollbarReservePx) / visibleCellWidth)
|
|
753
|
+
: Math.floor(Number(geometry.cols));
|
|
746
754
|
const rows = Math.floor(Number(geometry.rows));
|
|
747
755
|
if (!Number.isFinite(cols) || !Number.isFinite(rows) || cols <= 0 || rows <= 0) {
|
|
748
756
|
return null;
|
|
@@ -1566,6 +1574,8 @@ export class TerminalCore {
|
|
|
1566
1574
|
if (typeof this.terminal.onScroll === 'function') {
|
|
1567
1575
|
const disposable = this.terminal.onScroll(() => {
|
|
1568
1576
|
this.syncImeInputAnchor();
|
|
1577
|
+
this.scrollbarOverlay?.reveal();
|
|
1578
|
+
this.scrollbarOverlay?.sync();
|
|
1569
1579
|
this.requestDemandRender(false);
|
|
1570
1580
|
});
|
|
1571
1581
|
this.trackTerminalEventDisposable(disposable);
|
|
@@ -1853,6 +1863,7 @@ export class TerminalCore {
|
|
|
1853
1863
|
else {
|
|
1854
1864
|
this.requestDemandRender(shouldForceAfterWrite);
|
|
1855
1865
|
}
|
|
1866
|
+
this.scrollbarOverlay?.sync();
|
|
1856
1867
|
callback?.();
|
|
1857
1868
|
probe?.onTerminalWriteProfile?.({
|
|
1858
1869
|
totalMs: performance.now() - profileStartedAt,
|
|
@@ -2790,11 +2801,19 @@ export class TerminalCore {
|
|
|
2790
2801
|
this.setPresentationScale(appearance.presentationScale);
|
|
2791
2802
|
}
|
|
2792
2803
|
}
|
|
2804
|
+
setScrollbarOptions(options) {
|
|
2805
|
+
normalizeTerminalScrollbarOptions(options);
|
|
2806
|
+
const next = normalizeTerminalScrollbarOptions({ ...this.scrollbarOptions, ...options });
|
|
2807
|
+
this.scrollbarOptions = next;
|
|
2808
|
+
this.config = { ...this.config, scrollbar: next };
|
|
2809
|
+
this.scrollbarOverlay?.setOptions(next);
|
|
2810
|
+
}
|
|
2793
2811
|
setTheme(theme) {
|
|
2794
2812
|
const mapped = mapThemeToGhostty(theme);
|
|
2795
2813
|
// Persist latest theme so a future re-initialization can reuse it.
|
|
2796
2814
|
this.config = { ...this.config, theme: mapped };
|
|
2797
2815
|
this.themeColorTranslator = buildThemeColorTranslator(this.terminalThemeSource, mapped);
|
|
2816
|
+
this.scrollbarOverlay?.setBackgroundColor(mapped.background);
|
|
2798
2817
|
if (!this.terminal) {
|
|
2799
2818
|
return;
|
|
2800
2819
|
}
|
|
@@ -2934,6 +2953,8 @@ export class TerminalCore {
|
|
|
2934
2953
|
this.disposeInputBridge();
|
|
2935
2954
|
this.disposeTerminalEventListeners();
|
|
2936
2955
|
this.disposeSearchOverlay();
|
|
2956
|
+
this.scrollbarOverlay?.dispose();
|
|
2957
|
+
this.scrollbarOverlay = null;
|
|
2937
2958
|
this.fabricAttachSeq += 1;
|
|
2938
2959
|
this.cancelFabricAttachSchedule?.();
|
|
2939
2960
|
this.cancelFabricAttachSchedule = null;
|
|
@@ -3203,6 +3224,7 @@ export class TerminalCore {
|
|
|
3203
3224
|
terminalAny.cursorMoveEmitter?.fire?.();
|
|
3204
3225
|
}
|
|
3205
3226
|
this.syncImeInputAnchor();
|
|
3227
|
+
this.scrollbarOverlay?.sync();
|
|
3206
3228
|
const durationMs = performance.now() - startedAt;
|
|
3207
3229
|
getPerfProbe()?.onTerminalRender?.(durationMs);
|
|
3208
3230
|
if (this.config.rendererType !== 'webgl'
|