diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8b33d183c6..b4b3a9f21d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -23,7 +23,7 @@ opening an issue, read these pointers. - Mention precisely what went wrong. What did you expect to happen? What happened instead? Describe the exact steps a maintainer has to take to make the problem occur. -- If the problem can not be reproduced in the [demo of xterm.js](README.md#demo), please provide an HTML document that demonstrates the problem. +- If the problem can not be reproduced in the [demo of xterm.js](https://github.com/xtermjs/xterm.js/wiki/Contributing#running-the-demo), please provide an HTML document that demonstrates the problem. - Be polite. Issues with an indignant or belligerent tone tend to be moved to the bottom of the pile. @@ -33,6 +33,7 @@ opening an issue, read these pointers. - Make sure you have a [GitHub account](https://github.com/join) - Fork [xterm.js](https://github.com/sourcelair/xterm.js/) ([how to fork a repo](https://help.github.com/articles/fork-a-repo)) +- Get the [xterm.js demo](https://github.com/xtermjs/xterm.js/wiki/Contributing#running-the-demo) running - Make your changes - If your changes are easy to test or likely to regress, add tests. Tests go into `test`, directory. - Follow the general code style of the rest of the project (see below). diff --git a/src/Viewport.ts b/src/Viewport.ts index a8966d14af..e89676d91e 100644 --- a/src/Viewport.ts +++ b/src/Viewport.ts @@ -28,6 +28,9 @@ export class Viewport extends Disposable implements IViewport { // quick fix and could have a more robust solution in place that reset the value when needed. private _wheelPartialScroll: number = 0; + private _refreshAnimationFrame: number | null = null; + private _ignoreNextScrollEvent: boolean = false; + /** * Creates a new Viewport. * @param _terminal The terminal this viewport belongs to. @@ -62,6 +65,12 @@ export class Viewport extends Disposable implements IViewport { * necessary. */ private _refresh(): void { + if (this._refreshAnimationFrame === null) { + this._refreshAnimationFrame = requestAnimationFrame(() => this._innerRefresh()); + } + } + + private _innerRefresh(): void { if (this._charMeasure.height > 0) { this._currentRowHeight = this._terminal.renderer.dimensions.scaledCellHeight / window.devicePixelRatio; this._lastRecordedViewportHeight = this._viewportElement.offsetHeight; @@ -71,6 +80,17 @@ export class Viewport extends Disposable implements IViewport { this._scrollArea.style.height = this._lastRecordedBufferHeight + 'px'; } } + + // Sync scrollTop + const scrollTop = this._terminal.buffer.ydisp * this._currentRowHeight; + if (this._viewportElement.scrollTop !== scrollTop) { + // Ignore the next scroll event which will be triggered by setting the scrollTop as we do not + // want this event to scroll the terminal + this._ignoreNextScrollEvent = true; + this._viewportElement.scrollTop = scrollTop; + } + + this._refreshAnimationFrame = null; } /** @@ -90,12 +110,6 @@ export class Viewport extends Disposable implements IViewport { this._refresh(); } } - - // Sync scrollTop - const scrollTop = this._terminal.buffer.ydisp * this._currentRowHeight; - if (this._viewportElement.scrollTop !== scrollTop) { - this._viewportElement.scrollTop = scrollTop; - } } /** @@ -110,6 +124,13 @@ export class Viewport extends Disposable implements IViewport { return; } + // Ignore the event if it was flagged to ignore (when the source of the event is from Viewport) + if (this._ignoreNextScrollEvent) { + this._ignoreNextScrollEvent = false; + return; + } + + const newRow = Math.round(this._viewportElement.scrollTop / this._currentRowHeight); const diff = newRow - this._terminal.buffer.ydisp; this._terminal.scrollLines(diff, true); diff --git a/tslint.json b/tslint.json index 5dac55d689..40e26fcf7d 100644 --- a/tslint.json +++ b/tslint.json @@ -59,10 +59,7 @@ "esSpecCompliant": true } ], - "triple-equals": [ - true, - "allow-null-check" - ], + "triple-equals": true, "typedef-whitespace": [ true, { @@ -111,7 +108,6 @@ "prefer-const-enum": [ true ], - "prefer-const": true, - "triple-equals": true + "prefer-const": true } } diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 1db056393b..c8cc2cc6ce 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -425,6 +425,12 @@ declare module 'xterm' { */ emit(type: string, data?: any): void; + /** + * Adds an event listener to the Terminal, returning an IDisposable that can + * be used to conveniently remove the event listener. + * @param type The type of event. + * @param handler The event handler. + */ addDisposableListener(type: string, handler: (...args: any[]) => void): IDisposable; /**