Merge pull request #3205 from schrej/fix/scroll-events

emit onScroll events when user is scrolling
This commit is contained in:
Daniel Imms
2021-04-01 12:11:47 -07:00
committed by GitHub
4 changed files with 43 additions and 18 deletions
+9 -7
View File
@@ -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, IAnsiColorChangeEvent } from 'common/Types';
import { IKeyboardEvent, KeyboardResultType, CoreMouseEventType, CoreMouseButton, CoreMouseAction, ITerminalOptions, ScrollSource, IAnsiColorChangeEvent } from 'common/Types';
import { evaluateKeyboardEvent } from 'common/input/Keyboard';
import { EventEmitter, IEvent, forwardEvent } from 'common/EventEmitter';
import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine';
@@ -470,7 +470,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) => this.scrollLines(amount, false, ScrollSource.VIEWPORT),
this._viewportElement,
this._viewportScrollArea
);
@@ -504,8 +504,10 @@ export class Terminal extends CoreTerminal implements ITerminal {
this.textarea!.focus();
this.textarea!.select();
}));
this.register(this.onScroll(() => {
this.viewport!.syncScrollArea();
this.register(this._onScroll.event(ev => {
if (ev.source !== ScrollSource.VIEWPORT) {
this.viewport!.syncScrollArea();
}
this._selectionService!.refresh();
}));
this.register(addDisposableDomListener(this._viewportElement, 'scroll', () => this._selectionService!.refresh()));
@@ -860,8 +862,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);
}
@@ -1192,7 +1194,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 });
}
/**
+2 -2
View File
@@ -33,7 +33,7 @@ export class Viewport extends Disposable implements IViewport {
private _ignoreNextScrollEvent: boolean = false;
constructor(
private readonly _scrollLines: (amount: number, suppressEvent: boolean) => void,
private readonly _scrollLines: (amount: number) => void,
private readonly _viewportElement: HTMLElement,
private readonly _scrollArea: HTMLElement,
@IBufferService private readonly _bufferService: IBufferService,
@@ -156,7 +156,7 @@ export class Viewport extends Disposable implements IViewport {
const newRow = Math.round(this._lastScrollTop / this._currentRowHeight);
const diff = newRow - this._bufferService.buffer.ydisp;
this._scrollLines(diff, true);
this._scrollLines(diff);
}
/**
+22 -9
View File
@@ -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';
@@ -69,8 +69,21 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
public get onLineFeed(): IEvent<void> { 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<number>();
public get onScroll(): IEvent<number> { return this._onScroll.event; }
protected _onScroll = new EventEmitter<IScrollEvent, void>();
/**
* Internally we track the source of the scroll but this is meaningless outside the library so
* it's filtered out.
*/
protected _onScrollApi?: EventEmitter<number, void>;
public get onScroll(): IEvent<number, void> {
if (!this._onScrollApi) {
this._onScrollApi = new EventEmitter<number, void>();
this.register(this._onScroll.event(ev => {
this._onScrollApi?.fire(ev.position);
}));
}
return this._onScrollApi.event;
}
public get cols(): number { return this._bufferService.cols; }
public get rows(): number { return this._bufferService.rows; }
@@ -220,17 +233,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) {
@@ -250,7 +263,7 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
}
if (!suppressScrollEvent) {
this._onScroll.fire(buffer.ydisp);
this._onScroll.fire({ position: buffer.ydisp, source });
}
}
+10
View File
@@ -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<T> {
length: number;
maxLength: number;