diff --git a/addons/xterm-addon-webgl/src/WebglRenderer.ts b/addons/xterm-addon-webgl/src/WebglRenderer.ts index 8d6a4f49..b21f8c2f 100644 --- a/addons/xterm-addon-webgl/src/WebglRenderer.ts +++ b/addons/xterm-addon-webgl/src/WebglRenderer.ts @@ -16,6 +16,7 @@ import { Attributes, Content, FgFlags, NULL_CELL_CHAR, NULL_CELL_CODE } from 'co import { Terminal, IEvent } from 'xterm'; import { IRenderLayer } from './renderLayer/Types'; import { IRenderDimensions, IRenderer, IRequestRedrawEvent } from 'browser/renderer/Types'; +import { observeDevicePixelDimensions } from 'browser/renderer/DevicePixelObserver'; import { ITerminal, IColorSet } from 'browser/Types'; import { EventEmitter } from 'common/EventEmitter'; import { CellData } from 'common/buffer/CellData'; @@ -95,31 +96,7 @@ export class WebglRenderer extends Disposable implements IRenderer { } this.register(addDisposableDomListener(this._canvas, 'webglcontextlost', (e) => { this._onContextLoss.fire(e); })); - - // Observe any resizes to the canvas and extract the actual pixel size of the canvas if the - // devicePixelContentBoxSize API is supported. This allows correcting rounding errors when - // converting between CSS pixels and device pixels which causes blurry rendering when device - // pixel ratio is not a round number. - let observer: ResizeObserver | undefined = new ResizeObserver((entries) => { - const entry = entries.find((entry) => entry.target === this._canvas); - if (!entry) { - return; - } - - // Disconnect if devicePixelContentBoxSize isn't supported by the browser - if (!('devicePixelContentBoxSize' in entry)) { - observer?.disconnect(); - observer = undefined; - return; - } - - this._setCanvasDevicePixelDimensions( - entry.devicePixelContentBoxSize[0].inlineSize, - entry.devicePixelContentBoxSize[0].blockSize - ); - }); - observer.observe(this._canvas, { box: ['device-pixel-content-box'] } as any); - this.register(toDisposable(() => observer?.disconnect())); + this.register(observeDevicePixelDimensions(this._canvas, (w, h) => this._setCanvasDevicePixelDimensions(w, h))); this._core.screenElement!.appendChild(this._canvas); diff --git a/src/browser/renderer/DevicePixelObserver.ts b/src/browser/renderer/DevicePixelObserver.ts new file mode 100644 index 00000000..611eb910 --- /dev/null +++ b/src/browser/renderer/DevicePixelObserver.ts @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2022 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { toDisposable } from 'common/Lifecycle'; +import { IDisposable } from 'common/Types'; + +export function observeDevicePixelDimensions(element: HTMLElement, callback: (deviceWidth: number, deviceHeight: number) => void): IDisposable { + // Observe any resizes to the element and extract the actual pixel size of the element if the + // devicePixelContentBoxSize API is supported. This allows correcting rounding errors when + // converting between CSS pixels and device pixels which causes blurry rendering when device + // pixel ratio is not a round number. + let observer: ResizeObserver | undefined = new ResizeObserver((entries) => { + const entry = entries.find((entry) => entry.target === element); + if (!entry) { + return; + } + + // Disconnect if devicePixelContentBoxSize isn't supported by the browser + if (!('devicePixelContentBoxSize' in entry)) { + observer?.disconnect(); + observer = undefined; + return; + } + + callback( + entry.devicePixelContentBoxSize[0].inlineSize, + entry.devicePixelContentBoxSize[0].blockSize + ); + }); + observer.observe(element, { box: ['device-pixel-content-box'] } as any); + return toDisposable(() => observer?.disconnect()); +} diff --git a/src/browser/renderer/Renderer.ts b/src/browser/renderer/Renderer.ts index 04fdec77..45b7f1c1 100644 --- a/src/browser/renderer/Renderer.ts +++ b/src/browser/renderer/Renderer.ts @@ -14,6 +14,7 @@ import { ICharSizeService } from 'browser/services/Services'; import { IBufferService, IOptionsService, IInstantiationService } from 'common/services/Services'; import { removeTerminalFromCache } from 'browser/renderer/atlas/CharAtlasCache'; import { EventEmitter, IEvent } from 'common/EventEmitter'; +import { observeDevicePixelDimensions } from 'browser/renderer/DevicePixelObserver'; let nextRendererId = 1; @@ -63,31 +64,7 @@ export class Renderer extends Disposable implements IRenderer { this._devicePixelRatio = window.devicePixelRatio; this._updateDimensions(); - // Observe any resizes to the canvas and extract the actual pixel size of the canvas if the - // devicePixelContentBoxSize API is supported. This allows correcting rounding errors when - // converting between CSS pixels and device pixels which causes blurry rendering when device - // pixel ratio is not a round number. - const observedCanvas = this._renderLayers[0].canvas; - let observer: ResizeObserver | undefined = new ResizeObserver((entries) => { - const entry = entries.find((entry) => entry.target === observedCanvas); - if (!entry) { - return; - } - - // Disconnect if devicePixelContentBoxSize isn't supported by the browser - if (!('devicePixelContentBoxSize' in entry)) { - observer?.disconnect(); - observer = undefined; - return; - } - - this._setCanvasDevicePixelDimensions( - entry.devicePixelContentBoxSize[0].inlineSize, - entry.devicePixelContentBoxSize[0].blockSize - ); - }); - observer.observe(observedCanvas, { box: ['device-pixel-content-box'] } as any); - this.register(toDisposable(() => observer?.disconnect())); + this.register(observeDevicePixelDimensions(this._renderLayers[0].canvas, (w, h) => this._setCanvasDevicePixelDimensions(w, h))); this.onOptionsChanged(); }