From 6e12d94f11bdb2b12d5b6bedd419f893c9004f64 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Tue, 17 Oct 2023 09:10:04 -0700 Subject: [PATCH] Move window resize listeners over to onWindowChange --- src/browser/AccessibilityManager.ts | 9 ++++++--- src/browser/decorations/BufferDecorationRenderer.ts | 9 ++++++--- src/browser/decorations/OverviewRulerRenderer.ts | 9 ++++++--- src/browser/services/RenderService.ts | 8 ++++++-- src/common/EventEmitter.ts | 5 +++++ typings/xterm.d.ts | 3 ++- 6 files changed, 31 insertions(+), 12 deletions(-) diff --git a/src/browser/AccessibilityManager.ts b/src/browser/AccessibilityManager.ts index 703459f4..de00a1d3 100644 --- a/src/browser/AccessibilityManager.ts +++ b/src/browser/AccessibilityManager.ts @@ -6,11 +6,12 @@ import * as Strings from 'browser/LocalizableStrings'; import { ITerminal, IRenderDebouncer } from 'browser/Types'; import { TimeBasedDebouncer } from 'browser/TimeBasedDebouncer'; -import { Disposable, toDisposable } from 'common/Lifecycle'; +import { Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle'; import { ICoreBrowserService, IRenderService } from 'browser/services/Services'; import { addDisposableDomListener } from 'browser/Lifecycle'; import { IBuffer } from 'common/buffer/Types'; import { IInstantiationService } from 'common/services/Services'; +import { runAndSubscribe } from 'common/EventEmitter'; const MAX_ROWS_TO_READ = 20; @@ -97,8 +98,10 @@ export class AccessibilityManager extends Disposable { this.register(this._coreBrowserService.onDprChange(() => this._refreshRowsDimensions())); // This shouldn't be needed on modern browsers but is present in case the // media query that drives the ScreenDprMonitor isn't supported - // TODO: Listen to window change - this.register(addDisposableDomListener(window, 'resize', () => this._refreshRowsDimensions())); + const windowResizeListener = this.register(new MutableDisposable()); + this.register(runAndSubscribe(this._coreBrowserService.onWindowChange, () => { + windowResizeListener.value = addDisposableDomListener(this._coreBrowserService.window, 'resize', () => this._refreshRowsDimensions()); + })); this._refreshRows(); this.register(toDisposable(() => { diff --git a/src/browser/decorations/BufferDecorationRenderer.ts b/src/browser/decorations/BufferDecorationRenderer.ts index 3a0d7862..3fe56512 100644 --- a/src/browser/decorations/BufferDecorationRenderer.ts +++ b/src/browser/decorations/BufferDecorationRenderer.ts @@ -5,7 +5,8 @@ import { addDisposableDomListener } from 'browser/Lifecycle'; import { ICoreBrowserService, IRenderService } from 'browser/services/Services'; -import { Disposable, toDisposable } from 'common/Lifecycle'; +import { runAndSubscribe } from 'common/EventEmitter'; +import { Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle'; import { IBufferService, IDecorationService, IInternalDecoration } from 'common/services/Services'; export class BufferDecorationRenderer extends Disposable { @@ -34,8 +35,10 @@ export class BufferDecorationRenderer extends Disposable { this._dimensionsChanged = true; this._queueRefresh(); })); - // TODO: Listen to window change - this.register(addDisposableDomListener(window, 'resize', () => this._queueRefresh())); + const windowResizeListener = this.register(new MutableDisposable()); + this.register(runAndSubscribe(this._coreBrowserService.onWindowChange, () => { + windowResizeListener.value = addDisposableDomListener(this._coreBrowserService.window, 'resize', () => this._queueRefresh()); + })); this.register(this._bufferService.buffers.onBufferActivate(() => { this._altBufferIsActive = this._bufferService.buffer === this._bufferService.buffers.alt; })); diff --git a/src/browser/decorations/OverviewRulerRenderer.ts b/src/browser/decorations/OverviewRulerRenderer.ts index 57b6dfc6..157775f9 100644 --- a/src/browser/decorations/OverviewRulerRenderer.ts +++ b/src/browser/decorations/OverviewRulerRenderer.ts @@ -6,7 +6,8 @@ import { ColorZoneStore, IColorZone, IColorZoneStore } from 'browser/decorations/ColorZoneStore'; import { addDisposableDomListener } from 'browser/Lifecycle'; import { ICoreBrowserService, IRenderService } from 'browser/services/Services'; -import { Disposable, toDisposable } from 'common/Lifecycle'; +import { runAndSubscribe } from 'common/EventEmitter'; +import { Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle'; import { IBufferService, IDecorationService, IOptionsService } from 'common/services/Services'; // Helper objects to avoid excessive calculation and garbage collection during rendering. These are @@ -112,8 +113,10 @@ export class OverviewRulerRenderer extends Disposable { // overview ruler width changed this.register(this._optionsService.onSpecificOptionChange('overviewRulerWidth', () => this._queueRefresh(true))); // device pixel ratio changed - // TODO: Observe DPR instead / listen to window change - this.register(addDisposableDomListener(this._coreBrowserService.window, 'resize', () => this._queueRefresh(true))); + const windowResizeListener = this.register(new MutableDisposable()); + this.register(runAndSubscribe(this._coreBrowserService.onWindowChange, () => { + windowResizeListener.value = addDisposableDomListener(this._coreBrowserService.window, 'resize', () => this._queueRefresh(true)); + })); // set the canvas dimensions this._queueRefresh(true); } diff --git a/src/browser/services/RenderService.ts b/src/browser/services/RenderService.ts index 179ddeb2..7b9e6d79 100644 --- a/src/browser/services/RenderService.ts +++ b/src/browser/services/RenderService.ts @@ -8,7 +8,7 @@ import { RenderDebouncer } from 'browser/RenderDebouncer'; import { IRenderDebouncerWithCallback } from 'browser/Types'; import { IRenderDimensions, IRenderer } from 'browser/renderer/shared/Types'; import { ICharSizeService, ICoreBrowserService, IRenderService, IThemeService } from 'browser/services/Services'; -import { EventEmitter } from 'common/EventEmitter'; +import { EventEmitter, runAndSubscribe } from 'common/EventEmitter'; import { Disposable, MutableDisposable } from 'common/Lifecycle'; import { DebouncedIdleTask } from 'common/TaskQueue'; import { IBufferService, IDecorationService, IInstantiationService, IOptionsService } from 'common/services/Services'; @@ -103,7 +103,11 @@ export class RenderService extends Disposable implements IRenderService { // dprchange should handle this case, we need this as well for browsers that don't support the // matchMedia query. - // TODO: Listen to window change + // TODO: Merge this into onDprChange? + const windowResizeListener = this.register(new MutableDisposable()); + this.register(runAndSubscribe(coreBrowserService.onWindowChange, () => { + windowResizeListener.value = addDisposableDomListener(coreBrowserService.window, 'resize', () => this.handleDevicePixelRatioChange()); + })); this.register(addDisposableDomListener(coreBrowserService.window, 'resize', () => this.handleDevicePixelRatioChange())); this.register(themeService.onChangeColors(() => this._fullRefresh())); diff --git a/src/common/EventEmitter.ts b/src/common/EventEmitter.ts index fd959042..589748a3 100644 --- a/src/common/EventEmitter.ts +++ b/src/common/EventEmitter.ts @@ -71,3 +71,8 @@ export class EventEmitter implements IEventEmitter { export function forwardEvent(from: IEvent, to: IEventEmitter): IDisposable { return from(e => to.fire(e)); } + +export function runAndSubscribe(event: IEvent, handler: (e: T | undefined) => any): IDisposable { + handler(undefined); + return event(e => handler(e)); +} diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index b8028a18..b8c11455 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -973,7 +973,8 @@ declare module 'xterm' { resize(columns: number, rows: number): void; /** - * Opens the terminal within an element. + * Opens the terminal within an element. This should also be called if the + * xterm.js element ever changes browser window. * @param parent The element to create the terminal within. This element * must be visible (have dimensions) when `open` is called as several DOM- * based measurements need to be performed when this function is called.