From 8aa296933d2415601a6e95d53964ea6b71211f77 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 13 Jul 2019 17:48:57 -0700 Subject: [PATCH] Break Viewport's dependency on ITerminal --- src/Terminal.ts | 13 +++++++++--- src/TestUtils.test.ts | 4 ++-- src/Types.d.ts | 12 +---------- src/Viewport.ts | 46 +++++++++++++++++++----------------------- src/browser/Types.d.ts | 10 +++++++++ 5 files changed, 44 insertions(+), 41 deletions(-) diff --git a/src/Terminal.ts b/src/Terminal.ts index ef231b5d..75537ab4 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -21,7 +21,7 @@ * http://linux.die.net/man/7/urxvt */ -import { IInputHandlingTerminal, IViewport, ICompositionHelper, ITerminalOptions, ITerminal, IBrowser, CustomKeyEventHandler } from './Types'; +import { IInputHandlingTerminal, ICompositionHelper, ITerminalOptions, ITerminal, IBrowser, CustomKeyEventHandler } from './Types'; import { IRenderer, CharacterJoinerHandler } from 'browser/renderer/Types'; import { CompositionHelper } from 'browser/input/CompositionHelper'; import { Viewport } from './Viewport'; @@ -59,7 +59,7 @@ import { MouseService } from 'browser/services/MouseService'; import { IParams } from 'common/parser/Types'; import { CoreService } from 'common/services/CoreService'; import { LogService } from 'common/services/LogService'; -import { ILinkifier, IMouseZoneManager, LinkMatcherHandler, ILinkMatcherOptions } from 'browser/Types'; +import { ILinkifier, IMouseZoneManager, LinkMatcherHandler, ILinkMatcherOptions, IViewport } from 'browser/Types'; // Let it work inside Node.js for automated testing purposes. const document = (typeof window !== 'undefined') ? window.document : null; @@ -599,7 +599,14 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp this._soundService = new SoundService(this.optionsService); this._mouseService = new MouseService(this._renderService, this._charSizeService); - this.viewport = new Viewport(this, this._viewportElement, this._viewportScrollArea, this._renderService.dimensions, this._charSizeService); + this.viewport = new Viewport( + (amount: number, suppressEvent: boolean) => this.scrollLines(amount, suppressEvent), + this._viewportElement, + this._viewportScrollArea, + this._bufferService, + this._charSizeService, + this._renderService + ); this.viewport.onThemeChange(this._colorManager.colors); this.register(this.viewport); diff --git a/src/TestUtils.test.ts b/src/TestUtils.test.ts index 195321a2..0ee948d5 100644 --- a/src/TestUtils.test.ts +++ b/src/TestUtils.test.ts @@ -4,7 +4,7 @@ */ import { IRenderer, IRenderDimensions, CharacterJoinerHandler } from 'browser/renderer/Types'; -import { IInputHandlingTerminal, IViewport, ICompositionHelper, ITerminal, IBrowser, ITerminalOptions } from './Types'; +import { IInputHandlingTerminal, ICompositionHelper, ITerminal, IBrowser, ITerminalOptions } from './Types'; import { IBuffer, IBufferStringIterator, IBufferSet } from 'common/buffer/Types'; import { IBufferLine, ICellData, IAttributeData, ICircularList, XtermListener, ICharset } from 'common/Types'; import { Buffer } from 'common/buffer/Buffer'; @@ -12,7 +12,7 @@ import * as Browser from 'common/Platform'; import { IDisposable, IMarker, IEvent, ISelectionPosition } from 'xterm'; import { Terminal } from './Terminal'; import { AttributeData } from 'common/buffer/AttributeData'; -import { IColorManager, IColorSet, ILinkMatcherOptions, ILinkifier } from 'browser/Types'; +import { IColorManager, IColorSet, ILinkMatcherOptions, ILinkifier, IViewport } from 'browser/Types'; import { IOptionsService } from 'common/services/Services'; import { EventEmitter } from 'common/EventEmitter'; import { IParams } from 'common/parser/Types'; diff --git a/src/Types.d.ts b/src/Types.d.ts index 1a647927..124aa428 100644 --- a/src/Types.d.ts +++ b/src/Types.d.ts @@ -6,7 +6,7 @@ import { ITerminalOptions as IPublicTerminalOptions, IDisposable, IMarker, ISelectionPosition } from 'xterm'; import { ICharset, IAttributeData, CharData } from 'common/Types'; import { IEvent, IEventEmitter } from 'common/EventEmitter'; -import { IColorSet, ILinkifier, ILinkMatcherOptions } from 'browser/Types'; +import { IColorSet, ILinkifier, ILinkMatcherOptions, IViewport } from 'browser/Types'; import { IOptionsService } from 'common/services/Services'; import { IBuffer, IBufferSet } from 'common/buffer/Types'; import { IParams } from 'common/parser/Types'; @@ -68,16 +68,6 @@ export interface IInputHandlingTerminal { handleTitle(title: string): void; } -export interface IViewport extends IDisposable { - scrollBarWidth: number; - syncScrollArea(): void; - getLinesScrolled(ev: WheelEvent): number; - onWheel(ev: WheelEvent): void; - onTouchStart(ev: TouchEvent): void; - onTouchMove(ev: TouchEvent): void; - onThemeChange(colors: IColorSet): void; -} - export interface ICompositionHelper { compositionstart(): void; compositionupdate(ev: CompositionEvent): void; diff --git a/src/Viewport.ts b/src/Viewport.ts index cd5a282c..b2fd4e68 100644 --- a/src/Viewport.ts +++ b/src/Viewport.ts @@ -3,12 +3,11 @@ * @license MIT */ -import { ITerminal, IViewport } from './Types'; import { Disposable } from 'common/Lifecycle'; import { addDisposableDomListener } from 'browser/Lifecycle'; -import { IColorSet } from 'browser/Types'; -import { IRenderDimensions } from 'browser/renderer/Types'; -import { ICharSizeService } from 'browser/services/Services'; +import { IColorSet, IViewport } from 'browser/Types'; +import { ICharSizeService, IRenderService } from 'browser/services/Services'; +import { IBufferService } from 'common/services/Services'; const FALLBACK_SCROLL_BAR_WIDTH = 15; @@ -34,11 +33,12 @@ export class Viewport extends Disposable implements IViewport { private _ignoreNextScrollEvent: boolean = false; constructor( - private _terminal: ITerminal, - private _viewportElement: HTMLElement, - private _scrollArea: HTMLElement, - private _dimensions: IRenderDimensions, - private _charSizeService: ICharSizeService + private readonly _scrollLines: (amount: number, suppressEvent: boolean) => void, + private readonly _viewportElement: HTMLElement, + private readonly _scrollArea: HTMLElement, + private readonly _bufferService: IBufferService, + private readonly _charSizeService: ICharSizeService, + private readonly _renderService: IRenderService ) { super(); @@ -52,10 +52,6 @@ export class Viewport extends Disposable implements IViewport { setTimeout(() => this.syncScrollArea(), 0); } - public onDimensionsChance(dimensions: IRenderDimensions): void { - this._dimensions = dimensions; - } - public onThemeChange(colors: IColorSet): void { this._viewportElement.style.backgroundColor = colors.background.css; } @@ -72,9 +68,9 @@ export class Viewport extends Disposable implements IViewport { private _innerRefresh(): void { if (this._charSizeService.height > 0) { - this._currentRowHeight = this._dimensions.scaledCellHeight / window.devicePixelRatio; + this._currentRowHeight = this._renderService.dimensions.scaledCellHeight / window.devicePixelRatio; this._lastRecordedViewportHeight = this._viewportElement.offsetHeight; - const newBufferHeight = Math.round(this._currentRowHeight * this._lastRecordedBufferLength) + (this._lastRecordedViewportHeight - this._dimensions.canvasHeight); + const newBufferHeight = Math.round(this._currentRowHeight * this._lastRecordedBufferLength) + (this._lastRecordedViewportHeight - this._renderService.dimensions.canvasHeight); if (this._lastRecordedBufferHeight !== newBufferHeight) { this._lastRecordedBufferHeight = newBufferHeight; this._scrollArea.style.height = this._lastRecordedBufferHeight + 'px'; @@ -82,7 +78,7 @@ export class Viewport extends Disposable implements IViewport { } // Sync scrollTop - const scrollTop = this._terminal.buffer.ydisp * this._currentRowHeight; + const scrollTop = this._bufferService.buffer.ydisp * this._currentRowHeight; if (this._viewportElement.scrollTop !== scrollTop) { // Ignore the next scroll event which will be triggered by setting the scrollTop as we do not // want this event to scroll the terminal @@ -98,20 +94,20 @@ export class Viewport extends Disposable implements IViewport { */ public syncScrollArea(): void { // If buffer height changed - if (this._lastRecordedBufferLength !== this._terminal.buffer.lines.length) { - this._lastRecordedBufferLength = this._terminal.buffer.lines.length; + if (this._lastRecordedBufferLength !== this._bufferService.buffer.lines.length) { + this._lastRecordedBufferLength = this._bufferService.buffer.lines.length; this._refresh(); return; } // If viewport height changed - if (this._lastRecordedViewportHeight !== this._dimensions.canvasHeight) { + if (this._lastRecordedViewportHeight !== this._renderService.dimensions.canvasHeight) { this._refresh(); return; } // If the buffer position doesn't match last scroll top - const newScrollTop = this._terminal.buffer.ydisp * this._currentRowHeight; + const newScrollTop = this._bufferService.buffer.ydisp * this._currentRowHeight; if (this._lastScrollTop !== newScrollTop) { this._refresh(); return; @@ -124,7 +120,7 @@ export class Viewport extends Disposable implements IViewport { } // If row height changed - if (this._dimensions.scaledCellHeight / window.devicePixelRatio !== this._currentRowHeight) { + if (this._renderService.dimensions.scaledCellHeight / window.devicePixelRatio !== this._currentRowHeight) { this._refresh(); return; } @@ -152,8 +148,8 @@ export class Viewport extends Disposable implements IViewport { } const newRow = Math.round(this._lastScrollTop / this._currentRowHeight); - const diff = newRow - this._terminal.buffer.ydisp; - this._terminal.scrollLines(diff, true); + const diff = newRow - this._bufferService.buffer.ydisp; + this._scrollLines(diff, true); } /** @@ -183,7 +179,7 @@ export class Viewport extends Disposable implements IViewport { if (ev.deltaMode === WheelEvent.DOM_DELTA_LINE) { amount *= this._currentRowHeight; } else if (ev.deltaMode === WheelEvent.DOM_DELTA_PAGE) { - amount *= this._currentRowHeight * this._terminal.rows; + amount *= this._currentRowHeight * this._bufferService.rows; } return amount; } @@ -207,7 +203,7 @@ export class Viewport extends Disposable implements IViewport { amount = Math.floor(Math.abs(this._wheelPartialScroll)) * (this._wheelPartialScroll > 0 ? 1 : -1); this._wheelPartialScroll %= 1; } else if (ev.deltaMode === WheelEvent.DOM_DELTA_PAGE) { - amount *= this._terminal.rows; + amount *= this._bufferService.rows; } return amount; } diff --git a/src/browser/Types.d.ts b/src/browser/Types.d.ts index 985244b3..c9167316 100644 --- a/src/browser/Types.d.ts +++ b/src/browser/Types.d.ts @@ -24,6 +24,16 @@ export interface IColorSet { ansi: IColor[]; } +export interface IViewport extends IDisposable { + scrollBarWidth: number; + syncScrollArea(): void; + getLinesScrolled(ev: WheelEvent): number; + onWheel(ev: WheelEvent): void; + onTouchStart(ev: TouchEvent): void; + onTouchMove(ev: TouchEvent): void; + onThemeChange(colors: IColorSet): void; +} + export type LinkMatcherHandler = (event: MouseEvent, uri: string) => void; export type LinkMatcherValidationCallback = (uri: string, callback: (isValid: boolean) => void) => void;