Simplify terminal sticky scroll refresh by deferring to microtask

Fixes #207959
This commit is contained in:
Daniel Imms 2024-03-22 09:19:03 -07:00
parent 712a3eefbd
commit 789b9095a0
No known key found for this signature in database
GPG key ID: E5CF412B63651C69

View file

@ -59,6 +59,7 @@ export class TerminalStickyScrollOverlay extends Disposable {
private _refreshListeners = this._register(new MutableDisposable()); private _refreshListeners = this._register(new MutableDisposable());
private _state: OverlayState = OverlayState.Off; private _state: OverlayState = OverlayState.Off;
private _isRefreshQueued = false;
private _rawMaxLineCount: number = 5; private _rawMaxLineCount: number = 5;
constructor( constructor(
@ -114,7 +115,7 @@ export class TerminalStickyScrollOverlay extends Disposable {
})); }));
this._register(this._xterm.raw.onResize(() => { this._register(this._xterm.raw.onResize(() => {
this._syncOptions(); this._syncOptions();
this._throttledRefresh(); this._refresh();
})); }));
this._getSerializeAddonConstructor().then(SerializeAddon => { this._getSerializeAddonConstructor().then(SerializeAddon => {
@ -175,37 +176,15 @@ export class TerminalStickyScrollOverlay extends Disposable {
this._element?.classList.toggle(CssClasses.Visible, isVisible); this._element?.classList.toggle(CssClasses.Visible, isVisible);
} }
/**
* The entry point to refresh sticky scroll. This is synchronous and will call into the method
* that actually refreshes using either debouncing or throttling depending on the situation.
*
* The goal is that if the command has changed to update immediately (with throttling) and if
* the command is the same then update with debouncing as it's less likely updates will show up.
* This approach also helps with:
*
* - Cursor move only updates such as moving horizontally in pagers which without this may show
* the sticky scroll before hiding it again almost immediately due to everything not being
* parsed yet.
* - Improving performance due to deferring less important updates via debouncing.
* - Less flickering when scrolling, while still updating immediately when the command changes.
*/
private _refresh(): void { private _refresh(): void {
if (!this._xterm.raw.element?.parentElement || !this._stickyScrollOverlay || !this._serializeAddon) { if (this._isRefreshQueued) {
return; return;
} }
const command = this._commandDetection.getCommandForLine(this._xterm.raw.buffer.active.viewportY); this._isRefreshQueued = true;
if (command && this._currentStickyCommand !== command) { queueMicrotask(() => {
this._throttledRefresh();
} else {
// If it's the same command, do not throttle as the sticky scroll overlay height may
// need to be adjusted. This would cause a flicker if throttled.
this._refreshNow(); this._refreshNow();
} this._isRefreshQueued = false;
} });
@throttle(0)
private _throttledRefresh(): void {
this._refreshNow();
} }
private _refreshNow(): void { private _refreshNow(): void {