diff --git a/src/Terminal.ts b/src/Terminal.ts index 15c6335a..d42978f7 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -408,7 +408,7 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT case 'lineHeight': // When the font changes the size of the cells may change which requires a renderer clear this.renderer.clear(); - this.renderer.onResize(this.cols, this.rows); + this.renderer.onResize(this.cols, this.rows, false); this.refresh(0, this.rows - 1); // this.charMeasure.measure(this.options); case 'scrollback': @@ -620,14 +620,11 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT this.charMeasure.on('charsizechanged', () => this.viewport.syncScrollArea()); this.renderer = new Renderer(this); this.on('cursormove', () => this.renderer.onCursorMove()); - this.on('resize', () => this.renderer.onResize(this.cols, this.rows)); + this.on('resize', () => this.renderer.onResize(this.cols, this.rows, false)); this.on('blur', () => this.renderer.onBlur()); this.on('focus', () => this.renderer.onFocus()); - this.charMeasure.on('charsizechanged', () => { - this.renderer.onCharSizeChanged(this.charMeasure.width, this.charMeasure.height); - // Force a refresh for the char size change - this.renderer.queueRefresh(0, this.rows - 1); - }); + window.addEventListener('resize', () => this.renderer.onWindowResize(window.devicePixelRatio)); + this.charMeasure.on('charsizechanged', () => this.renderer.onResize(this.cols, this.rows, true)); this.selectionManager = new SelectionManager(this, this.buffer, this.charMeasure); this.element.addEventListener('mousedown', (e: MouseEvent) => this.selectionManager.onMouseDown(e)); diff --git a/src/renderer/Interfaces.ts b/src/renderer/Interfaces.ts index 04e24e19..e6b09843 100644 --- a/src/renderer/Interfaces.ts +++ b/src/renderer/Interfaces.ts @@ -2,8 +2,9 @@ import { ITerminal, ITerminalOptions, ITheme } from '../Interfaces'; export interface IRenderer { setTheme(theme: ITheme): IColorSet; - onResize(cols: number, rows: number): void; - onCharSizeChanged(charWidth: number, charHeight: number): void; + onWindowResize(devicePixelRatio: number): void; + onResize(cols: number, rows: number, didCharSizeChange: boolean): void; + onCharSizeChanged(): void; onBlur(): void; onFocus(): void; onSelectionChanged(start: [number, number], end: [number, number]): void; diff --git a/src/renderer/Renderer.ts b/src/renderer/Renderer.ts index a6d679a2..c032bc8f 100644 --- a/src/renderer/Renderer.ts +++ b/src/renderer/Renderer.ts @@ -18,6 +18,7 @@ export class Renderer implements IRenderer { private _refreshAnimationFrame = null; private _renderLayers: IRenderLayer[]; + private _devicePixelRatio: number; private _colorManager: ColorManager; @@ -29,6 +30,16 @@ export class Renderer implements IRenderer { new ForegroundRenderLayer(this._terminal.element, 2, this._colorManager.colors), new CursorRenderLayer(this._terminal.element, 3, this._colorManager.colors) ]; + this._devicePixelRatio = window.devicePixelRatio; + } + + public onWindowResize(devicePixelRatio: number): void { + // If the device pixel ratio changed, the char atlas needs to be regenerated + // and the terminal needs to refreshed + if (this._devicePixelRatio !== devicePixelRatio) { + this._devicePixelRatio = devicePixelRatio; + this.onResize(this._terminal.cols, this._terminal.rows, true); + } } public setTheme(theme: ITheme): IColorSet { @@ -45,19 +56,20 @@ export class Renderer implements IRenderer { return this._colorManager.colors; } - public onResize(cols: number, rows: number): void { + public onResize(cols: number, rows: number, didCharSizeChange: boolean): void { if (!this._terminal.charMeasure.width || !this._terminal.charMeasure.height) { return; } - const width = this._terminal.charMeasure.width * this._terminal.cols; - const height = Math.floor(this._terminal.charMeasure.height * this._terminal.options.lineHeight) * this._terminal.rows; - this._renderLayers.forEach(l => l.resize(this._terminal, width, height, false)); + const width = this._terminal.charMeasure.width * cols; + const height = Math.floor(this._terminal.charMeasure.height * this._terminal.options.lineHeight) * rows; + // Resize all render layers + this._renderLayers.forEach(l => l.resize(this._terminal, width, height, didCharSizeChange)); + // Force a refresh + this._terminal.refresh(0, this._terminal.rows - 1); } - public onCharSizeChanged(charWidth: number, charHeight: number): void { - const width = charWidth * this._terminal.cols; - const height = Math.floor(charHeight * this._terminal.options.lineHeight) * this._terminal.rows; - this._renderLayers.forEach(l => l.resize(this._terminal, width, height, true)); + public onCharSizeChanged(): void { + this.onResize(this._terminal.cols, this._terminal.rows, true); } public onBlur(): void { diff --git a/src/utils/TestUtils.test.ts b/src/utils/TestUtils.test.ts index ed0a19fb..652c3aa3 100644 --- a/src/utils/TestUtils.test.ts +++ b/src/utils/TestUtils.test.ts @@ -214,13 +214,14 @@ export class MockBuffer implements IBuffer { export class MockRenderer implements IRenderer { setTheme(theme: ITheme): IColorSet { return {}; } - onResize(cols: number, rows: number): void {} - onCharSizeChanged(charWidth: number, charHeight: number): void {} + onResize(cols: number, rows: number, didCharSizeChange: boolean): void {} + onCharSizeChanged(): void {} onBlur(): void {} onFocus(): void {} onSelectionChanged(start: [number, number], end: [number, number]): void {} onCursorMove(): void {} onOptionsChanged(): void {} + onWindowResize(devicePixelRatio: number): void {} clear(): void {} queueRefresh(start: number, end: number): void {} }