From 4e8e6b978889c32fa4d8711c87dac2a1d5552637 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Sat, 24 Sep 2022 11:45:48 -0700 Subject: [PATCH 1/4] Defer paused renderer resize to idle callback --- src/browser/services/RenderService.ts | 10 +++++++++- src/common/IdleTaskQueue.ts | 26 +++++++++++++++++++++++--- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/browser/services/RenderService.ts b/src/browser/services/RenderService.ts index 7db0e5cd..880a0667 100644 --- a/src/browser/services/RenderService.ts +++ b/src/browser/services/RenderService.ts @@ -12,6 +12,7 @@ import { addDisposableDomListener } from 'browser/Lifecycle'; import { IColorSet, IRenderDebouncerWithCallback } from 'browser/Types'; import { IOptionsService, IBufferService, IDecorationService } from 'common/services/Services'; import { ICharSizeService, ICoreBrowserService, IRenderService } from 'browser/services/Services'; +import { IdleTaskQueue } from 'common/IdleTaskQueue'; interface ISelectionState { start: [number, number] | undefined; @@ -105,6 +106,7 @@ export class RenderService extends Disposable implements IRenderService { } if (!this._isPaused && this._needsFullRefresh) { + this._pausedResizeQueue.flush(); this.refreshRows(0, this._rowCount - 1); this._needsFullRefresh = false; } @@ -203,8 +205,14 @@ export class RenderService extends Disposable implements IRenderService { this.refreshRows(0, this._rowCount - 1); } + private _pausedResizeQueue = new IdleTaskQueue(); public onResize(cols: number, rows: number): void { - this._renderer.onResize(cols, rows); + if (this._isPaused) { + this._pausedResizeQueue.clear(); + this._pausedResizeQueue.enqueue(() => this._renderer.onResize(cols, rows)); + } else { + this._renderer.onResize(cols, rows); + } this._fullRefresh(); } diff --git a/src/common/IdleTaskQueue.ts b/src/common/IdleTaskQueue.ts index 240a26ff..167e79e9 100644 --- a/src/common/IdleTaskQueue.ts +++ b/src/common/IdleTaskQueue.ts @@ -29,6 +29,28 @@ export class IdleTaskQueue { this._start(); } + /** + * Flushes the queue, running all remaining tasks synchronously. + */ + public flush(): void { + while (this._i < this._tasks.length) { + this._tasks[this._i++](); + } + this.clear(); + } + + /** + * Clears any remaining tasks from the queue, these will not be run. + */ + public clear(): void { + if (this._idleCallback) { + cancelIdleCallback(this._idleCallback); + this._idleCallback = undefined; + } + this._i = 0; + this._tasks.length = 0; + } + private _start(): void { if (!this._idleCallback) { this._idleCallback = requestIdleCallback(() => this._process()); @@ -45,8 +67,6 @@ export class IdleTaskQueue { return; } } - // Clear the queue - this._i = 0; - this._tasks.length = 0; + this.clear(); } } From 4ac5a91c95aa877c457d476c80a389551a4a8b61 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Sat, 24 Sep 2022 11:56:46 -0700 Subject: [PATCH 2/4] Make DebouncedIdleTask helper --- src/browser/services/RenderService.ts | 9 ++++----- src/common/{IdleTaskQueue.ts => Idle.ts} | 24 ++++++++++++++++++++++-- 2 files changed, 26 insertions(+), 7 deletions(-) rename src/common/{IdleTaskQueue.ts => Idle.ts} (79%) diff --git a/src/browser/services/RenderService.ts b/src/browser/services/RenderService.ts index 880a0667..ca1321d6 100644 --- a/src/browser/services/RenderService.ts +++ b/src/browser/services/RenderService.ts @@ -12,7 +12,7 @@ import { addDisposableDomListener } from 'browser/Lifecycle'; import { IColorSet, IRenderDebouncerWithCallback } from 'browser/Types'; import { IOptionsService, IBufferService, IDecorationService } from 'common/services/Services'; import { ICharSizeService, ICoreBrowserService, IRenderService } from 'browser/services/Services'; -import { IdleTaskQueue } from 'common/IdleTaskQueue'; +import { DebouncedIdleTask } from 'common/Idle'; interface ISelectionState { start: [number, number] | undefined; @@ -106,7 +106,7 @@ export class RenderService extends Disposable implements IRenderService { } if (!this._isPaused && this._needsFullRefresh) { - this._pausedResizeQueue.flush(); + this._pausedResizeTask.flush(); this.refreshRows(0, this._rowCount - 1); this._needsFullRefresh = false; } @@ -205,11 +205,10 @@ export class RenderService extends Disposable implements IRenderService { this.refreshRows(0, this._rowCount - 1); } - private _pausedResizeQueue = new IdleTaskQueue(); + private _pausedResizeTask = new DebouncedIdleTask(); public onResize(cols: number, rows: number): void { if (this._isPaused) { - this._pausedResizeQueue.clear(); - this._pausedResizeQueue.enqueue(() => this._renderer.onResize(cols, rows)); + this._pausedResizeTask.set(() => this._renderer.onResize(cols, rows)); } else { this._renderer.onResize(cols, rows); } diff --git a/src/common/IdleTaskQueue.ts b/src/common/Idle.ts similarity index 79% rename from src/common/IdleTaskQueue.ts rename to src/common/Idle.ts index 167e79e9..529d38a4 100644 --- a/src/common/IdleTaskQueue.ts +++ b/src/common/Idle.ts @@ -9,7 +9,7 @@ * and care should be taken to ensure they're non-urgent and will not introduce race conditions. */ export class IdleTaskQueue { - private _tasks: Function[] = []; + private _tasks: (() => void)[] = []; private _idleCallback?: number; private _maxTaskDuration: number; private _i = 0; @@ -24,7 +24,7 @@ export class IdleTaskQueue { /** * Adds a task to the queue which will run in a future idle callback. */ - public enqueue(task: Function): void { + public enqueue(task: () => void): void { this._tasks.push(task); this._start(); } @@ -70,3 +70,23 @@ export class IdleTaskQueue { this.clear(); } } + +export class DebouncedIdleTask { + private _queue: IdleTaskQueue; + + /** + * @param targetFps The target frame rate. + */ + constructor(targetFps: number = 240) { + this._queue = new IdleTaskQueue(targetFps); + } + + public set(task: () => void): void { + this._queue.clear(); + this._queue.enqueue(task); + } + + public flush(): void { + this._queue.flush(); + } +} From 66efb0388abdf8c8dea9c3b6ed3bc51a6916b6bf Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Sat, 24 Sep 2022 11:57:12 -0700 Subject: [PATCH 3/4] Move prop to top --- src/browser/services/RenderService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/services/RenderService.ts b/src/browser/services/RenderService.ts index ca1321d6..3849bdd3 100644 --- a/src/browser/services/RenderService.ts +++ b/src/browser/services/RenderService.ts @@ -25,6 +25,7 @@ export class RenderService extends Disposable implements IRenderService { private _renderDebouncer: IRenderDebouncerWithCallback; private _screenDprMonitor: ScreenDprMonitor; + private _pausedResizeTask = new DebouncedIdleTask(); private _isPaused: boolean = false; private _needsFullRefresh: boolean = false; @@ -205,7 +206,6 @@ export class RenderService extends Disposable implements IRenderService { this.refreshRows(0, this._rowCount - 1); } - private _pausedResizeTask = new DebouncedIdleTask(); public onResize(cols: number, rows: number): void { if (this._isPaused) { this._pausedResizeTask.set(() => this._renderer.onResize(cols, rows)); From aec1f2b2be7687d333d1eedf4724a88e2bf642f1 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Sat, 24 Sep 2022 11:58:17 -0700 Subject: [PATCH 4/4] Fix import --- addons/xterm-addon-webgl/src/atlas/WebglCharAtlas.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/xterm-addon-webgl/src/atlas/WebglCharAtlas.ts b/addons/xterm-addon-webgl/src/atlas/WebglCharAtlas.ts index d23caac0..dfcede38 100644 --- a/addons/xterm-addon-webgl/src/atlas/WebglCharAtlas.ts +++ b/addons/xterm-addon-webgl/src/atlas/WebglCharAtlas.ts @@ -16,7 +16,7 @@ import { tryDrawCustomChar } from 'browser/renderer/CustomGlyphs'; import { excludeFromContrastRatioDemands, isPowerlineGlyph, isRestrictedPowerlineGlyph } from 'browser/renderer/RendererUtils'; import { IUnicodeService } from 'common/services/Services'; import { FourKeyMap } from 'common/MultiKeyMap'; -import { IdleTaskQueue } from 'common/IdleTaskQueue'; +import { IdleTaskQueue } from 'common/Idle'; // For debugging purposes, it can be useful to set this to a really tiny value, // to verify that LRU eviction works.