diff --git a/src/Viewport.test.ts b/src/Viewport.test.ts index 5b106b4345..fc2cd1174c 100644 --- a/src/Viewport.test.ts +++ b/src/Viewport.test.ts @@ -1,6 +1,11 @@ import { assert } from 'chai'; import { Viewport } from './Viewport'; +class MockWindow { + // Disable refreshLoop in test + public requestAnimationFrame() { } +} + describe('Viewport', () => { var terminal; var viewportElement; @@ -11,6 +16,7 @@ describe('Viewport', () => { const CHARACTER_HEIGHT = 10; beforeEach(() => { + (global).window = new MockWindow(); terminal = { lines: [], rows: 0, @@ -73,10 +79,14 @@ describe('Viewport', () => { terminal.rows = 1; assert.equal(scrollAreaElement.style.height, 0 * CHARACTER_HEIGHT + 'px'); viewport.syncScrollArea(); + assert.ok(viewport.isRefreshQueued); + viewport.refresh(); assert.equal(viewportElement.style.height, 1 * CHARACTER_HEIGHT + 'px'); assert.equal(scrollAreaElement.style.height, 1 * CHARACTER_HEIGHT + 'px'); terminal.lines.push(''); viewport.syncScrollArea(); + assert.ok(viewport.isRefreshQueued); + viewport.refresh(); assert.equal(viewportElement.style.height, 1 * CHARACTER_HEIGHT + 'px'); assert.equal(scrollAreaElement.style.height, 2 * CHARACTER_HEIGHT + 'px'); }); diff --git a/src/Viewport.ts b/src/Viewport.ts index 3aa1319fb1..32a71dde0b 100644 --- a/src/Viewport.ts +++ b/src/Viewport.ts @@ -12,6 +12,7 @@ export class Viewport { private currentRowHeight: number; private lastRecordedBufferLength: number; private lastRecordedViewportHeight: number; + private isRefreshQueued: boolean; /** * Creates a new Viewport. @@ -29,12 +30,25 @@ export class Viewport { this.currentRowHeight = 0; this.lastRecordedBufferLength = 0; this.lastRecordedViewportHeight = 0; + this.isRefreshQueued = false; this.terminal.on('scroll', this.syncScrollArea.bind(this)); this.terminal.on('resize', this.syncScrollArea.bind(this)); this.viewportElement.addEventListener('scroll', this.onScroll.bind(this)); this.syncScrollArea(); + this.refreshLoop(); + } + + /** + * Queues a refresh to be done on next animation frame. + */ + private refreshLoop(): void { + if (this.isRefreshQueued) { + this.refresh(); + this.isRefreshQueued = false; + } + window.requestAnimationFrame(this.refreshLoop.bind(this)); } /** @@ -68,15 +82,15 @@ export class Viewport { if (this.lastRecordedBufferLength !== this.terminal.lines.length) { // If buffer height changed this.lastRecordedBufferLength = this.terminal.lines.length; - this.refresh(); + this.isRefreshQueued = true; } else if (this.lastRecordedViewportHeight !== this.terminal.rows) { // If viewport height changed - this.refresh(); + this.isRefreshQueued = true; } else { // If size has changed, refresh viewport var size = this.charMeasureElement.getBoundingClientRect(); if (size.height !== this.currentRowHeight) { - this.refresh(size); + this.isRefreshQueued = true; } }