Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add smoothScroll to scrollLines #4482

Merged
merged 9 commits into from
Aug 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/browser/Terminal.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { MockViewport, MockCompositionHelper, MockRenderer, TestTerminal } from
import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine';
import { CellData } from 'common/buffer/CellData';
import { MockUnicodeService } from 'common/TestUtils.test';
import { IMarker } from 'common/Types';
import { IMarker, ScrollSource } from 'common/Types';
import { ICoreService } from 'common/services/Services';

const INIT_COLS = 80;
Expand All @@ -29,6 +29,7 @@ describe('Terminal', () => {
term.refresh = () => { };
(term as any).renderer = new MockRenderer();
term.viewport = new MockViewport();
term.viewport.onRequestScrollLines(e => term.scrollLines(e.amount, e.suppressScrollEvent, ScrollSource.VIEWPORT));
(term as any)._compositionHelper = new MockCompositionHelper();
(term as any).element = {
classList: {
Expand Down
17 changes: 9 additions & 8 deletions src/browser/Terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -497,11 +497,8 @@ export class Terminal extends CoreTerminal implements ITerminal {
this._mouseService = this._instantiationService.createInstance(MouseService);
this._instantiationService.setService(IMouseService, this._mouseService);

this.viewport = this._instantiationService.createInstance(Viewport,
(amount: number) => this.scrollLines(amount, true, ScrollSource.VIEWPORT),
this._viewportElement,
this._viewportScrollArea
);
this.viewport = this._instantiationService.createInstance(Viewport, this._viewportElement, this._viewportScrollArea);
this.viewport.onRequestScrollLines(e => this.scrollLines(e.amount, e.suppressScrollEvent, ScrollSource.VIEWPORT)),
this.register(this._inputHandler.onRequestSyncScrollBar(() => this.viewport!.syncScrollArea()));
this.register(this.viewport);

Expand Down Expand Up @@ -870,8 +867,12 @@ export class Terminal extends CoreTerminal implements ITerminal {
}

public scrollLines(disp: number, suppressScrollEvent?: boolean, source = ScrollSource.TERMINAL): void {
Tyriar marked this conversation as resolved.
Show resolved Hide resolved
super.scrollLines(disp, suppressScrollEvent, source);
this.refresh(0, this.rows - 1);
if (source === ScrollSource.VIEWPORT) {
super.scrollLines(disp, suppressScrollEvent, source);
this.refresh(0, this.rows - 1);
} else {
this.viewport?.scrollLines(disp);
}
}

public paste(data: string): void {
Expand Down Expand Up @@ -1003,7 +1004,7 @@ export class Terminal extends CoreTerminal implements ITerminal {

if (!shouldIgnoreComposition && !this._compositionHelper!.keydown(event)) {
if (this.options.scrollOnUserInput && this.buffer.ybase !== this.buffer.ydisp) {
this._bufferService.scrollToBottom();
this.scrollToBottom();
}
return false;
}
Expand Down
5 changes: 5 additions & 0 deletions src/browser/TestUtils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,8 @@ export class MockRenderer implements IRenderer {
}

export class MockViewport implements IViewport {
private readonly _onRequestScrollLines = new EventEmitter<{ amount: number, suppressScrollEvent: boolean }>();
public readonly onRequestScrollLines = this._onRequestScrollLines.event;
public dispose(): void {
throw new Error('Method not implemented.');
}
Expand All @@ -319,6 +321,9 @@ export class MockViewport implements IViewport {
public getBufferElements(startLine: number, endLine?: number | undefined): { bufferElements: HTMLElement[], cursorElement?: HTMLElement | undefined } {
throw new Error('Method not implemented.');
}
public scrollLines(disp: number): void {
this._onRequestScrollLines.fire({ amount: disp, suppressScrollEvent: false });
}
}

export class MockCompositionHelper implements ICompositionHelper {
Expand Down
20 changes: 20 additions & 0 deletions src/browser/Types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,28 @@ export interface IPublicTerminal extends IDisposable {
selectAll(): void;
selectLines(start: number, end: number): void;
dispose(): void;
/**
* Scroll the display of the terminal
* @param amount The number of lines to scroll down (negative scroll up).
*/
scrollLines(amount: number): void;
/**
* Scroll the display of the terminal by a number of pages.
* @param pageCount The number of pages to scroll (negative scrolls up).
*/
scrollPages(pageCount: number): void;
/**
* Scrolls the display of the terminal to the top.
*/
scrollToTop(): void;
/**
* Scrolls the display of the terminal to the bottom.
*/
scrollToBottom(): void;
/**
* Scrolls to a line within the buffer.
* @param line The 0-based line index to scroll to.
*/
scrollToLine(line: number): void;
clear(): void;
write(data: string | Uint8Array, callback?: () => void): void;
Expand Down Expand Up @@ -142,12 +160,14 @@ export interface IPartialColorSet {

export interface IViewport extends IDisposable {
scrollBarWidth: number;
readonly onRequestScrollLines: IEvent<{ amount: number, suppressScrollEvent: boolean }>;
syncScrollArea(immediate?: boolean): void;
getLinesScrolled(ev: WheelEvent): number;
getBufferElements(startLine: number, endLine?: number): { bufferElements: HTMLElement[], cursorElement?: HTMLElement };
handleWheel(ev: WheelEvent): boolean;
handleTouchStart(ev: TouchEvent): void;
handleTouchMove(ev: TouchEvent): boolean;
scrollLines(disp: number): void; // todo api name?
}

export interface ILinkifierEvent {
Expand Down
26 changes: 23 additions & 3 deletions src/browser/Viewport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { ICharSizeService, ICoreBrowserService, IRenderService, IThemeService }
import { IBufferService, IOptionsService } from 'common/services/Services';
import { IBuffer } from 'common/buffer/Types';
import { IRenderDimensions } from 'browser/renderer/shared/Types';
import { EventEmitter } from 'common/EventEmitter';

const FALLBACK_SCROLL_BAR_WIDTH = 15;

Expand Down Expand Up @@ -48,8 +49,10 @@ export class Viewport extends Disposable implements IViewport {
target: -1
};

private readonly _onRequestScrollLines = this.register(new EventEmitter<{ amount: number, suppressScrollEvent: boolean }>());
public readonly onRequestScrollLines = this._onRequestScrollLines.event;

constructor(
private readonly _scrollLines: (amount: number) => void,
private readonly _viewportElement: HTMLElement,
private readonly _scrollArea: HTMLElement,
@IBufferService private readonly _bufferService: IBufferService,
Expand Down Expand Up @@ -175,13 +178,13 @@ export class Viewport extends Disposable implements IViewport {
if (this._ignoreNextScrollEvent) {
this._ignoreNextScrollEvent = false;
// Still trigger the scroll so lines get refreshed
this._scrollLines(0);
this._onRequestScrollLines.fire({ amount: 0, suppressScrollEvent: true });
return;
}

const newRow = Math.round(this._lastScrollTop / this._currentRowHeight);
const diff = newRow - this._bufferService.buffer.ydisp;
this._scrollLines(diff);
this._onRequestScrollLines.fire({ amount: diff, suppressScrollEvent: true });
}

private _smoothScroll(): void {
Expand Down Expand Up @@ -263,6 +266,23 @@ export class Viewport extends Disposable implements IViewport {
return this._bubbleScroll(ev, amount);
}

public scrollLines(disp: number): void {
if (!this._optionsService.rawOptions.smoothScrollDuration) {
this._onRequestScrollLines.fire({ amount: disp, suppressScrollEvent: false });
} else {
const amount = disp * this._currentRowHeight;
this._smoothScrollState.startTime = Date.now();
if (this._smoothScrollPercent() < 1) {
this._smoothScrollState.origin = this._viewportElement.scrollTop;
this._smoothScrollState.target = this._smoothScrollState.origin + amount;
this._smoothScrollState.target = Math.max(Math.min(this._smoothScrollState.target, this._viewportElement.scrollHeight), 0);
this._smoothScroll();
} else {
this._clearSmoothScrollState();
}
}
}

private _getPixelsScrolled(ev: WheelEvent): number {
// Do nothing if it's not a vertical scroll event
if (ev.deltaY === 0 || ev.shiftKey) {
Expand Down
28 changes: 11 additions & 17 deletions src/common/CoreTerminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,38 +195,32 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
/**
* 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 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 source Which component the event came from.
*/
public scrollLines(disp: number, suppressScrollEvent?: boolean, source?: ScrollSource): void {
this._bufferService.scrollLines(disp, suppressScrollEvent, source);
}

/**
* Scroll the display of the terminal by a number of pages.
* @param pageCount The number of pages to scroll (negative scrolls up).
*/
public scrollPages(pageCount: number): void {
this._bufferService.scrollPages(pageCount);
this.scrollLines(pageCount * (this.rows - 1));
}

/**
* Scrolls the display of the terminal to the top.
*/
public scrollToTop(): void {
this._bufferService.scrollToTop();
this.scrollLines(-this._bufferService.buffer.ydisp);
}

/**
* Scrolls the display of the terminal to the bottom.
*/
public scrollToBottom(): void {
this._bufferService.scrollToBottom();
this.scrollLines(this._bufferService.buffer.ybase - this._bufferService.buffer.ydisp);
}

public scrollToLine(line: number): void {
this._bufferService.scrollToLine(line);
const scrollAmount = line - this._bufferService.buffer.ydisp;
if (scrollAmount !== 0) {
this.scrollLines(scrollAmount);
}
}

/** Add handler for ESC escape sequence. See xterm.d.ts for details. */
Expand Down
29 changes: 0 additions & 29 deletions src/common/services/BufferService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,33 +147,4 @@ export class BufferService extends Disposable implements IBufferService {
this._onScroll.fire(buffer.ydisp);
}
}

/**
* Scroll the display of the terminal by a number of pages.
* @param pageCount The number of pages to scroll (negative scrolls up).
*/
public scrollPages(pageCount: number): void {
this.scrollLines(pageCount * (this.rows - 1));
}

/**
* Scrolls the display of the terminal to the top.
*/
public scrollToTop(): void {
this.scrollLines(-this.buffer.ydisp);
}

/**
* Scrolls the display of the terminal to the bottom.
*/
public scrollToBottom(): void {
this.scrollLines(this.buffer.ybase - this.buffer.ydisp);
}

public scrollToLine(line: number): void {
const scrollAmount = line - this.buffer.ydisp;
if (scrollAmount !== 0) {
this.scrollLines(scrollAmount);
}
}
}
4 changes: 0 additions & 4 deletions src/common/services/Services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,7 @@ export interface IBufferService {
onResize: IEvent<{ cols: number, rows: number }>;
onScroll: IEvent<number>;
scroll(eraseAttr: IAttributeData, isWrapped?: boolean): void;
scrollToBottom(): void;
scrollToTop(): void;
scrollToLine(line: number): void;
scrollLines(disp: number, suppressScrollEvent?: boolean, source?: ScrollSource): void;
scrollPages(pageCount: number): void;
resize(cols: number, rows: number): void;
reset(): void;
}
Expand Down