From 8b2b0f6abc44a53f7434620bba1103df69e37d27 Mon Sep 17 00:00:00 2001 From: Jakob Schrettenbrunner Date: Tue, 12 Jan 2021 22:32:20 +0000 Subject: [PATCH] add richer ScrollEvent that includes the source --- src/browser/Terminal.ts | 12 ++++++------ src/common/CoreTerminal.ts | 32 +++++++++++++++++++++++--------- src/common/Types.d.ts | 10 ++++++++++ 3 files changed, 39 insertions(+), 15 deletions(-) diff --git a/src/browser/Terminal.ts b/src/browser/Terminal.ts index f8b8b3e4..b507a6b1 100644 --- a/src/browser/Terminal.ts +++ b/src/browser/Terminal.ts @@ -39,7 +39,7 @@ import { MouseZoneManager } from 'browser/MouseZoneManager'; import { AccessibilityManager } from './AccessibilityManager'; import { ITheme, IMarker, IDisposable, ISelectionPosition, ILinkProvider } from 'xterm'; import { DomRenderer } from 'browser/renderer/dom/DomRenderer'; -import { IKeyboardEvent, KeyboardResultType, CoreMouseEventType, CoreMouseButton, CoreMouseAction, ITerminalOptions } from 'common/Types'; +import { IKeyboardEvent, KeyboardResultType, CoreMouseEventType, CoreMouseButton, CoreMouseAction, ITerminalOptions, ScrollSource } from 'common/Types'; import { evaluateKeyboardEvent } from 'common/input/Keyboard'; import { EventEmitter, IEvent, forwardEvent } from 'common/EventEmitter'; import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine'; @@ -448,7 +448,7 @@ export class Terminal extends CoreTerminal implements ITerminal { this._instantiationService.setService(IMouseService, this._mouseService); this.viewport = this._instantiationService.createInstance(Viewport, - (amount: number, suppressEvent: boolean) => this.scrollLines(amount, suppressEvent), + (amount: number, suppressEvent: boolean) => this.scrollLines(amount, suppressEvent, ScrollSource.VIEWPORT), this._viewportElement, this._viewportScrollArea ); @@ -481,7 +481,7 @@ export class Terminal extends CoreTerminal implements ITerminal { this.textarea!.select(); })); this.register(this.onScroll(() => { - this.viewport!.syncScrollArea(); + this.viewport!.syncScrollArea(); this._selectionService!.refresh(); })); this.register(addDisposableDomListener(this._viewportElement, 'scroll', () => this._selectionService!.refresh())); @@ -836,8 +836,8 @@ export class Terminal extends CoreTerminal implements ITerminal { } } - public scrollLines(disp: number, suppressScrollEvent?: boolean): void { - super.scrollLines(disp, suppressScrollEvent); + public scrollLines(disp: number, suppressScrollEvent?: boolean, source = ScrollSource.TERMINAL): void { + super.scrollLines(disp, suppressScrollEvent, source); this.refresh(0, this.rows - 1); } @@ -1168,7 +1168,7 @@ export class Terminal extends CoreTerminal implements ITerminal { this.buffer.lines.push(this.buffer.getBlankLine(DEFAULT_ATTR_DATA)); } this.refresh(0, this.rows - 1); - this._onScroll.fire(this.buffer.ydisp); + this._onScroll.fire({position: this.buffer.ydisp, source: ScrollSource.TERMINAL }); } /** diff --git a/src/common/CoreTerminal.ts b/src/common/CoreTerminal.ts index 2f636349..86492ab3 100644 --- a/src/common/CoreTerminal.ts +++ b/src/common/CoreTerminal.ts @@ -27,7 +27,7 @@ import { InstantiationService } from 'common/services/InstantiationService'; import { LogService } from 'common/services/LogService'; import { BufferService, MINIMUM_COLS, MINIMUM_ROWS } from 'common/services/BufferService'; import { OptionsService } from 'common/services/OptionsService'; -import { ITerminalOptions, IDisposable, IBufferLine, IAttributeData, ICoreTerminal } from 'common/Types'; +import { ITerminalOptions, IDisposable, IBufferLine, IAttributeData, ICoreTerminal, IKeyboardEvent, IScrollEvent, ScrollSource } from 'common/Types'; import { CoreService } from 'common/services/CoreService'; import { EventEmitter, IEvent, forwardEvent } from 'common/EventEmitter'; import { CoreMouseService } from 'common/services/CoreMouseService'; @@ -66,8 +66,12 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal { public get onLineFeed(): IEvent { return this._onLineFeed.event; } private _onResize = new EventEmitter<{ cols: number, rows: number }>(); public get onResize(): IEvent<{ cols: number, rows: number }> { return this._onResize.event; } - protected _onScroll = new EventEmitter(); - public get onScroll(): IEvent { return this._onScroll.event; } + protected _onScroll = new EventEmitter(); + /** + * An emitter for legacy on scroll events that just included the position, and not the source. + * Used to maintain API consistency for the onScroll method. + */ + protected _legacyOnScroll?: EventEmitter; public get cols(): number { return this._bufferService.cols; } public get rows(): number { return this._bufferService.rows; } @@ -204,17 +208,17 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal { // Flag rows that need updating this._dirtyRowService.markRangeDirty(buffer.scrollTop, buffer.scrollBottom); - this._onScroll.fire(buffer.ydisp); + this._onScroll.fire({position: buffer.ydisp, source: ScrollSource.TERMINAL}); } /** * Scroll the display of the terminal * @param disp The number of lines to scroll down (negative scroll up). - * @param suppressScrollEvent Don't emit the scroll event as scrollLines. This is used - * to avoid unwanted events being handled by the viewport when the event was triggered from the - * viewport originally. + * @param suppressScrollEvent Don't emit an onScroll event. + * @param source The source of the scroll action. Emitted as part of the onScroll event + * to avoid cyclic invocations if the event originated from the Viewport. */ - public scrollLines(disp: number, suppressScrollEvent?: boolean): void { + public scrollLines(disp: number, suppressScrollEvent = false, source = ScrollSource.TERMINAL): void { const buffer = this._bufferService.buffer; if (disp < 0) { if (buffer.ydisp === 0) { @@ -234,7 +238,7 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal { } if (!suppressScrollEvent) { - this._onScroll.fire(buffer.ydisp); + this._onScroll.fire({position: buffer.ydisp, source}); } } @@ -267,6 +271,16 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal { } } + public get onScroll(): IEvent { + if (!this._legacyOnScroll) { + this._legacyOnScroll = new EventEmitter(); + this.register(this._onScroll.event(ev => { + this._legacyOnScroll?.fire(ev.position); + })); + } + return this._legacyOnScroll.event; + } + /** Add handler for ESC escape sequence. See xterm.d.ts for details. */ public addEscHandler(id: IFunctionIdentifier, callback: () => boolean): IDisposable { return this._inputHandler.addEscHandler(id, callback); diff --git a/src/common/Types.d.ts b/src/common/Types.d.ts index bd0d11c6..4fff64f5 100644 --- a/src/common/Types.d.ts +++ b/src/common/Types.d.ts @@ -42,6 +42,16 @@ export interface IKeyboardEvent { type: string; } +export interface IScrollEvent { + position: number; + source: ScrollSource; +} + +export const enum ScrollSource { + TERMINAL, + VIEWPORT, +} + export interface ICircularList { length: number; maxLength: number;