diff --git a/src/AccessibilityManager.ts b/src/AccessibilityManager.ts index 4351a336..aabb5b6f 100644 --- a/src/AccessibilityManager.ts +++ b/src/AccessibilityManager.ts @@ -58,7 +58,7 @@ export class AccessibilityManager extends Disposable { this._rowElements[0].addEventListener('focus', this._topBoundaryFocusListener); this._rowElements[this._rowElements.length - 1].addEventListener('focus', this._bottomBoundaryFocusListener); - this._refreshRowsDimensions(); + this.refreshRowsDimensions(); this._accessibilityTreeRoot.appendChild(this._rowContainer); this._renderRowsDebouncer = new RenderDebouncer(this._renderRows.bind(this)); @@ -84,11 +84,10 @@ export class AccessibilityManager extends Disposable { // TODO: Maybe renderer should fire an event on terminal when the characters change and that // should be listened to instead? That would mean that the order of events are always // guarenteed - this.register(this._terminal.addDisposableListener('dprchange', () => this._refreshRowsDimensions())); - this.register(this._terminal.renderer.onCanvasResize(() => this._refreshRowsDimensions())); + this.register(this._terminal.addDisposableListener('dprchange', () => this.refreshRowsDimensions())); // This shouldn't be needed on modern browsers but is present in case the // media query that drives the dprchange event isn't supported - this.register(addDisposableDomListener(window, 'resize', () => this._refreshRowsDimensions())); + this.register(addDisposableDomListener(window, 'resize', () => this.refreshRowsDimensions())); } public dispose(): void { @@ -174,7 +173,7 @@ export class AccessibilityManager extends Disposable { // Add bottom boundary listener this._rowElements[this._rowElements.length - 1].addEventListener('focus', this._bottomBoundaryFocusListener); - this._refreshRowsDimensions(); + this.refreshRowsDimensions(); } private _createAccessibilityTreeNode(): HTMLElement { @@ -257,7 +256,7 @@ export class AccessibilityManager extends Disposable { } } - private _refreshRowsDimensions(): void { + public refreshRowsDimensions(): void { if (!this._terminal.renderer.dimensions.actualCellHeight) { return; } diff --git a/src/Terminal.ts b/src/Terminal.ts index b241cc23..4f91d27e 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -773,6 +773,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II this._setupRenderer(); this._renderCoordinator = new RenderCoordinator(this.renderer, this.rows); + this._renderCoordinator.onRender(e => this._onRender.fire(e)); this.onResize(e => this._renderCoordinator.resize(e.cols, e.rows)); this.viewport = new Viewport(this, this._viewportElement, this._viewportScrollArea, this.charMeasure); @@ -788,7 +789,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II // matchMedia query. this.register(addDisposableDomListener(window, 'resize', () => this.renderer.onWindowResize(window.devicePixelRatio))); this.register(this.charMeasure.onCharSizeChanged(() => this.renderer.onCharSizeChanged())); - this.register(this.renderer.onCanvasResize(() => this.viewport.syncScrollArea())); + this.register(this._renderCoordinator.onCanvasResize(() => this.viewport.syncScrollArea())); this.selectionManager = new SelectionManager(this, this.charMeasure); this.register(this.selectionManager.onSelectionChange(() => this._onSelectionChange.fire())); @@ -821,6 +822,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II // Note that this must be done *after* the renderer is created in order to // ensure the correct order of the dprchange event this._accessibilityManager = new AccessibilityManager(this); + this._accessibilityManager.register(this._renderCoordinator.onCanvasResize(() => this._accessibilityManager.refreshRowsDimensions())); } // Measure the character size @@ -848,7 +850,6 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II if (this._renderCoordinator) { this._renderCoordinator.setRenderer(this.renderer); } - this.renderer.onRender(e => this._onRender.fire(e)); this.register(this.renderer); } diff --git a/src/renderer/RenderCoordinator.ts b/src/renderer/RenderCoordinator.ts index 0a4d4b99..8ee3fb69 100644 --- a/src/renderer/RenderCoordinator.ts +++ b/src/renderer/RenderCoordinator.ts @@ -5,23 +5,56 @@ import { IRenderer } from './Types'; import { RenderDebouncer } from '../ui/RenderDebouncer'; +import { EventEmitter2, IEvent } from '../common/EventEmitter2'; export class RenderCoordinator { private _renderDebouncer: RenderDebouncer; + private _onCanvasResize = new EventEmitter2<{ width: number, height: number }>(); + public get onCanvasResize(): IEvent<{ width: number, height: number }> { return this._onCanvasResize.event; } + private _onRender = new EventEmitter2<{ start: number, end: number }>(); + public get onRender(): IEvent<{ start: number, end: number }> { return this._onRender.event; } + + private _canvasWidth: number = 0; + private _canvasHeight: number = 0; + constructor( private _renderer: IRenderer, private _rowCount: number ) { - this._renderDebouncer = new RenderDebouncer((start, end) => this._renderer.renderRows(start, end)); + this._renderDebouncer = new RenderDebouncer((start, end) => this._renderRows(start, end)); } public refreshRows(start: number, end: number): void { this._renderDebouncer.refresh(start, end, this._rowCount); } + private _renderRows(start: number, end: number): void { + this._renderer.renderRows(start, end); + this._onRender.fire({ start, end }); + } + public resize(cols: number, rows: number): void { this._rowCount = rows; + this._fireOnCanvasResize(); + } + + public changeOptions(): void { + this._renderer.onOptionsChanged(); + this._fireOnCanvasResize(); + } + + private _fireOnCanvasResize(): void { + // Don't fire the event if the dimensions haven't changed + if (this._renderer.dimensions.canvasWidth === this._canvasWidth && this._renderer.dimensions.canvasHeight === this._canvasHeight) { + return; + } + this._canvasWidth = this._renderer.dimensions.canvasWidth; + this._canvasHeight = this._renderer.dimensions.canvasHeight; + this._onCanvasResize.fire({ + width: this._canvasWidth, + height: this._canvasHeight + }); } public setRenderer(renderer: IRenderer): void { diff --git a/src/renderer/Renderer.ts b/src/renderer/Renderer.ts index 98fc50fc..240e04ec 100644 --- a/src/renderer/Renderer.ts +++ b/src/renderer/Renderer.ts @@ -11,12 +11,10 @@ import { ITerminal, CharacterJoinerHandler } from '../Types'; import { LinkRenderLayer } from './LinkRenderLayer'; import { ScreenDprMonitor } from '../ui/ScreenDprMonitor'; import { CharacterJoinerRegistry } from '../renderer/CharacterJoinerRegistry'; -import { EventEmitter2, IEvent } from '../common/EventEmitter2'; import { Disposable } from '../common/Lifecycle'; import { IColorSet } from '../ui/Types'; export class Renderer extends Disposable implements IRenderer { - private _renderLayers: IRenderLayer[]; private _devicePixelRatio: number; private _screenDprMonitor: ScreenDprMonitor; @@ -26,11 +24,6 @@ export class Renderer extends Disposable implements IRenderer { public dimensions: IRenderDimensions; - private _onCanvasResize = new EventEmitter2<{ width: number, height: number }>(); - public get onCanvasResize(): IEvent<{ width: number, height: number }> { return this._onCanvasResize.event; } - private _onRender = new EventEmitter2<{ start: number, end: number }>(); - public get onRender(): IEvent<{ start: number, end: number }> { return this._onRender.event; } - constructor( private _terminal: ITerminal, private _colors: IColorSet @@ -130,11 +123,6 @@ export class Renderer extends Disposable implements IRenderer { // Resize the screen this._terminal.screenElement.style.width = `${this.dimensions.canvasWidth}px`; this._terminal.screenElement.style.height = `${this.dimensions.canvasHeight}px`; - - this._onCanvasResize.fire({ - width: this.dimensions.canvasWidth, - height: this.dimensions.canvasHeight - }); } public onCharSizeChanged(): void { @@ -179,7 +167,6 @@ export class Renderer extends Disposable implements IRenderer { */ public renderRows(start: number, end: number): void { this._renderLayers.forEach(l => l.onGridChanged(this._terminal, start, end)); - this._onRender.fire({ start, end }); } /** diff --git a/src/renderer/Types.ts b/src/renderer/Types.ts index 3b00820a..d08360ef 100644 --- a/src/renderer/Types.ts +++ b/src/renderer/Types.ts @@ -5,7 +5,6 @@ import { ITerminal, CharacterJoinerHandler } from '../Types'; import { IDisposable } from 'xterm'; -import { IEvent } from '../common/EventEmitter2'; import { IColorSet } from '../ui/Types'; /** @@ -28,9 +27,6 @@ export const enum FLAGS { export interface IRenderer extends IDisposable { dimensions: IRenderDimensions; - onCanvasResize: IEvent<{ width: number, height: number }>; - onRender: IEvent<{ start: number, end: number }>; - dispose(): void; onThemeChange(colors: IColorSet): void; onWindowResize(devicePixelRatio: number): void; diff --git a/src/renderer/dom/DomRenderer.ts b/src/renderer/dom/DomRenderer.ts index d0c4e20c..d1f877e5 100644 --- a/src/renderer/dom/DomRenderer.ts +++ b/src/renderer/dom/DomRenderer.ts @@ -7,7 +7,6 @@ import { IRenderer, IRenderDimensions } from '../Types'; import { ILinkifierEvent, ITerminal, CharacterJoinerHandler } from '../../Types'; import { BOLD_CLASS, ITALIC_CLASS, CURSOR_CLASS, CURSOR_STYLE_BLOCK_CLASS, CURSOR_BLINK_CLASS, CURSOR_STYLE_BAR_CLASS, CURSOR_STYLE_UNDERLINE_CLASS, DomRendererRowFactory } from './DomRendererRowFactory'; import { INVERTED_DEFAULT_COLOR } from '../atlas/Types'; -import { EventEmitter2, IEvent } from '../../common/EventEmitter2'; import { Disposable } from '../../common/Lifecycle'; import { IColorSet } from '../../ui/Types'; @@ -40,12 +39,6 @@ export class DomRenderer extends Disposable implements IRenderer { public dimensions: IRenderDimensions; - // TODO: These events should be owned by RenderCoordinator - private _onCanvasResize = new EventEmitter2<{ width: number, height: number }>(); - public get onCanvasResize(): IEvent<{ width: number, height: number }> { return this._onCanvasResize.event; } - private _onRender = new EventEmitter2<{ start: number, end: number }>(); - public get onRender(): IEvent<{ start: number, end: number }> { return this._onRender.event; } - constructor( private _terminal: ITerminal, private _colors: IColorSet @@ -240,10 +233,6 @@ export class DomRenderer extends Disposable implements IRenderer { public onResize(cols: number, rows: number): void { this._refreshRowElements(cols, rows); this._updateDimensions(); - this._onCanvasResize.fire({ - width: this.dimensions.canvasWidth, - height: this.dimensions.canvasHeight - }); } public onCharSizeChanged(): void { @@ -351,8 +340,6 @@ export class DomRenderer extends Disposable implements IRenderer { const cursorStyle = terminal.options.cursorStyle; rowElement.appendChild(this._rowFactory.createRow(lineData, row === cursorAbsoluteY, cursorStyle, cursorX, cursorBlink, this.dimensions.actualCellWidth, terminal.cols)); } - - this._onRender.fire({ start, end }); } private get _terminalSelector(): string {