mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
Merge pull request #3205 from schrej/fix/scroll-events
emit onScroll events when user is scrolling
This commit is contained in:
@@ -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 });
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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 });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vendored
+10
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user