diff --git a/src/AccessibilityManager.ts b/src/AccessibilityManager.ts index 866dc3c7..aeba5d8b 100644 --- a/src/AccessibilityManager.ts +++ b/src/AccessibilityManager.ts @@ -74,7 +74,7 @@ export class AccessibilityManager extends Disposable { this.register(this._renderRowsDebouncer); this.register(this._terminal.addDisposableListener('resize', data => this._onResize(data.rows))); this.register(this._terminal.addDisposableListener('refresh', data => this._refreshRows(data.start, data.end))); - this.register(this._terminal.addDisposableListener('scroll', data => this._refreshRows())); + this.register(this._terminal.onScroll(() => this._refreshRows())); // Line feed is an issue as the prompt won't be read out after a command is run this.register(this._terminal.addDisposableListener('a11y.char', (char) => this._onChar(char))); this.register(this._terminal.onLineFeed(() => this._onChar('\n'))); diff --git a/src/InputHandler.ts b/src/InputHandler.ts index da167e26..c77b1c60 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -111,6 +111,8 @@ export class InputHandler extends Disposable implements IInputHandler { public get onCursorMove(): IEvent { return this._onCursorMove.event; } private _onLineFeed = new EventEmitter2(); public get onLineFeed(): IEvent { return this._onLineFeed.event; } + private _onScroll = new EventEmitter2(); + public get onScroll(): IEvent { return this._onScroll.event; } constructor( protected _terminal: IInputHandlingTerminal, @@ -764,7 +766,7 @@ export class InputHandler extends Disposable implements IInputHandler { this._terminal.buffer.ybase = Math.max(this._terminal.buffer.ybase - scrollBackSize, 0); this._terminal.buffer.ydisp = Math.max(this._terminal.buffer.ydisp - scrollBackSize, 0); // Force a scroll event to refresh viewport - this._terminal.emit('scroll', 0); + this._onScroll.fire(0); } break; } diff --git a/src/Terminal.test.ts b/src/Terminal.test.ts index b44baa5b..b4818347 100644 --- a/src/Terminal.test.ts +++ b/src/Terminal.test.ts @@ -90,7 +90,6 @@ describe('xterm.js', () => { term.on('cursormove', () => { done(); }); - term.write('foo'); }); }); @@ -100,11 +99,26 @@ describe('xterm.js', () => { term.on('linefeed', () => { done(); }); - term.write('\n'); }); }); + describe('scroll', () => { + it('should emit a scroll event when scrollback is created', (done) => { + term.on('scroll', () => { + done(); + }); + term.write('\n'.repeat(INIT_ROWS)); + }); + it('should emit a scroll event when scrollback is cleared', (done) => { + term.write('\n'.repeat(INIT_ROWS)); + term.on('scroll', () => { + done(); + }); + term.clear(); + }); + }); + describe(`keypress (including 'key' event)`, () => { it('should receive a string and event object', (done) => { let steps = 0; diff --git a/src/Terminal.ts b/src/Terminal.ts index 662ce7eb..dfdb8569 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -263,7 +263,6 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II // TODO: Replace EventEmitter with EventEmitter2 internally this.on('selection', () => this._onSelectionChange.fire()); this.on('data', e => this._onInput.fire(e)); - this.on('scroll', e => this._onScroll.fire(e)); this.on('refresh', e => this._onRender.fire(e)); // TODO: Remove these in v4 @@ -272,6 +271,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II this.onKey(e => this.emit('key', e.key, e.domEvent)); this.onLineFeed(() => this.emit('linefeed')); this.onResize(e => this.emit('resize', e)); + this.onScroll(e => this.emit('scroll', e)); this.onTitleChange(e => this.emit('title', e)); } @@ -740,7 +740,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II this._mouseZoneManager = new MouseZoneManager(this); this.register(this._mouseZoneManager); - this.register(this.addDisposableListener('scroll', () => this._mouseZoneManager.clearAll())); + this.register(this.onScroll(() => this._mouseZoneManager.clearAll())); this.linkifier.attachToDom(this._mouseZoneManager); this.textarea = document.createElement('textarea'); @@ -795,7 +795,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II this.textarea.focus(); this.textarea.select(); })); - this.register(this.addDisposableListener('scroll', () => { + this.register(this.onScroll(() => { this.viewport.syncScrollArea(); this.selectionManager.refresh(); })); @@ -1302,13 +1302,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II this.updateRange(this.buffer.scrollTop); this.updateRange(this.buffer.scrollBottom); - /** - * This event is emitted whenever the terminal is scrolled. - * The one parameter passed is the new y display position. - * - * @event scroll - */ - this.emit('scroll', this.buffer.ydisp); + this._onScroll.fire(this.buffer.ydisp); } /** @@ -1337,7 +1331,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II } if (!suppressScrollEvent) { - this.emit('scroll', this.buffer.ydisp); + this._onScroll.fire(this.buffer.ydisp); } this.refresh(0, this.rows - 1); @@ -1825,7 +1819,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II this.buffer.lines.push(this.buffer.getBlankLine(DEFAULT_ATTR_DATA)); } this.refresh(0, this.rows - 1); - this.emit('scroll', this.buffer.ydisp); + this._onScroll.fire(this.buffer.ydisp); } /**