From 1f60a398b277f2daaac994285db081730a6ae2c1 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Tue, 22 Mar 2022 15:04:22 -0400 Subject: [PATCH] on render, fire when height has changed (was 0) --- .../Decorations/OverviewRulerRenderer.ts | 46 ++++++++++++++----- src/browser/Terminal.ts | 5 +- src/browser/TestUtils.test.ts | 1 + src/browser/services/RenderService.ts | 7 ++- src/browser/services/Services.ts | 4 ++ 5 files changed, 45 insertions(+), 18 deletions(-) diff --git a/src/browser/Decorations/OverviewRulerRenderer.ts b/src/browser/Decorations/OverviewRulerRenderer.ts index 8c63f5e3..9d6e4904 100644 --- a/src/browser/Decorations/OverviewRulerRenderer.ts +++ b/src/browser/Decorations/OverviewRulerRenderer.ts @@ -38,6 +38,10 @@ export class OverviewRulerRenderer extends Disposable { } private _animationFrame: number | undefined; + private _canvasHeight: number | undefined; + private _canvasWidth: number | undefined; + private _shouldUpdateDimensions: boolean | undefined = true; + constructor( private readonly _viewportElement: HTMLElement, private readonly _screenElement: HTMLElement, @@ -49,7 +53,7 @@ export class OverviewRulerRenderer extends Disposable { super(); this._canvas = document.createElement('canvas'); this._canvas.classList.add('xterm-decoration-overview-ruler'); - this.refreshCanvasDimensions(); + this._refreshCanvasDimensions(); this._viewportElement.parentElement?.insertBefore(this._canvas, this._viewportElement); const ctx = this._canvas.getContext('2d'); if (!ctx) { @@ -62,6 +66,11 @@ export class OverviewRulerRenderer extends Disposable { this._canvas!.style.display = this._bufferService.buffer === this._bufferService.buffers.alt ? 'none' : 'block'; })); this.register(this._renderService.onRenderedBufferChange(() => this._queueRefresh())); + this.register(this._renderService.onRender(() => { + if (this._canvasHeight !== this._screenElement.clientHeight) { + this._queueRefresh(true); + } + })); this.register(this._renderService.onDimensionsChange(() => this._queueRefresh(true, true))); this.register(addDisposableDomListener(window, 'resize', () => this._queueRefresh(true))); this.register(this._decorationService.onDecorationRegistered(() => this._queueRefresh(undefined, true))); @@ -102,6 +111,7 @@ export class OverviewRulerRenderer extends Disposable { drawX.left = 0; drawX.center = drawWidth.left; drawX.right = drawWidth.left + drawWidth.center; + this._shouldUpdateDimensions = false; } private _refreshStyle(decoration: IInternalDecoration, updateAnchor?: boolean): void { @@ -122,24 +132,35 @@ export class OverviewRulerRenderer extends Disposable { /* x */ drawX[decoration.options.overviewRulerOptions.position!], /* y */ Math.round( (this._canvas.height - 1) * // -1 to ensure at least 2px are allowed for decoration on last line - (decoration.options.marker.line / this._bufferService.buffers.active.lines.length) - drawHeight[decoration.options.overviewRulerOptions.position!] / 2 + (decoration.options.marker.line / this._bufferService.buffers.active.lines.length) - drawHeight[decoration.options.overviewRulerOptions.position!] / 2 ), /* w */ drawWidth[decoration.options.overviewRulerOptions.position!], /* h */ drawHeight[decoration.options.overviewRulerOptions.position!] ); } - public refreshCanvasDimensions(): void { - this._canvas.style.width = `${this._width}px`; - this._canvas.style.height = `${this._screenElement.clientHeight}px`; - this._canvas.width = Math.round(this._width * window.devicePixelRatio); - this._canvas.height = Math.round(this._screenElement.clientHeight * window.devicePixelRatio); - this._refreshDrawConstants(); + private _refreshCanvasDimensions(): void { + let updated = false; + if (this._canvasWidth !== this._width) { + this._canvas.style.width = `${this._width}px`; + this._canvas.width = Math.round(this._width * window.devicePixelRatio); + this._canvasWidth = this._canvas.width; + updated = true; + } + if (this._canvasHeight !== Math.round(this._screenElement.clientHeight * window.devicePixelRatio)) { + this._canvas.style.height = `${this._screenElement.clientHeight}px`; + this._canvas.height = Math.round(this._screenElement.clientHeight * window.devicePixelRatio); + this._canvasHeight = this._canvas.height; + updated = true; + } + if (updated) { + this._refreshDrawConstants(); + } } - private _refreshDecorations(updateCanvasDimensions?: boolean, updateAnchor?: boolean): void { - if (updateCanvasDimensions) { - this.refreshCanvasDimensions(); + private _refreshDecorations(updateAnchor?: boolean): void { + if (this._shouldUpdateDimensions) { + this._refreshCanvasDimensions(); } this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height); for (const decoration of this._decorationService.decorations) { @@ -165,10 +186,11 @@ export class OverviewRulerRenderer extends Disposable { private _queueRefresh(updateCanvasDimensions?: boolean, updateAnchor?: boolean): void { if (this._animationFrame !== undefined) { + this._shouldUpdateDimensions = updateCanvasDimensions || this._shouldUpdateDimensions; return; } this._animationFrame = window.requestAnimationFrame(() => { - this._refreshDecorations(updateCanvasDimensions, updateAnchor); + this._refreshDecorations(updateAnchor); this._animationFrame = undefined; }); } diff --git a/src/browser/Terminal.ts b/src/browser/Terminal.ts index 6560a976..f14b5217 100644 --- a/src/browser/Terminal.ts +++ b/src/browser/Terminal.ts @@ -175,9 +175,7 @@ export class Terminal extends CoreTerminal implements ITerminal { // Setup InputHandler listeners this.register(this._inputHandler.onRequestBell(() => this.bell())); - this.register(this._inputHandler.onRequestRefreshRows((start, end) => { - this.refresh(start, end); - })); + this.register(this._inputHandler.onRequestRefreshRows((start, end) => this.refresh(start, end))); this.register(this._inputHandler.onRequestSendFocus(() => this._reportFocus())); this.register(this._inputHandler.onRequestReset(() => this.reset())); this.register(this._inputHandler.onRequestWindowsOptionsReport(type => this._reportWindowsOptions(type))); @@ -909,7 +907,6 @@ export class Terminal extends CoreTerminal implements ITerminal { */ public refresh(start: number, end: number): void { this._renderService?.refreshRows(start, end); - this._overviewRulerRenderer?.refreshCanvasDimensions(); } /** diff --git a/src/browser/TestUtils.test.ts b/src/browser/TestUtils.test.ts index ac048be6..85e2bb55 100644 --- a/src/browser/TestUtils.test.ts +++ b/src/browser/TestUtils.test.ts @@ -371,6 +371,7 @@ export class MockRenderService implements IRenderService { public serviceBrand: undefined; public onDimensionsChange: IEvent = new EventEmitter().event; public onRenderedBufferChange: IEvent<{ start: number, end: number }, void> = new EventEmitter<{ start: number, end: number }>().event; + public onRender: IEvent<{ start: number, end: number }, void> = new EventEmitter<{ start: number, end: number }>().event; public onRefreshRequest: IEvent<{ start: number, end: number}, void> = new EventEmitter<{ start: number, end: number }>().event; public dimensions: IRenderDimensions = { scaledCharWidth: 0, diff --git a/src/browser/services/RenderService.ts b/src/browser/services/RenderService.ts index da458abc..91b510a3 100644 --- a/src/browser/services/RenderService.ts +++ b/src/browser/services/RenderService.ts @@ -39,8 +39,10 @@ export class RenderService extends Disposable implements IRenderService { private _onDimensionsChange = new EventEmitter(); public get onDimensionsChange(): IEvent { return this._onDimensionsChange.event; } + private _onRenderedBufferChange = new EventEmitter<{ start: number, end: number }>(); + public get onRenderedBufferChange(): IEvent<{ start: number, end: number }> { return this._onRenderedBufferChange.event; } private _onRender = new EventEmitter<{ start: number, end: number }>(); - public get onRenderedBufferChange(): IEvent<{ start: number, end: number }> { return this._onRender.event; } + public get onRender(): IEvent<{ start: number, end: number }> { return this._onRender.event; } private _onRefreshRequest = new EventEmitter<{ start: number, end: number }>(); public get onRefreshRequest(): IEvent<{ start: number, end: number }> { return this._onRefreshRequest.event; } @@ -122,8 +124,9 @@ export class RenderService extends Disposable implements IRenderService { // Fire render event only if it was not a redraw if (!this._isNextRenderRedrawOnly) { - this._onRender.fire({ start, end }); + this._onRenderedBufferChange.fire({ start, end }); } + this._onRender.fire({ start, end }); this._isNextRenderRedrawOnly = true; } diff --git a/src/browser/services/Services.ts b/src/browser/services/Services.ts index 1598ef02..7191d0ed 100644 --- a/src/browser/services/Services.ts +++ b/src/browser/services/Services.ts @@ -50,6 +50,10 @@ export interface IRenderService extends IDisposable { * or selections are rendered. */ onRenderedBufferChange: IEvent<{ start: number, end: number }>; + /** + * Fires on render + */ + onRender: IEvent<{ start: number, end: number }>; onRefreshRequest: IEvent<{ start: number, end: number }>; dimensions: IRenderDimensions;