From ef5beb670678c8bcda1bb226d91bfbfd89518598 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 29 Dec 2017 08:30:13 -0800 Subject: [PATCH 1/4] Update charatlas when monitor DPI changes Fixes #1118 --- src/Terminal.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Terminal.ts b/src/Terminal.ts index afea5e90..3026c9a3 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -637,7 +637,11 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT this.on('resize', () => this.renderer.onResize(this.cols, this.rows, false)); this.on('blur', () => this.renderer.onBlur()); this.on('focus', () => this.renderer.onFocus()); - window.addEventListener('resize', () => this.renderer.onWindowResize(window.devicePixelRatio)); + const rendererResizeListener = () => this.renderer.onWindowResize(window.devicePixelRatio); + // Listen for window zoom + window.addEventListener('resize', () => rendererResizeListener); + // Listen for monitor DPI change + window.matchMedia('screen and (-webkit-min-device-pixel-ratio: 1.5)').addListener(rendererResizeListener); this.charMeasure.on('charsizechanged', () => this.renderer.onResize(this.cols, this.rows, true)); this.renderer.on('resize', (dimensions) => this.viewport.syncScrollArea()); From 72d946e089a4014e510f5d60751c391444e5f891 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 29 Dec 2017 13:54:01 -0800 Subject: [PATCH 2/4] Use a more robust solution to changing devicePixelRatio --- src/Terminal.ts | 5 --- src/renderer/Renderer.ts | 5 +++ src/utils/ScreenDprMonitor.ts | 62 +++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 src/utils/ScreenDprMonitor.ts diff --git a/src/Terminal.ts b/src/Terminal.ts index 3026c9a3..dd2bf405 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -637,11 +637,6 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT this.on('resize', () => this.renderer.onResize(this.cols, this.rows, false)); this.on('blur', () => this.renderer.onBlur()); this.on('focus', () => this.renderer.onFocus()); - const rendererResizeListener = () => this.renderer.onWindowResize(window.devicePixelRatio); - // Listen for window zoom - window.addEventListener('resize', () => rendererResizeListener); - // Listen for monitor DPI change - window.matchMedia('screen and (-webkit-min-device-pixel-ratio: 1.5)').addListener(rendererResizeListener); this.charMeasure.on('charsizechanged', () => this.renderer.onResize(this.cols, this.rows, true)); this.renderer.on('resize', (dimensions) => this.viewport.syncScrollArea()); diff --git a/src/renderer/Renderer.ts b/src/renderer/Renderer.ts index 36727eac..422d424c 100644 --- a/src/renderer/Renderer.ts +++ b/src/renderer/Renderer.ts @@ -13,6 +13,7 @@ import { BaseRenderLayer } from './BaseRenderLayer'; import { IRenderLayer, IColorSet, IRenderer, IRenderDimensions } from './Interfaces'; import { LinkRenderLayer } from './LinkRenderLayer'; import { EventEmitter } from '../EventEmitter'; +import { ScreenDprMonitor } from '../utils/ScreenDprMonitor'; export class Renderer extends EventEmitter implements IRenderer { /** A queue of the rows to be refreshed */ @@ -21,6 +22,7 @@ export class Renderer extends EventEmitter implements IRenderer { private _renderLayers: IRenderLayer[]; private _devicePixelRatio: number; + private _screenDprMonitor: ScreenDprMonitor; public colorManager: ColorManager; public dimensions: IRenderDimensions; @@ -53,6 +55,9 @@ export class Renderer extends EventEmitter implements IRenderer { }; this._devicePixelRatio = window.devicePixelRatio; this._updateDimensions(); + + this._screenDprMonitor = new ScreenDprMonitor(); + this._screenDprMonitor.setListener(() => this.onWindowResize(window.devicePixelRatio)); } public onWindowResize(devicePixelRatio: number): void { diff --git a/src/utils/ScreenDprMonitor.ts b/src/utils/ScreenDprMonitor.ts new file mode 100644 index 00000000..5c5f762c --- /dev/null +++ b/src/utils/ScreenDprMonitor.ts @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +export type ScreenDprListener = (newDevicePixelRatio?: number, oldDevicePixelRatio?: number) => void; + +/** + * The screen device pixel ratio monitor allows listening for when the + * window.devicePixelRatio value changes. This is done not with polling but with + * the use of window.matchMedia to watch media queries. When the event fires, + * the listener will be reattached using a different media query to ensure that + * any further changes will register. + * + * The listener should fire on both window zoom changes and switching to a + * monitor with a different DPI. + */ +export class ScreenDprMonitor { + private _currentDevicePixelRatio: number; + private _outerListener: MediaQueryListListener; + private _listener: ScreenDprListener; + private _minMediaMatchList: MediaQueryList; + private _maxMediaMatchList: MediaQueryList; + + public setListener(listener: ScreenDprListener): void { + if (this._listener) { + this.clearListener(); + } + this._listener = listener; + this._outerListener = () => { + this._listener(window.devicePixelRatio, this._currentDevicePixelRatio); + this._updateDpr(); + }; + this._updateDpr(); + } + + private _updateDpr(): void { + // Clear listeners for old DPR + if (this._minMediaMatchList) { + this._minMediaMatchList.removeListener(this._outerListener); + } + if (this._maxMediaMatchList) { + this._maxMediaMatchList.removeListener(this._outerListener); + } + // Add listeners for new DPR + this._currentDevicePixelRatio = window.devicePixelRatio; + this._minMediaMatchList = window.matchMedia(`screen and (-webkit-min-device-pixel-ratio: ${window.devicePixelRatio})`); + this._maxMediaMatchList = window.matchMedia(`screen and (-webkit-max-device-pixel-ratio: ${window.devicePixelRatio})`); + this._minMediaMatchList.addListener(this._outerListener); + this._maxMediaMatchList.addListener(this._outerListener); + } + + public clearListener(): void { + if (!this._listener) { + return; + } + this._minMediaMatchList.removeListener(this._outerListener); + this._maxMediaMatchList.removeListener(this._outerListener); + this._listener = null; + this._outerListener = null; + } +} From ecc1055c10c8842b0104a19509aba552513cc7dc Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 2 Jan 2018 10:11:24 -0800 Subject: [PATCH 3/4] Listen to resolution media query --- src/utils/ScreenDprMonitor.ts | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/utils/ScreenDprMonitor.ts b/src/utils/ScreenDprMonitor.ts index 5c5f762c..405a18f8 100644 --- a/src/utils/ScreenDprMonitor.ts +++ b/src/utils/ScreenDprMonitor.ts @@ -19,8 +19,7 @@ export class ScreenDprMonitor { private _currentDevicePixelRatio: number; private _outerListener: MediaQueryListListener; private _listener: ScreenDprListener; - private _minMediaMatchList: MediaQueryList; - private _maxMediaMatchList: MediaQueryList; + private _resolutionMediaMatchList: MediaQueryList; public setListener(listener: ScreenDprListener): void { if (this._listener) { @@ -28,6 +27,7 @@ export class ScreenDprMonitor { } this._listener = listener; this._outerListener = () => { + console.log('change!'); this._listener(window.devicePixelRatio, this._currentDevicePixelRatio); this._updateDpr(); }; @@ -36,26 +36,20 @@ export class ScreenDprMonitor { private _updateDpr(): void { // Clear listeners for old DPR - if (this._minMediaMatchList) { - this._minMediaMatchList.removeListener(this._outerListener); - } - if (this._maxMediaMatchList) { - this._maxMediaMatchList.removeListener(this._outerListener); + if (this._resolutionMediaMatchList) { + this._resolutionMediaMatchList.removeListener(this._outerListener); } // Add listeners for new DPR this._currentDevicePixelRatio = window.devicePixelRatio; - this._minMediaMatchList = window.matchMedia(`screen and (-webkit-min-device-pixel-ratio: ${window.devicePixelRatio})`); - this._maxMediaMatchList = window.matchMedia(`screen and (-webkit-max-device-pixel-ratio: ${window.devicePixelRatio})`); - this._minMediaMatchList.addListener(this._outerListener); - this._maxMediaMatchList.addListener(this._outerListener); + this._resolutionMediaMatchList = window.matchMedia(`screen and (resolution: ${window.devicePixelRatio}dppx)`); + this._resolutionMediaMatchList.addListener(this._outerListener); } public clearListener(): void { if (!this._listener) { return; } - this._minMediaMatchList.removeListener(this._outerListener); - this._maxMediaMatchList.removeListener(this._outerListener); + this._resolutionMediaMatchList.removeListener(this._outerListener); this._listener = null; this._outerListener = null; } From 248fbccfd9c9bcb124bd0930867178e5b534ce91 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 5 Jan 2018 14:18:16 -0800 Subject: [PATCH 4/4] Remove console.log --- src/utils/ScreenDprMonitor.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/utils/ScreenDprMonitor.ts b/src/utils/ScreenDprMonitor.ts index 405a18f8..15f3ac00 100644 --- a/src/utils/ScreenDprMonitor.ts +++ b/src/utils/ScreenDprMonitor.ts @@ -27,7 +27,6 @@ export class ScreenDprMonitor { } this._listener = listener; this._outerListener = () => { - console.log('change!'); this._listener(window.devicePixelRatio, this._currentDevicePixelRatio); this._updateDpr(); };