diff --git a/src/browser/scrollable/abstractScrollbar.ts b/src/browser/scrollable/abstractScrollbar.ts index a87d94b6..528ebfee 100644 --- a/src/browser/scrollable/abstractScrollbar.ts +++ b/src/browser/scrollable/abstractScrollbar.ts @@ -20,280 +20,280 @@ import { INewScrollPosition, Scrollable, ScrollbarVisibility } from './scrollabl const POINTER_DRAG_RESET_DISTANCE = 140; export interface ISimplifiedPointerEvent { - buttons: number; - pageX: number; - pageY: number; + buttons: number; + pageX: number; + pageY: number; } export interface ScrollbarHost { - onMouseWheel(mouseWheelEvent: StandardWheelEvent): void; - onDragStart(): void; - onDragEnd(): void; + onMouseWheel(mouseWheelEvent: StandardWheelEvent): void; + onDragStart(): void; + onDragEnd(): void; } export interface AbstractScrollbarOptions { - lazyRender: boolean; - host: ScrollbarHost; - scrollbarState: ScrollbarState; - visibility: ScrollbarVisibility; - extraScrollbarClassName: string; - scrollable: Scrollable; - scrollByPage: boolean; + lazyRender: boolean; + host: ScrollbarHost; + scrollbarState: ScrollbarState; + visibility: ScrollbarVisibility; + extraScrollbarClassName: string; + scrollable: Scrollable; + scrollByPage: boolean; } export abstract class AbstractScrollbar extends Widget { - protected _host: ScrollbarHost; - protected _scrollable: Scrollable; - protected _scrollByPage: boolean; - private _lazyRender: boolean; - protected _scrollbarState: ScrollbarState; - protected _visibilityController: ScrollbarVisibilityController; - private _pointerMoveMonitor: GlobalPointerMoveMonitor; + protected _host: ScrollbarHost; + protected _scrollable: Scrollable; + protected _scrollByPage: boolean; + private _lazyRender: boolean; + protected _scrollbarState: ScrollbarState; + protected _visibilityController: ScrollbarVisibilityController; + private _pointerMoveMonitor: GlobalPointerMoveMonitor; - public domNode: FastDomNode; - public slider!: FastDomNode; + public domNode: FastDomNode; + public slider!: FastDomNode; - protected _shouldRender: boolean; + protected _shouldRender: boolean; - constructor(opts: AbstractScrollbarOptions) { - super(); - this._lazyRender = opts.lazyRender; - this._host = opts.host; - this._scrollable = opts.scrollable; - this._scrollByPage = opts.scrollByPage; - this._scrollbarState = opts.scrollbarState; - this._visibilityController = this._register(new ScrollbarVisibilityController(opts.visibility, 'visible scrollbar ' + opts.extraScrollbarClassName, 'invisible scrollbar ' + opts.extraScrollbarClassName)); - this._visibilityController.setIsNeeded(this._scrollbarState.isNeeded()); - this._pointerMoveMonitor = this._register(new GlobalPointerMoveMonitor()); - this._shouldRender = true; - this.domNode = createFastDomNode(document.createElement('div')); - this.domNode.setAttribute('role', 'presentation'); - this.domNode.setAttribute('aria-hidden', 'true'); + constructor(opts: AbstractScrollbarOptions) { + super(); + this._lazyRender = opts.lazyRender; + this._host = opts.host; + this._scrollable = opts.scrollable; + this._scrollByPage = opts.scrollByPage; + this._scrollbarState = opts.scrollbarState; + this._visibilityController = this._register(new ScrollbarVisibilityController(opts.visibility, 'visible scrollbar ' + opts.extraScrollbarClassName, 'invisible scrollbar ' + opts.extraScrollbarClassName)); + this._visibilityController.setIsNeeded(this._scrollbarState.isNeeded()); + this._pointerMoveMonitor = this._register(new GlobalPointerMoveMonitor()); + this._shouldRender = true; + this.domNode = createFastDomNode(document.createElement('div')); + this.domNode.setAttribute('role', 'presentation'); + this.domNode.setAttribute('aria-hidden', 'true'); - this._visibilityController.setDomNode(this.domNode); - this.domNode.setPosition('absolute'); + this._visibilityController.setDomNode(this.domNode); + this.domNode.setPosition('absolute'); - this._register(dom.addDisposableListener(this.domNode.domNode, dom.EventType.POINTER_DOWN, (e: PointerEvent) => this._domNodePointerDown(e))); - } + this._register(dom.addDisposableListener(this.domNode.domNode, dom.EventType.POINTER_DOWN, (e: PointerEvent) => this._domNodePointerDown(e))); + } - // ----------------- creation + // ----------------- creation - /** - * Creates the dom node for an arrow & adds it to the container - */ - protected _createArrow(opts: ScrollbarArrowOptions): void { - const arrow = this._register(new ScrollbarArrow(opts)); - this.domNode.domNode.appendChild(arrow.bgDomNode); - this.domNode.domNode.appendChild(arrow.domNode); - } + /** + * Creates the dom node for an arrow & adds it to the container + */ + protected _createArrow(opts: ScrollbarArrowOptions): void { + const arrow = this._register(new ScrollbarArrow(opts)); + this.domNode.domNode.appendChild(arrow.bgDomNode); + this.domNode.domNode.appendChild(arrow.domNode); + } - /** - * Creates the slider dom node, adds it to the container & hooks up the events - */ - protected _createSlider(top: number, left: number, width: number | undefined, height: number | undefined): void { - this.slider = createFastDomNode(document.createElement('div')); - this.slider.setClassName('slider'); - this.slider.setPosition('absolute'); - this.slider.setTop(top); - this.slider.setLeft(left); - if (typeof width === 'number') { - this.slider.setWidth(width); - } - if (typeof height === 'number') { - this.slider.setHeight(height); - } - this.slider.setLayerHinting(true); - this.slider.setContain('strict'); + /** + * Creates the slider dom node, adds it to the container & hooks up the events + */ + protected _createSlider(top: number, left: number, width: number | undefined, height: number | undefined): void { + this.slider = createFastDomNode(document.createElement('div')); + this.slider.setClassName('slider'); + this.slider.setPosition('absolute'); + this.slider.setTop(top); + this.slider.setLeft(left); + if (typeof width === 'number') { + this.slider.setWidth(width); + } + if (typeof height === 'number') { + this.slider.setHeight(height); + } + this.slider.setLayerHinting(true); + this.slider.setContain('strict'); - this.domNode.domNode.appendChild(this.slider.domNode); + this.domNode.domNode.appendChild(this.slider.domNode); - this._register(dom.addDisposableListener( - this.slider.domNode, - dom.EventType.POINTER_DOWN, - (e: PointerEvent) => { - if (e.button === 0) { - e.preventDefault(); - this._sliderPointerDown(e); - } - } - )); + this._register(dom.addDisposableListener( + this.slider.domNode, + dom.EventType.POINTER_DOWN, + (e: PointerEvent) => { + if (e.button === 0) { + e.preventDefault(); + this._sliderPointerDown(e); + } + } + )); - this.onclick(this.slider.domNode, e => { - if (e.leftButton) { - e.stopPropagation(); - } - }); - } + this.onclick(this.slider.domNode, e => { + if (e.leftButton) { + e.stopPropagation(); + } + }); + } - // ----------------- Update state + // ----------------- Update state - protected _onElementSize(visibleSize: number): boolean { - if (this._scrollbarState.setVisibleSize(visibleSize)) { - this._visibilityController.setIsNeeded(this._scrollbarState.isNeeded()); - this._shouldRender = true; - if (!this._lazyRender) { - this.render(); - } - } - return this._shouldRender; - } + protected _onElementSize(visibleSize: number): boolean { + if (this._scrollbarState.setVisibleSize(visibleSize)) { + this._visibilityController.setIsNeeded(this._scrollbarState.isNeeded()); + this._shouldRender = true; + if (!this._lazyRender) { + this.render(); + } + } + return this._shouldRender; + } - protected _onElementScrollSize(elementScrollSize: number): boolean { - if (this._scrollbarState.setScrollSize(elementScrollSize)) { - this._visibilityController.setIsNeeded(this._scrollbarState.isNeeded()); - this._shouldRender = true; - if (!this._lazyRender) { - this.render(); - } - } - return this._shouldRender; - } + protected _onElementScrollSize(elementScrollSize: number): boolean { + if (this._scrollbarState.setScrollSize(elementScrollSize)) { + this._visibilityController.setIsNeeded(this._scrollbarState.isNeeded()); + this._shouldRender = true; + if (!this._lazyRender) { + this.render(); + } + } + return this._shouldRender; + } - protected _onElementScrollPosition(elementScrollPosition: number): boolean { - if (this._scrollbarState.setScrollPosition(elementScrollPosition)) { - this._visibilityController.setIsNeeded(this._scrollbarState.isNeeded()); - this._shouldRender = true; - if (!this._lazyRender) { - this.render(); - } - } - return this._shouldRender; - } + protected _onElementScrollPosition(elementScrollPosition: number): boolean { + if (this._scrollbarState.setScrollPosition(elementScrollPosition)) { + this._visibilityController.setIsNeeded(this._scrollbarState.isNeeded()); + this._shouldRender = true; + if (!this._lazyRender) { + this.render(); + } + } + return this._shouldRender; + } - // ----------------- rendering + // ----------------- rendering - public beginReveal(): void { - this._visibilityController.setShouldBeVisible(true); - } + public beginReveal(): void { + this._visibilityController.setShouldBeVisible(true); + } - public beginHide(): void { - this._visibilityController.setShouldBeVisible(false); - } + public beginHide(): void { + this._visibilityController.setShouldBeVisible(false); + } - public render(): void { - if (!this._shouldRender) { - return; - } - this._shouldRender = false; + public render(): void { + if (!this._shouldRender) { + return; + } + this._shouldRender = false; - this._renderDomNode(this._scrollbarState.getRectangleLargeSize(), this._scrollbarState.getRectangleSmallSize()); - this._updateSlider(this._scrollbarState.getSliderSize(), this._scrollbarState.getArrowSize() + this._scrollbarState.getSliderPosition()); - } - // ----------------- DOM events + this._renderDomNode(this._scrollbarState.getRectangleLargeSize(), this._scrollbarState.getRectangleSmallSize()); + this._updateSlider(this._scrollbarState.getSliderSize(), this._scrollbarState.getArrowSize() + this._scrollbarState.getSliderPosition()); + } + // ----------------- DOM events - private _domNodePointerDown(e: PointerEvent): void { - if (e.target !== this.domNode.domNode) { - return; - } - this._onPointerDown(e); - } + private _domNodePointerDown(e: PointerEvent): void { + if (e.target !== this.domNode.domNode) { + return; + } + this._onPointerDown(e); + } - public delegatePointerDown(e: PointerEvent): void { - const domTop = this.domNode.domNode.getClientRects()[0].top; - const sliderStart = domTop + this._scrollbarState.getSliderPosition(); - const sliderStop = domTop + this._scrollbarState.getSliderPosition() + this._scrollbarState.getSliderSize(); - const pointerPos = this._sliderPointerPosition(e); - if (sliderStart <= pointerPos && pointerPos <= sliderStop) { - if (e.button === 0) { - e.preventDefault(); - this._sliderPointerDown(e); - } - } else { - this._onPointerDown(e); - } - } + public delegatePointerDown(e: PointerEvent): void { + const domTop = this.domNode.domNode.getClientRects()[0].top; + const sliderStart = domTop + this._scrollbarState.getSliderPosition(); + const sliderStop = domTop + this._scrollbarState.getSliderPosition() + this._scrollbarState.getSliderSize(); + const pointerPos = this._sliderPointerPosition(e); + if (sliderStart <= pointerPos && pointerPos <= sliderStop) { + if (e.button === 0) { + e.preventDefault(); + this._sliderPointerDown(e); + } + } else { + this._onPointerDown(e); + } + } - private _onPointerDown(e: PointerEvent): void { - let offsetX: number; - let offsetY: number; - if (e.target === this.domNode.domNode && typeof e.offsetX === 'number' && typeof e.offsetY === 'number') { - offsetX = e.offsetX; - offsetY = e.offsetY; - } else { - const domNodePosition = dom.getDomNodePagePosition(this.domNode.domNode); - offsetX = e.pageX - domNodePosition.left; - offsetY = e.pageY - domNodePosition.top; - } + private _onPointerDown(e: PointerEvent): void { + let offsetX: number; + let offsetY: number; + if (e.target === this.domNode.domNode && typeof e.offsetX === 'number' && typeof e.offsetY === 'number') { + offsetX = e.offsetX; + offsetY = e.offsetY; + } else { + const domNodePosition = dom.getDomNodePagePosition(this.domNode.domNode); + offsetX = e.pageX - domNodePosition.left; + offsetY = e.pageY - domNodePosition.top; + } - const offset = this._pointerDownRelativePosition(offsetX, offsetY); - this._setDesiredScrollPositionNow( - this._scrollByPage - ? this._scrollbarState.getDesiredScrollPositionFromOffsetPaged(offset) - : this._scrollbarState.getDesiredScrollPositionFromOffset(offset) - ); + const offset = this._pointerDownRelativePosition(offsetX, offsetY); + this._setDesiredScrollPositionNow( + this._scrollByPage + ? this._scrollbarState.getDesiredScrollPositionFromOffsetPaged(offset) + : this._scrollbarState.getDesiredScrollPositionFromOffset(offset) + ); - if (e.button === 0) { - e.preventDefault(); - this._sliderPointerDown(e); - } - } + if (e.button === 0) { + e.preventDefault(); + this._sliderPointerDown(e); + } + } - private _sliderPointerDown(e: PointerEvent): void { - if (!e.target || !(e.target instanceof Element)) { - return; - } - const initialPointerPosition = this._sliderPointerPosition(e); - const initialPointerOrthogonalPosition = this._sliderOrthogonalPointerPosition(e); - const initialScrollbarState = this._scrollbarState.clone(); - this.slider.toggleClassName('active', true); + private _sliderPointerDown(e: PointerEvent): void { + if (!e.target || !(e.target instanceof Element)) { + return; + } + const initialPointerPosition = this._sliderPointerPosition(e); + const initialPointerOrthogonalPosition = this._sliderOrthogonalPointerPosition(e); + const initialScrollbarState = this._scrollbarState.clone(); + this.slider.toggleClassName('active', true); - this._pointerMoveMonitor.startMonitoring( - e.target, - e.pointerId, - e.buttons, - (pointerMoveData: PointerEvent) => { - const pointerOrthogonalPosition = this._sliderOrthogonalPointerPosition(pointerMoveData); - const pointerOrthogonalDelta = Math.abs(pointerOrthogonalPosition - initialPointerOrthogonalPosition); + this._pointerMoveMonitor.startMonitoring( + e.target, + e.pointerId, + e.buttons, + (pointerMoveData: PointerEvent) => { + const pointerOrthogonalPosition = this._sliderOrthogonalPointerPosition(pointerMoveData); + const pointerOrthogonalDelta = Math.abs(pointerOrthogonalPosition - initialPointerOrthogonalPosition); - if (platform.isWindows && pointerOrthogonalDelta > POINTER_DRAG_RESET_DISTANCE) { - this._setDesiredScrollPositionNow(initialScrollbarState.getScrollPosition()); - return; - } + if (platform.isWindows && pointerOrthogonalDelta > POINTER_DRAG_RESET_DISTANCE) { + this._setDesiredScrollPositionNow(initialScrollbarState.getScrollPosition()); + return; + } - const pointerPosition = this._sliderPointerPosition(pointerMoveData); - const pointerDelta = pointerPosition - initialPointerPosition; - this._setDesiredScrollPositionNow(initialScrollbarState.getDesiredScrollPositionFromDelta(pointerDelta)); - }, - () => { - this.slider.toggleClassName('active', false); - this._host.onDragEnd(); - } - ); + const pointerPosition = this._sliderPointerPosition(pointerMoveData); + const pointerDelta = pointerPosition - initialPointerPosition; + this._setDesiredScrollPositionNow(initialScrollbarState.getDesiredScrollPositionFromDelta(pointerDelta)); + }, + () => { + this.slider.toggleClassName('active', false); + this._host.onDragEnd(); + } + ); - this._host.onDragStart(); - } + this._host.onDragStart(); + } - private _setDesiredScrollPositionNow(_desiredScrollPosition: number): void { + private _setDesiredScrollPositionNow(_desiredScrollPosition: number): void { - const desiredScrollPosition: INewScrollPosition = {}; - this.writeScrollPosition(desiredScrollPosition, _desiredScrollPosition); + const desiredScrollPosition: INewScrollPosition = {}; + this.writeScrollPosition(desiredScrollPosition, _desiredScrollPosition); - this._scrollable.setScrollPositionNow(desiredScrollPosition); - } + this._scrollable.setScrollPositionNow(desiredScrollPosition); + } - public updateScrollbarSize(scrollbarSize: number): void { - this._updateScrollbarSize(scrollbarSize); - this._scrollbarState.setScrollbarSize(scrollbarSize); - this._shouldRender = true; - if (!this._lazyRender) { - this.render(); - } - } + public updateScrollbarSize(scrollbarSize: number): void { + this._updateScrollbarSize(scrollbarSize); + this._scrollbarState.setScrollbarSize(scrollbarSize); + this._shouldRender = true; + if (!this._lazyRender) { + this.render(); + } + } - public isNeeded(): boolean { - return this._scrollbarState.isNeeded(); - } + public isNeeded(): boolean { + return this._scrollbarState.isNeeded(); + } - // ----------------- Overwrite these + // ----------------- Overwrite these - protected abstract _renderDomNode(largeSize: number, smallSize: number): void; - protected abstract _updateSlider(sliderSize: number, sliderPosition: number): void; + protected abstract _renderDomNode(largeSize: number, smallSize: number): void; + protected abstract _updateSlider(sliderSize: number, sliderPosition: number): void; - protected abstract _pointerDownRelativePosition(offsetX: number, offsetY: number): number; - protected abstract _sliderPointerPosition(e: ISimplifiedPointerEvent): number; - protected abstract _sliderOrthogonalPointerPosition(e: ISimplifiedPointerEvent): number; - protected abstract _updateScrollbarSize(size: number): void; + protected abstract _pointerDownRelativePosition(offsetX: number, offsetY: number): number; + protected abstract _sliderPointerPosition(e: ISimplifiedPointerEvent): number; + protected abstract _sliderOrthogonalPointerPosition(e: ISimplifiedPointerEvent): number; + protected abstract _updateScrollbarSize(size: number): void; - public abstract writeScrollPosition(target: INewScrollPosition, scrollPosition: number): void; + public abstract writeScrollPosition(target: INewScrollPosition, scrollPosition: number): void; } diff --git a/src/browser/scrollable/browser.ts b/src/browser/scrollable/browser.ts index 72dd0bcb..495ee92c 100644 --- a/src/browser/scrollable/browser.ts +++ b/src/browser/scrollable/browser.ts @@ -8,93 +8,93 @@ import { Emitter } from './event'; class WindowManager { - static readonly INSTANCE = new WindowManager(); + static readonly INSTANCE = new WindowManager(); - // --- Zoom Level + // --- Zoom Level - private readonly mapWindowIdToZoomLevel = new Map(); + private readonly mapWindowIdToZoomLevel = new Map(); - private readonly _onDidChangeZoomLevel = new Emitter(); - readonly onDidChangeZoomLevel = this._onDidChangeZoomLevel.event; + private readonly _onDidChangeZoomLevel = new Emitter(); + readonly onDidChangeZoomLevel = this._onDidChangeZoomLevel.event; - getZoomLevel(targetWindow: Window): number { - return this.mapWindowIdToZoomLevel.get(this.getWindowId(targetWindow)) ?? 0; - } - setZoomLevel(zoomLevel: number, targetWindow: Window): void { - if (this.getZoomLevel(targetWindow) === zoomLevel) { - return; - } + getZoomLevel(targetWindow: Window): number { + return this.mapWindowIdToZoomLevel.get(this.getWindowId(targetWindow)) ?? 0; + } + setZoomLevel(zoomLevel: number, targetWindow: Window): void { + if (this.getZoomLevel(targetWindow) === zoomLevel) { + return; + } - const targetWindowId = this.getWindowId(targetWindow); - this.mapWindowIdToZoomLevel.set(targetWindowId, zoomLevel); - this._onDidChangeZoomLevel.fire(targetWindowId); - } + const targetWindowId = this.getWindowId(targetWindow); + this.mapWindowIdToZoomLevel.set(targetWindowId, zoomLevel); + this._onDidChangeZoomLevel.fire(targetWindowId); + } - // --- Zoom Factor + // --- Zoom Factor - private readonly mapWindowIdToZoomFactor = new Map(); + private readonly mapWindowIdToZoomFactor = new Map(); - getZoomFactor(targetWindow: Window): number { - return this.mapWindowIdToZoomFactor.get(this.getWindowId(targetWindow)) ?? 1; - } - setZoomFactor(zoomFactor: number, targetWindow: Window): void { - this.mapWindowIdToZoomFactor.set(this.getWindowId(targetWindow), zoomFactor); - } + getZoomFactor(targetWindow: Window): number { + return this.mapWindowIdToZoomFactor.get(this.getWindowId(targetWindow)) ?? 1; + } + setZoomFactor(zoomFactor: number, targetWindow: Window): void { + this.mapWindowIdToZoomFactor.set(this.getWindowId(targetWindow), zoomFactor); + } - // --- Fullscreen + // --- Fullscreen - private readonly _onDidChangeFullscreen = new Emitter(); - readonly onDidChangeFullscreen = this._onDidChangeFullscreen.event; + private readonly _onDidChangeFullscreen = new Emitter(); + readonly onDidChangeFullscreen = this._onDidChangeFullscreen.event; - private readonly mapWindowIdToFullScreen = new Map(); + private readonly mapWindowIdToFullScreen = new Map(); - setFullscreen(fullscreen: boolean, targetWindow: Window): void { - if (this.isFullscreen(targetWindow) === fullscreen) { - return; - } + setFullscreen(fullscreen: boolean, targetWindow: Window): void { + if (this.isFullscreen(targetWindow) === fullscreen) { + return; + } - const windowId = this.getWindowId(targetWindow); - this.mapWindowIdToFullScreen.set(windowId, fullscreen); - this._onDidChangeFullscreen.fire(windowId); - } - isFullscreen(targetWindow: Window): boolean { - return !!this.mapWindowIdToFullScreen.get(this.getWindowId(targetWindow)); - } + const windowId = this.getWindowId(targetWindow); + this.mapWindowIdToFullScreen.set(windowId, fullscreen); + this._onDidChangeFullscreen.fire(windowId); + } + isFullscreen(targetWindow: Window): boolean { + return !!this.mapWindowIdToFullScreen.get(this.getWindowId(targetWindow)); + } - private getWindowId(targetWindow: Window): number { - return (targetWindow as CodeWindow).vscodeWindowId; - } + private getWindowId(targetWindow: Window): number { + return (targetWindow as CodeWindow).vscodeWindowId; + } } export function addMatchMediaChangeListener(targetWindow: Window, query: string | MediaQueryList, callback: (this: MediaQueryList, ev: MediaQueryListEvent) => any): void { - if (typeof query === 'string') { - query = targetWindow.matchMedia(query); - } - query.addEventListener('change', callback); + if (typeof query === 'string') { + query = targetWindow.matchMedia(query); + } + query.addEventListener('change', callback); } /** A zoom index, e.g. 1, 2, 3 */ export function setZoomLevel(zoomLevel: number, targetWindow: Window): void { - WindowManager.INSTANCE.setZoomLevel(zoomLevel, targetWindow); + WindowManager.INSTANCE.setZoomLevel(zoomLevel, targetWindow); } export function getZoomLevel(targetWindow: Window): number { - return WindowManager.INSTANCE.getZoomLevel(targetWindow); + return WindowManager.INSTANCE.getZoomLevel(targetWindow); } export const onDidChangeZoomLevel = WindowManager.INSTANCE.onDidChangeZoomLevel; /** The zoom scale for an index, e.g. 1, 1.2, 1.4 */ export function getZoomFactor(targetWindow: Window): number { - return WindowManager.INSTANCE.getZoomFactor(targetWindow); + return WindowManager.INSTANCE.getZoomFactor(targetWindow); } export function setZoomFactor(zoomFactor: number, targetWindow: Window): void { - WindowManager.INSTANCE.setZoomFactor(zoomFactor, targetWindow); + WindowManager.INSTANCE.setZoomFactor(zoomFactor, targetWindow); } export function setFullscreen(fullscreen: boolean, targetWindow: Window): void { - WindowManager.INSTANCE.setFullscreen(fullscreen, targetWindow); + WindowManager.INSTANCE.setFullscreen(fullscreen, targetWindow); } export function isFullscreen(targetWindow: Window): boolean { - return WindowManager.INSTANCE.isFullscreen(targetWindow); + return WindowManager.INSTANCE.isFullscreen(targetWindow); } export const onDidChangeFullscreen = WindowManager.INSTANCE.onDidChangeFullscreen; @@ -110,32 +110,32 @@ export const isAndroid = (userAgent.indexOf('Android') >= 0); let standalone = false; if (typeof mainWindow.matchMedia === 'function') { - const standaloneMatchMedia = mainWindow.matchMedia('(display-mode: standalone) or (display-mode: window-controls-overlay)'); - const fullScreenMatchMedia = mainWindow.matchMedia('(display-mode: fullscreen)'); - standalone = standaloneMatchMedia.matches; - addMatchMediaChangeListener(mainWindow, standaloneMatchMedia, ({ matches }) => { - // entering fullscreen would change standaloneMatchMedia.matches to false - // if standalone is true (running as PWA) and entering fullscreen, skip this change - if (standalone && fullScreenMatchMedia.matches) { - return; - } - // otherwise update standalone (browser to PWA or PWA to browser) - standalone = matches; - }); + const standaloneMatchMedia = mainWindow.matchMedia('(display-mode: standalone) or (display-mode: window-controls-overlay)'); + const fullScreenMatchMedia = mainWindow.matchMedia('(display-mode: fullscreen)'); + standalone = standaloneMatchMedia.matches; + addMatchMediaChangeListener(mainWindow, standaloneMatchMedia, ({ matches }) => { + // entering fullscreen would change standaloneMatchMedia.matches to false + // if standalone is true (running as PWA) and entering fullscreen, skip this change + if (standalone && fullScreenMatchMedia.matches) { + return; + } + // otherwise update standalone (browser to PWA or PWA to browser) + standalone = matches; + }); } export function isStandalone(): boolean { - return standalone; + return standalone; } // Visible means that the feature is enabled, not necessarily being rendered // e.g. visible is true even in fullscreen mode where the controls are hidden // See docs at https://developer.mozilla.org/en-US/docs/Web/API/WindowControlsOverlay/visible export function isWCOEnabled(): boolean { - return (navigator as any)?.windowControlsOverlay?.visible; + return (navigator as any)?.windowControlsOverlay?.visible; } // Returns the bounding rect of the titlebar area if it is supported and defined // See docs at https://developer.mozilla.org/en-US/docs/Web/API/WindowControlsOverlay/getTitlebarAreaRect export function getWCOBoundingRect(): DOMRect | undefined { - return (navigator as any)?.windowControlsOverlay?.getTitlebarAreaRect(); + return (navigator as any)?.windowControlsOverlay?.getTitlebarAreaRect(); } diff --git a/src/browser/scrollable/collections.ts b/src/browser/scrollable/collections.ts index d0df190c..3a1505d9 100644 --- a/src/browser/scrollable/collections.ts +++ b/src/browser/scrollable/collections.ts @@ -20,48 +20,48 @@ export type INumberDictionary = Record; * group function. */ export function groupBy(data: V[], groupFn: (element: V) => K): Record { - const result: Record = Object.create(null); - for (const element of data) { - const key = groupFn(element); - let target = result[key]; - if (!target) { - target = result[key] = []; - } - target.push(element); - } - return result; + const result: Record = Object.create(null); + for (const element of data) { + const key = groupFn(element); + let target = result[key]; + if (!target) { + target = result[key] = []; + } + target.push(element); + } + return result; } -export function diffSets(before: Set, after: Set): { removed: T[]; added: T[] } { - const removed: T[] = []; - const added: T[] = []; - for (const element of before) { - if (!after.has(element)) { - removed.push(element); - } - } - for (const element of after) { - if (!before.has(element)) { - added.push(element); - } - } - return { removed, added }; +export function diffSets(before: Set, after: Set): { removed: T[], added: T[] } { + const removed: T[] = []; + const added: T[] = []; + for (const element of before) { + if (!after.has(element)) { + removed.push(element); + } + } + for (const element of after) { + if (!before.has(element)) { + added.push(element); + } + } + return { removed, added }; } -export function diffMaps(before: Map, after: Map): { removed: V[]; added: V[] } { - const removed: V[] = []; - const added: V[] = []; - for (const [index, value] of before) { - if (!after.has(index)) { - removed.push(value); - } - } - for (const [index, value] of after) { - if (!before.has(index)) { - added.push(value); - } - } - return { removed, added }; +export function diffMaps(before: Map, after: Map): { removed: V[], added: V[] } { + const removed: V[] = []; + const added: V[] = []; + for (const [index, value] of before) { + if (!after.has(index)) { + removed.push(value); + } + } + for (const [index, value] of after) { + if (!before.has(index)) { + added.push(value); + } + } + return { removed, added }; } /** @@ -72,69 +72,69 @@ export function diffMaps(before: Map, after: Map): { removed: * @returns A new set containing the elements that are in both `setA` and `setB`. */ export function intersection(setA: Set, setB: Iterable): Set { - const result = new Set(); - for (const elem of setB) { - if (setA.has(elem)) { - result.add(elem); - } - } - return result; + const result = new Set(); + for (const elem of setB) { + if (setA.has(elem)) { + result.add(elem); + } + } + return result; } export class SetWithKey implements Set { - private _map = new Map(); + private _map = new Map(); - constructor(values: T[], private toKey: (t: T) => any) { - for (const value of values) { - this.add(value); - } - } + constructor(values: T[], private toKey: (t: T) => any) { + for (const value of values) { + this.add(value); + } + } - get size(): number { - return this._map.size; - } + get size(): number { + return this._map.size; + } - add(value: T): this { - const key = this.toKey(value); - this._map.set(key, value); - return this; - } + add(value: T): this { + const key = this.toKey(value); + this._map.set(key, value); + return this; + } - delete(value: T): boolean { - return this._map.delete(this.toKey(value)); - } + delete(value: T): boolean { + return this._map.delete(this.toKey(value)); + } - has(value: T): boolean { - return this._map.has(this.toKey(value)); - } + has(value: T): boolean { + return this._map.has(this.toKey(value)); + } - *entries(): IterableIterator<[T, T]> { - for (const entry of this._map.values()) { - yield [entry, entry]; - } - } + *entries(): IterableIterator<[T, T]> { + for (const entry of this._map.values()) { + yield [entry, entry]; + } + } - keys(): IterableIterator { - return this.values(); - } + keys(): IterableIterator { + return this.values(); + } - *values(): IterableIterator { - for (const entry of this._map.values()) { - yield entry; - } - } + *values(): IterableIterator { + for (const entry of this._map.values()) { + yield entry; + } + } - clear(): void { - this._map.clear(); - } + clear(): void { + this._map.clear(); + } - forEach(callbackfn: (value: T, value2: T, set: Set) => void, thisArg?: any): void { - this._map.forEach(entry => callbackfn.call(thisArg, entry, entry, this)); - } + forEach(callbackfn: (value: T, value2: T, set: Set) => void, thisArg?: any): void { + this._map.forEach(entry => callbackfn.call(thisArg, entry, entry, this)); + } - [Symbol.iterator](): IterableIterator { - return this.values(); - } + [Symbol.iterator](): IterableIterator { + return this.values(); + } - [Symbol.toStringTag]: string = 'SetWithKey'; + [Symbol.toStringTag]: string = 'SetWithKey'; } diff --git a/src/browser/scrollable/decorators.ts b/src/browser/scrollable/decorators.ts index 34592a7b..ae9c760a 100644 --- a/src/browser/scrollable/decorators.ts +++ b/src/browser/scrollable/decorators.ts @@ -4,127 +4,127 @@ *--------------------------------------------------------------------------------------------*/ function createDecorator(mapFn: (fn: Function, key: string) => Function): Function { - return (target: any, key: string, descriptor: any) => { - let fnKey: string | null = null; - let fn: Function | null = null; + return (target: any, key: string, descriptor: any) => { + let fnKey: string | null = null; + let fn: Function | null = null; - if (typeof descriptor.value === 'function') { - fnKey = 'value'; - fn = descriptor.value; - } else if (typeof descriptor.get === 'function') { - fnKey = 'get'; - fn = descriptor.get; - } + if (typeof descriptor.value === 'function') { + fnKey = 'value'; + fn = descriptor.value; + } else if (typeof descriptor.get === 'function') { + fnKey = 'get'; + fn = descriptor.get; + } - if (!fn) { - throw new Error('not supported'); - } + if (!fn) { + throw new Error('not supported'); + } - descriptor[fnKey!] = mapFn(fn, key); - }; + descriptor[fnKey!] = mapFn(fn, key); + }; } export function memoize(_target: any, key: string, descriptor: any) { - let fnKey: string | null = null; - let fn: Function | null = null; + let fnKey: string | null = null; + let fn: Function | null = null; - if (typeof descriptor.value === 'function') { - fnKey = 'value'; - fn = descriptor.value; + if (typeof descriptor.value === 'function') { + fnKey = 'value'; + fn = descriptor.value; - if (fn!.length !== 0) { - console.warn('Memoize should only be used in functions with zero parameters'); - } - } else if (typeof descriptor.get === 'function') { - fnKey = 'get'; - fn = descriptor.get; - } + if (fn!.length !== 0) { + console.warn('Memoize should only be used in functions with zero parameters'); + } + } else if (typeof descriptor.get === 'function') { + fnKey = 'get'; + fn = descriptor.get; + } - if (!fn) { - throw new Error('not supported'); - } + if (!fn) { + throw new Error('not supported'); + } - const memoizeKey = `$memoize$${key}`; - descriptor[fnKey!] = function (...args: any[]) { - if (!this.hasOwnProperty(memoizeKey)) { - Object.defineProperty(this, memoizeKey, { - configurable: false, - enumerable: false, - writable: false, - value: fn.apply(this, args) - }); - } + const memoizeKey = `$memoize$${key}`; + descriptor[fnKey!] = function (...args: any[]) { + if (!this.hasOwnProperty(memoizeKey)) { + Object.defineProperty(this, memoizeKey, { + configurable: false, + enumerable: false, + writable: false, + value: fn.apply(this, args) + }); + } - return this[memoizeKey]; - }; + return this[memoizeKey]; + }; } export interface IDebounceReducer { - (previousValue: T, ...args: any[]): T; + (previousValue: T, ...args: any[]): T; } export function debounce(delay: number, reducer?: IDebounceReducer, initialValueProvider?: () => T): Function { - return createDecorator((fn, key) => { - const timerKey = `$debounce$${key}`; - const resultKey = `$debounce$result$${key}`; + return createDecorator((fn, key) => { + const timerKey = `$debounce$${key}`; + const resultKey = `$debounce$result$${key}`; - return function (this: any, ...args: any[]) { - if (!this[resultKey]) { - this[resultKey] = initialValueProvider ? initialValueProvider() : undefined; - } + return function (this: any, ...args: any[]) { + if (!this[resultKey]) { + this[resultKey] = initialValueProvider ? initialValueProvider() : undefined; + } - clearTimeout(this[timerKey]); + clearTimeout(this[timerKey]); - if (reducer) { - this[resultKey] = reducer(this[resultKey], ...args); - args = [this[resultKey]]; - } + if (reducer) { + this[resultKey] = reducer(this[resultKey], ...args); + args = [this[resultKey]]; + } - this[timerKey] = setTimeout(() => { - fn.apply(this, args); - this[resultKey] = initialValueProvider ? initialValueProvider() : undefined; - }, delay); - }; - }); + this[timerKey] = setTimeout(() => { + fn.apply(this, args); + this[resultKey] = initialValueProvider ? initialValueProvider() : undefined; + }, delay); + }; + }); } export function throttle(delay: number, reducer?: IDebounceReducer, initialValueProvider?: () => T): Function { - return createDecorator((fn, key) => { - const timerKey = `$throttle$timer$${key}`; - const resultKey = `$throttle$result$${key}`; - const lastRunKey = `$throttle$lastRun$${key}`; - const pendingKey = `$throttle$pending$${key}`; + return createDecorator((fn, key) => { + const timerKey = `$throttle$timer$${key}`; + const resultKey = `$throttle$result$${key}`; + const lastRunKey = `$throttle$lastRun$${key}`; + const pendingKey = `$throttle$pending$${key}`; - return function (this: any, ...args: any[]) { - if (!this[resultKey]) { - this[resultKey] = initialValueProvider ? initialValueProvider() : undefined; - } - if (this[lastRunKey] === null || this[lastRunKey] === undefined) { - this[lastRunKey] = -Number.MAX_VALUE; - } + return function (this: any, ...args: any[]) { + if (!this[resultKey]) { + this[resultKey] = initialValueProvider ? initialValueProvider() : undefined; + } + if (this[lastRunKey] === null || this[lastRunKey] === undefined) { + this[lastRunKey] = -Number.MAX_VALUE; + } - if (reducer) { - this[resultKey] = reducer(this[resultKey], ...args); - } + if (reducer) { + this[resultKey] = reducer(this[resultKey], ...args); + } - if (this[pendingKey]) { - return; - } + if (this[pendingKey]) { + return; + } - const nextTime = this[lastRunKey] + delay; - if (nextTime <= Date.now()) { - this[lastRunKey] = Date.now(); - fn.apply(this, [this[resultKey]]); - this[resultKey] = initialValueProvider ? initialValueProvider() : undefined; - } else { - this[pendingKey] = true; - this[timerKey] = setTimeout(() => { - this[pendingKey] = false; - this[lastRunKey] = Date.now(); - fn.apply(this, [this[resultKey]]); - this[resultKey] = initialValueProvider ? initialValueProvider() : undefined; - }, nextTime - Date.now()); - } - }; - }); + const nextTime = this[lastRunKey] + delay; + if (nextTime <= Date.now()) { + this[lastRunKey] = Date.now(); + fn.apply(this, [this[resultKey]]); + this[resultKey] = initialValueProvider ? initialValueProvider() : undefined; + } else { + this[pendingKey] = true; + this[timerKey] = setTimeout(() => { + this[pendingKey] = false; + this[lastRunKey] = Date.now(); + fn.apply(this, [this[resultKey]]); + this[resultKey] = initialValueProvider ? initialValueProvider() : undefined; + }, nextTime - Date.now()); + } + }; + }); } diff --git a/src/browser/scrollable/event.ts b/src/browser/scrollable/event.ts index 97351595..20fb94d9 100644 --- a/src/browser/scrollable/event.ts +++ b/src/browser/scrollable/event.ts @@ -12,7 +12,7 @@ export interface Event { } export class Emitter { - private _listeners: { fn: (e: T) => any; thisArgs: any }[] = []; + private _listeners: { fn: (e: T) => any, thisArgs: any }[] = []; private _disposed = false; private _event: Event | undefined; diff --git a/src/browser/scrollable/fastDomNode.ts b/src/browser/scrollable/fastDomNode.ts index 5190bae6..9eba7f7f 100644 --- a/src/browser/scrollable/fastDomNode.ts +++ b/src/browser/scrollable/fastDomNode.ts @@ -5,316 +5,316 @@ export class FastDomNode { - private _maxWidth: string = ''; - private _width: string = ''; - private _height: string = ''; - private _top: string = ''; - private _left: string = ''; - private _bottom: string = ''; - private _right: string = ''; - private _paddingTop: string = ''; - private _paddingLeft: string = ''; - private _paddingBottom: string = ''; - private _paddingRight: string = ''; - private _fontFamily: string = ''; - private _fontWeight: string = ''; - private _fontSize: string = ''; - private _fontStyle: string = ''; - private _fontFeatureSettings: string = ''; - private _fontVariationSettings: string = ''; - private _textDecoration: string = ''; - private _lineHeight: string = ''; - private _letterSpacing: string = ''; - private _className: string = ''; - private _display: string = ''; - private _position: string = ''; - private _visibility: string = ''; - private _color: string = ''; - private _backgroundColor: string = ''; - private _layerHint: boolean = false; - private _contain: 'none' | 'strict' | 'content' | 'size' | 'layout' | 'style' | 'paint' = 'none'; - private _boxShadow: string = ''; + private _maxWidth: string = ''; + private _width: string = ''; + private _height: string = ''; + private _top: string = ''; + private _left: string = ''; + private _bottom: string = ''; + private _right: string = ''; + private _paddingTop: string = ''; + private _paddingLeft: string = ''; + private _paddingBottom: string = ''; + private _paddingRight: string = ''; + private _fontFamily: string = ''; + private _fontWeight: string = ''; + private _fontSize: string = ''; + private _fontStyle: string = ''; + private _fontFeatureSettings: string = ''; + private _fontVariationSettings: string = ''; + private _textDecoration: string = ''; + private _lineHeight: string = ''; + private _letterSpacing: string = ''; + private _className: string = ''; + private _display: string = ''; + private _position: string = ''; + private _visibility: string = ''; + private _color: string = ''; + private _backgroundColor: string = ''; + private _layerHint: boolean = false; + private _contain: 'none' | 'strict' | 'content' | 'size' | 'layout' | 'style' | 'paint' = 'none'; + private _boxShadow: string = ''; - constructor( - public readonly domNode: T - ) { } + constructor( + public readonly domNode: T + ) { } - public setMaxWidth(_maxWidth: number | string): void { - const maxWidth = numberAsPixels(_maxWidth); - if (this._maxWidth === maxWidth) { - return; - } - this._maxWidth = maxWidth; - this.domNode.style.maxWidth = this._maxWidth; - } + public setMaxWidth(_maxWidth: number | string): void { + const maxWidth = numberAsPixels(_maxWidth); + if (this._maxWidth === maxWidth) { + return; + } + this._maxWidth = maxWidth; + this.domNode.style.maxWidth = this._maxWidth; + } - public setWidth(_width: number | string): void { - const width = numberAsPixels(_width); - if (this._width === width) { - return; - } - this._width = width; - this.domNode.style.width = this._width; - } + public setWidth(_width: number | string): void { + const width = numberAsPixels(_width); + if (this._width === width) { + return; + } + this._width = width; + this.domNode.style.width = this._width; + } - public setHeight(_height: number | string): void { - const height = numberAsPixels(_height); - if (this._height === height) { - return; - } - this._height = height; - this.domNode.style.height = this._height; - } + public setHeight(_height: number | string): void { + const height = numberAsPixels(_height); + if (this._height === height) { + return; + } + this._height = height; + this.domNode.style.height = this._height; + } - public setTop(_top: number | string): void { - const top = numberAsPixels(_top); - if (this._top === top) { - return; - } - this._top = top; - this.domNode.style.top = this._top; - } + public setTop(_top: number | string): void { + const top = numberAsPixels(_top); + if (this._top === top) { + return; + } + this._top = top; + this.domNode.style.top = this._top; + } - public setLeft(_left: number | string): void { - const left = numberAsPixels(_left); - if (this._left === left) { - return; - } - this._left = left; - this.domNode.style.left = this._left; - } + public setLeft(_left: number | string): void { + const left = numberAsPixels(_left); + if (this._left === left) { + return; + } + this._left = left; + this.domNode.style.left = this._left; + } - public setBottom(_bottom: number | string): void { - const bottom = numberAsPixels(_bottom); - if (this._bottom === bottom) { - return; - } - this._bottom = bottom; - this.domNode.style.bottom = this._bottom; - } + public setBottom(_bottom: number | string): void { + const bottom = numberAsPixels(_bottom); + if (this._bottom === bottom) { + return; + } + this._bottom = bottom; + this.domNode.style.bottom = this._bottom; + } - public setRight(_right: number | string): void { - const right = numberAsPixels(_right); - if (this._right === right) { - return; - } - this._right = right; - this.domNode.style.right = this._right; - } + public setRight(_right: number | string): void { + const right = numberAsPixels(_right); + if (this._right === right) { + return; + } + this._right = right; + this.domNode.style.right = this._right; + } - public setPaddingTop(_paddingTop: number | string): void { - const paddingTop = numberAsPixels(_paddingTop); - if (this._paddingTop === paddingTop) { - return; - } - this._paddingTop = paddingTop; - this.domNode.style.paddingTop = this._paddingTop; - } + public setPaddingTop(_paddingTop: number | string): void { + const paddingTop = numberAsPixels(_paddingTop); + if (this._paddingTop === paddingTop) { + return; + } + this._paddingTop = paddingTop; + this.domNode.style.paddingTop = this._paddingTop; + } - public setPaddingLeft(_paddingLeft: number | string): void { - const paddingLeft = numberAsPixels(_paddingLeft); - if (this._paddingLeft === paddingLeft) { - return; - } - this._paddingLeft = paddingLeft; - this.domNode.style.paddingLeft = this._paddingLeft; - } + public setPaddingLeft(_paddingLeft: number | string): void { + const paddingLeft = numberAsPixels(_paddingLeft); + if (this._paddingLeft === paddingLeft) { + return; + } + this._paddingLeft = paddingLeft; + this.domNode.style.paddingLeft = this._paddingLeft; + } - public setPaddingBottom(_paddingBottom: number | string): void { - const paddingBottom = numberAsPixels(_paddingBottom); - if (this._paddingBottom === paddingBottom) { - return; - } - this._paddingBottom = paddingBottom; - this.domNode.style.paddingBottom = this._paddingBottom; - } + public setPaddingBottom(_paddingBottom: number | string): void { + const paddingBottom = numberAsPixels(_paddingBottom); + if (this._paddingBottom === paddingBottom) { + return; + } + this._paddingBottom = paddingBottom; + this.domNode.style.paddingBottom = this._paddingBottom; + } - public setPaddingRight(_paddingRight: number | string): void { - const paddingRight = numberAsPixels(_paddingRight); - if (this._paddingRight === paddingRight) { - return; - } - this._paddingRight = paddingRight; - this.domNode.style.paddingRight = this._paddingRight; - } + public setPaddingRight(_paddingRight: number | string): void { + const paddingRight = numberAsPixels(_paddingRight); + if (this._paddingRight === paddingRight) { + return; + } + this._paddingRight = paddingRight; + this.domNode.style.paddingRight = this._paddingRight; + } - public setFontFamily(fontFamily: string): void { - if (this._fontFamily === fontFamily) { - return; - } - this._fontFamily = fontFamily; - this.domNode.style.fontFamily = this._fontFamily; - } + public setFontFamily(fontFamily: string): void { + if (this._fontFamily === fontFamily) { + return; + } + this._fontFamily = fontFamily; + this.domNode.style.fontFamily = this._fontFamily; + } - public setFontWeight(fontWeight: string): void { - if (this._fontWeight === fontWeight) { - return; - } - this._fontWeight = fontWeight; - this.domNode.style.fontWeight = this._fontWeight; - } + public setFontWeight(fontWeight: string): void { + if (this._fontWeight === fontWeight) { + return; + } + this._fontWeight = fontWeight; + this.domNode.style.fontWeight = this._fontWeight; + } - public setFontSize(_fontSize: number | string): void { - const fontSize = numberAsPixels(_fontSize); - if (this._fontSize === fontSize) { - return; - } - this._fontSize = fontSize; - this.domNode.style.fontSize = this._fontSize; - } + public setFontSize(_fontSize: number | string): void { + const fontSize = numberAsPixels(_fontSize); + if (this._fontSize === fontSize) { + return; + } + this._fontSize = fontSize; + this.domNode.style.fontSize = this._fontSize; + } - public setFontStyle(fontStyle: string): void { - if (this._fontStyle === fontStyle) { - return; - } - this._fontStyle = fontStyle; - this.domNode.style.fontStyle = this._fontStyle; - } + public setFontStyle(fontStyle: string): void { + if (this._fontStyle === fontStyle) { + return; + } + this._fontStyle = fontStyle; + this.domNode.style.fontStyle = this._fontStyle; + } - public setFontFeatureSettings(fontFeatureSettings: string): void { - if (this._fontFeatureSettings === fontFeatureSettings) { - return; - } - this._fontFeatureSettings = fontFeatureSettings; - this.domNode.style.fontFeatureSettings = this._fontFeatureSettings; - } + public setFontFeatureSettings(fontFeatureSettings: string): void { + if (this._fontFeatureSettings === fontFeatureSettings) { + return; + } + this._fontFeatureSettings = fontFeatureSettings; + this.domNode.style.fontFeatureSettings = this._fontFeatureSettings; + } - public setFontVariationSettings(fontVariationSettings: string): void { - if (this._fontVariationSettings === fontVariationSettings) { - return; - } - this._fontVariationSettings = fontVariationSettings; - this.domNode.style.fontVariationSettings = this._fontVariationSettings; - } + public setFontVariationSettings(fontVariationSettings: string): void { + if (this._fontVariationSettings === fontVariationSettings) { + return; + } + this._fontVariationSettings = fontVariationSettings; + this.domNode.style.fontVariationSettings = this._fontVariationSettings; + } - public setTextDecoration(textDecoration: string): void { - if (this._textDecoration === textDecoration) { - return; - } - this._textDecoration = textDecoration; - this.domNode.style.textDecoration = this._textDecoration; - } + public setTextDecoration(textDecoration: string): void { + if (this._textDecoration === textDecoration) { + return; + } + this._textDecoration = textDecoration; + this.domNode.style.textDecoration = this._textDecoration; + } - public setLineHeight(_lineHeight: number | string): void { - const lineHeight = numberAsPixels(_lineHeight); - if (this._lineHeight === lineHeight) { - return; - } - this._lineHeight = lineHeight; - this.domNode.style.lineHeight = this._lineHeight; - } + public setLineHeight(_lineHeight: number | string): void { + const lineHeight = numberAsPixels(_lineHeight); + if (this._lineHeight === lineHeight) { + return; + } + this._lineHeight = lineHeight; + this.domNode.style.lineHeight = this._lineHeight; + } - public setLetterSpacing(_letterSpacing: number | string): void { - const letterSpacing = numberAsPixels(_letterSpacing); - if (this._letterSpacing === letterSpacing) { - return; - } - this._letterSpacing = letterSpacing; - this.domNode.style.letterSpacing = this._letterSpacing; - } + public setLetterSpacing(_letterSpacing: number | string): void { + const letterSpacing = numberAsPixels(_letterSpacing); + if (this._letterSpacing === letterSpacing) { + return; + } + this._letterSpacing = letterSpacing; + this.domNode.style.letterSpacing = this._letterSpacing; + } - public setClassName(className: string): void { - if (this._className === className) { - return; - } - this._className = className; - this.domNode.className = this._className; - } + public setClassName(className: string): void { + if (this._className === className) { + return; + } + this._className = className; + this.domNode.className = this._className; + } - public toggleClassName(className: string, shouldHaveIt?: boolean): void { - this.domNode.classList.toggle(className, shouldHaveIt); - this._className = this.domNode.className; - } + public toggleClassName(className: string, shouldHaveIt?: boolean): void { + this.domNode.classList.toggle(className, shouldHaveIt); + this._className = this.domNode.className; + } - public setDisplay(display: string): void { - if (this._display === display) { - return; - } - this._display = display; - this.domNode.style.display = this._display; - } + public setDisplay(display: string): void { + if (this._display === display) { + return; + } + this._display = display; + this.domNode.style.display = this._display; + } - public setPosition(position: string): void { - if (this._position === position) { - return; - } - this._position = position; - this.domNode.style.position = this._position; - } + public setPosition(position: string): void { + if (this._position === position) { + return; + } + this._position = position; + this.domNode.style.position = this._position; + } - public setVisibility(visibility: string): void { - if (this._visibility === visibility) { - return; - } - this._visibility = visibility; - this.domNode.style.visibility = this._visibility; - } + public setVisibility(visibility: string): void { + if (this._visibility === visibility) { + return; + } + this._visibility = visibility; + this.domNode.style.visibility = this._visibility; + } - public setColor(color: string): void { - if (this._color === color) { - return; - } - this._color = color; - this.domNode.style.color = this._color; - } + public setColor(color: string): void { + if (this._color === color) { + return; + } + this._color = color; + this.domNode.style.color = this._color; + } - public setBackgroundColor(backgroundColor: string): void { - if (this._backgroundColor === backgroundColor) { - return; - } - this._backgroundColor = backgroundColor; - this.domNode.style.backgroundColor = this._backgroundColor; - } + public setBackgroundColor(backgroundColor: string): void { + if (this._backgroundColor === backgroundColor) { + return; + } + this._backgroundColor = backgroundColor; + this.domNode.style.backgroundColor = this._backgroundColor; + } - public setLayerHinting(layerHint: boolean): void { - if (this._layerHint === layerHint) { - return; - } - this._layerHint = layerHint; - if (layerHint) { - this.domNode.style.transform = 'translate3d(0px, 0px, 0px)'; - } else { - this.domNode.style.transform = ''; - } - } + public setLayerHinting(layerHint: boolean): void { + if (this._layerHint === layerHint) { + return; + } + this._layerHint = layerHint; + if (layerHint) { + this.domNode.style.transform = 'translate3d(0px, 0px, 0px)'; + } else { + this.domNode.style.transform = ''; + } + } - public setContain(contain: 'none' | 'strict' | 'content' | 'size' | 'layout' | 'style' | 'paint'): void { - if (this._contain === contain) { - return; - } - this._contain = contain; - this.domNode.style.contain = this._contain; - } + public setContain(contain: 'none' | 'strict' | 'content' | 'size' | 'layout' | 'style' | 'paint'): void { + if (this._contain === contain) { + return; + } + this._contain = contain; + this.domNode.style.contain = this._contain; + } - public setBoxShadow(boxShadow: string): void { - if (this._boxShadow === boxShadow) { - return; - } - this._boxShadow = boxShadow; - this.domNode.style.boxShadow = this._boxShadow; - } + public setBoxShadow(boxShadow: string): void { + if (this._boxShadow === boxShadow) { + return; + } + this._boxShadow = boxShadow; + this.domNode.style.boxShadow = this._boxShadow; + } - public setAttribute(name: string, value: string): void { - this.domNode.setAttribute(name, value); - } + public setAttribute(name: string, value: string): void { + this.domNode.setAttribute(name, value); + } - public removeAttribute(name: string): void { - this.domNode.removeAttribute(name); - } + public removeAttribute(name: string): void { + this.domNode.removeAttribute(name); + } - public appendChild(child: FastDomNode): void { - this.domNode.appendChild(child.domNode); - } + public appendChild(child: FastDomNode): void { + this.domNode.appendChild(child.domNode); + } - public removeChild(child: FastDomNode): void { - this.domNode.removeChild(child.domNode); - } + public removeChild(child: FastDomNode): void { + this.domNode.removeChild(child.domNode); + } } export function createFastDomNode(domNode: T): FastDomNode { - return new FastDomNode(domNode); + return new FastDomNode(domNode); } function numberAsPixels(value: number | string): string { - return (typeof value === 'number' ? `${value}px` : value); + return (typeof value === 'number' ? `${value}px` : value); } diff --git a/src/browser/scrollable/functional.ts b/src/browser/scrollable/functional.ts index d580cf37..803f61c5 100644 --- a/src/browser/scrollable/functional.ts +++ b/src/browser/scrollable/functional.ts @@ -7,26 +7,26 @@ * Given a function, returns a function that is only calling that function once. */ export function createSingleCallFunction(this: unknown, fn: T, fnDidRunCallback?: () => void): T { - const _this = this; - let didCall = false; - let result: unknown; + const _this = this; + let didCall = false; + let result: unknown; - return function () { - if (didCall) { - return result; - } + return function () { + if (didCall) { + return result; + } - didCall = true; - if (fnDidRunCallback) { - try { - result = fn.apply(_this, arguments); - } finally { - fnDidRunCallback(); - } - } else { - result = fn.apply(_this, arguments); - } + didCall = true; + if (fnDidRunCallback) { + try { + result = fn.apply(_this, arguments); + } finally { + fnDidRunCallback(); + } + } else { + result = fn.apply(_this, arguments); + } - return result; - } as unknown as T; + return result; + } as unknown as T; } diff --git a/src/browser/scrollable/globalPointerMoveMonitor.ts b/src/browser/scrollable/globalPointerMoveMonitor.ts index e39541cc..fdc024c1 100644 --- a/src/browser/scrollable/globalPointerMoveMonitor.ts +++ b/src/browser/scrollable/globalPointerMoveMonitor.ts @@ -7,89 +7,89 @@ import * as dom from './dom'; import { DisposableStore, IDisposable, toDisposable } from './lifecycle'; export interface IPointerMoveCallback { - (event: PointerEvent): void; + (event: PointerEvent): void; } export interface IOnStopCallback { - (browserEvent?: PointerEvent | KeyboardEvent): void; + (browserEvent?: PointerEvent | KeyboardEvent): void; } export class GlobalPointerMoveMonitor implements IDisposable { - private readonly _hooks = new DisposableStore(); - private _pointerMoveCallback: IPointerMoveCallback | null = null; - private _onStopCallback: IOnStopCallback | null = null; + private readonly _hooks = new DisposableStore(); + private _pointerMoveCallback: IPointerMoveCallback | null = null; + private _onStopCallback: IOnStopCallback | null = null; - public dispose(): void { - this.stopMonitoring(false); - this._hooks.dispose(); - } + public dispose(): void { + this.stopMonitoring(false); + this._hooks.dispose(); + } - public stopMonitoring(invokeStopCallback: boolean, browserEvent?: PointerEvent | KeyboardEvent): void { - if (!this.isMonitoring()) { - return; - } + public stopMonitoring(invokeStopCallback: boolean, browserEvent?: PointerEvent | KeyboardEvent): void { + if (!this.isMonitoring()) { + return; + } - this._hooks.clear(); - this._pointerMoveCallback = null; - const onStopCallback = this._onStopCallback; - this._onStopCallback = null; + this._hooks.clear(); + this._pointerMoveCallback = null; + const onStopCallback = this._onStopCallback; + this._onStopCallback = null; - if (invokeStopCallback && onStopCallback) { - onStopCallback(browserEvent); - } - } + if (invokeStopCallback && onStopCallback) { + onStopCallback(browserEvent); + } + } - public isMonitoring(): boolean { - return !!this._pointerMoveCallback; - } + public isMonitoring(): boolean { + return !!this._pointerMoveCallback; + } - public startMonitoring( - initialElement: Element, - pointerId: number, - initialButtons: number, - pointerMoveCallback: IPointerMoveCallback, - onStopCallback: IOnStopCallback - ): void { - if (this.isMonitoring()) { - this.stopMonitoring(false); - } - this._pointerMoveCallback = pointerMoveCallback; - this._onStopCallback = onStopCallback; + public startMonitoring( + initialElement: Element, + pointerId: number, + initialButtons: number, + pointerMoveCallback: IPointerMoveCallback, + onStopCallback: IOnStopCallback + ): void { + if (this.isMonitoring()) { + this.stopMonitoring(false); + } + this._pointerMoveCallback = pointerMoveCallback; + this._onStopCallback = onStopCallback; - let eventSource: Element | Window = initialElement; + let eventSource: Element | Window = initialElement; - try { - initialElement.setPointerCapture(pointerId); - this._hooks.add(toDisposable(() => { - try { - initialElement.releasePointerCapture(pointerId); - } catch (err) { - // ignore - } - })); - } catch (err) { - eventSource = dom.getWindow(initialElement); - } + try { + initialElement.setPointerCapture(pointerId); + this._hooks.add(toDisposable(() => { + try { + initialElement.releasePointerCapture(pointerId); + } catch (err) { + // ignore + } + })); + } catch (err) { + eventSource = dom.getWindow(initialElement); + } - this._hooks.add(dom.addDisposableListener( - eventSource, - dom.EventType.POINTER_MOVE, - (e) => { - if (e.buttons !== initialButtons) { - this.stopMonitoring(true); - return; - } + this._hooks.add(dom.addDisposableListener( + eventSource, + dom.EventType.POINTER_MOVE, + (e) => { + if (e.buttons !== initialButtons) { + this.stopMonitoring(true); + return; + } - e.preventDefault(); - this._pointerMoveCallback!(e); - } - )); + e.preventDefault(); + this._pointerMoveCallback!(e); + } + )); - this._hooks.add(dom.addDisposableListener( - eventSource, - dom.EventType.POINTER_UP, - (e: PointerEvent) => this.stopMonitoring(true) - )); - } + this._hooks.add(dom.addDisposableListener( + eventSource, + dom.EventType.POINTER_UP, + (e: PointerEvent) => this.stopMonitoring(true) + )); + } } diff --git a/src/browser/scrollable/horizontalScrollbar.ts b/src/browser/scrollable/horizontalScrollbar.ts index 13548026..8f9732e3 100644 --- a/src/browser/scrollable/horizontalScrollbar.ts +++ b/src/browser/scrollable/horizontalScrollbar.ts @@ -10,76 +10,76 @@ import { INewScrollPosition, Scrollable, ScrollbarVisibility, ScrollEvent } from export class HorizontalScrollbar extends AbstractScrollbar { - constructor(scrollable: Scrollable, options: ScrollableElementResolvedOptions, host: ScrollbarHost) { - const scrollDimensions = scrollable.getScrollDimensions(); - const scrollPosition = scrollable.getCurrentScrollPosition(); - super({ - lazyRender: options.lazyRender, - host: host, - scrollbarState: new ScrollbarState( - (options.horizontalHasArrows ? options.arrowSize : 0), - (options.horizontal === ScrollbarVisibility.Hidden ? 0 : options.horizontalScrollbarSize), - (options.vertical === ScrollbarVisibility.Hidden ? 0 : options.verticalScrollbarSize), - scrollDimensions.width, - scrollDimensions.scrollWidth, - scrollPosition.scrollLeft - ), - visibility: options.horizontal, - extraScrollbarClassName: 'horizontal', - scrollable: scrollable, - scrollByPage: options.scrollByPage - }); + constructor(scrollable: Scrollable, options: ScrollableElementResolvedOptions, host: ScrollbarHost) { + const scrollDimensions = scrollable.getScrollDimensions(); + const scrollPosition = scrollable.getCurrentScrollPosition(); + super({ + lazyRender: options.lazyRender, + host: host, + scrollbarState: new ScrollbarState( + (options.horizontalHasArrows ? options.arrowSize : 0), + (options.horizontal === ScrollbarVisibility.Hidden ? 0 : options.horizontalScrollbarSize), + (options.vertical === ScrollbarVisibility.Hidden ? 0 : options.verticalScrollbarSize), + scrollDimensions.width, + scrollDimensions.scrollWidth, + scrollPosition.scrollLeft + ), + visibility: options.horizontal, + extraScrollbarClassName: 'horizontal', + scrollable: scrollable, + scrollByPage: options.scrollByPage + }); - if (options.horizontalHasArrows) { - throw new Error('horizontalHasArrows is not supported in xterm.js'); - } + if (options.horizontalHasArrows) { + throw new Error('horizontalHasArrows is not supported in xterm.js'); + } - this._createSlider(Math.floor((options.horizontalScrollbarSize - options.horizontalSliderSize) / 2), 0, undefined, options.horizontalSliderSize); - } + this._createSlider(Math.floor((options.horizontalScrollbarSize - options.horizontalSliderSize) / 2), 0, undefined, options.horizontalSliderSize); + } - protected _updateSlider(sliderSize: number, sliderPosition: number): void { - this.slider.setWidth(sliderSize); - this.slider.setLeft(sliderPosition); - } + protected _updateSlider(sliderSize: number, sliderPosition: number): void { + this.slider.setWidth(sliderSize); + this.slider.setLeft(sliderPosition); + } - protected _renderDomNode(largeSize: number, smallSize: number): void { - this.domNode.setWidth(largeSize); - this.domNode.setHeight(smallSize); - this.domNode.setLeft(0); - this.domNode.setBottom(0); - } + protected _renderDomNode(largeSize: number, smallSize: number): void { + this.domNode.setWidth(largeSize); + this.domNode.setHeight(smallSize); + this.domNode.setLeft(0); + this.domNode.setBottom(0); + } - public onDidScroll(e: ScrollEvent): boolean { - this._shouldRender = this._onElementScrollSize(e.scrollWidth) || this._shouldRender; - this._shouldRender = this._onElementScrollPosition(e.scrollLeft) || this._shouldRender; - this._shouldRender = this._onElementSize(e.width) || this._shouldRender; - return this._shouldRender; - } + public onDidScroll(e: ScrollEvent): boolean { + this._shouldRender = this._onElementScrollSize(e.scrollWidth) || this._shouldRender; + this._shouldRender = this._onElementScrollPosition(e.scrollLeft) || this._shouldRender; + this._shouldRender = this._onElementSize(e.width) || this._shouldRender; + return this._shouldRender; + } - protected _pointerDownRelativePosition(offsetX: number, offsetY: number): number { - return offsetX; - } + protected _pointerDownRelativePosition(offsetX: number, offsetY: number): number { + return offsetX; + } - protected _sliderPointerPosition(e: ISimplifiedPointerEvent): number { - return e.pageX; - } + protected _sliderPointerPosition(e: ISimplifiedPointerEvent): number { + return e.pageX; + } - protected _sliderOrthogonalPointerPosition(e: ISimplifiedPointerEvent): number { - return e.pageY; - } + protected _sliderOrthogonalPointerPosition(e: ISimplifiedPointerEvent): number { + return e.pageY; + } - protected _updateScrollbarSize(size: number): void { - this.slider.setHeight(size); - } + protected _updateScrollbarSize(size: number): void { + this.slider.setHeight(size); + } - public writeScrollPosition(target: INewScrollPosition, scrollPosition: number): void { - target.scrollLeft = scrollPosition; - } + public writeScrollPosition(target: INewScrollPosition, scrollPosition: number): void { + target.scrollLeft = scrollPosition; + } - public updateOptions(options: ScrollableElementResolvedOptions): void { - this.updateScrollbarSize(options.horizontal === ScrollbarVisibility.Hidden ? 0 : options.horizontalScrollbarSize); - this._scrollbarState.setOppositeScrollbarSize(options.vertical === ScrollbarVisibility.Hidden ? 0 : options.verticalScrollbarSize); - this._visibilityController.setVisibility(options.horizontal); - this._scrollByPage = options.scrollByPage; - } + public updateOptions(options: ScrollableElementResolvedOptions): void { + this.updateScrollbarSize(options.horizontal === ScrollbarVisibility.Hidden ? 0 : options.horizontalScrollbarSize); + this._scrollbarState.setOppositeScrollbarSize(options.vertical === ScrollbarVisibility.Hidden ? 0 : options.verticalScrollbarSize); + this._visibilityController.setVisibility(options.horizontal); + this._scrollByPage = options.scrollByPage; + } } diff --git a/src/browser/scrollable/iframe.ts b/src/browser/scrollable/iframe.ts index e8522e03..f595b385 100644 --- a/src/browser/scrollable/iframe.ts +++ b/src/browser/scrollable/iframe.ts @@ -7,129 +7,129 @@ * Represents a window in a possible chain of iframes */ interface IWindowChainElement { - /** - * The window object for it - */ - readonly window: WeakRef; - /** - * The iframe element inside the window.parent corresponding to window - */ - readonly iframeElement: Element | null; + /** + * The window object for it + */ + readonly window: WeakRef; + /** + * The iframe element inside the window.parent corresponding to window + */ + readonly iframeElement: Element | null; } const sameOriginWindowChainCache = new WeakMap(); function getParentWindowIfSameOrigin(w: Window): Window | null { - if (!w.parent || w.parent === w) { - return null; - } + if (!w.parent || w.parent === w) { + return null; + } - // Cannot really tell if we have access to the parent window unless we try to access something in it - try { - const location = w.location; - const parentLocation = w.parent.location; - if (location.origin !== 'null' && parentLocation.origin !== 'null' && location.origin !== parentLocation.origin) { - return null; - } - } catch (e) { - return null; - } + // Cannot really tell if we have access to the parent window unless we try to access something in it + try { + const location = w.location; + const parentLocation = w.parent.location; + if (location.origin !== 'null' && parentLocation.origin !== 'null' && location.origin !== parentLocation.origin) { + return null; + } + } catch (e) { + return null; + } - return w.parent; + return w.parent; } export class IframeUtils { - /** - * Returns a chain of embedded windows with the same origin (which can be accessed programmatically). - * Having a chain of length 1 might mean that the current execution environment is running outside of an iframe or inside an iframe embedded in a window with a different origin. - */ - private static getSameOriginWindowChain(targetWindow: Window): IWindowChainElement[] { - let windowChainCache = sameOriginWindowChainCache.get(targetWindow); - if (!windowChainCache) { - windowChainCache = []; - sameOriginWindowChainCache.set(targetWindow, windowChainCache); - let w: Window | null = targetWindow; - let parent: Window | null; - do { - parent = getParentWindowIfSameOrigin(w); - if (parent) { - windowChainCache.push({ - window: new WeakRef(w), - iframeElement: w.frameElement || null - }); - } else { - windowChainCache.push({ - window: new WeakRef(w), - iframeElement: null - }); - } - w = parent; - } while (w); - } - return windowChainCache.slice(0); - } + /** + * Returns a chain of embedded windows with the same origin (which can be accessed programmatically). + * Having a chain of length 1 might mean that the current execution environment is running outside of an iframe or inside an iframe embedded in a window with a different origin. + */ + private static getSameOriginWindowChain(targetWindow: Window): IWindowChainElement[] { + let windowChainCache = sameOriginWindowChainCache.get(targetWindow); + if (!windowChainCache) { + windowChainCache = []; + sameOriginWindowChainCache.set(targetWindow, windowChainCache); + let w: Window | null = targetWindow; + let parent: Window | null; + do { + parent = getParentWindowIfSameOrigin(w); + if (parent) { + windowChainCache.push({ + window: new WeakRef(w), + iframeElement: w.frameElement || null + }); + } else { + windowChainCache.push({ + window: new WeakRef(w), + iframeElement: null + }); + } + w = parent; + } while (w); + } + return windowChainCache.slice(0); + } - /** - * Returns the position of `childWindow` relative to `ancestorWindow` - */ - public static getPositionOfChildWindowRelativeToAncestorWindow(childWindow: Window, ancestorWindow: Window | null) { + /** + * Returns the position of `childWindow` relative to `ancestorWindow` + */ + public static getPositionOfChildWindowRelativeToAncestorWindow(childWindow: Window, ancestorWindow: Window | null) { - if (!ancestorWindow || childWindow === ancestorWindow) { - return { - top: 0, - left: 0 - }; - } + if (!ancestorWindow || childWindow === ancestorWindow) { + return { + top: 0, + left: 0 + }; + } - let top = 0, left = 0; + let top = 0; let left = 0; - const windowChain = this.getSameOriginWindowChain(childWindow); + const windowChain = this.getSameOriginWindowChain(childWindow); - for (const windowChainEl of windowChain) { - const windowInChain = windowChainEl.window.deref(); - top += windowInChain?.scrollY ?? 0; - left += windowInChain?.scrollX ?? 0; + for (const windowChainEl of windowChain) { + const windowInChain = windowChainEl.window.deref(); + top += windowInChain?.scrollY ?? 0; + left += windowInChain?.scrollX ?? 0; - if (windowInChain === ancestorWindow) { - break; - } + if (windowInChain === ancestorWindow) { + break; + } - if (!windowChainEl.iframeElement) { - break; - } + if (!windowChainEl.iframeElement) { + break; + } - const boundingRect = windowChainEl.iframeElement.getBoundingClientRect(); - top += boundingRect.top; - left += boundingRect.left; - } + const boundingRect = windowChainEl.iframeElement.getBoundingClientRect(); + top += boundingRect.top; + left += boundingRect.left; + } - return { - top: top, - left: left - }; - } + return { + top: top, + left: left + }; + } } /** * Returns a sha-256 composed of `parentOrigin` and `salt` converted to base 32 */ export async function parentOriginHash(parentOrigin: string, salt: string): Promise { - // This same code is also inlined at `src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html` - if (!crypto.subtle) { - throw new Error(`'crypto.subtle' is not available so webviews will not work. This is likely because the editor is not running in a secure context (https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts).`); - } + // This same code is also inlined at `src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html` + if (!crypto.subtle) { + throw new Error(`'crypto.subtle' is not available so webviews will not work. This is likely because the editor is not running in a secure context (https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts).`); + } - const strData = JSON.stringify({ parentOrigin, salt }); - const encoder = new TextEncoder(); - const arrData = encoder.encode(strData); - const hash = await crypto.subtle.digest('sha-256', arrData); - return sha256AsBase32(hash); + const strData = JSON.stringify({ parentOrigin, salt }); + const encoder = new TextEncoder(); + const arrData = encoder.encode(strData); + const hash = await crypto.subtle.digest('sha-256', arrData); + return sha256AsBase32(hash); } function sha256AsBase32(bytes: ArrayBuffer): string { - const array = Array.from(new Uint8Array(bytes)); - const hexArray = array.map(b => b.toString(16).padStart(2, '0')).join(''); - // sha256 has 256 bits, so we need at most ceil(lg(2^256-1)/lg(32)) = 52 chars to represent it in base 32 - return BigInt(`0x${hexArray}`).toString(32).padStart(52, '0'); + const array = Array.from(new Uint8Array(bytes)); + const hexArray = array.map(b => b.toString(16).padStart(2, '0')).join(''); + // sha256 has 256 bits, so we need at most ceil(lg(2^256-1)/lg(32)) = 52 chars to represent it in base 32 + return BigInt(`0x${hexArray}`).toString(32).padStart(52, '0'); } diff --git a/src/browser/scrollable/iterator.ts b/src/browser/scrollable/iterator.ts index c329ed6d..5430bac4 100644 --- a/src/browser/scrollable/iterator.ts +++ b/src/browser/scrollable/iterator.ts @@ -5,155 +5,155 @@ export namespace Iterable { - export function is(thing: any): thing is Iterable { - return thing && typeof thing === 'object' && typeof thing[Symbol.iterator] === 'function'; - } + export function is(thing: any): thing is Iterable { + return thing && typeof thing === 'object' && typeof thing[Symbol.iterator] === 'function'; + } - const _empty: Iterable = Object.freeze([]); - export function empty(): Iterable { - return _empty; - } + const _empty: Iterable = Object.freeze([]); + export function empty(): Iterable { + return _empty; + } - export function* single(element: T): Iterable { - yield element; - } + export function* single(element: T): Iterable { + yield element; + } - export function wrap(iterableOrElement: Iterable | T): Iterable { - if (is(iterableOrElement)) { - return iterableOrElement; - } else { - return single(iterableOrElement); - } - } + export function wrap(iterableOrElement: Iterable | T): Iterable { + if (is(iterableOrElement)) { + return iterableOrElement; + } + return single(iterableOrElement); - export function from(iterable: Iterable | undefined | null): Iterable { - return iterable || _empty; - } + } - export function* reverse(array: Array): Iterable { - for (let i = array.length - 1; i >= 0; i--) { - yield array[i]; - } - } + export function from(iterable: Iterable | undefined | null): Iterable { + return iterable || _empty; + } - export function isEmpty(iterable: Iterable | undefined | null): boolean { - return !iterable || iterable[Symbol.iterator]().next().done === true; - } + export function* reverse(array: T[]): Iterable { + for (let i = array.length - 1; i >= 0; i--) { + yield array[i]; + } + } - export function first(iterable: Iterable): T | undefined { - return iterable[Symbol.iterator]().next().value; - } + export function isEmpty(iterable: Iterable | undefined | null): boolean { + return !iterable || iterable[Symbol.iterator]().next().done === true; + } - export function some(iterable: Iterable, predicate: (t: T, i: number) => unknown): boolean { - let i = 0; - for (const element of iterable) { - if (predicate(element, i++)) { - return true; - } - } - return false; - } + export function first(iterable: Iterable): T | undefined { + return iterable[Symbol.iterator]().next().value; + } - export function find(iterable: Iterable, predicate: (t: T) => t is R): R | undefined; - export function find(iterable: Iterable, predicate: (t: T) => boolean): T | undefined; - export function find(iterable: Iterable, predicate: (t: T) => boolean): T | undefined { - for (const element of iterable) { - if (predicate(element)) { - return element; - } - } + export function some(iterable: Iterable, predicate: (t: T, i: number) => unknown): boolean { + let i = 0; + for (const element of iterable) { + if (predicate(element, i++)) { + return true; + } + } + return false; + } - return undefined; - } + export function find(iterable: Iterable, predicate: (t: T) => t is R): R | undefined; + export function find(iterable: Iterable, predicate: (t: T) => boolean): T | undefined; + export function find(iterable: Iterable, predicate: (t: T) => boolean): T | undefined { + for (const element of iterable) { + if (predicate(element)) { + return element; + } + } - export function filter(iterable: Iterable, predicate: (t: T) => t is R): Iterable; - export function filter(iterable: Iterable, predicate: (t: T) => boolean): Iterable; - export function* filter(iterable: Iterable, predicate: (t: T) => boolean): Iterable { - for (const element of iterable) { - if (predicate(element)) { - yield element; - } - } - } + return undefined; + } - export function* map(iterable: Iterable, fn: (t: T, index: number) => R): Iterable { - let index = 0; - for (const element of iterable) { - yield fn(element, index++); - } - } + export function filter(iterable: Iterable, predicate: (t: T) => t is R): Iterable; + export function filter(iterable: Iterable, predicate: (t: T) => boolean): Iterable; + export function* filter(iterable: Iterable, predicate: (t: T) => boolean): Iterable { + for (const element of iterable) { + if (predicate(element)) { + yield element; + } + } + } - export function* flatMap(iterable: Iterable, fn: (t: T, index: number) => Iterable): Iterable { - let index = 0; - for (const element of iterable) { - yield* fn(element, index++); - } - } + export function* map(iterable: Iterable, fn: (t: T, index: number) => R): Iterable { + let index = 0; + for (const element of iterable) { + yield fn(element, index++); + } + } - export function* concat(...iterables: Iterable[]): Iterable { - for (const iterable of iterables) { - yield* iterable; - } - } + export function* flatMap(iterable: Iterable, fn: (t: T, index: number) => Iterable): Iterable { + let index = 0; + for (const element of iterable) { + yield* fn(element, index++); + } + } - export function reduce(iterable: Iterable, reducer: (previousValue: R, currentValue: T) => R, initialValue: R): R { - let value = initialValue; - for (const element of iterable) { - value = reducer(value, element); - } - return value; - } + export function* concat(...iterables: Iterable[]): Iterable { + for (const iterable of iterables) { + yield* iterable; + } + } - /** - * Returns an iterable slice of the array, with the same semantics as `array.slice()`. - */ - export function* slice(arr: ReadonlyArray, from: number, to = arr.length): Iterable { - if (from < 0) { - from += arr.length; - } + export function reduce(iterable: Iterable, reducer: (previousValue: R, currentValue: T) => R, initialValue: R): R { + let value = initialValue; + for (const element of iterable) { + value = reducer(value, element); + } + return value; + } - if (to < 0) { - to += arr.length; - } else if (to > arr.length) { - to = arr.length; - } + /** + * Returns an iterable slice of the array, with the same semantics as `array.slice()`. + */ + export function* slice(arr: ReadonlyArray, from: number, to = arr.length): Iterable { + if (from < 0) { + from += arr.length; + } - for (; from < to; from++) { - yield arr[from]; - } - } + if (to < 0) { + to += arr.length; + } else if (to > arr.length) { + to = arr.length; + } - /** - * Consumes `atMost` elements from iterable and returns the consumed elements, - * and an iterable for the rest of the elements. - */ - export function consume(iterable: Iterable, atMost: number = Number.POSITIVE_INFINITY): [T[], Iterable] { - const consumed: T[] = []; + for (; from < to; from++) { + yield arr[from]; + } + } - if (atMost === 0) { - return [consumed, iterable]; - } + /** + * Consumes `atMost` elements from iterable and returns the consumed elements, + * and an iterable for the rest of the elements. + */ + export function consume(iterable: Iterable, atMost: number = Number.POSITIVE_INFINITY): [T[], Iterable] { + const consumed: T[] = []; - const iterator = iterable[Symbol.iterator](); + if (atMost === 0) { + return [consumed, iterable]; + } - for (let i = 0; i < atMost; i++) { - const next = iterator.next(); + const iterator = iterable[Symbol.iterator](); - if (next.done) { - return [consumed, Iterable.empty()]; - } + for (let i = 0; i < atMost; i++) { + const next = iterator.next(); - consumed.push(next.value); - } + if (next.done) { + return [consumed, Iterable.empty()]; + } - return [consumed, { [Symbol.iterator]() { return iterator; } }]; - } + consumed.push(next.value); + } - export async function asyncToArray(iterable: AsyncIterable): Promise { - const result: T[] = []; - for await (const item of iterable) { - result.push(item); - } - return Promise.resolve(result); - } + return [consumed, { [Symbol.iterator]() { return iterator; } }]; + } + + export async function asyncToArray(iterable: AsyncIterable): Promise { + const result: T[] = []; + for await (const item of iterable) { + result.push(item); + } + return Promise.resolve(result); + } } diff --git a/src/browser/scrollable/linkedList.ts b/src/browser/scrollable/linkedList.ts index 42a1c2aa..80a4751c 100644 --- a/src/browser/scrollable/linkedList.ts +++ b/src/browser/scrollable/linkedList.ts @@ -5,138 +5,138 @@ class Node { - static readonly Undefined = new Node(undefined); + static readonly Undefined = new Node(undefined); - element: E; - next: Node; - prev: Node; + element: E; + next: Node; + prev: Node; - constructor(element: E) { - this.element = element; - this.next = Node.Undefined; - this.prev = Node.Undefined; - } + constructor(element: E) { + this.element = element; + this.next = Node.Undefined; + this.prev = Node.Undefined; + } } export class LinkedList { - private _first: Node = Node.Undefined; - private _last: Node = Node.Undefined; - private _size: number = 0; + private _first: Node = Node.Undefined; + private _last: Node = Node.Undefined; + private _size: number = 0; - get size(): number { - return this._size; - } + get size(): number { + return this._size; + } - isEmpty(): boolean { - return this._first === Node.Undefined; - } + isEmpty(): boolean { + return this._first === Node.Undefined; + } - clear(): void { - let node = this._first; - while (node !== Node.Undefined) { - const next = node.next; - node.prev = Node.Undefined; - node.next = Node.Undefined; - node = next; - } + clear(): void { + let node = this._first; + while (node !== Node.Undefined) { + const next = node.next; + node.prev = Node.Undefined; + node.next = Node.Undefined; + node = next; + } - this._first = Node.Undefined; - this._last = Node.Undefined; - this._size = 0; - } + this._first = Node.Undefined; + this._last = Node.Undefined; + this._size = 0; + } - unshift(element: E): () => void { - return this._insert(element, false); - } + unshift(element: E): () => void { + return this._insert(element, false); + } - push(element: E): () => void { - return this._insert(element, true); - } + push(element: E): () => void { + return this._insert(element, true); + } - private _insert(element: E, atTheEnd: boolean): () => void { - const newNode = new Node(element); - if (this._first === Node.Undefined) { - this._first = newNode; - this._last = newNode; + private _insert(element: E, atTheEnd: boolean): () => void { + const newNode = new Node(element); + if (this._first === Node.Undefined) { + this._first = newNode; + this._last = newNode; - } else if (atTheEnd) { - // push - const oldLast = this._last; - this._last = newNode; - newNode.prev = oldLast; - oldLast.next = newNode; + } else if (atTheEnd) { + // push + const oldLast = this._last; + this._last = newNode; + newNode.prev = oldLast; + oldLast.next = newNode; - } else { - // unshift - const oldFirst = this._first; - this._first = newNode; - newNode.next = oldFirst; - oldFirst.prev = newNode; - } - this._size += 1; + } else { + // unshift + const oldFirst = this._first; + this._first = newNode; + newNode.next = oldFirst; + oldFirst.prev = newNode; + } + this._size += 1; - let didRemove = false; - return () => { - if (!didRemove) { - didRemove = true; - this._remove(newNode); - } - }; - } + let didRemove = false; + return () => { + if (!didRemove) { + didRemove = true; + this._remove(newNode); + } + }; + } - shift(): E | undefined { - if (this._first === Node.Undefined) { - return undefined; - } else { - const res = this._first.element; - this._remove(this._first); - return res; - } - } + shift(): E | undefined { + if (this._first === Node.Undefined) { + return undefined; + } + const res = this._first.element; + this._remove(this._first); + return res; - pop(): E | undefined { - if (this._last === Node.Undefined) { - return undefined; - } else { - const res = this._last.element; - this._remove(this._last); - return res; - } - } + } - private _remove(node: Node): void { - if (node.prev !== Node.Undefined && node.next !== Node.Undefined) { - // middle - const anchor = node.prev; - anchor.next = node.next; - node.next.prev = anchor; + pop(): E | undefined { + if (this._last === Node.Undefined) { + return undefined; + } + const res = this._last.element; + this._remove(this._last); + return res; - } else if (node.prev === Node.Undefined && node.next === Node.Undefined) { - // only node - this._first = Node.Undefined; - this._last = Node.Undefined; + } - } else if (node.next === Node.Undefined) { - // last - this._last = this._last.prev!; - this._last.next = Node.Undefined; + private _remove(node: Node): void { + if (node.prev !== Node.Undefined && node.next !== Node.Undefined) { + // middle + const anchor = node.prev; + anchor.next = node.next; + node.next.prev = anchor; - } else if (node.prev === Node.Undefined) { - // first - this._first = this._first.next!; - this._first.prev = Node.Undefined; - } + } else if (node.prev === Node.Undefined && node.next === Node.Undefined) { + // only node + this._first = Node.Undefined; + this._last = Node.Undefined; - // done - this._size -= 1; - } + } else if (node.next === Node.Undefined) { + // last + this._last = this._last.prev!; + this._last.next = Node.Undefined; - *[Symbol.iterator](): Iterator { - let node = this._first; - while (node !== Node.Undefined) { - yield node.element; - node = node.next; - } - } + } else if (node.prev === Node.Undefined) { + // first + this._first = this._first.next!; + this._first.prev = Node.Undefined; + } + + // done + this._size -= 1; + } + + *[Symbol.iterator](): Iterator { + let node = this._first; + while (node !== Node.Undefined) { + yield node.element; + node = node.next; + } + } } diff --git a/src/browser/scrollable/map.ts b/src/browser/scrollable/map.ts index 5aa55f48..900df9c6 100644 --- a/src/browser/scrollable/map.ts +++ b/src/browser/scrollable/map.ts @@ -4,69 +4,69 @@ *--------------------------------------------------------------------------------------------*/ export function getOrSet(map: Map, key: K, value: V): V { - let result = map.get(key); - if (result === undefined) { - result = value; - map.set(key, result); - } + let result = map.get(key); + if (result === undefined) { + result = value; + map.set(key, result); + } - return result; + return result; } export function mapToString(map: Map): string { - const entries: string[] = []; - map.forEach((value, key) => { - entries.push(`${key} => ${value}`); - }); + const entries: string[] = []; + map.forEach((value, key) => { + entries.push(`${key} => ${value}`); + }); - return `Map(${map.size}) {${entries.join(', ')}}`; + return `Map(${map.size}) {${entries.join(', ')}}`; } export function setToString(set: Set): string { - const entries: K[] = []; - set.forEach(value => { - entries.push(value); - }); + const entries: K[] = []; + set.forEach(value => { + entries.push(value); + }); - return `Set(${set.size}) {${entries.join(', ')}}`; + return `Set(${set.size}) {${entries.join(', ')}}`; } export const enum Touch { - None = 0, - AsOld = 1, - AsNew = 2 + None = 0, + AsOld = 1, + AsNew = 2 } export class CounterSet { - private map = new Map(); + private map = new Map(); - add(value: T): CounterSet { - this.map.set(value, (this.map.get(value) || 0) + 1); - return this; - } + add(value: T): CounterSet { + this.map.set(value, (this.map.get(value) || 0) + 1); + return this; + } - delete(value: T): boolean { - let counter = this.map.get(value) || 0; + delete(value: T): boolean { + let counter = this.map.get(value) || 0; - if (counter === 0) { - return false; - } + if (counter === 0) { + return false; + } - counter--; + counter--; - if (counter === 0) { - this.map.delete(value); - } else { - this.map.set(value, counter); - } + if (counter === 0) { + this.map.delete(value); + } else { + this.map.set(value, counter); + } - return true; - } + return true; + } - has(value: T): boolean { - return this.map.has(value); - } + has(value: T): boolean { + return this.map.has(value); + } } /** @@ -75,128 +75,128 @@ export class CounterSet { */ export class BidirectionalMap { - private readonly _m1 = new Map(); - private readonly _m2 = new Map(); + private readonly _m1 = new Map(); + private readonly _m2 = new Map(); - constructor(entries?: readonly (readonly [K, V])[]) { - if (entries) { - for (const [key, value] of entries) { - this.set(key, value); - } - } - } + constructor(entries?: ReadonlyArray) { + if (entries) { + for (const [key, value] of entries) { + this.set(key, value); + } + } + } - clear(): void { - this._m1.clear(); - this._m2.clear(); - } + clear(): void { + this._m1.clear(); + this._m2.clear(); + } - set(key: K, value: V): void { - this._m1.set(key, value); - this._m2.set(value, key); - } + set(key: K, value: V): void { + this._m1.set(key, value); + this._m2.set(value, key); + } - get(key: K): V | undefined { - return this._m1.get(key); - } + get(key: K): V | undefined { + return this._m1.get(key); + } - getKey(value: V): K | undefined { - return this._m2.get(value); - } + getKey(value: V): K | undefined { + return this._m2.get(value); + } - delete(key: K): boolean { - const value = this._m1.get(key); - if (value === undefined) { - return false; - } - this._m1.delete(key); - this._m2.delete(value); - return true; - } + delete(key: K): boolean { + const value = this._m1.get(key); + if (value === undefined) { + return false; + } + this._m1.delete(key); + this._m2.delete(value); + return true; + } - forEach(callbackfn: (value: V, key: K, map: BidirectionalMap) => void, thisArg?: any): void { - this._m1.forEach((value, key) => { - callbackfn.call(thisArg, value, key, this); - }); - } + forEach(callbackfn: (value: V, key: K, map: BidirectionalMap) => void, thisArg?: any): void { + this._m1.forEach((value, key) => { + callbackfn.call(thisArg, value, key, this); + }); + } - keys(): IterableIterator { - return this._m1.keys(); - } + keys(): IterableIterator { + return this._m1.keys(); + } - values(): IterableIterator { - return this._m1.values(); - } + values(): IterableIterator { + return this._m1.values(); + } } export class SetMap { - private map = new Map>(); + private map = new Map>(); - add(key: K, value: V): void { - let values = this.map.get(key); + add(key: K, value: V): void { + let values = this.map.get(key); - if (!values) { - values = new Set(); - this.map.set(key, values); - } + if (!values) { + values = new Set(); + this.map.set(key, values); + } - values.add(value); - } + values.add(value); + } - delete(key: K, value: V): void { - const values = this.map.get(key); + delete(key: K, value: V): void { + const values = this.map.get(key); - if (!values) { - return; - } + if (!values) { + return; + } - values.delete(value); + values.delete(value); - if (values.size === 0) { - this.map.delete(key); - } - } + if (values.size === 0) { + this.map.delete(key); + } + } - forEach(key: K, fn: (value: V) => void): void { - const values = this.map.get(key); + forEach(key: K, fn: (value: V) => void): void { + const values = this.map.get(key); - if (!values) { - return; - } + if (!values) { + return; + } - values.forEach(fn); - } + values.forEach(fn); + } - get(key: K): ReadonlySet { - const values = this.map.get(key); - if (!values) { - return new Set(); - } - return values; - } + get(key: K): ReadonlySet { + const values = this.map.get(key); + if (!values) { + return new Set(); + } + return values; + } } export function mapsStrictEqualIgnoreOrder(a: Map, b: Map): boolean { - if (a === b) { - return true; - } + if (a === b) { + return true; + } - if (a.size !== b.size) { - return false; - } + if (a.size !== b.size) { + return false; + } - for (const [key, value] of a) { - if (!b.has(key) || b.get(key) !== value) { - return false; - } - } + for (const [key, value] of a) { + if (!b.has(key) || b.get(key) !== value) { + return false; + } + } - for (const [key] of b) { - if (!a.has(key)) { - return false; - } - } + for (const [key] of b) { + if (!a.has(key)) { + return false; + } + } - return true; + return true; } diff --git a/src/browser/scrollable/mouseEvent.ts b/src/browser/scrollable/mouseEvent.ts index 08b8e453..b4ec846a 100644 --- a/src/browser/scrollable/mouseEvent.ts +++ b/src/browser/scrollable/mouseEvent.ts @@ -8,195 +8,195 @@ import { IframeUtils } from './iframe'; import * as platform from './platform'; export interface IMouseEvent { - readonly browserEvent: MouseEvent; - readonly leftButton: boolean; - readonly middleButton: boolean; - readonly rightButton: boolean; - readonly buttons: number; - readonly target: HTMLElement; - readonly detail: number; - readonly posx: number; - readonly posy: number; - readonly ctrlKey: boolean; - readonly shiftKey: boolean; - readonly altKey: boolean; - readonly metaKey: boolean; - readonly timestamp: number; + readonly browserEvent: MouseEvent; + readonly leftButton: boolean; + readonly middleButton: boolean; + readonly rightButton: boolean; + readonly buttons: number; + readonly target: HTMLElement; + readonly detail: number; + readonly posx: number; + readonly posy: number; + readonly ctrlKey: boolean; + readonly shiftKey: boolean; + readonly altKey: boolean; + readonly metaKey: boolean; + readonly timestamp: number; - preventDefault(): void; - stopPropagation(): void; + preventDefault(): void; + stopPropagation(): void; } export class StandardMouseEvent implements IMouseEvent { - public readonly browserEvent: MouseEvent; + public readonly browserEvent: MouseEvent; - public readonly leftButton: boolean; - public readonly middleButton: boolean; - public readonly rightButton: boolean; - public readonly buttons: number; - public readonly target: HTMLElement; - public detail: number; - public readonly posx: number; - public readonly posy: number; - public readonly ctrlKey: boolean; - public readonly shiftKey: boolean; - public readonly altKey: boolean; - public readonly metaKey: boolean; - public readonly timestamp: number; + public readonly leftButton: boolean; + public readonly middleButton: boolean; + public readonly rightButton: boolean; + public readonly buttons: number; + public readonly target: HTMLElement; + public detail: number; + public readonly posx: number; + public readonly posy: number; + public readonly ctrlKey: boolean; + public readonly shiftKey: boolean; + public readonly altKey: boolean; + public readonly metaKey: boolean; + public readonly timestamp: number; - constructor(targetWindow: Window, e: MouseEvent) { - this.timestamp = Date.now(); - this.browserEvent = e; - this.leftButton = e.button === 0; - this.middleButton = e.button === 1; - this.rightButton = e.button === 2; - this.buttons = e.buttons; + constructor(targetWindow: Window, e: MouseEvent) { + this.timestamp = Date.now(); + this.browserEvent = e; + this.leftButton = e.button === 0; + this.middleButton = e.button === 1; + this.rightButton = e.button === 2; + this.buttons = e.buttons; - this.target = e.target as HTMLElement; + this.target = e.target as HTMLElement; - this.detail = e.detail || 1; - if (e.type === 'dblclick') { - this.detail = 2; - } - this.ctrlKey = e.ctrlKey; - this.shiftKey = e.shiftKey; - this.altKey = e.altKey; - this.metaKey = e.metaKey; + this.detail = e.detail || 1; + if (e.type === 'dblclick') { + this.detail = 2; + } + this.ctrlKey = e.ctrlKey; + this.shiftKey = e.shiftKey; + this.altKey = e.altKey; + this.metaKey = e.metaKey; - if (typeof e.pageX === 'number') { - this.posx = e.pageX; - this.posy = e.pageY; - } else { - this.posx = e.clientX + this.target.ownerDocument.body.scrollLeft + this.target.ownerDocument.documentElement.scrollLeft; - this.posy = e.clientY + this.target.ownerDocument.body.scrollTop + this.target.ownerDocument.documentElement.scrollTop; - } + if (typeof e.pageX === 'number') { + this.posx = e.pageX; + this.posy = e.pageY; + } else { + this.posx = e.clientX + this.target.ownerDocument.body.scrollLeft + this.target.ownerDocument.documentElement.scrollLeft; + this.posy = e.clientY + this.target.ownerDocument.body.scrollTop + this.target.ownerDocument.documentElement.scrollTop; + } - const iframeOffsets = IframeUtils.getPositionOfChildWindowRelativeToAncestorWindow(targetWindow, e.view); - this.posx -= iframeOffsets.left; - this.posy -= iframeOffsets.top; - } + const iframeOffsets = IframeUtils.getPositionOfChildWindowRelativeToAncestorWindow(targetWindow, e.view); + this.posx -= iframeOffsets.left; + this.posy -= iframeOffsets.top; + } - public preventDefault(): void { - this.browserEvent.preventDefault(); - } + public preventDefault(): void { + this.browserEvent.preventDefault(); + } - public stopPropagation(): void { - this.browserEvent.stopPropagation(); - } + public stopPropagation(): void { + this.browserEvent.stopPropagation(); + } } export interface IMouseWheelEvent extends MouseEvent { - readonly wheelDelta: number; - readonly wheelDeltaX: number; - readonly wheelDeltaY: number; + readonly wheelDelta: number; + readonly wheelDeltaX: number; + readonly wheelDeltaY: number; - readonly deltaX: number; - readonly deltaY: number; - readonly deltaZ: number; - readonly deltaMode: number; + readonly deltaX: number; + readonly deltaY: number; + readonly deltaZ: number; + readonly deltaMode: number; } interface IWebKitMouseWheelEvent { - wheelDeltaY: number; - wheelDeltaX: number; + wheelDeltaY: number; + wheelDeltaX: number; } interface IGeckoMouseWheelEvent { - HORIZONTAL_AXIS: number; - VERTICAL_AXIS: number; - axis: number; - detail: number; + HORIZONTAL_AXIS: number; + VERTICAL_AXIS: number; + axis: number; + detail: number; } export class StandardWheelEvent { - public readonly browserEvent: IMouseWheelEvent | null; - public readonly deltaY: number; - public readonly deltaX: number; - public readonly target: Node | null; + public readonly browserEvent: IMouseWheelEvent | null; + public readonly deltaY: number; + public readonly deltaX: number; + public readonly target: Node | null; - constructor(e: IMouseWheelEvent | null, deltaX: number = 0, deltaY: number = 0) { + constructor(e: IMouseWheelEvent | null, deltaX: number = 0, deltaY: number = 0) { - this.browserEvent = e || null; - this.target = e ? (e.target || (e as any).targetNode || e.srcElement) : null; + this.browserEvent = e || null; + this.target = e ? (e.target || (e as any).targetNode || e.srcElement) : null; - this.deltaY = deltaY; - this.deltaX = deltaX; + this.deltaY = deltaY; + this.deltaX = deltaX; - let shouldFactorDPR: boolean = false; - if (browser.isChrome) { - const chromeVersionMatch = navigator.userAgent.match(/Chrome\/(\d+)/); - const chromeMajorVersion = chromeVersionMatch ? parseInt(chromeVersionMatch[1]) : 123; - shouldFactorDPR = chromeMajorVersion <= 122; - } + let shouldFactorDPR: boolean = false; + if (browser.isChrome) { + const chromeVersionMatch = navigator.userAgent.match(/Chrome\/(\d+)/); + const chromeMajorVersion = chromeVersionMatch ? parseInt(chromeVersionMatch[1]) : 123; + shouldFactorDPR = chromeMajorVersion <= 122; + } - if (e) { - const e1 = e as IWebKitMouseWheelEvent as any; - const e2 = e as unknown as IGeckoMouseWheelEvent; - const devicePixelRatio = e.view?.devicePixelRatio || 1; + if (e) { + const e1 = e as IWebKitMouseWheelEvent as any; + const e2 = e as unknown as IGeckoMouseWheelEvent; + const devicePixelRatio = e.view?.devicePixelRatio || 1; - if (typeof e1.wheelDeltaY !== 'undefined') { - if (shouldFactorDPR) { - this.deltaY = e1.wheelDeltaY / (120 * devicePixelRatio); - } else { - this.deltaY = e1.wheelDeltaY / 120; - } - } else if (typeof e2.VERTICAL_AXIS !== 'undefined' && e2.axis === e2.VERTICAL_AXIS) { - this.deltaY = -e2.detail / 3; - } else if (e.type === 'wheel') { - const ev = e as unknown as WheelEvent; + if (typeof e1.wheelDeltaY !== 'undefined') { + if (shouldFactorDPR) { + this.deltaY = e1.wheelDeltaY / (120 * devicePixelRatio); + } else { + this.deltaY = e1.wheelDeltaY / 120; + } + } else if (typeof e2.VERTICAL_AXIS !== 'undefined' && e2.axis === e2.VERTICAL_AXIS) { + this.deltaY = -e2.detail / 3; + } else if (e.type === 'wheel') { + const ev = e as unknown as WheelEvent; - if (ev.deltaMode === ev.DOM_DELTA_LINE) { - if (browser.isFirefox && !platform.isMacintosh) { - this.deltaY = -e.deltaY / 3; - } else { - this.deltaY = -e.deltaY; - } - } else { - this.deltaY = -e.deltaY / 40; - } - } + if (ev.deltaMode === ev.DOM_DELTA_LINE) { + if (browser.isFirefox && !platform.isMacintosh) { + this.deltaY = -e.deltaY / 3; + } else { + this.deltaY = -e.deltaY; + } + } else { + this.deltaY = -e.deltaY / 40; + } + } - if (typeof e1.wheelDeltaX !== 'undefined') { - if (browser.isSafari && platform.isWindows) { - this.deltaX = -(e1.wheelDeltaX / 120); - } else if (shouldFactorDPR) { - this.deltaX = e1.wheelDeltaX / (120 * devicePixelRatio); - } else { - this.deltaX = e1.wheelDeltaX / 120; - } - } else if (typeof e2.HORIZONTAL_AXIS !== 'undefined' && e2.axis === e2.HORIZONTAL_AXIS) { - this.deltaX = -e.detail / 3; - } else if (e.type === 'wheel') { - const ev = e as unknown as WheelEvent; + if (typeof e1.wheelDeltaX !== 'undefined') { + if (browser.isSafari && platform.isWindows) { + this.deltaX = -(e1.wheelDeltaX / 120); + } else if (shouldFactorDPR) { + this.deltaX = e1.wheelDeltaX / (120 * devicePixelRatio); + } else { + this.deltaX = e1.wheelDeltaX / 120; + } + } else if (typeof e2.HORIZONTAL_AXIS !== 'undefined' && e2.axis === e2.HORIZONTAL_AXIS) { + this.deltaX = -e.detail / 3; + } else if (e.type === 'wheel') { + const ev = e as unknown as WheelEvent; - if (ev.deltaMode === ev.DOM_DELTA_LINE) { - if (browser.isFirefox && !platform.isMacintosh) { - this.deltaX = -e.deltaX / 3; - } else { - this.deltaX = -e.deltaX; - } - } else { - this.deltaX = -e.deltaX / 40; - } - } + if (ev.deltaMode === ev.DOM_DELTA_LINE) { + if (browser.isFirefox && !platform.isMacintosh) { + this.deltaX = -e.deltaX / 3; + } else { + this.deltaX = -e.deltaX; + } + } else { + this.deltaX = -e.deltaX / 40; + } + } - if (this.deltaY === 0 && this.deltaX === 0 && e.wheelDelta) { - if (shouldFactorDPR) { - this.deltaY = e.wheelDelta / (120 * devicePixelRatio); - } else { - this.deltaY = e.wheelDelta / 120; - } - } - } - } + if (this.deltaY === 0 && this.deltaX === 0 && e.wheelDelta) { + if (shouldFactorDPR) { + this.deltaY = e.wheelDelta / (120 * devicePixelRatio); + } else { + this.deltaY = e.wheelDelta / 120; + } + } + } + } - public preventDefault(): void { - this.browserEvent?.preventDefault(); - } + public preventDefault(): void { + this.browserEvent?.preventDefault(); + } - public stopPropagation(): void { - this.browserEvent?.stopPropagation(); - } + public stopPropagation(): void { + this.browserEvent?.stopPropagation(); + } } diff --git a/src/browser/scrollable/numbers.ts b/src/browser/scrollable/numbers.ts index ab4c9f92..78be7f21 100644 --- a/src/browser/scrollable/numbers.ts +++ b/src/browser/scrollable/numbers.ts @@ -4,95 +4,95 @@ *--------------------------------------------------------------------------------------------*/ export function clamp(value: number, min: number, max: number): number { - return Math.min(Math.max(value, min), max); + return Math.min(Math.max(value, min), max); } export function rot(index: number, modulo: number): number { - return (modulo + (index % modulo)) % modulo; + return (modulo + (index % modulo)) % modulo; } export class Counter { - private _next = 0; + private _next = 0; - getNext(): number { - return this._next++; - } + getNext(): number { + return this._next++; + } } export class MovingAverage { - private _n = 1; - private _val = 0; + private _n = 1; + private _val = 0; - update(value: number): number { - this._val = this._val + (value - this._val) / this._n; - this._n += 1; - return this._val; - } + update(value: number): number { + this._val = this._val + (value - this._val) / this._n; + this._n += 1; + return this._val; + } - get value(): number { - return this._val; - } + get value(): number { + return this._val; + } } export class SlidingWindowAverage { - private _n: number = 0; - private _val = 0; + private _n: number = 0; + private _val = 0; - private readonly _values: number[] = []; - private _index: number = 0; - private _sum = 0; + private readonly _values: number[] = []; + private _index: number = 0; + private _sum = 0; - constructor(size: number) { - this._values = new Array(size); - this._values.fill(0, 0, size); - } + constructor(size: number) { + this._values = new Array(size); + this._values.fill(0, 0, size); + } - update(value: number): number { - const oldValue = this._values[this._index]; - this._values[this._index] = value; - this._index = (this._index + 1) % this._values.length; + update(value: number): number { + const oldValue = this._values[this._index]; + this._values[this._index] = value; + this._index = (this._index + 1) % this._values.length; - this._sum -= oldValue; - this._sum += value; + this._sum -= oldValue; + this._sum += value; - if (this._n < this._values.length) { - this._n += 1; - } + if (this._n < this._values.length) { + this._n += 1; + } - this._val = this._sum / this._n; - return this._val; - } + this._val = this._sum / this._n; + return this._val; + } - get value(): number { - return this._val; - } + get value(): number { + return this._val; + } } /** Returns whether the point is within the triangle formed by the following 6 x/y point pairs */ export function isPointWithinTriangle( - x: number, y: number, - ax: number, ay: number, - bx: number, by: number, - cx: number, cy: number + x: number, y: number, + ax: number, ay: number, + bx: number, by: number, + cx: number, cy: number ) { - const v0x = cx - ax; - const v0y = cy - ay; - const v1x = bx - ax; - const v1y = by - ay; - const v2x = x - ax; - const v2y = y - ay; + const v0x = cx - ax; + const v0y = cy - ay; + const v1x = bx - ax; + const v1y = by - ay; + const v2x = x - ax; + const v2y = y - ay; - const dot00 = v0x * v0x + v0y * v0y; - const dot01 = v0x * v1x + v0y * v1y; - const dot02 = v0x * v2x + v0y * v2y; - const dot11 = v1x * v1x + v1y * v1y; - const dot12 = v1x * v2x + v1y * v2y; + const dot00 = v0x * v0x + v0y * v0y; + const dot01 = v0x * v1x + v0y * v1y; + const dot02 = v0x * v2x + v0y * v2y; + const dot11 = v1x * v1x + v1y * v1y; + const dot12 = v1x * v2x + v1y * v2y; - const invDenom = 1 / (dot00 * dot11 - dot01 * dot01); - const u = (dot11 * dot02 - dot01 * dot12) * invDenom; - const v = (dot00 * dot12 - dot01 * dot02) * invDenom; + const invDenom = 1 / (dot00 * dot11 - dot01 * dot01); + const u = (dot11 * dot02 - dot01 * dot12) * invDenom; + const v = (dot00 * dot12 - dot01 * dot02) * invDenom; - return u >= 0 && v >= 0 && u + v < 1; + return u >= 0 && v >= 0 && u + v < 1; } diff --git a/src/browser/scrollable/scrollable.ts b/src/browser/scrollable/scrollable.ts index 5935fdcd..7e3f5858 100644 --- a/src/browser/scrollable/scrollable.ts +++ b/src/browser/scrollable/scrollable.ts @@ -7,104 +7,104 @@ import { Emitter, Event } from './event'; import { Disposable, IDisposable } from './lifecycle'; export const enum ScrollbarVisibility { - Auto = 1, - Hidden = 2, - Visible = 3 + Auto = 1, + Hidden = 2, + Visible = 3 } export interface ScrollEvent { - inSmoothScrolling: boolean; + inSmoothScrolling: boolean; - oldWidth: number; - oldScrollWidth: number; - oldScrollLeft: number; + oldWidth: number; + oldScrollWidth: number; + oldScrollLeft: number; - width: number; - scrollWidth: number; - scrollLeft: number; + width: number; + scrollWidth: number; + scrollLeft: number; - oldHeight: number; - oldScrollHeight: number; - oldScrollTop: number; + oldHeight: number; + oldScrollHeight: number; + oldScrollTop: number; - height: number; - scrollHeight: number; - scrollTop: number; + height: number; + scrollHeight: number; + scrollTop: number; - widthChanged: boolean; - scrollWidthChanged: boolean; - scrollLeftChanged: boolean; + widthChanged: boolean; + scrollWidthChanged: boolean; + scrollLeftChanged: boolean; - heightChanged: boolean; - scrollHeightChanged: boolean; - scrollTopChanged: boolean; + heightChanged: boolean; + scrollHeightChanged: boolean; + scrollTopChanged: boolean; } export class ScrollState implements IScrollDimensions, IScrollPosition { - _scrollStateBrand: void = undefined; + _scrollStateBrand: void = undefined; - public readonly rawScrollLeft: number; - public readonly rawScrollTop: number; + public readonly rawScrollLeft: number; + public readonly rawScrollTop: number; - public readonly width: number; - public readonly scrollWidth: number; - public readonly scrollLeft: number; - public readonly height: number; - public readonly scrollHeight: number; - public readonly scrollTop: number; + public readonly width: number; + public readonly scrollWidth: number; + public readonly scrollLeft: number; + public readonly height: number; + public readonly scrollHeight: number; + public readonly scrollTop: number; - constructor( - private readonly _forceIntegerValues: boolean, - width: number, - scrollWidth: number, - scrollLeft: number, - height: number, - scrollHeight: number, - scrollTop: number - ) { - if (this._forceIntegerValues) { - width = width | 0; - scrollWidth = scrollWidth | 0; - scrollLeft = scrollLeft | 0; - height = height | 0; - scrollHeight = scrollHeight | 0; - scrollTop = scrollTop | 0; - } + constructor( + private readonly _forceIntegerValues: boolean, + width: number, + scrollWidth: number, + scrollLeft: number, + height: number, + scrollHeight: number, + scrollTop: number + ) { + if (this._forceIntegerValues) { + width = width | 0; + scrollWidth = scrollWidth | 0; + scrollLeft = scrollLeft | 0; + height = height | 0; + scrollHeight = scrollHeight | 0; + scrollTop = scrollTop | 0; + } - this.rawScrollLeft = scrollLeft; - this.rawScrollTop = scrollTop; + this.rawScrollLeft = scrollLeft; + this.rawScrollTop = scrollTop; - if (width < 0) { - width = 0; - } - if (scrollLeft + width > scrollWidth) { - scrollLeft = scrollWidth - width; - } - if (scrollLeft < 0) { - scrollLeft = 0; - } + if (width < 0) { + width = 0; + } + if (scrollLeft + width > scrollWidth) { + scrollLeft = scrollWidth - width; + } + if (scrollLeft < 0) { + scrollLeft = 0; + } - if (height < 0) { - height = 0; - } - if (scrollTop + height > scrollHeight) { - scrollTop = scrollHeight - height; - } - if (scrollTop < 0) { - scrollTop = 0; - } + if (height < 0) { + height = 0; + } + if (scrollTop + height > scrollHeight) { + scrollTop = scrollHeight - height; + } + if (scrollTop < 0) { + scrollTop = 0; + } - this.width = width; - this.scrollWidth = scrollWidth; - this.scrollLeft = scrollLeft; - this.height = height; - this.scrollHeight = scrollHeight; - this.scrollTop = scrollTop; - } + this.width = width; + this.scrollWidth = scrollWidth; + this.scrollLeft = scrollLeft; + this.height = height; + this.scrollHeight = scrollHeight; + this.scrollTop = scrollTop; + } - public equals(other: ScrollState): boolean { - return ( - this.rawScrollLeft === other.rawScrollLeft + public equals(other: ScrollState): boolean { + return ( + this.rawScrollLeft === other.rawScrollLeft && this.rawScrollTop === other.rawScrollTop && this.width === other.width && this.scrollWidth === other.scrollWidth @@ -112,379 +112,379 @@ export class ScrollState implements IScrollDimensions, IScrollPosition { && this.height === other.height && this.scrollHeight === other.scrollHeight && this.scrollTop === other.scrollTop - ); - } + ); + } - public withScrollDimensions(update: INewScrollDimensions, useRawScrollPositions: boolean): ScrollState { - return new ScrollState( - this._forceIntegerValues, - (typeof update.width !== 'undefined' ? update.width : this.width), - (typeof update.scrollWidth !== 'undefined' ? update.scrollWidth : this.scrollWidth), - useRawScrollPositions ? this.rawScrollLeft : this.scrollLeft, - (typeof update.height !== 'undefined' ? update.height : this.height), - (typeof update.scrollHeight !== 'undefined' ? update.scrollHeight : this.scrollHeight), - useRawScrollPositions ? this.rawScrollTop : this.scrollTop - ); - } + public withScrollDimensions(update: INewScrollDimensions, useRawScrollPositions: boolean): ScrollState { + return new ScrollState( + this._forceIntegerValues, + (typeof update.width !== 'undefined' ? update.width : this.width), + (typeof update.scrollWidth !== 'undefined' ? update.scrollWidth : this.scrollWidth), + useRawScrollPositions ? this.rawScrollLeft : this.scrollLeft, + (typeof update.height !== 'undefined' ? update.height : this.height), + (typeof update.scrollHeight !== 'undefined' ? update.scrollHeight : this.scrollHeight), + useRawScrollPositions ? this.rawScrollTop : this.scrollTop + ); + } - public withScrollPosition(update: INewScrollPosition): ScrollState { - return new ScrollState( - this._forceIntegerValues, - this.width, - this.scrollWidth, - (typeof update.scrollLeft !== 'undefined' ? update.scrollLeft : this.rawScrollLeft), - this.height, - this.scrollHeight, - (typeof update.scrollTop !== 'undefined' ? update.scrollTop : this.rawScrollTop) - ); - } + public withScrollPosition(update: INewScrollPosition): ScrollState { + return new ScrollState( + this._forceIntegerValues, + this.width, + this.scrollWidth, + (typeof update.scrollLeft !== 'undefined' ? update.scrollLeft : this.rawScrollLeft), + this.height, + this.scrollHeight, + (typeof update.scrollTop !== 'undefined' ? update.scrollTop : this.rawScrollTop) + ); + } - public createScrollEvent(previous: ScrollState, inSmoothScrolling: boolean): ScrollEvent { - const widthChanged = (this.width !== previous.width); - const scrollWidthChanged = (this.scrollWidth !== previous.scrollWidth); - const scrollLeftChanged = (this.scrollLeft !== previous.scrollLeft); + public createScrollEvent(previous: ScrollState, inSmoothScrolling: boolean): ScrollEvent { + const widthChanged = (this.width !== previous.width); + const scrollWidthChanged = (this.scrollWidth !== previous.scrollWidth); + const scrollLeftChanged = (this.scrollLeft !== previous.scrollLeft); - const heightChanged = (this.height !== previous.height); - const scrollHeightChanged = (this.scrollHeight !== previous.scrollHeight); - const scrollTopChanged = (this.scrollTop !== previous.scrollTop); + const heightChanged = (this.height !== previous.height); + const scrollHeightChanged = (this.scrollHeight !== previous.scrollHeight); + const scrollTopChanged = (this.scrollTop !== previous.scrollTop); - return { - inSmoothScrolling: inSmoothScrolling, - oldWidth: previous.width, - oldScrollWidth: previous.scrollWidth, - oldScrollLeft: previous.scrollLeft, + return { + inSmoothScrolling: inSmoothScrolling, + oldWidth: previous.width, + oldScrollWidth: previous.scrollWidth, + oldScrollLeft: previous.scrollLeft, - width: this.width, - scrollWidth: this.scrollWidth, - scrollLeft: this.scrollLeft, + width: this.width, + scrollWidth: this.scrollWidth, + scrollLeft: this.scrollLeft, - oldHeight: previous.height, - oldScrollHeight: previous.scrollHeight, - oldScrollTop: previous.scrollTop, + oldHeight: previous.height, + oldScrollHeight: previous.scrollHeight, + oldScrollTop: previous.scrollTop, - height: this.height, - scrollHeight: this.scrollHeight, - scrollTop: this.scrollTop, + height: this.height, + scrollHeight: this.scrollHeight, + scrollTop: this.scrollTop, - widthChanged: widthChanged, - scrollWidthChanged: scrollWidthChanged, - scrollLeftChanged: scrollLeftChanged, + widthChanged: widthChanged, + scrollWidthChanged: scrollWidthChanged, + scrollLeftChanged: scrollLeftChanged, - heightChanged: heightChanged, - scrollHeightChanged: scrollHeightChanged, - scrollTopChanged: scrollTopChanged, - }; - } + heightChanged: heightChanged, + scrollHeightChanged: scrollHeightChanged, + scrollTopChanged: scrollTopChanged, + }; + } } export interface IScrollDimensions { - readonly width: number; - readonly scrollWidth: number; - readonly height: number; - readonly scrollHeight: number; + readonly width: number; + readonly scrollWidth: number; + readonly height: number; + readonly scrollHeight: number; } export interface INewScrollDimensions { - width?: number; - scrollWidth?: number; - height?: number; - scrollHeight?: number; + width?: number; + scrollWidth?: number; + height?: number; + scrollHeight?: number; } export interface IScrollPosition { - readonly scrollLeft: number; - readonly scrollTop: number; + readonly scrollLeft: number; + readonly scrollTop: number; } export interface ISmoothScrollPosition { - readonly scrollLeft: number; - readonly scrollTop: number; + readonly scrollLeft: number; + readonly scrollTop: number; - readonly width: number; - readonly height: number; + readonly width: number; + readonly height: number; } export interface INewScrollPosition { - scrollLeft?: number; - scrollTop?: number; + scrollLeft?: number; + scrollTop?: number; } export interface IScrollableOptions { - forceIntegerValues: boolean; - smoothScrollDuration: number; - scheduleAtNextAnimationFrame: (callback: () => void) => IDisposable; + forceIntegerValues: boolean; + smoothScrollDuration: number; + scheduleAtNextAnimationFrame: (callback: () => void) => IDisposable; } export class Scrollable extends Disposable { - _scrollableBrand: void = undefined; + _scrollableBrand: void = undefined; - private _smoothScrollDuration: number; - private readonly _scheduleAtNextAnimationFrame: (callback: () => void) => IDisposable; - private _state: ScrollState; - private _smoothScrolling: SmoothScrollingOperation | null; + private _smoothScrollDuration: number; + private readonly _scheduleAtNextAnimationFrame: (callback: () => void) => IDisposable; + private _state: ScrollState; + private _smoothScrolling: SmoothScrollingOperation | null; - private _onScroll = this._register(new Emitter()); - public readonly onScroll: Event = this._onScroll.event; + private _onScroll = this._register(new Emitter()); + public readonly onScroll: Event = this._onScroll.event; - constructor(options: IScrollableOptions) { - super(); + constructor(options: IScrollableOptions) { + super(); - this._smoothScrollDuration = options.smoothScrollDuration; - this._scheduleAtNextAnimationFrame = options.scheduleAtNextAnimationFrame; - this._state = new ScrollState(options.forceIntegerValues, 0, 0, 0, 0, 0, 0); - this._smoothScrolling = null; - } + this._smoothScrollDuration = options.smoothScrollDuration; + this._scheduleAtNextAnimationFrame = options.scheduleAtNextAnimationFrame; + this._state = new ScrollState(options.forceIntegerValues, 0, 0, 0, 0, 0, 0); + this._smoothScrolling = null; + } - public override dispose(): void { - if (this._smoothScrolling) { - this._smoothScrolling.dispose(); - this._smoothScrolling = null; - } - super.dispose(); - } + public override dispose(): void { + if (this._smoothScrolling) { + this._smoothScrolling.dispose(); + this._smoothScrolling = null; + } + super.dispose(); + } - public setSmoothScrollDuration(smoothScrollDuration: number): void { - this._smoothScrollDuration = smoothScrollDuration; - } + public setSmoothScrollDuration(smoothScrollDuration: number): void { + this._smoothScrollDuration = smoothScrollDuration; + } - public validateScrollPosition(scrollPosition: INewScrollPosition): IScrollPosition { - return this._state.withScrollPosition(scrollPosition); - } + public validateScrollPosition(scrollPosition: INewScrollPosition): IScrollPosition { + return this._state.withScrollPosition(scrollPosition); + } - public getScrollDimensions(): IScrollDimensions { - return this._state; - } + public getScrollDimensions(): IScrollDimensions { + return this._state; + } - public setScrollDimensions(dimensions: INewScrollDimensions, useRawScrollPositions: boolean): void { - const newState = this._state.withScrollDimensions(dimensions, useRawScrollPositions); - this._setState(newState, Boolean(this._smoothScrolling)); + public setScrollDimensions(dimensions: INewScrollDimensions, useRawScrollPositions: boolean): void { + const newState = this._state.withScrollDimensions(dimensions, useRawScrollPositions); + this._setState(newState, Boolean(this._smoothScrolling)); - this._smoothScrolling?.acceptScrollDimensions(this._state); - } + this._smoothScrolling?.acceptScrollDimensions(this._state); + } - public getFutureScrollPosition(): IScrollPosition { - if (this._smoothScrolling) { - return this._smoothScrolling.to; - } - return this._state; - } + public getFutureScrollPosition(): IScrollPosition { + if (this._smoothScrolling) { + return this._smoothScrolling.to; + } + return this._state; + } - public getCurrentScrollPosition(): IScrollPosition { - return this._state; - } + public getCurrentScrollPosition(): IScrollPosition { + return this._state; + } - public setScrollPositionNow(update: INewScrollPosition): void { - const newState = this._state.withScrollPosition(update); + public setScrollPositionNow(update: INewScrollPosition): void { + const newState = this._state.withScrollPosition(update); - if (this._smoothScrolling) { - this._smoothScrolling.dispose(); - this._smoothScrolling = null; - } + if (this._smoothScrolling) { + this._smoothScrolling.dispose(); + this._smoothScrolling = null; + } - this._setState(newState, false); - } + this._setState(newState, false); + } - public setScrollPositionSmooth(update: INewScrollPosition, reuseAnimation?: boolean): void { - if (this._smoothScrollDuration === 0) { - return this.setScrollPositionNow(update); - } + public setScrollPositionSmooth(update: INewScrollPosition, reuseAnimation?: boolean): void { + if (this._smoothScrollDuration === 0) { + this.setScrollPositionNow(update); return; + } - if (this._smoothScrolling) { - update = { - scrollLeft: (typeof update.scrollLeft === 'undefined' ? this._smoothScrolling.to.scrollLeft : update.scrollLeft), - scrollTop: (typeof update.scrollTop === 'undefined' ? this._smoothScrolling.to.scrollTop : update.scrollTop) - }; + if (this._smoothScrolling) { + update = { + scrollLeft: (typeof update.scrollLeft === 'undefined' ? this._smoothScrolling.to.scrollLeft : update.scrollLeft), + scrollTop: (typeof update.scrollTop === 'undefined' ? this._smoothScrolling.to.scrollTop : update.scrollTop) + }; - const validTarget = this._state.withScrollPosition(update); + const validTarget = this._state.withScrollPosition(update); - if (this._smoothScrolling.to.scrollLeft === validTarget.scrollLeft && this._smoothScrolling.to.scrollTop === validTarget.scrollTop) { - return; - } - let newSmoothScrolling: SmoothScrollingOperation; - if (reuseAnimation) { - newSmoothScrolling = new SmoothScrollingOperation(this._smoothScrolling.from, validTarget, this._smoothScrolling.startTime, this._smoothScrolling.duration); - } else { - newSmoothScrolling = this._smoothScrolling.combine(this._state, validTarget, this._smoothScrollDuration); - } - this._smoothScrolling.dispose(); - this._smoothScrolling = newSmoothScrolling; - } else { - const validTarget = this._state.withScrollPosition(update); + if (this._smoothScrolling.to.scrollLeft === validTarget.scrollLeft && this._smoothScrolling.to.scrollTop === validTarget.scrollTop) { + return; + } + let newSmoothScrolling: SmoothScrollingOperation; + if (reuseAnimation) { + newSmoothScrolling = new SmoothScrollingOperation(this._smoothScrolling.from, validTarget, this._smoothScrolling.startTime, this._smoothScrolling.duration); + } else { + newSmoothScrolling = this._smoothScrolling.combine(this._state, validTarget, this._smoothScrollDuration); + } + this._smoothScrolling.dispose(); + this._smoothScrolling = newSmoothScrolling; + } else { + const validTarget = this._state.withScrollPosition(update); - this._smoothScrolling = SmoothScrollingOperation.start(this._state, validTarget, this._smoothScrollDuration); - } + this._smoothScrolling = SmoothScrollingOperation.start(this._state, validTarget, this._smoothScrollDuration); + } - this._smoothScrolling.animationFrameDisposable = this._scheduleAtNextAnimationFrame(() => { - if (!this._smoothScrolling) { - return; - } - this._smoothScrolling.animationFrameDisposable = null; - this._performSmoothScrolling(); - }); - } + this._smoothScrolling.animationFrameDisposable = this._scheduleAtNextAnimationFrame(() => { + if (!this._smoothScrolling) { + return; + } + this._smoothScrolling.animationFrameDisposable = null; + this._performSmoothScrolling(); + }); + } - public hasPendingScrollAnimation(): boolean { - return Boolean(this._smoothScrolling); - } + public hasPendingScrollAnimation(): boolean { + return Boolean(this._smoothScrolling); + } - private _performSmoothScrolling(): void { - if (!this._smoothScrolling) { - return; - } - const update = this._smoothScrolling.tick(); - const newState = this._state.withScrollPosition(update); + private _performSmoothScrolling(): void { + if (!this._smoothScrolling) { + return; + } + const update = this._smoothScrolling.tick(); + const newState = this._state.withScrollPosition(update); - this._setState(newState, true); + this._setState(newState, true); - if (!this._smoothScrolling) { - return; - } + if (!this._smoothScrolling) { + return; + } - if (update.isDone) { - this._smoothScrolling.dispose(); - this._smoothScrolling = null; - return; - } + if (update.isDone) { + this._smoothScrolling.dispose(); + this._smoothScrolling = null; + return; + } - this._smoothScrolling.animationFrameDisposable = this._scheduleAtNextAnimationFrame(() => { - if (!this._smoothScrolling) { - return; - } - this._smoothScrolling.animationFrameDisposable = null; - this._performSmoothScrolling(); - }); - } + this._smoothScrolling.animationFrameDisposable = this._scheduleAtNextAnimationFrame(() => { + if (!this._smoothScrolling) { + return; + } + this._smoothScrolling.animationFrameDisposable = null; + this._performSmoothScrolling(); + }); + } - private _setState(newState: ScrollState, inSmoothScrolling: boolean): void { - const oldState = this._state; - if (oldState.equals(newState)) { - return; - } - this._state = newState; - this._onScroll.fire(this._state.createScrollEvent(oldState, inSmoothScrolling)); - } + private _setState(newState: ScrollState, inSmoothScrolling: boolean): void { + const oldState = this._state; + if (oldState.equals(newState)) { + return; + } + this._state = newState; + this._onScroll.fire(this._state.createScrollEvent(oldState, inSmoothScrolling)); + } } export class SmoothScrollingUpdate { - public readonly scrollLeft: number; - public readonly scrollTop: number; - public readonly isDone: boolean; + public readonly scrollLeft: number; + public readonly scrollTop: number; + public readonly isDone: boolean; - constructor(scrollLeft: number, scrollTop: number, isDone: boolean) { - this.scrollLeft = scrollLeft; - this.scrollTop = scrollTop; - this.isDone = isDone; - } + constructor(scrollLeft: number, scrollTop: number, isDone: boolean) { + this.scrollLeft = scrollLeft; + this.scrollTop = scrollTop; + this.isDone = isDone; + } } interface IAnimation { - (completion: number): number; + (completion: number): number; } function createEaseOutCubic(from: number, to: number): IAnimation { - const delta = to - from; - return function (completion: number): number { - return from + delta * easeOutCubic(completion); - }; + const delta = to - from; + return function (completion: number): number { + return from + delta * easeOutCubic(completion); + }; } function createComposed(a: IAnimation, b: IAnimation, cut: number): IAnimation { - return function (completion: number): number { - if (completion < cut) { - return a(completion / cut); - } - return b((completion - cut) / (1 - cut)); - }; + return function (completion: number): number { + if (completion < cut) { + return a(completion / cut); + } + return b((completion - cut) / (1 - cut)); + }; } export class SmoothScrollingOperation { - public readonly from: ISmoothScrollPosition; - public to: ISmoothScrollPosition; - public readonly duration: number; - public readonly startTime: number; - public animationFrameDisposable: IDisposable | null; + public readonly from: ISmoothScrollPosition; + public to: ISmoothScrollPosition; + public readonly duration: number; + public readonly startTime: number; + public animationFrameDisposable: IDisposable | null; - private scrollLeft!: IAnimation; - private scrollTop!: IAnimation; + private scrollLeft!: IAnimation; + private scrollTop!: IAnimation; - constructor(from: ISmoothScrollPosition, to: ISmoothScrollPosition, startTime: number, duration: number) { - this.from = from; - this.to = to; - this.duration = duration; - this.startTime = startTime; + constructor(from: ISmoothScrollPosition, to: ISmoothScrollPosition, startTime: number, duration: number) { + this.from = from; + this.to = to; + this.duration = duration; + this.startTime = startTime; - this.animationFrameDisposable = null; + this.animationFrameDisposable = null; - this._initAnimations(); - } + this._initAnimations(); + } - private _initAnimations(): void { - this.scrollLeft = this._initAnimation(this.from.scrollLeft, this.to.scrollLeft, this.to.width); - this.scrollTop = this._initAnimation(this.from.scrollTop, this.to.scrollTop, this.to.height); - } + private _initAnimations(): void { + this.scrollLeft = this._initAnimation(this.from.scrollLeft, this.to.scrollLeft, this.to.width); + this.scrollTop = this._initAnimation(this.from.scrollTop, this.to.scrollTop, this.to.height); + } - private _initAnimation(from: number, to: number, viewportSize: number): IAnimation { - const delta = Math.abs(from - to); - if (delta > 2.5 * viewportSize) { - let stop1: number, stop2: number; - if (from < to) { - stop1 = from + 0.75 * viewportSize; - stop2 = to - 0.75 * viewportSize; - } else { - stop1 = from - 0.75 * viewportSize; - stop2 = to + 0.75 * viewportSize; - } - return createComposed(createEaseOutCubic(from, stop1), createEaseOutCubic(stop2, to), 0.33); - } - return createEaseOutCubic(from, to); - } + private _initAnimation(from: number, to: number, viewportSize: number): IAnimation { + const delta = Math.abs(from - to); + if (delta > 2.5 * viewportSize) { + let stop1: number; let stop2: number; + if (from < to) { + stop1 = from + 0.75 * viewportSize; + stop2 = to - 0.75 * viewportSize; + } else { + stop1 = from - 0.75 * viewportSize; + stop2 = to + 0.75 * viewportSize; + } + return createComposed(createEaseOutCubic(from, stop1), createEaseOutCubic(stop2, to), 0.33); + } + return createEaseOutCubic(from, to); + } - public dispose(): void { - if (this.animationFrameDisposable !== null) { - this.animationFrameDisposable.dispose(); - this.animationFrameDisposable = null; - } - } + public dispose(): void { + if (this.animationFrameDisposable !== null) { + this.animationFrameDisposable.dispose(); + this.animationFrameDisposable = null; + } + } - public acceptScrollDimensions(state: ScrollState): void { - this.to = state.withScrollPosition(this.to); - this._initAnimations(); - } + public acceptScrollDimensions(state: ScrollState): void { + this.to = state.withScrollPosition(this.to); + this._initAnimations(); + } - public tick(): SmoothScrollingUpdate { - return this._tick(Date.now()); - } + public tick(): SmoothScrollingUpdate { + return this._tick(Date.now()); + } - protected _tick(now: number): SmoothScrollingUpdate { - const completion = (now - this.startTime) / this.duration; + protected _tick(now: number): SmoothScrollingUpdate { + const completion = (now - this.startTime) / this.duration; - if (completion < 1) { - const newScrollLeft = this.scrollLeft(completion); - const newScrollTop = this.scrollTop(completion); - return new SmoothScrollingUpdate(newScrollLeft, newScrollTop, false); - } + if (completion < 1) { + const newScrollLeft = this.scrollLeft(completion); + const newScrollTop = this.scrollTop(completion); + return new SmoothScrollingUpdate(newScrollLeft, newScrollTop, false); + } - return new SmoothScrollingUpdate(this.to.scrollLeft, this.to.scrollTop, true); - } + return new SmoothScrollingUpdate(this.to.scrollLeft, this.to.scrollTop, true); + } - public combine(from: ISmoothScrollPosition, to: ISmoothScrollPosition, duration: number): SmoothScrollingOperation { - return SmoothScrollingOperation.start(from, to, duration); - } + public combine(from: ISmoothScrollPosition, to: ISmoothScrollPosition, duration: number): SmoothScrollingOperation { + return SmoothScrollingOperation.start(from, to, duration); + } - public static start(from: ISmoothScrollPosition, to: ISmoothScrollPosition, duration: number): SmoothScrollingOperation { - duration = duration + 10; - const startTime = Date.now() - 10; + public static start(from: ISmoothScrollPosition, to: ISmoothScrollPosition, duration: number): SmoothScrollingOperation { + duration = duration + 10; + const startTime = Date.now() - 10; - return new SmoothScrollingOperation(from, to, startTime, duration); - } + return new SmoothScrollingOperation(from, to, startTime, duration); + } } function easeInCubic(t: number) { - return Math.pow(t, 3); + return Math.pow(t, 3); } function easeOutCubic(t: number) { - return 1 - easeInCubic(1 - t); + return 1 - easeInCubic(1 - t); } diff --git a/src/browser/scrollable/scrollableElement.ts b/src/browser/scrollable/scrollableElement.ts index 7dd4e755..30821215 100644 --- a/src/browser/scrollable/scrollableElement.ts +++ b/src/browser/scrollable/scrollableElement.ts @@ -24,642 +24,642 @@ const SCROLL_WHEEL_SENSITIVITY = 50; const SCROLL_WHEEL_SMOOTH_SCROLL_ENABLED = true; export interface IOverviewRulerLayoutInfo { - parent: HTMLElement; - insertBefore: HTMLElement; + parent: HTMLElement; + insertBefore: HTMLElement; } class MouseWheelClassifierItem { - public timestamp: number; - public deltaX: number; - public deltaY: number; - public score: number; + public timestamp: number; + public deltaX: number; + public deltaY: number; + public score: number; - constructor(timestamp: number, deltaX: number, deltaY: number) { - this.timestamp = timestamp; - this.deltaX = deltaX; - this.deltaY = deltaY; - this.score = 0; - } + constructor(timestamp: number, deltaX: number, deltaY: number) { + this.timestamp = timestamp; + this.deltaX = deltaX; + this.deltaY = deltaY; + this.score = 0; + } } export class MouseWheelClassifier { - public static readonly INSTANCE = new MouseWheelClassifier(); + public static readonly INSTANCE = new MouseWheelClassifier(); - private readonly _capacity: number; - private _memory: MouseWheelClassifierItem[]; - private _front: number; - private _rear: number; + private readonly _capacity: number; + private _memory: MouseWheelClassifierItem[]; + private _front: number; + private _rear: number; - constructor() { - this._capacity = 5; - this._memory = []; - this._front = -1; - this._rear = -1; - } + constructor() { + this._capacity = 5; + this._memory = []; + this._front = -1; + this._rear = -1; + } - public isPhysicalMouseWheel(): boolean { - if (this._front === -1 && this._rear === -1) { - return false; - } + public isPhysicalMouseWheel(): boolean { + if (this._front === -1 && this._rear === -1) { + return false; + } - let remainingInfluence = 1; - let score = 0; - let iteration = 1; + let remainingInfluence = 1; + let score = 0; + let iteration = 1; - let index = this._rear; - do { - const influence = (index === this._front ? remainingInfluence : Math.pow(2, -iteration)); - remainingInfluence -= influence; - score += this._memory[index].score * influence; + let index = this._rear; + do { + const influence = (index === this._front ? remainingInfluence : Math.pow(2, -iteration)); + remainingInfluence -= influence; + score += this._memory[index].score * influence; - if (index === this._front) { - break; - } + if (index === this._front) { + break; + } - index = (this._capacity + index - 1) % this._capacity; - iteration++; - } while (true); + index = (this._capacity + index - 1) % this._capacity; + iteration++; + } while (true); - return (score <= 0.5); - } + return (score <= 0.5); + } - public acceptStandardWheelEvent(e: StandardWheelEvent): void { - if (isChrome) { - const targetWindow = dom.getWindow(e.browserEvent); - const pageZoomFactor = getZoomFactor(targetWindow); - this.accept(Date.now(), e.deltaX * pageZoomFactor, e.deltaY * pageZoomFactor); - } else { - this.accept(Date.now(), e.deltaX, e.deltaY); - } - } + public acceptStandardWheelEvent(e: StandardWheelEvent): void { + if (isChrome) { + const targetWindow = dom.getWindow(e.browserEvent); + const pageZoomFactor = getZoomFactor(targetWindow); + this.accept(Date.now(), e.deltaX * pageZoomFactor, e.deltaY * pageZoomFactor); + } else { + this.accept(Date.now(), e.deltaX, e.deltaY); + } + } - public accept(timestamp: number, deltaX: number, deltaY: number): void { - let previousItem = null; - const item = new MouseWheelClassifierItem(timestamp, deltaX, deltaY); + public accept(timestamp: number, deltaX: number, deltaY: number): void { + let previousItem = null; + const item = new MouseWheelClassifierItem(timestamp, deltaX, deltaY); - if (this._front === -1 && this._rear === -1) { - this._memory[0] = item; - this._front = 0; - this._rear = 0; - } else { - previousItem = this._memory[this._rear]; + if (this._front === -1 && this._rear === -1) { + this._memory[0] = item; + this._front = 0; + this._rear = 0; + } else { + previousItem = this._memory[this._rear]; - this._rear = (this._rear + 1) % this._capacity; - if (this._rear === this._front) { - this._front = (this._front + 1) % this._capacity; - } - this._memory[this._rear] = item; - } + this._rear = (this._rear + 1) % this._capacity; + if (this._rear === this._front) { + this._front = (this._front + 1) % this._capacity; + } + this._memory[this._rear] = item; + } - item.score = this._computeScore(item, previousItem); - } + item.score = this._computeScore(item, previousItem); + } - private _computeScore(item: MouseWheelClassifierItem, previousItem: MouseWheelClassifierItem | null): number { + private _computeScore(item: MouseWheelClassifierItem, previousItem: MouseWheelClassifierItem | null): number { - if (Math.abs(item.deltaX) > 0 && Math.abs(item.deltaY) > 0) { - return 1; - } + if (Math.abs(item.deltaX) > 0 && Math.abs(item.deltaY) > 0) { + return 1; + } - let score: number = 0.5; + let score: number = 0.5; - if (!this._isAlmostInt(item.deltaX) || !this._isAlmostInt(item.deltaY)) { - score += 0.25; - } + if (!this._isAlmostInt(item.deltaX) || !this._isAlmostInt(item.deltaY)) { + score += 0.25; + } - if (previousItem) { - const absDeltaX = Math.abs(item.deltaX); - const absDeltaY = Math.abs(item.deltaY); + if (previousItem) { + const absDeltaX = Math.abs(item.deltaX); + const absDeltaY = Math.abs(item.deltaY); - const absPreviousDeltaX = Math.abs(previousItem.deltaX); - const absPreviousDeltaY = Math.abs(previousItem.deltaY); + const absPreviousDeltaX = Math.abs(previousItem.deltaX); + const absPreviousDeltaY = Math.abs(previousItem.deltaY); - const minDeltaX = Math.max(Math.min(absDeltaX, absPreviousDeltaX), 1); - const minDeltaY = Math.max(Math.min(absDeltaY, absPreviousDeltaY), 1); + const minDeltaX = Math.max(Math.min(absDeltaX, absPreviousDeltaX), 1); + const minDeltaY = Math.max(Math.min(absDeltaY, absPreviousDeltaY), 1); - const maxDeltaX = Math.max(absDeltaX, absPreviousDeltaX); - const maxDeltaY = Math.max(absDeltaY, absPreviousDeltaY); + const maxDeltaX = Math.max(absDeltaX, absPreviousDeltaX); + const maxDeltaY = Math.max(absDeltaY, absPreviousDeltaY); - const isSameModulo = (maxDeltaX % minDeltaX === 0 && maxDeltaY % minDeltaY === 0); - if (isSameModulo) { - score -= 0.5; - } - } + const isSameModulo = (maxDeltaX % minDeltaX === 0 && maxDeltaY % minDeltaY === 0); + if (isSameModulo) { + score -= 0.5; + } + } - return Math.min(Math.max(score, 0), 1); - } + return Math.min(Math.max(score, 0), 1); + } - private _isAlmostInt(value: number): boolean { - const delta = Math.abs(Math.round(value) - value); - return (delta < 0.01); - } + private _isAlmostInt(value: number): boolean { + const delta = Math.abs(Math.round(value) - value); + return (delta < 0.01); + } } export abstract class AbstractScrollableElement extends Widget { - private readonly _options: ScrollableElementResolvedOptions; - protected readonly _scrollable: Scrollable; - private readonly _verticalScrollbar: VerticalScrollbar; - private readonly _horizontalScrollbar: HorizontalScrollbar; - private readonly _domNode: HTMLElement; + private readonly _options: ScrollableElementResolvedOptions; + protected readonly _scrollable: Scrollable; + private readonly _verticalScrollbar: VerticalScrollbar; + private readonly _horizontalScrollbar: HorizontalScrollbar; + private readonly _domNode: HTMLElement; - private readonly _leftShadowDomNode: FastDomNode | null; - private readonly _topShadowDomNode: FastDomNode | null; - private readonly _topLeftShadowDomNode: FastDomNode | null; + private readonly _leftShadowDomNode: FastDomNode | null; + private readonly _topShadowDomNode: FastDomNode | null; + private readonly _topLeftShadowDomNode: FastDomNode | null; - private readonly _listenOnDomNode: HTMLElement; + private readonly _listenOnDomNode: HTMLElement; - private _mouseWheelToDispose: IDisposable[]; + private _mouseWheelToDispose: IDisposable[]; - private _isDragging: boolean; - private _mouseIsOver: boolean; + private _isDragging: boolean; + private _mouseIsOver: boolean; - private readonly _hideTimeout: TimeoutTimer; - private _shouldRender: boolean; + private readonly _hideTimeout: TimeoutTimer; + private _shouldRender: boolean; - private _revealOnScroll: boolean; + private _revealOnScroll: boolean; - private readonly _onScroll = this._register(new Emitter()); - public readonly onScroll: Event = this._onScroll.event; + private readonly _onScroll = this._register(new Emitter()); + public readonly onScroll: Event = this._onScroll.event; - private readonly _onWillScroll = this._register(new Emitter()); - public readonly onWillScroll: Event = this._onWillScroll.event; + private readonly _onWillScroll = this._register(new Emitter()); + public readonly onWillScroll: Event = this._onWillScroll.event; - public get options(): Readonly { - return this._options; - } + public get options(): Readonly { + return this._options; + } - protected constructor(element: HTMLElement, options: ScrollableElementCreationOptions, scrollable: Scrollable) { - super(); - this._options = resolveOptions(options); - this._scrollable = scrollable; + protected constructor(element: HTMLElement, options: ScrollableElementCreationOptions, scrollable: Scrollable) { + super(); + this._options = resolveOptions(options); + this._scrollable = scrollable; - this._register(this._scrollable.onScroll((e) => { - this._onWillScroll.fire(e); - this._onDidScroll(e); - this._onScroll.fire(e); - })); + this._register(this._scrollable.onScroll((e) => { + this._onWillScroll.fire(e); + this._onDidScroll(e); + this._onScroll.fire(e); + })); - const scrollbarHost: ScrollbarHost = { - onMouseWheel: (mouseWheelEvent: StandardWheelEvent) => this._onMouseWheel(mouseWheelEvent), - onDragStart: () => this._onDragStart(), - onDragEnd: () => this._onDragEnd(), - }; - this._verticalScrollbar = this._register(new VerticalScrollbar(this._scrollable, this._options, scrollbarHost)); - this._horizontalScrollbar = this._register(new HorizontalScrollbar(this._scrollable, this._options, scrollbarHost)); + const scrollbarHost: ScrollbarHost = { + onMouseWheel: (mouseWheelEvent: StandardWheelEvent) => this._onMouseWheel(mouseWheelEvent), + onDragStart: () => this._onDragStart(), + onDragEnd: () => this._onDragEnd(), + }; + this._verticalScrollbar = this._register(new VerticalScrollbar(this._scrollable, this._options, scrollbarHost)); + this._horizontalScrollbar = this._register(new HorizontalScrollbar(this._scrollable, this._options, scrollbarHost)); - this._domNode = document.createElement('div'); - this._domNode.className = 'xterm-scrollable-element ' + this._options.className; - this._domNode.setAttribute('role', 'presentation'); - this._domNode.style.position = 'relative'; - this._domNode.appendChild(element); - this._domNode.appendChild(this._horizontalScrollbar.domNode.domNode); - this._domNode.appendChild(this._verticalScrollbar.domNode.domNode); + this._domNode = document.createElement('div'); + this._domNode.className = 'xterm-scrollable-element ' + this._options.className; + this._domNode.setAttribute('role', 'presentation'); + this._domNode.style.position = 'relative'; + this._domNode.appendChild(element); + this._domNode.appendChild(this._horizontalScrollbar.domNode.domNode); + this._domNode.appendChild(this._verticalScrollbar.domNode.domNode); - if (this._options.useShadows) { - this._leftShadowDomNode = createFastDomNode(document.createElement('div')); - this._leftShadowDomNode.setClassName('shadow'); - this._domNode.appendChild(this._leftShadowDomNode.domNode); + if (this._options.useShadows) { + this._leftShadowDomNode = createFastDomNode(document.createElement('div')); + this._leftShadowDomNode.setClassName('shadow'); + this._domNode.appendChild(this._leftShadowDomNode.domNode); - this._topShadowDomNode = createFastDomNode(document.createElement('div')); - this._topShadowDomNode.setClassName('shadow'); - this._domNode.appendChild(this._topShadowDomNode.domNode); + this._topShadowDomNode = createFastDomNode(document.createElement('div')); + this._topShadowDomNode.setClassName('shadow'); + this._domNode.appendChild(this._topShadowDomNode.domNode); - this._topLeftShadowDomNode = createFastDomNode(document.createElement('div')); - this._topLeftShadowDomNode.setClassName('shadow'); - this._domNode.appendChild(this._topLeftShadowDomNode.domNode); - } else { - this._leftShadowDomNode = null; - this._topShadowDomNode = null; - this._topLeftShadowDomNode = null; - } + this._topLeftShadowDomNode = createFastDomNode(document.createElement('div')); + this._topLeftShadowDomNode.setClassName('shadow'); + this._domNode.appendChild(this._topLeftShadowDomNode.domNode); + } else { + this._leftShadowDomNode = null; + this._topShadowDomNode = null; + this._topLeftShadowDomNode = null; + } - this._listenOnDomNode = this._options.listenOnDomNode || this._domNode; + this._listenOnDomNode = this._options.listenOnDomNode || this._domNode; - this._mouseWheelToDispose = []; - this._setListeningToMouseWheel(this._options.handleMouseWheel); + this._mouseWheelToDispose = []; + this._setListeningToMouseWheel(this._options.handleMouseWheel); - this.onmouseover(this._listenOnDomNode, (e) => this._onMouseOver(e)); - this.onmouseleave(this._listenOnDomNode, (e) => this._onMouseLeave(e)); + this.onmouseover(this._listenOnDomNode, (e) => this._onMouseOver(e)); + this.onmouseleave(this._listenOnDomNode, (e) => this._onMouseLeave(e)); - this._hideTimeout = this._register(new TimeoutTimer()); - this._isDragging = false; - this._mouseIsOver = false; + this._hideTimeout = this._register(new TimeoutTimer()); + this._isDragging = false; + this._mouseIsOver = false; - this._shouldRender = true; + this._shouldRender = true; - this._revealOnScroll = true; - } + this._revealOnScroll = true; + } - public override dispose(): void { - this._mouseWheelToDispose = dispose(this._mouseWheelToDispose); - super.dispose(); - } + public override dispose(): void { + this._mouseWheelToDispose = dispose(this._mouseWheelToDispose); + super.dispose(); + } - public getDomNode(): HTMLElement { - return this._domNode; - } + public getDomNode(): HTMLElement { + return this._domNode; + } - public getOverviewRulerLayoutInfo(): IOverviewRulerLayoutInfo { - return { - parent: this._domNode, - insertBefore: this._verticalScrollbar.domNode.domNode, - }; - } + public getOverviewRulerLayoutInfo(): IOverviewRulerLayoutInfo { + return { + parent: this._domNode, + insertBefore: this._verticalScrollbar.domNode.domNode, + }; + } - public delegateVerticalScrollbarPointerDown(browserEvent: PointerEvent): void { - this._verticalScrollbar.delegatePointerDown(browserEvent); - } + public delegateVerticalScrollbarPointerDown(browserEvent: PointerEvent): void { + this._verticalScrollbar.delegatePointerDown(browserEvent); + } - public getScrollDimensions(): IScrollDimensions { - return this._scrollable.getScrollDimensions(); - } + public getScrollDimensions(): IScrollDimensions { + return this._scrollable.getScrollDimensions(); + } - public setScrollDimensions(dimensions: INewScrollDimensions): void { - this._scrollable.setScrollDimensions(dimensions, false); - } + public setScrollDimensions(dimensions: INewScrollDimensions): void { + this._scrollable.setScrollDimensions(dimensions, false); + } - public updateClassName(newClassName: string): void { - this._options.className = newClassName; - if (platform.isMacintosh) { - this._options.className += ' mac'; - } - this._domNode.className = 'xterm-scrollable-element ' + this._options.className; - } + public updateClassName(newClassName: string): void { + this._options.className = newClassName; + if (platform.isMacintosh) { + this._options.className += ' mac'; + } + this._domNode.className = 'xterm-scrollable-element ' + this._options.className; + } - public updateOptions(newOptions: ScrollableElementChangeOptions): void { - if (typeof newOptions.handleMouseWheel !== 'undefined') { - this._options.handleMouseWheel = newOptions.handleMouseWheel; - this._setListeningToMouseWheel(this._options.handleMouseWheel); - } - if (typeof newOptions.mouseWheelScrollSensitivity !== 'undefined') { - this._options.mouseWheelScrollSensitivity = newOptions.mouseWheelScrollSensitivity; - } - if (typeof newOptions.fastScrollSensitivity !== 'undefined') { - this._options.fastScrollSensitivity = newOptions.fastScrollSensitivity; - } - if (typeof newOptions.scrollPredominantAxis !== 'undefined') { - this._options.scrollPredominantAxis = newOptions.scrollPredominantAxis; - } - if (typeof newOptions.horizontal !== 'undefined') { - this._options.horizontal = newOptions.horizontal; - } - if (typeof newOptions.vertical !== 'undefined') { - this._options.vertical = newOptions.vertical; - } - if (typeof newOptions.horizontalScrollbarSize !== 'undefined') { - this._options.horizontalScrollbarSize = newOptions.horizontalScrollbarSize; - } - if (typeof newOptions.verticalScrollbarSize !== 'undefined') { - this._options.verticalScrollbarSize = newOptions.verticalScrollbarSize; - } - if (typeof newOptions.scrollByPage !== 'undefined') { - this._options.scrollByPage = newOptions.scrollByPage; - } - this._horizontalScrollbar.updateOptions(this._options); - this._verticalScrollbar.updateOptions(this._options); + public updateOptions(newOptions: ScrollableElementChangeOptions): void { + if (typeof newOptions.handleMouseWheel !== 'undefined') { + this._options.handleMouseWheel = newOptions.handleMouseWheel; + this._setListeningToMouseWheel(this._options.handleMouseWheel); + } + if (typeof newOptions.mouseWheelScrollSensitivity !== 'undefined') { + this._options.mouseWheelScrollSensitivity = newOptions.mouseWheelScrollSensitivity; + } + if (typeof newOptions.fastScrollSensitivity !== 'undefined') { + this._options.fastScrollSensitivity = newOptions.fastScrollSensitivity; + } + if (typeof newOptions.scrollPredominantAxis !== 'undefined') { + this._options.scrollPredominantAxis = newOptions.scrollPredominantAxis; + } + if (typeof newOptions.horizontal !== 'undefined') { + this._options.horizontal = newOptions.horizontal; + } + if (typeof newOptions.vertical !== 'undefined') { + this._options.vertical = newOptions.vertical; + } + if (typeof newOptions.horizontalScrollbarSize !== 'undefined') { + this._options.horizontalScrollbarSize = newOptions.horizontalScrollbarSize; + } + if (typeof newOptions.verticalScrollbarSize !== 'undefined') { + this._options.verticalScrollbarSize = newOptions.verticalScrollbarSize; + } + if (typeof newOptions.scrollByPage !== 'undefined') { + this._options.scrollByPage = newOptions.scrollByPage; + } + this._horizontalScrollbar.updateOptions(this._options); + this._verticalScrollbar.updateOptions(this._options); - if (!this._options.lazyRender) { - this._render(); - } - } + if (!this._options.lazyRender) { + this._render(); + } + } - public setRevealOnScroll(value: boolean) { - this._revealOnScroll = value; - } + public setRevealOnScroll(value: boolean) { + this._revealOnScroll = value; + } - public delegateScrollFromMouseWheelEvent(browserEvent: IMouseWheelEvent) { - this._onMouseWheel(new StandardWheelEvent(browserEvent)); - } + public delegateScrollFromMouseWheelEvent(browserEvent: IMouseWheelEvent) { + this._onMouseWheel(new StandardWheelEvent(browserEvent)); + } - // -------------------- mouse wheel scrolling -------------------- + // -------------------- mouse wheel scrolling -------------------- - private _setListeningToMouseWheel(shouldListen: boolean): void { - const isListening = (this._mouseWheelToDispose.length > 0); + private _setListeningToMouseWheel(shouldListen: boolean): void { + const isListening = (this._mouseWheelToDispose.length > 0); - if (isListening === shouldListen) { - return; - } + if (isListening === shouldListen) { + return; + } - this._mouseWheelToDispose = dispose(this._mouseWheelToDispose); + this._mouseWheelToDispose = dispose(this._mouseWheelToDispose); - if (shouldListen) { - const onMouseWheel = (browserEvent: IMouseWheelEvent) => { - this._onMouseWheel(new StandardWheelEvent(browserEvent)); - }; + if (shouldListen) { + const onMouseWheel = (browserEvent: IMouseWheelEvent) => { + this._onMouseWheel(new StandardWheelEvent(browserEvent)); + }; - this._mouseWheelToDispose.push(dom.addDisposableListener(this._listenOnDomNode, dom.EventType.MOUSE_WHEEL, onMouseWheel, { passive: false })); - } - } + this._mouseWheelToDispose.push(dom.addDisposableListener(this._listenOnDomNode, dom.EventType.MOUSE_WHEEL, onMouseWheel, { passive: false })); + } + } - private _onMouseWheel(e: StandardWheelEvent): void { - if (e.browserEvent?.defaultPrevented) { - return; - } + private _onMouseWheel(e: StandardWheelEvent): void { + if (e.browserEvent?.defaultPrevented) { + return; + } - const classifier = MouseWheelClassifier.INSTANCE; - if (SCROLL_WHEEL_SMOOTH_SCROLL_ENABLED) { - classifier.acceptStandardWheelEvent(e); - } + const classifier = MouseWheelClassifier.INSTANCE; + if (SCROLL_WHEEL_SMOOTH_SCROLL_ENABLED) { + classifier.acceptStandardWheelEvent(e); + } - let didScroll = false; + let didScroll = false; - if (e.deltaY || e.deltaX) { - let deltaY = e.deltaY * this._options.mouseWheelScrollSensitivity; - let deltaX = e.deltaX * this._options.mouseWheelScrollSensitivity; + if (e.deltaY || e.deltaX) { + let deltaY = e.deltaY * this._options.mouseWheelScrollSensitivity; + let deltaX = e.deltaX * this._options.mouseWheelScrollSensitivity; - if (this._options.scrollPredominantAxis) { - if (this._options.scrollYToX && deltaX + deltaY === 0) { - deltaX = deltaY = 0; - } else if (Math.abs(deltaY) >= Math.abs(deltaX)) { - deltaX = 0; - } else { - deltaY = 0; - } - } + if (this._options.scrollPredominantAxis) { + if (this._options.scrollYToX && deltaX + deltaY === 0) { + deltaX = deltaY = 0; + } else if (Math.abs(deltaY) >= Math.abs(deltaX)) { + deltaX = 0; + } else { + deltaY = 0; + } + } - if (this._options.flipAxes) { - [deltaY, deltaX] = [deltaX, deltaY]; - } + if (this._options.flipAxes) { + [deltaY, deltaX] = [deltaX, deltaY]; + } - const shiftConvert = !platform.isMacintosh && e.browserEvent && e.browserEvent.shiftKey; - if ((this._options.scrollYToX || shiftConvert) && !deltaX) { - deltaX = deltaY; - deltaY = 0; - } + const shiftConvert = !platform.isMacintosh && e.browserEvent && e.browserEvent.shiftKey; + if ((this._options.scrollYToX || shiftConvert) && !deltaX) { + deltaX = deltaY; + deltaY = 0; + } - if (e.browserEvent && e.browserEvent.altKey) { - deltaX = deltaX * this._options.fastScrollSensitivity; - deltaY = deltaY * this._options.fastScrollSensitivity; - } + if (e.browserEvent && e.browserEvent.altKey) { + deltaX = deltaX * this._options.fastScrollSensitivity; + deltaY = deltaY * this._options.fastScrollSensitivity; + } - const futureScrollPosition = this._scrollable.getFutureScrollPosition(); + const futureScrollPosition = this._scrollable.getFutureScrollPosition(); - let desiredScrollPosition: INewScrollPosition = {}; - if (deltaY) { - const deltaScrollTop = SCROLL_WHEEL_SENSITIVITY * deltaY; - const desiredScrollTop = futureScrollPosition.scrollTop - (deltaScrollTop < 0 ? Math.floor(deltaScrollTop) : Math.ceil(deltaScrollTop)); - this._verticalScrollbar.writeScrollPosition(desiredScrollPosition, desiredScrollTop); - } - if (deltaX) { - const deltaScrollLeft = SCROLL_WHEEL_SENSITIVITY * deltaX; - const desiredScrollLeft = futureScrollPosition.scrollLeft - (deltaScrollLeft < 0 ? Math.floor(deltaScrollLeft) : Math.ceil(deltaScrollLeft)); - this._horizontalScrollbar.writeScrollPosition(desiredScrollPosition, desiredScrollLeft); - } + let desiredScrollPosition: INewScrollPosition = {}; + if (deltaY) { + const deltaScrollTop = SCROLL_WHEEL_SENSITIVITY * deltaY; + const desiredScrollTop = futureScrollPosition.scrollTop - (deltaScrollTop < 0 ? Math.floor(deltaScrollTop) : Math.ceil(deltaScrollTop)); + this._verticalScrollbar.writeScrollPosition(desiredScrollPosition, desiredScrollTop); + } + if (deltaX) { + const deltaScrollLeft = SCROLL_WHEEL_SENSITIVITY * deltaX; + const desiredScrollLeft = futureScrollPosition.scrollLeft - (deltaScrollLeft < 0 ? Math.floor(deltaScrollLeft) : Math.ceil(deltaScrollLeft)); + this._horizontalScrollbar.writeScrollPosition(desiredScrollPosition, desiredScrollLeft); + } - desiredScrollPosition = this._scrollable.validateScrollPosition(desiredScrollPosition); + desiredScrollPosition = this._scrollable.validateScrollPosition(desiredScrollPosition); - if (futureScrollPosition.scrollLeft !== desiredScrollPosition.scrollLeft || futureScrollPosition.scrollTop !== desiredScrollPosition.scrollTop) { + if (futureScrollPosition.scrollLeft !== desiredScrollPosition.scrollLeft || futureScrollPosition.scrollTop !== desiredScrollPosition.scrollTop) { - const canPerformSmoothScroll = ( - SCROLL_WHEEL_SMOOTH_SCROLL_ENABLED + const canPerformSmoothScroll = ( + SCROLL_WHEEL_SMOOTH_SCROLL_ENABLED && this._options.mouseWheelSmoothScroll && classifier.isPhysicalMouseWheel() - ); + ); - if (canPerformSmoothScroll) { - this._scrollable.setScrollPositionSmooth(desiredScrollPosition); - } else { - this._scrollable.setScrollPositionNow(desiredScrollPosition); - } + if (canPerformSmoothScroll) { + this._scrollable.setScrollPositionSmooth(desiredScrollPosition); + } else { + this._scrollable.setScrollPositionNow(desiredScrollPosition); + } - didScroll = true; - } - } + didScroll = true; + } + } - let consumeMouseWheel = didScroll; - if (!consumeMouseWheel && this._options.alwaysConsumeMouseWheel) { - consumeMouseWheel = true; - } - if (!consumeMouseWheel && this._options.consumeMouseWheelIfScrollbarIsNeeded && (this._verticalScrollbar.isNeeded() || this._horizontalScrollbar.isNeeded())) { - consumeMouseWheel = true; - } + let consumeMouseWheel = didScroll; + if (!consumeMouseWheel && this._options.alwaysConsumeMouseWheel) { + consumeMouseWheel = true; + } + if (!consumeMouseWheel && this._options.consumeMouseWheelIfScrollbarIsNeeded && (this._verticalScrollbar.isNeeded() || this._horizontalScrollbar.isNeeded())) { + consumeMouseWheel = true; + } - if (consumeMouseWheel) { - e.preventDefault(); - e.stopPropagation(); - } - } + if (consumeMouseWheel) { + e.preventDefault(); + e.stopPropagation(); + } + } - private _onDidScroll(e: ScrollEvent): void { - this._shouldRender = this._horizontalScrollbar.onDidScroll(e) || this._shouldRender; - this._shouldRender = this._verticalScrollbar.onDidScroll(e) || this._shouldRender; + private _onDidScroll(e: ScrollEvent): void { + this._shouldRender = this._horizontalScrollbar.onDidScroll(e) || this._shouldRender; + this._shouldRender = this._verticalScrollbar.onDidScroll(e) || this._shouldRender; - if (this._options.useShadows) { - this._shouldRender = true; - } + if (this._options.useShadows) { + this._shouldRender = true; + } - if (this._revealOnScroll) { - this._reveal(); - } + if (this._revealOnScroll) { + this._reveal(); + } - if (!this._options.lazyRender) { - this._render(); - } - } + if (!this._options.lazyRender) { + this._render(); + } + } - public renderNow(): void { - if (!this._options.lazyRender) { - throw new Error('Please use `lazyRender` together with `renderNow`!'); - } + public renderNow(): void { + if (!this._options.lazyRender) { + throw new Error('Please use `lazyRender` together with `renderNow`!'); + } - this._render(); - } + this._render(); + } - private _render(): void { - if (!this._shouldRender) { - return; - } + private _render(): void { + if (!this._shouldRender) { + return; + } - this._shouldRender = false; + this._shouldRender = false; - this._horizontalScrollbar.render(); - this._verticalScrollbar.render(); + this._horizontalScrollbar.render(); + this._verticalScrollbar.render(); - if (this._options.useShadows) { - const scrollState = this._scrollable.getCurrentScrollPosition(); - const enableTop = scrollState.scrollTop > 0; - const enableLeft = scrollState.scrollLeft > 0; + if (this._options.useShadows) { + const scrollState = this._scrollable.getCurrentScrollPosition(); + const enableTop = scrollState.scrollTop > 0; + const enableLeft = scrollState.scrollLeft > 0; - const leftClassName = (enableLeft ? ' left' : ''); - const topClassName = (enableTop ? ' top' : ''); - const topLeftClassName = (enableLeft || enableTop ? ' top-left-corner' : ''); - this._leftShadowDomNode!.setClassName(`shadow${leftClassName}`); - this._topShadowDomNode!.setClassName(`shadow${topClassName}`); - this._topLeftShadowDomNode!.setClassName(`shadow${topLeftClassName}${topClassName}${leftClassName}`); - } - } + const leftClassName = (enableLeft ? ' left' : ''); + const topClassName = (enableTop ? ' top' : ''); + const topLeftClassName = (enableLeft || enableTop ? ' top-left-corner' : ''); + this._leftShadowDomNode!.setClassName(`shadow${leftClassName}`); + this._topShadowDomNode!.setClassName(`shadow${topClassName}`); + this._topLeftShadowDomNode!.setClassName(`shadow${topLeftClassName}${topClassName}${leftClassName}`); + } + } - // -------------------- fade in / fade out -------------------- + // -------------------- fade in / fade out -------------------- - private _onDragStart(): void { - this._isDragging = true; - this._reveal(); - } + private _onDragStart(): void { + this._isDragging = true; + this._reveal(); + } - private _onDragEnd(): void { - this._isDragging = false; - this._hide(); - } + private _onDragEnd(): void { + this._isDragging = false; + this._hide(); + } - private _onMouseLeave(e: IMouseEvent): void { - this._mouseIsOver = false; - this._hide(); - } + private _onMouseLeave(e: IMouseEvent): void { + this._mouseIsOver = false; + this._hide(); + } - private _onMouseOver(e: IMouseEvent): void { - this._mouseIsOver = true; - this._reveal(); - } + private _onMouseOver(e: IMouseEvent): void { + this._mouseIsOver = true; + this._reveal(); + } - private _reveal(): void { - this._verticalScrollbar.beginReveal(); - this._horizontalScrollbar.beginReveal(); - this._scheduleHide(); - } + private _reveal(): void { + this._verticalScrollbar.beginReveal(); + this._horizontalScrollbar.beginReveal(); + this._scheduleHide(); + } - private _hide(): void { - if (!this._mouseIsOver && !this._isDragging) { - this._verticalScrollbar.beginHide(); - this._horizontalScrollbar.beginHide(); - } - } + private _hide(): void { + if (!this._mouseIsOver && !this._isDragging) { + this._verticalScrollbar.beginHide(); + this._horizontalScrollbar.beginHide(); + } + } - private _scheduleHide(): void { - if (!this._mouseIsOver && !this._isDragging) { - this._hideTimeout.cancelAndSet(() => this._hide(), HIDE_TIMEOUT); - } - } + private _scheduleHide(): void { + if (!this._mouseIsOver && !this._isDragging) { + this._hideTimeout.cancelAndSet(() => this._hide(), HIDE_TIMEOUT); + } + } } export class ScrollableElement extends AbstractScrollableElement { - constructor(element: HTMLElement, options: ScrollableElementCreationOptions) { - options = options || {}; - options.mouseWheelSmoothScroll = false; - const scrollable = new Scrollable({ - forceIntegerValues: true, - smoothScrollDuration: 0, - scheduleAtNextAnimationFrame: (callback) => dom.scheduleAtNextAnimationFrame(dom.getWindow(element), callback) - }); - super(element, options, scrollable); - this._register(scrollable); - } + constructor(element: HTMLElement, options: ScrollableElementCreationOptions) { + options = options || {}; + options.mouseWheelSmoothScroll = false; + const scrollable = new Scrollable({ + forceIntegerValues: true, + smoothScrollDuration: 0, + scheduleAtNextAnimationFrame: (callback) => dom.scheduleAtNextAnimationFrame(dom.getWindow(element), callback) + }); + super(element, options, scrollable); + this._register(scrollable); + } - public setScrollPosition(update: INewScrollPosition): void { - this._scrollable.setScrollPositionNow(update); - } + public setScrollPosition(update: INewScrollPosition): void { + this._scrollable.setScrollPositionNow(update); + } - public getScrollPosition(): IScrollPosition { - return this._scrollable.getCurrentScrollPosition(); - } + public getScrollPosition(): IScrollPosition { + return this._scrollable.getCurrentScrollPosition(); + } } export class SmoothScrollableElement extends AbstractScrollableElement { - constructor(element: HTMLElement, options: ScrollableElementCreationOptions, scrollable: Scrollable) { - super(element, options, scrollable); - } + constructor(element: HTMLElement, options: ScrollableElementCreationOptions, scrollable: Scrollable) { + super(element, options, scrollable); + } - public setScrollPosition(update: INewScrollPosition & { reuseAnimation?: boolean }): void { - if (update.reuseAnimation) { - this._scrollable.setScrollPositionSmooth(update, update.reuseAnimation); - } else { - this._scrollable.setScrollPositionNow(update); - } - } + public setScrollPosition(update: INewScrollPosition & { reuseAnimation?: boolean }): void { + if (update.reuseAnimation) { + this._scrollable.setScrollPositionSmooth(update, update.reuseAnimation); + } else { + this._scrollable.setScrollPositionNow(update); + } + } - public getScrollPosition(): IScrollPosition { - return this._scrollable.getCurrentScrollPosition(); - } + public getScrollPosition(): IScrollPosition { + return this._scrollable.getCurrentScrollPosition(); + } } export class DomScrollableElement extends AbstractScrollableElement { - private _element: HTMLElement; + private _element: HTMLElement; - constructor(element: HTMLElement, options: ScrollableElementCreationOptions) { - options = options || {}; - options.mouseWheelSmoothScroll = false; - const scrollable = new Scrollable({ - forceIntegerValues: false, - smoothScrollDuration: 0, - scheduleAtNextAnimationFrame: (callback) => dom.scheduleAtNextAnimationFrame(dom.getWindow(element), callback) - }); - super(element, options, scrollable); - this._register(scrollable); - this._element = element; - this._register(this.onScroll((e) => { - if (e.scrollTopChanged) { - this._element.scrollTop = e.scrollTop; - } - if (e.scrollLeftChanged) { - this._element.scrollLeft = e.scrollLeft; - } - })); - this.scanDomNode(); - } + constructor(element: HTMLElement, options: ScrollableElementCreationOptions) { + options = options || {}; + options.mouseWheelSmoothScroll = false; + const scrollable = new Scrollable({ + forceIntegerValues: false, + smoothScrollDuration: 0, + scheduleAtNextAnimationFrame: (callback) => dom.scheduleAtNextAnimationFrame(dom.getWindow(element), callback) + }); + super(element, options, scrollable); + this._register(scrollable); + this._element = element; + this._register(this.onScroll((e) => { + if (e.scrollTopChanged) { + this._element.scrollTop = e.scrollTop; + } + if (e.scrollLeftChanged) { + this._element.scrollLeft = e.scrollLeft; + } + })); + this.scanDomNode(); + } - public setScrollPosition(update: INewScrollPosition): void { - this._scrollable.setScrollPositionNow(update); - } + public setScrollPosition(update: INewScrollPosition): void { + this._scrollable.setScrollPositionNow(update); + } - public getScrollPosition(): IScrollPosition { - return this._scrollable.getCurrentScrollPosition(); - } + public getScrollPosition(): IScrollPosition { + return this._scrollable.getCurrentScrollPosition(); + } - public scanDomNode(): void { - this.setScrollDimensions({ - width: this._element.clientWidth, - scrollWidth: this._element.scrollWidth, - height: this._element.clientHeight, - scrollHeight: this._element.scrollHeight - }); - this.setScrollPosition({ - scrollLeft: this._element.scrollLeft, - scrollTop: this._element.scrollTop, - }); - } + public scanDomNode(): void { + this.setScrollDimensions({ + width: this._element.clientWidth, + scrollWidth: this._element.scrollWidth, + height: this._element.clientHeight, + scrollHeight: this._element.scrollHeight + }); + this.setScrollPosition({ + scrollLeft: this._element.scrollLeft, + scrollTop: this._element.scrollTop, + }); + } } function resolveOptions(opts: ScrollableElementCreationOptions): ScrollableElementResolvedOptions { - const result: ScrollableElementResolvedOptions = { - lazyRender: (typeof opts.lazyRender !== 'undefined' ? opts.lazyRender : false), - className: (typeof opts.className !== 'undefined' ? opts.className : ''), - useShadows: (typeof opts.useShadows !== 'undefined' ? opts.useShadows : true), - handleMouseWheel: (typeof opts.handleMouseWheel !== 'undefined' ? opts.handleMouseWheel : true), - flipAxes: (typeof opts.flipAxes !== 'undefined' ? opts.flipAxes : false), - consumeMouseWheelIfScrollbarIsNeeded: (typeof opts.consumeMouseWheelIfScrollbarIsNeeded !== 'undefined' ? opts.consumeMouseWheelIfScrollbarIsNeeded : false), - alwaysConsumeMouseWheel: (typeof opts.alwaysConsumeMouseWheel !== 'undefined' ? opts.alwaysConsumeMouseWheel : false), - scrollYToX: (typeof opts.scrollYToX !== 'undefined' ? opts.scrollYToX : false), - mouseWheelScrollSensitivity: (typeof opts.mouseWheelScrollSensitivity !== 'undefined' ? opts.mouseWheelScrollSensitivity : 1), - fastScrollSensitivity: (typeof opts.fastScrollSensitivity !== 'undefined' ? opts.fastScrollSensitivity : 5), - scrollPredominantAxis: (typeof opts.scrollPredominantAxis !== 'undefined' ? opts.scrollPredominantAxis : true), - mouseWheelSmoothScroll: (typeof opts.mouseWheelSmoothScroll !== 'undefined' ? opts.mouseWheelSmoothScroll : true), - arrowSize: (typeof opts.arrowSize !== 'undefined' ? opts.arrowSize : 11), + const result: ScrollableElementResolvedOptions = { + lazyRender: (typeof opts.lazyRender !== 'undefined' ? opts.lazyRender : false), + className: (typeof opts.className !== 'undefined' ? opts.className : ''), + useShadows: (typeof opts.useShadows !== 'undefined' ? opts.useShadows : true), + handleMouseWheel: (typeof opts.handleMouseWheel !== 'undefined' ? opts.handleMouseWheel : true), + flipAxes: (typeof opts.flipAxes !== 'undefined' ? opts.flipAxes : false), + consumeMouseWheelIfScrollbarIsNeeded: (typeof opts.consumeMouseWheelIfScrollbarIsNeeded !== 'undefined' ? opts.consumeMouseWheelIfScrollbarIsNeeded : false), + alwaysConsumeMouseWheel: (typeof opts.alwaysConsumeMouseWheel !== 'undefined' ? opts.alwaysConsumeMouseWheel : false), + scrollYToX: (typeof opts.scrollYToX !== 'undefined' ? opts.scrollYToX : false), + mouseWheelScrollSensitivity: (typeof opts.mouseWheelScrollSensitivity !== 'undefined' ? opts.mouseWheelScrollSensitivity : 1), + fastScrollSensitivity: (typeof opts.fastScrollSensitivity !== 'undefined' ? opts.fastScrollSensitivity : 5), + scrollPredominantAxis: (typeof opts.scrollPredominantAxis !== 'undefined' ? opts.scrollPredominantAxis : true), + mouseWheelSmoothScroll: (typeof opts.mouseWheelSmoothScroll !== 'undefined' ? opts.mouseWheelSmoothScroll : true), + arrowSize: (typeof opts.arrowSize !== 'undefined' ? opts.arrowSize : 11), - listenOnDomNode: (typeof opts.listenOnDomNode !== 'undefined' ? opts.listenOnDomNode : null), + listenOnDomNode: (typeof opts.listenOnDomNode !== 'undefined' ? opts.listenOnDomNode : null), - horizontal: (typeof opts.horizontal !== 'undefined' ? opts.horizontal : ScrollbarVisibility.Auto), - horizontalScrollbarSize: (typeof opts.horizontalScrollbarSize !== 'undefined' ? opts.horizontalScrollbarSize : 10), - horizontalSliderSize: (typeof opts.horizontalSliderSize !== 'undefined' ? opts.horizontalSliderSize : 0), - horizontalHasArrows: (typeof opts.horizontalHasArrows !== 'undefined' ? opts.horizontalHasArrows : false), + horizontal: (typeof opts.horizontal !== 'undefined' ? opts.horizontal : ScrollbarVisibility.Auto), + horizontalScrollbarSize: (typeof opts.horizontalScrollbarSize !== 'undefined' ? opts.horizontalScrollbarSize : 10), + horizontalSliderSize: (typeof opts.horizontalSliderSize !== 'undefined' ? opts.horizontalSliderSize : 0), + horizontalHasArrows: (typeof opts.horizontalHasArrows !== 'undefined' ? opts.horizontalHasArrows : false), - vertical: (typeof opts.vertical !== 'undefined' ? opts.vertical : ScrollbarVisibility.Auto), - verticalScrollbarSize: (typeof opts.verticalScrollbarSize !== 'undefined' ? opts.verticalScrollbarSize : 10), - verticalHasArrows: (typeof opts.verticalHasArrows !== 'undefined' ? opts.verticalHasArrows : false), - verticalSliderSize: (typeof opts.verticalSliderSize !== 'undefined' ? opts.verticalSliderSize : 0), + vertical: (typeof opts.vertical !== 'undefined' ? opts.vertical : ScrollbarVisibility.Auto), + verticalScrollbarSize: (typeof opts.verticalScrollbarSize !== 'undefined' ? opts.verticalScrollbarSize : 10), + verticalHasArrows: (typeof opts.verticalHasArrows !== 'undefined' ? opts.verticalHasArrows : false), + verticalSliderSize: (typeof opts.verticalSliderSize !== 'undefined' ? opts.verticalSliderSize : 0), - scrollByPage: (typeof opts.scrollByPage !== 'undefined' ? opts.scrollByPage : false) - }; + scrollByPage: (typeof opts.scrollByPage !== 'undefined' ? opts.scrollByPage : false) + }; - result.horizontalSliderSize = (typeof opts.horizontalSliderSize !== 'undefined' ? opts.horizontalSliderSize : result.horizontalScrollbarSize); - result.verticalSliderSize = (typeof opts.verticalSliderSize !== 'undefined' ? opts.verticalSliderSize : result.verticalScrollbarSize); + result.horizontalSliderSize = (typeof opts.horizontalSliderSize !== 'undefined' ? opts.horizontalSliderSize : result.horizontalScrollbarSize); + result.verticalSliderSize = (typeof opts.verticalSliderSize !== 'undefined' ? opts.verticalSliderSize : result.verticalScrollbarSize); - if (platform.isMacintosh) { - result.className += ' mac'; - } + if (platform.isMacintosh) { + result.className += ' mac'; + } - return result; + return result; } diff --git a/src/browser/scrollable/scrollableElementOptions.ts b/src/browser/scrollable/scrollableElementOptions.ts index fd363b73..c3cf4ea6 100644 --- a/src/browser/scrollable/scrollableElementOptions.ts +++ b/src/browser/scrollable/scrollableElementOptions.ts @@ -6,160 +6,160 @@ import { ScrollbarVisibility } from './scrollable'; export interface ScrollableElementCreationOptions { - /** - * The scrollable element should not do any DOM mutations until renderNow() is called. - * Defaults to false. - */ - lazyRender?: boolean; - /** - * CSS Class name for the scrollable element. - */ - className?: string; - /** - * Drop subtle horizontal and vertical shadows. - * Defaults to false. - */ - useShadows?: boolean; - /** - * Handle mouse wheel (listen to mouse wheel scrolling). - * Defaults to true - */ - handleMouseWheel?: boolean; - /** - * If mouse wheel is handled, make mouse wheel scrolling smooth. - * Defaults to true. - */ - mouseWheelSmoothScroll?: boolean; - /** - * Flip axes. Treat vertical scrolling like horizontal and vice-versa. - * Defaults to false. - */ - flipAxes?: boolean; - /** - * If enabled, will scroll horizontally when scrolling vertical. - * Defaults to false. - */ - scrollYToX?: boolean; - /** - * Consume all mouse wheel events if a scrollbar is needed (i.e. scrollSize > size). - * Defaults to false. - */ - consumeMouseWheelIfScrollbarIsNeeded?: boolean; - /** - * Always consume mouse wheel events, even when scrolling is no longer possible. - * Defaults to false. - */ - alwaysConsumeMouseWheel?: boolean; - /** - * A multiplier to be used on the `deltaX` and `deltaY` of mouse wheel scroll events. - * Defaults to 1. - */ - mouseWheelScrollSensitivity?: number; - /** - * FastScrolling mulitplier speed when pressing `Alt` - * Defaults to 5. - */ - fastScrollSensitivity?: number; - /** - * Whether the scrollable will only scroll along the predominant axis when scrolling both - * vertically and horizontally at the same time. - * Prevents horizontal drift when scrolling vertically on a trackpad. - * Defaults to true. - */ - scrollPredominantAxis?: boolean; - /** - * Height for vertical arrows (top/bottom) and width for horizontal arrows (left/right). - * Defaults to 11. - */ - arrowSize?: number; - /** - * The dom node events should be bound to. - * If no listenOnDomNode is provided, the dom node passed to the constructor will be used for event listening. - */ - listenOnDomNode?: HTMLElement; - /** - * Control the visibility of the horizontal scrollbar. - * Accepted values: 'auto' (on mouse over), 'visible' (always visible), 'hidden' (never visible) - * Defaults to 'auto'. - */ - horizontal?: ScrollbarVisibility; - /** - * Height (in px) of the horizontal scrollbar. - * Defaults to 10. - */ - horizontalScrollbarSize?: number; - /** - * Height (in px) of the horizontal scrollbar slider. - * Defaults to `horizontalScrollbarSize` - */ - horizontalSliderSize?: number; - /** - * Render arrows (left/right) for the horizontal scrollbar. - * Defaults to false. - */ - horizontalHasArrows?: boolean; - /** - * Control the visibility of the vertical scrollbar. - * Accepted values: 'auto' (on mouse over), 'visible' (always visible), 'hidden' (never visible) - * Defaults to 'auto'. - */ - vertical?: ScrollbarVisibility; - /** - * Width (in px) of the vertical scrollbar. - * Defaults to 10. - */ - verticalScrollbarSize?: number; - /** - * Width (in px) of the vertical scrollbar slider. - * Defaults to `verticalScrollbarSize` - */ - verticalSliderSize?: number; - /** - * Render arrows (top/bottom) for the vertical scrollbar. - * Defaults to false. - */ - verticalHasArrows?: boolean; - /** - * Scroll gutter clicks move by page vs. jump to position. - * Defaults to false. - */ - scrollByPage?: boolean; + /** + * The scrollable element should not do any DOM mutations until renderNow() is called. + * Defaults to false. + */ + lazyRender?: boolean; + /** + * CSS Class name for the scrollable element. + */ + className?: string; + /** + * Drop subtle horizontal and vertical shadows. + * Defaults to false. + */ + useShadows?: boolean; + /** + * Handle mouse wheel (listen to mouse wheel scrolling). + * Defaults to true + */ + handleMouseWheel?: boolean; + /** + * If mouse wheel is handled, make mouse wheel scrolling smooth. + * Defaults to true. + */ + mouseWheelSmoothScroll?: boolean; + /** + * Flip axes. Treat vertical scrolling like horizontal and vice-versa. + * Defaults to false. + */ + flipAxes?: boolean; + /** + * If enabled, will scroll horizontally when scrolling vertical. + * Defaults to false. + */ + scrollYToX?: boolean; + /** + * Consume all mouse wheel events if a scrollbar is needed (i.e. scrollSize > size). + * Defaults to false. + */ + consumeMouseWheelIfScrollbarIsNeeded?: boolean; + /** + * Always consume mouse wheel events, even when scrolling is no longer possible. + * Defaults to false. + */ + alwaysConsumeMouseWheel?: boolean; + /** + * A multiplier to be used on the `deltaX` and `deltaY` of mouse wheel scroll events. + * Defaults to 1. + */ + mouseWheelScrollSensitivity?: number; + /** + * FastScrolling mulitplier speed when pressing `Alt` + * Defaults to 5. + */ + fastScrollSensitivity?: number; + /** + * Whether the scrollable will only scroll along the predominant axis when scrolling both + * vertically and horizontally at the same time. + * Prevents horizontal drift when scrolling vertically on a trackpad. + * Defaults to true. + */ + scrollPredominantAxis?: boolean; + /** + * Height for vertical arrows (top/bottom) and width for horizontal arrows (left/right). + * Defaults to 11. + */ + arrowSize?: number; + /** + * The dom node events should be bound to. + * If no listenOnDomNode is provided, the dom node passed to the constructor will be used for event listening. + */ + listenOnDomNode?: HTMLElement; + /** + * Control the visibility of the horizontal scrollbar. + * Accepted values: 'auto' (on mouse over), 'visible' (always visible), 'hidden' (never visible) + * Defaults to 'auto'. + */ + horizontal?: ScrollbarVisibility; + /** + * Height (in px) of the horizontal scrollbar. + * Defaults to 10. + */ + horizontalScrollbarSize?: number; + /** + * Height (in px) of the horizontal scrollbar slider. + * Defaults to `horizontalScrollbarSize` + */ + horizontalSliderSize?: number; + /** + * Render arrows (left/right) for the horizontal scrollbar. + * Defaults to false. + */ + horizontalHasArrows?: boolean; + /** + * Control the visibility of the vertical scrollbar. + * Accepted values: 'auto' (on mouse over), 'visible' (always visible), 'hidden' (never visible) + * Defaults to 'auto'. + */ + vertical?: ScrollbarVisibility; + /** + * Width (in px) of the vertical scrollbar. + * Defaults to 10. + */ + verticalScrollbarSize?: number; + /** + * Width (in px) of the vertical scrollbar slider. + * Defaults to `verticalScrollbarSize` + */ + verticalSliderSize?: number; + /** + * Render arrows (top/bottom) for the vertical scrollbar. + * Defaults to false. + */ + verticalHasArrows?: boolean; + /** + * Scroll gutter clicks move by page vs. jump to position. + * Defaults to false. + */ + scrollByPage?: boolean; } export interface ScrollableElementChangeOptions { - handleMouseWheel?: boolean; - mouseWheelScrollSensitivity?: number; - fastScrollSensitivity?: number; - scrollPredominantAxis?: boolean; - horizontal?: ScrollbarVisibility; - horizontalScrollbarSize?: number; - vertical?: ScrollbarVisibility; - verticalScrollbarSize?: number; - scrollByPage?: boolean; + handleMouseWheel?: boolean; + mouseWheelScrollSensitivity?: number; + fastScrollSensitivity?: number; + scrollPredominantAxis?: boolean; + horizontal?: ScrollbarVisibility; + horizontalScrollbarSize?: number; + vertical?: ScrollbarVisibility; + verticalScrollbarSize?: number; + scrollByPage?: boolean; } export interface ScrollableElementResolvedOptions { - lazyRender: boolean; - className: string; - useShadows: boolean; - handleMouseWheel: boolean; - flipAxes: boolean; - scrollYToX: boolean; - consumeMouseWheelIfScrollbarIsNeeded: boolean; - alwaysConsumeMouseWheel: boolean; - mouseWheelScrollSensitivity: number; - fastScrollSensitivity: number; - scrollPredominantAxis: boolean; - mouseWheelSmoothScroll: boolean; - arrowSize: number; - listenOnDomNode: HTMLElement | null; - horizontal: ScrollbarVisibility; - horizontalScrollbarSize: number; - horizontalSliderSize: number; - horizontalHasArrows: boolean; - vertical: ScrollbarVisibility; - verticalScrollbarSize: number; - verticalSliderSize: number; - verticalHasArrows: boolean; - scrollByPage: boolean; + lazyRender: boolean; + className: string; + useShadows: boolean; + handleMouseWheel: boolean; + flipAxes: boolean; + scrollYToX: boolean; + consumeMouseWheelIfScrollbarIsNeeded: boolean; + alwaysConsumeMouseWheel: boolean; + mouseWheelScrollSensitivity: number; + fastScrollSensitivity: number; + scrollPredominantAxis: boolean; + mouseWheelSmoothScroll: boolean; + arrowSize: number; + listenOnDomNode: HTMLElement | null; + horizontal: ScrollbarVisibility; + horizontalScrollbarSize: number; + horizontalSliderSize: number; + horizontalHasArrows: boolean; + vertical: ScrollbarVisibility; + verticalScrollbarSize: number; + verticalSliderSize: number; + verticalHasArrows: boolean; + scrollByPage: boolean; } diff --git a/src/browser/scrollable/scrollbarArrow.ts b/src/browser/scrollable/scrollbarArrow.ts index 649ae9f0..ef403a03 100644 --- a/src/browser/scrollable/scrollbarArrow.ts +++ b/src/browser/scrollable/scrollbarArrow.ts @@ -14,101 +14,101 @@ import * as dom from './dom'; export const ARROW_IMG_SIZE = 11; export interface ScrollbarArrowOptions { - onActivate: () => void; - className: string; - // icon: ThemeIcon; + onActivate: () => void; + className: string; + // icon: ThemeIcon; - bgWidth: number; - bgHeight: number; + bgWidth: number; + bgHeight: number; - top?: number; - left?: number; - bottom?: number; - right?: number; + top?: number; + left?: number; + bottom?: number; + right?: number; } export class ScrollbarArrow extends Widget { - private _onActivate: () => void; - public bgDomNode: HTMLElement; - public domNode: HTMLElement; - private _pointerdownRepeatTimer: dom.WindowIntervalTimer; - private _pointerdownScheduleRepeatTimer: TimeoutTimer; - private _pointerMoveMonitor: GlobalPointerMoveMonitor; + private _onActivate: () => void; + public bgDomNode: HTMLElement; + public domNode: HTMLElement; + private _pointerdownRepeatTimer: dom.WindowIntervalTimer; + private _pointerdownScheduleRepeatTimer: TimeoutTimer; + private _pointerMoveMonitor: GlobalPointerMoveMonitor; - constructor(opts: ScrollbarArrowOptions) { - super(); - this._onActivate = opts.onActivate; + constructor(opts: ScrollbarArrowOptions) { + super(); + this._onActivate = opts.onActivate; - this.bgDomNode = document.createElement('div'); - this.bgDomNode.className = 'arrow-background'; - this.bgDomNode.style.position = 'absolute'; - this.bgDomNode.style.width = opts.bgWidth + 'px'; - this.bgDomNode.style.height = opts.bgHeight + 'px'; - if (typeof opts.top !== 'undefined') { - this.bgDomNode.style.top = '0px'; - } - if (typeof opts.left !== 'undefined') { - this.bgDomNode.style.left = '0px'; - } - if (typeof opts.bottom !== 'undefined') { - this.bgDomNode.style.bottom = '0px'; - } - if (typeof opts.right !== 'undefined') { - this.bgDomNode.style.right = '0px'; - } + this.bgDomNode = document.createElement('div'); + this.bgDomNode.className = 'arrow-background'; + this.bgDomNode.style.position = 'absolute'; + this.bgDomNode.style.width = opts.bgWidth + 'px'; + this.bgDomNode.style.height = opts.bgHeight + 'px'; + if (typeof opts.top !== 'undefined') { + this.bgDomNode.style.top = '0px'; + } + if (typeof opts.left !== 'undefined') { + this.bgDomNode.style.left = '0px'; + } + if (typeof opts.bottom !== 'undefined') { + this.bgDomNode.style.bottom = '0px'; + } + if (typeof opts.right !== 'undefined') { + this.bgDomNode.style.right = '0px'; + } - this.domNode = document.createElement('div'); - this.domNode.className = opts.className; - // this.domNode.classList.add(...ThemeIcon.asClassNameArray(opts.icon)); + this.domNode = document.createElement('div'); + this.domNode.className = opts.className; + // this.domNode.classList.add(...ThemeIcon.asClassNameArray(opts.icon)); - this.domNode.style.position = 'absolute'; - this.domNode.style.width = ARROW_IMG_SIZE + 'px'; - this.domNode.style.height = ARROW_IMG_SIZE + 'px'; - if (typeof opts.top !== 'undefined') { - this.domNode.style.top = opts.top + 'px'; - } - if (typeof opts.left !== 'undefined') { - this.domNode.style.left = opts.left + 'px'; - } - if (typeof opts.bottom !== 'undefined') { - this.domNode.style.bottom = opts.bottom + 'px'; - } - if (typeof opts.right !== 'undefined') { - this.domNode.style.right = opts.right + 'px'; - } + this.domNode.style.position = 'absolute'; + this.domNode.style.width = ARROW_IMG_SIZE + 'px'; + this.domNode.style.height = ARROW_IMG_SIZE + 'px'; + if (typeof opts.top !== 'undefined') { + this.domNode.style.top = opts.top + 'px'; + } + if (typeof opts.left !== 'undefined') { + this.domNode.style.left = opts.left + 'px'; + } + if (typeof opts.bottom !== 'undefined') { + this.domNode.style.bottom = opts.bottom + 'px'; + } + if (typeof opts.right !== 'undefined') { + this.domNode.style.right = opts.right + 'px'; + } - this._pointerMoveMonitor = this._register(new GlobalPointerMoveMonitor()); - this._register(dom.addStandardDisposableListener(this.bgDomNode, dom.EventType.POINTER_DOWN, (e) => this._arrowPointerDown(e))); - this._register(dom.addStandardDisposableListener(this.domNode, dom.EventType.POINTER_DOWN, (e) => this._arrowPointerDown(e))); + this._pointerMoveMonitor = this._register(new GlobalPointerMoveMonitor()); + this._register(dom.addStandardDisposableListener(this.bgDomNode, dom.EventType.POINTER_DOWN, (e) => this._arrowPointerDown(e))); + this._register(dom.addStandardDisposableListener(this.domNode, dom.EventType.POINTER_DOWN, (e) => this._arrowPointerDown(e))); - this._pointerdownRepeatTimer = this._register(new dom.WindowIntervalTimer()); - this._pointerdownScheduleRepeatTimer = this._register(new TimeoutTimer()); - } + this._pointerdownRepeatTimer = this._register(new dom.WindowIntervalTimer()); + this._pointerdownScheduleRepeatTimer = this._register(new TimeoutTimer()); + } - private _arrowPointerDown(e: PointerEvent): void { - if (!e.target || !(e.target instanceof Element)) { - return; - } - const scheduleRepeater = () => { - this._pointerdownRepeatTimer.cancelAndSet(() => this._onActivate(), 1000 / 24, dom.getWindow(e)); - }; + private _arrowPointerDown(e: PointerEvent): void { + if (!e.target || !(e.target instanceof Element)) { + return; + } + const scheduleRepeater = () => { + this._pointerdownRepeatTimer.cancelAndSet(() => this._onActivate(), 1000 / 24, dom.getWindow(e)); + }; - this._onActivate(); - this._pointerdownRepeatTimer.cancel(); - this._pointerdownScheduleRepeatTimer.cancelAndSet(scheduleRepeater, 200); + this._onActivate(); + this._pointerdownRepeatTimer.cancel(); + this._pointerdownScheduleRepeatTimer.cancelAndSet(scheduleRepeater, 200); - this._pointerMoveMonitor.startMonitoring( - e.target, - e.pointerId, - e.buttons, - (pointerMoveData) => { /* Intentional empty */ }, - () => { - this._pointerdownRepeatTimer.cancel(); - this._pointerdownScheduleRepeatTimer.cancel(); - } - ); + this._pointerMoveMonitor.startMonitoring( + e.target, + e.pointerId, + e.buttons, + (pointerMoveData) => { /* Intentional empty */ }, + () => { + this._pointerdownRepeatTimer.cancel(); + this._pointerdownScheduleRepeatTimer.cancel(); + } + ); - e.preventDefault(); - } + e.preventDefault(); + } } diff --git a/src/browser/scrollable/scrollbarState.ts b/src/browser/scrollable/scrollbarState.ts index 8cb9c105..1aa7e3a6 100644 --- a/src/browser/scrollable/scrollbarState.ts +++ b/src/browser/scrollable/scrollbarState.ts @@ -10,214 +10,214 @@ const MINIMUM_SLIDER_SIZE = 20; export class ScrollbarState { - /** - * For the vertical scrollbar: the width. - * For the horizontal scrollbar: the height. - */ - private _scrollbarSize: number; + /** + * For the vertical scrollbar: the width. + * For the horizontal scrollbar: the height. + */ + private _scrollbarSize: number; - /** - * For the vertical scrollbar: the height of the pair horizontal scrollbar. - * For the horizontal scrollbar: the width of the pair vertical scrollbar. - */ - private _oppositeScrollbarSize: number; + /** + * For the vertical scrollbar: the height of the pair horizontal scrollbar. + * For the horizontal scrollbar: the width of the pair vertical scrollbar. + */ + private _oppositeScrollbarSize: number; - /** - * For the vertical scrollbar: the height of the scrollbar's arrows. - * For the horizontal scrollbar: the width of the scrollbar's arrows. - */ - private readonly _arrowSize: number; + /** + * For the vertical scrollbar: the height of the scrollbar's arrows. + * For the horizontal scrollbar: the width of the scrollbar's arrows. + */ + private readonly _arrowSize: number; - // --- variables - /** - * For the vertical scrollbar: the viewport height. - * For the horizontal scrollbar: the viewport width. - */ - private _visibleSize: number; + // --- variables + /** + * For the vertical scrollbar: the viewport height. + * For the horizontal scrollbar: the viewport width. + */ + private _visibleSize: number; - /** - * For the vertical scrollbar: the scroll height. - * For the horizontal scrollbar: the scroll width. - */ - private _scrollSize: number; + /** + * For the vertical scrollbar: the scroll height. + * For the horizontal scrollbar: the scroll width. + */ + private _scrollSize: number; - /** - * For the vertical scrollbar: the scroll top. - * For the horizontal scrollbar: the scroll left. - */ - private _scrollPosition: number; + /** + * For the vertical scrollbar: the scroll top. + * For the horizontal scrollbar: the scroll left. + */ + private _scrollPosition: number; - // --- computed variables + // --- computed variables - /** - * `visibleSize` - `oppositeScrollbarSize` - */ - private _computedAvailableSize: number; - /** - * (`scrollSize` > 0 && `scrollSize` > `visibleSize`) - */ - private _computedIsNeeded: boolean; + /** + * `visibleSize` - `oppositeScrollbarSize` + */ + private _computedAvailableSize: number; + /** + * (`scrollSize` > 0 && `scrollSize` > `visibleSize`) + */ + private _computedIsNeeded: boolean; - private _computedSliderSize: number; - private _computedSliderRatio: number; - private _computedSliderPosition: number; + private _computedSliderSize: number; + private _computedSliderRatio: number; + private _computedSliderPosition: number; - constructor(arrowSize: number, scrollbarSize: number, oppositeScrollbarSize: number, visibleSize: number, scrollSize: number, scrollPosition: number) { - this._scrollbarSize = Math.round(scrollbarSize); - this._oppositeScrollbarSize = Math.round(oppositeScrollbarSize); - this._arrowSize = Math.round(arrowSize); + constructor(arrowSize: number, scrollbarSize: number, oppositeScrollbarSize: number, visibleSize: number, scrollSize: number, scrollPosition: number) { + this._scrollbarSize = Math.round(scrollbarSize); + this._oppositeScrollbarSize = Math.round(oppositeScrollbarSize); + this._arrowSize = Math.round(arrowSize); - this._visibleSize = visibleSize; - this._scrollSize = scrollSize; - this._scrollPosition = scrollPosition; + this._visibleSize = visibleSize; + this._scrollSize = scrollSize; + this._scrollPosition = scrollPosition; - this._computedAvailableSize = 0; - this._computedIsNeeded = false; - this._computedSliderSize = 0; - this._computedSliderRatio = 0; - this._computedSliderPosition = 0; + this._computedAvailableSize = 0; + this._computedIsNeeded = false; + this._computedSliderSize = 0; + this._computedSliderRatio = 0; + this._computedSliderPosition = 0; - this._refreshComputedValues(); - } + this._refreshComputedValues(); + } - public clone(): ScrollbarState { - return new ScrollbarState(this._arrowSize, this._scrollbarSize, this._oppositeScrollbarSize, this._visibleSize, this._scrollSize, this._scrollPosition); - } + public clone(): ScrollbarState { + return new ScrollbarState(this._arrowSize, this._scrollbarSize, this._oppositeScrollbarSize, this._visibleSize, this._scrollSize, this._scrollPosition); + } - public setVisibleSize(visibleSize: number): boolean { - const iVisibleSize = Math.round(visibleSize); - if (this._visibleSize !== iVisibleSize) { - this._visibleSize = iVisibleSize; - this._refreshComputedValues(); - return true; - } - return false; - } + public setVisibleSize(visibleSize: number): boolean { + const iVisibleSize = Math.round(visibleSize); + if (this._visibleSize !== iVisibleSize) { + this._visibleSize = iVisibleSize; + this._refreshComputedValues(); + return true; + } + return false; + } - public setScrollSize(scrollSize: number): boolean { - const iScrollSize = Math.round(scrollSize); - if (this._scrollSize !== iScrollSize) { - this._scrollSize = iScrollSize; - this._refreshComputedValues(); - return true; - } - return false; - } + public setScrollSize(scrollSize: number): boolean { + const iScrollSize = Math.round(scrollSize); + if (this._scrollSize !== iScrollSize) { + this._scrollSize = iScrollSize; + this._refreshComputedValues(); + return true; + } + return false; + } - public setScrollPosition(scrollPosition: number): boolean { - const iScrollPosition = Math.round(scrollPosition); - if (this._scrollPosition !== iScrollPosition) { - this._scrollPosition = iScrollPosition; - this._refreshComputedValues(); - return true; - } - return false; - } + public setScrollPosition(scrollPosition: number): boolean { + const iScrollPosition = Math.round(scrollPosition); + if (this._scrollPosition !== iScrollPosition) { + this._scrollPosition = iScrollPosition; + this._refreshComputedValues(); + return true; + } + return false; + } - public setScrollbarSize(scrollbarSize: number): void { - this._scrollbarSize = Math.round(scrollbarSize); - } + public setScrollbarSize(scrollbarSize: number): void { + this._scrollbarSize = Math.round(scrollbarSize); + } - public setOppositeScrollbarSize(oppositeScrollbarSize: number): void { - this._oppositeScrollbarSize = Math.round(oppositeScrollbarSize); - } + public setOppositeScrollbarSize(oppositeScrollbarSize: number): void { + this._oppositeScrollbarSize = Math.round(oppositeScrollbarSize); + } - private static _computeValues(oppositeScrollbarSize: number, arrowSize: number, visibleSize: number, scrollSize: number, scrollPosition: number) { - const computedAvailableSize = Math.max(0, visibleSize - oppositeScrollbarSize); - const computedRepresentableSize = Math.max(0, computedAvailableSize - 2 * arrowSize); - const computedIsNeeded = (scrollSize > 0 && scrollSize > visibleSize); + private static _computeValues(oppositeScrollbarSize: number, arrowSize: number, visibleSize: number, scrollSize: number, scrollPosition: number) { + const computedAvailableSize = Math.max(0, visibleSize - oppositeScrollbarSize); + const computedRepresentableSize = Math.max(0, computedAvailableSize - 2 * arrowSize); + const computedIsNeeded = (scrollSize > 0 && scrollSize > visibleSize); - if (!computedIsNeeded) { - return { - computedAvailableSize: Math.round(computedAvailableSize), - computedIsNeeded: computedIsNeeded, - computedSliderSize: Math.round(computedRepresentableSize), - computedSliderRatio: 0, - computedSliderPosition: 0, - }; - } + if (!computedIsNeeded) { + return { + computedAvailableSize: Math.round(computedAvailableSize), + computedIsNeeded: computedIsNeeded, + computedSliderSize: Math.round(computedRepresentableSize), + computedSliderRatio: 0, + computedSliderPosition: 0, + }; + } - const computedSliderSize = Math.round(Math.max(MINIMUM_SLIDER_SIZE, Math.floor(visibleSize * computedRepresentableSize / scrollSize))); + const computedSliderSize = Math.round(Math.max(MINIMUM_SLIDER_SIZE, Math.floor(visibleSize * computedRepresentableSize / scrollSize))); - const computedSliderRatio = (computedRepresentableSize - computedSliderSize) / (scrollSize - visibleSize); - const computedSliderPosition = (scrollPosition * computedSliderRatio); + const computedSliderRatio = (computedRepresentableSize - computedSliderSize) / (scrollSize - visibleSize); + const computedSliderPosition = (scrollPosition * computedSliderRatio); - return { - computedAvailableSize: Math.round(computedAvailableSize), - computedIsNeeded: computedIsNeeded, - computedSliderSize: Math.round(computedSliderSize), - computedSliderRatio: computedSliderRatio, - computedSliderPosition: Math.round(computedSliderPosition), - }; - } + return { + computedAvailableSize: Math.round(computedAvailableSize), + computedIsNeeded: computedIsNeeded, + computedSliderSize: Math.round(computedSliderSize), + computedSliderRatio: computedSliderRatio, + computedSliderPosition: Math.round(computedSliderPosition), + }; + } - private _refreshComputedValues(): void { - const r = ScrollbarState._computeValues(this._oppositeScrollbarSize, this._arrowSize, this._visibleSize, this._scrollSize, this._scrollPosition); - this._computedAvailableSize = r.computedAvailableSize; - this._computedIsNeeded = r.computedIsNeeded; - this._computedSliderSize = r.computedSliderSize; - this._computedSliderRatio = r.computedSliderRatio; - this._computedSliderPosition = r.computedSliderPosition; - } + private _refreshComputedValues(): void { + const r = ScrollbarState._computeValues(this._oppositeScrollbarSize, this._arrowSize, this._visibleSize, this._scrollSize, this._scrollPosition); + this._computedAvailableSize = r.computedAvailableSize; + this._computedIsNeeded = r.computedIsNeeded; + this._computedSliderSize = r.computedSliderSize; + this._computedSliderRatio = r.computedSliderRatio; + this._computedSliderPosition = r.computedSliderPosition; + } - public getArrowSize(): number { - return this._arrowSize; - } + public getArrowSize(): number { + return this._arrowSize; + } - public getScrollPosition(): number { - return this._scrollPosition; - } + public getScrollPosition(): number { + return this._scrollPosition; + } - public getRectangleLargeSize(): number { - return this._computedAvailableSize; - } + public getRectangleLargeSize(): number { + return this._computedAvailableSize; + } - public getRectangleSmallSize(): number { - return this._scrollbarSize; - } + public getRectangleSmallSize(): number { + return this._scrollbarSize; + } - public isNeeded(): boolean { - return this._computedIsNeeded; - } + public isNeeded(): boolean { + return this._computedIsNeeded; + } - public getSliderSize(): number { - return this._computedSliderSize; - } + public getSliderSize(): number { + return this._computedSliderSize; + } - public getSliderPosition(): number { - return this._computedSliderPosition; - } + public getSliderPosition(): number { + return this._computedSliderPosition; + } - public getDesiredScrollPositionFromOffset(offset: number): number { - if (!this._computedIsNeeded) { - return 0; - } + public getDesiredScrollPositionFromOffset(offset: number): number { + if (!this._computedIsNeeded) { + return 0; + } - const desiredSliderPosition = offset - this._arrowSize - this._computedSliderSize / 2; - return Math.round(desiredSliderPosition / this._computedSliderRatio); - } + const desiredSliderPosition = offset - this._arrowSize - this._computedSliderSize / 2; + return Math.round(desiredSliderPosition / this._computedSliderRatio); + } - public getDesiredScrollPositionFromOffsetPaged(offset: number): number { - if (!this._computedIsNeeded) { - return 0; - } + public getDesiredScrollPositionFromOffsetPaged(offset: number): number { + if (!this._computedIsNeeded) { + return 0; + } - const correctedOffset = offset - this._arrowSize; - let desiredScrollPosition = this._scrollPosition; - if (correctedOffset < this._computedSliderPosition) { - desiredScrollPosition -= this._visibleSize; - } else { - desiredScrollPosition += this._visibleSize; - } - return desiredScrollPosition; - } + const correctedOffset = offset - this._arrowSize; + let desiredScrollPosition = this._scrollPosition; + if (correctedOffset < this._computedSliderPosition) { + desiredScrollPosition -= this._visibleSize; + } else { + desiredScrollPosition += this._visibleSize; + } + return desiredScrollPosition; + } - public getDesiredScrollPositionFromDelta(delta: number): number { - if (!this._computedIsNeeded) { - return 0; - } + public getDesiredScrollPositionFromDelta(delta: number): number { + if (!this._computedIsNeeded) { + return 0; + } - const desiredSliderPosition = this._computedSliderPosition + delta; - return Math.round(desiredSliderPosition / this._computedSliderRatio); - } + const desiredSliderPosition = this._computedSliderPosition + delta; + return Math.round(desiredSliderPosition / this._computedSliderRatio); + } } diff --git a/src/browser/scrollable/scrollbarVisibilityController.ts b/src/browser/scrollable/scrollbarVisibilityController.ts index f8c22460..5ef550b4 100644 --- a/src/browser/scrollable/scrollbarVisibilityController.ts +++ b/src/browser/scrollable/scrollbarVisibilityController.ts @@ -9,105 +9,105 @@ import { Disposable } from './lifecycle'; import { ScrollbarVisibility } from './scrollable'; export class ScrollbarVisibilityController extends Disposable { - private _visibility: ScrollbarVisibility; - private _visibleClassName: string; - private _invisibleClassName: string; - private _domNode: FastDomNode | null; - private _rawShouldBeVisible: boolean; - private _shouldBeVisible: boolean; - private _isNeeded: boolean; - private _isVisible: boolean; - private _revealTimer: TimeoutTimer; + private _visibility: ScrollbarVisibility; + private _visibleClassName: string; + private _invisibleClassName: string; + private _domNode: FastDomNode | null; + private _rawShouldBeVisible: boolean; + private _shouldBeVisible: boolean; + private _isNeeded: boolean; + private _isVisible: boolean; + private _revealTimer: TimeoutTimer; - constructor(visibility: ScrollbarVisibility, visibleClassName: string, invisibleClassName: string) { - super(); - this._visibility = visibility; - this._visibleClassName = visibleClassName; - this._invisibleClassName = invisibleClassName; - this._domNode = null; - this._isVisible = false; - this._isNeeded = false; - this._rawShouldBeVisible = false; - this._shouldBeVisible = false; - this._revealTimer = this._register(new TimeoutTimer()); - } + constructor(visibility: ScrollbarVisibility, visibleClassName: string, invisibleClassName: string) { + super(); + this._visibility = visibility; + this._visibleClassName = visibleClassName; + this._invisibleClassName = invisibleClassName; + this._domNode = null; + this._isVisible = false; + this._isNeeded = false; + this._rawShouldBeVisible = false; + this._shouldBeVisible = false; + this._revealTimer = this._register(new TimeoutTimer()); + } - public setVisibility(visibility: ScrollbarVisibility): void { - if (this._visibility !== visibility) { - this._visibility = visibility; - this._updateShouldBeVisible(); - } - } + public setVisibility(visibility: ScrollbarVisibility): void { + if (this._visibility !== visibility) { + this._visibility = visibility; + this._updateShouldBeVisible(); + } + } - public setShouldBeVisible(rawShouldBeVisible: boolean): void { - this._rawShouldBeVisible = rawShouldBeVisible; - this._updateShouldBeVisible(); - } + public setShouldBeVisible(rawShouldBeVisible: boolean): void { + this._rawShouldBeVisible = rawShouldBeVisible; + this._updateShouldBeVisible(); + } - private _applyVisibilitySetting(): boolean { - if (this._visibility === ScrollbarVisibility.Hidden) { - return false; - } - if (this._visibility === ScrollbarVisibility.Visible) { - return true; - } - return this._rawShouldBeVisible; - } + private _applyVisibilitySetting(): boolean { + if (this._visibility === ScrollbarVisibility.Hidden) { + return false; + } + if (this._visibility === ScrollbarVisibility.Visible) { + return true; + } + return this._rawShouldBeVisible; + } - private _updateShouldBeVisible(): void { - const shouldBeVisible = this._applyVisibilitySetting(); + private _updateShouldBeVisible(): void { + const shouldBeVisible = this._applyVisibilitySetting(); - if (this._shouldBeVisible !== shouldBeVisible) { - this._shouldBeVisible = shouldBeVisible; - this.ensureVisibility(); - } - } + if (this._shouldBeVisible !== shouldBeVisible) { + this._shouldBeVisible = shouldBeVisible; + this.ensureVisibility(); + } + } - public setIsNeeded(isNeeded: boolean): void { - if (this._isNeeded !== isNeeded) { - this._isNeeded = isNeeded; - this.ensureVisibility(); - } - } + public setIsNeeded(isNeeded: boolean): void { + if (this._isNeeded !== isNeeded) { + this._isNeeded = isNeeded; + this.ensureVisibility(); + } + } - public setDomNode(domNode: FastDomNode): void { - this._domNode = domNode; - this._domNode.setClassName(this._invisibleClassName); + public setDomNode(domNode: FastDomNode): void { + this._domNode = domNode; + this._domNode.setClassName(this._invisibleClassName); - this.setShouldBeVisible(false); - } + this.setShouldBeVisible(false); + } - public ensureVisibility(): void { + public ensureVisibility(): void { - if (!this._isNeeded) { - this._hide(false); - return; - } + if (!this._isNeeded) { + this._hide(false); + return; + } - if (this._shouldBeVisible) { - this._reveal(); - } else { - this._hide(true); - } - } + if (this._shouldBeVisible) { + this._reveal(); + } else { + this._hide(true); + } + } - private _reveal(): void { - if (this._isVisible) { - return; - } - this._isVisible = true; + private _reveal(): void { + if (this._isVisible) { + return; + } + this._isVisible = true; - this._revealTimer.setIfNotSet(() => { - this._domNode?.setClassName(this._visibleClassName); - }, 0); - } + this._revealTimer.setIfNotSet(() => { + this._domNode?.setClassName(this._visibleClassName); + }, 0); + } - private _hide(withFadeAway: boolean): void { - this._revealTimer.cancel(); - if (!this._isVisible) { - return; - } - this._isVisible = false; - this._domNode?.setClassName(this._invisibleClassName + (withFadeAway ? ' fade' : '')); - } + private _hide(withFadeAway: boolean): void { + this._revealTimer.cancel(); + if (!this._isVisible) { + return; + } + this._isVisible = false; + this._domNode?.setClassName(this._invisibleClassName + (withFadeAway ? ' fade' : '')); + } } diff --git a/src/browser/scrollable/stopwatch.ts b/src/browser/scrollable/stopwatch.ts index e32c0dd9..b9993984 100644 --- a/src/browser/scrollable/stopwatch.ts +++ b/src/browser/scrollable/stopwatch.ts @@ -10,34 +10,34 @@ const hasPerformanceNow = (globalThis.performance && typeof globalThis.performan export class StopWatch { - private _startTime: number; - private _stopTime: number; + private _startTime: number; + private _stopTime: number; - private readonly _now: () => number; + private readonly _now: () => number; - public static create(highResolution?: boolean): StopWatch { - return new StopWatch(highResolution); - } + public static create(highResolution?: boolean): StopWatch { + return new StopWatch(highResolution); + } - constructor(highResolution?: boolean) { - this._now = hasPerformanceNow && highResolution === false ? Date.now : globalThis.performance!.now.bind(globalThis.performance); - this._startTime = this._now(); - this._stopTime = -1; - } + constructor(highResolution?: boolean) { + this._now = hasPerformanceNow && highResolution === false ? Date.now : globalThis.performance!.now.bind(globalThis.performance); + this._startTime = this._now(); + this._stopTime = -1; + } - public stop(): void { - this._stopTime = this._now(); - } + public stop(): void { + this._stopTime = this._now(); + } - public reset(): void { - this._startTime = this._now(); - this._stopTime = -1; - } + public reset(): void { + this._startTime = this._now(); + this._stopTime = -1; + } - public elapsed(): number { - if (this._stopTime !== -1) { - return this._stopTime - this._startTime; - } - return this._now() - this._startTime; - } + public elapsed(): number { + if (this._stopTime !== -1) { + return this._stopTime - this._startTime; + } + return this._now() - this._startTime; + } } diff --git a/src/browser/scrollable/symbols.ts b/src/browser/scrollable/symbols.ts index 9aa8e5bb..5064287c 100644 --- a/src/browser/scrollable/symbols.ts +++ b/src/browser/scrollable/symbols.ts @@ -5,5 +5,5 @@ /** * Can be passed into the Delayed to defer using a microtask - * */ + */ export const MicrotaskDelay = Symbol('MicrotaskDelay'); diff --git a/src/browser/scrollable/touch.ts b/src/browser/scrollable/touch.ts index e9304cf8..90c60bf0 100644 --- a/src/browser/scrollable/touch.ts +++ b/src/browser/scrollable/touch.ts @@ -12,353 +12,353 @@ import { Disposable, IDisposable, markAsSingleton, toDisposable } from './lifecy import { LinkedList } from './linkedList'; export namespace EventType { - export const Tap = '-xterm-gesturetap'; - export const Change = '-xterm-gesturechange'; - export const Start = '-xterm-gesturestart'; - export const End = '-xterm-gesturesend'; - export const Contextmenu = '-xterm-gesturecontextmenu'; + export const Tap = '-xterm-gesturetap'; + export const Change = '-xterm-gesturechange'; + export const Start = '-xterm-gesturestart'; + export const End = '-xterm-gesturesend'; + export const Contextmenu = '-xterm-gesturecontextmenu'; } interface TouchData { - id: number; - initialTarget: EventTarget; - initialTimeStamp: number; - initialPageX: number; - initialPageY: number; - rollingTimestamps: number[]; - rollingPageX: number[]; - rollingPageY: number[]; + id: number; + initialTarget: EventTarget; + initialTimeStamp: number; + initialPageX: number; + initialPageY: number; + rollingTimestamps: number[]; + rollingPageX: number[]; + rollingPageY: number[]; } export interface GestureEvent extends MouseEvent { - initialTarget: EventTarget | undefined; - translationX: number; - translationY: number; - pageX: number; - pageY: number; - tapCount: number; + initialTarget: EventTarget | undefined; + translationX: number; + translationY: number; + pageX: number; + pageY: number; + tapCount: number; } interface Touch { - identifier: number; - screenX: number; - screenY: number; - clientX: number; - clientY: number; - pageX: number; - pageY: number; - radiusX: number; - radiusY: number; - rotationAngle: number; - force: number; - target: Element; + identifier: number; + screenX: number; + screenY: number; + clientX: number; + clientY: number; + pageX: number; + pageY: number; + radiusX: number; + radiusY: number; + rotationAngle: number; + force: number; + target: Element; } interface TouchList { - [i: number]: Touch; - length: number; - item(index: number): Touch; - identifiedTouch(id: number): Touch; + [i: number]: Touch; + length: number; + item(index: number): Touch; + identifiedTouch(id: number): Touch; } interface TouchEvent extends Event { - touches: TouchList; - targetTouches: TouchList; - changedTouches: TouchList; + touches: TouchList; + targetTouches: TouchList; + changedTouches: TouchList; } export class Gesture extends Disposable { - private static readonly SCROLL_FRICTION = -0.005; - private static INSTANCE: Gesture; - private static readonly HOLD_DELAY = 700; + private static readonly SCROLL_FRICTION = -0.005; + private static INSTANCE: Gesture; + private static readonly HOLD_DELAY = 700; - private dispatched = false; - private readonly targets = new LinkedList(); - private readonly ignoreTargets = new LinkedList(); - private handle: IDisposable | null; + private dispatched = false; + private readonly targets = new LinkedList(); + private readonly ignoreTargets = new LinkedList(); + private handle: IDisposable | null; - private readonly activeTouches: { [id: number]: TouchData }; + private readonly activeTouches: { [id: number]: TouchData }; - private _lastSetTapCountTime: number; + private _lastSetTapCountTime: number; - private static readonly CLEAR_TAP_COUNT_TIME = 400; // ms + private static readonly CLEAR_TAP_COUNT_TIME = 400; // ms - private constructor() { - super(); + private constructor() { + super(); - this.activeTouches = {}; - this.handle = null; - this._lastSetTapCountTime = 0; + this.activeTouches = {}; + this.handle = null; + this._lastSetTapCountTime = 0; - this._register(EventUtils.runAndSubscribe(DomUtils.onDidRegisterWindow, ({ window, disposables }) => { - disposables.add(DomUtils.addDisposableListener(window.document, 'touchstart', (e: TouchEvent) => this.onTouchStart(e), { passive: false })); - disposables.add(DomUtils.addDisposableListener(window.document, 'touchend', (e: TouchEvent) => this.onTouchEnd(window, e))); - disposables.add(DomUtils.addDisposableListener(window.document, 'touchmove', (e: TouchEvent) => this.onTouchMove(e), { passive: false })); - }, { window: mainWindow, disposables: this._store })); - } + this._register(EventUtils.runAndSubscribe(DomUtils.onDidRegisterWindow, ({ window, disposables }) => { + disposables.add(DomUtils.addDisposableListener(window.document, 'touchstart', (e: TouchEvent) => this.onTouchStart(e), { passive: false })); + disposables.add(DomUtils.addDisposableListener(window.document, 'touchend', (e: TouchEvent) => this.onTouchEnd(window, e))); + disposables.add(DomUtils.addDisposableListener(window.document, 'touchmove', (e: TouchEvent) => this.onTouchMove(e), { passive: false })); + }, { window: mainWindow, disposables: this._store })); + } - public static addTarget(element: HTMLElement): IDisposable { - if (!Gesture.isTouchDevice()) { - return Disposable.None; - } - if (!Gesture.INSTANCE) { - Gesture.INSTANCE = markAsSingleton(new Gesture()); - } + public static addTarget(element: HTMLElement): IDisposable { + if (!Gesture.isTouchDevice()) { + return Disposable.None; + } + if (!Gesture.INSTANCE) { + Gesture.INSTANCE = markAsSingleton(new Gesture()); + } - const remove = Gesture.INSTANCE.targets.push(element); - return toDisposable(remove); - } + const remove = Gesture.INSTANCE.targets.push(element); + return toDisposable(remove); + } - public static ignoreTarget(element: HTMLElement): IDisposable { - if (!Gesture.isTouchDevice()) { - return Disposable.None; - } - if (!Gesture.INSTANCE) { - Gesture.INSTANCE = markAsSingleton(new Gesture()); - } + public static ignoreTarget(element: HTMLElement): IDisposable { + if (!Gesture.isTouchDevice()) { + return Disposable.None; + } + if (!Gesture.INSTANCE) { + Gesture.INSTANCE = markAsSingleton(new Gesture()); + } - const remove = Gesture.INSTANCE.ignoreTargets.push(element); - return toDisposable(remove); - } + const remove = Gesture.INSTANCE.ignoreTargets.push(element); + return toDisposable(remove); + } - @memoize - static isTouchDevice(): boolean { - return 'ontouchstart' in mainWindow || navigator.maxTouchPoints > 0; - } + @memoize + static isTouchDevice(): boolean { + return 'ontouchstart' in mainWindow || navigator.maxTouchPoints > 0; + } - public override dispose(): void { - if (this.handle) { - this.handle.dispose(); - this.handle = null; - } + public override dispose(): void { + if (this.handle) { + this.handle.dispose(); + this.handle = null; + } - super.dispose(); - } + super.dispose(); + } - private onTouchStart(e: TouchEvent): void { - const timestamp = Date.now(); + private onTouchStart(e: TouchEvent): void { + const timestamp = Date.now(); - if (this.handle) { - this.handle.dispose(); - this.handle = null; - } + if (this.handle) { + this.handle.dispose(); + this.handle = null; + } - for (let i = 0, len = e.targetTouches.length; i < len; i++) { - const touch = e.targetTouches.item(i); + for (let i = 0, len = e.targetTouches.length; i < len; i++) { + const touch = e.targetTouches.item(i); - this.activeTouches[touch.identifier] = { - id: touch.identifier, - initialTarget: touch.target, - initialTimeStamp: timestamp, - initialPageX: touch.pageX, - initialPageY: touch.pageY, - rollingTimestamps: [timestamp], - rollingPageX: [touch.pageX], - rollingPageY: [touch.pageY] - }; + this.activeTouches[touch.identifier] = { + id: touch.identifier, + initialTarget: touch.target, + initialTimeStamp: timestamp, + initialPageX: touch.pageX, + initialPageY: touch.pageY, + rollingTimestamps: [timestamp], + rollingPageX: [touch.pageX], + rollingPageY: [touch.pageY] + }; - const evt = this.newGestureEvent(EventType.Start, touch.target); - evt.pageX = touch.pageX; - evt.pageY = touch.pageY; - this.dispatchEvent(evt); - } + const evt = this.newGestureEvent(EventType.Start, touch.target); + evt.pageX = touch.pageX; + evt.pageY = touch.pageY; + this.dispatchEvent(evt); + } - if (this.dispatched) { - e.preventDefault(); - e.stopPropagation(); - this.dispatched = false; - } - } + if (this.dispatched) { + e.preventDefault(); + e.stopPropagation(); + this.dispatched = false; + } + } - private onTouchEnd(targetWindow: Window, e: TouchEvent): void { - const timestamp = Date.now(); + private onTouchEnd(targetWindow: Window, e: TouchEvent): void { + const timestamp = Date.now(); - const activeTouchCount = Object.keys(this.activeTouches).length; + const activeTouchCount = Object.keys(this.activeTouches).length; - for (let i = 0, len = e.changedTouches.length; i < len; i++) { + for (let i = 0, len = e.changedTouches.length; i < len; i++) { - const touch = e.changedTouches.item(i); + const touch = e.changedTouches.item(i); - if (!this.activeTouches.hasOwnProperty(String(touch.identifier))) { - console.warn('move of an UNKNOWN touch', touch); - continue; - } + if (!this.activeTouches.hasOwnProperty(String(touch.identifier))) { + console.warn('move of an UNKNOWN touch', touch); + continue; + } - const data = this.activeTouches[touch.identifier], - holdTime = Date.now() - data.initialTimeStamp; + const data = this.activeTouches[touch.identifier]; + const holdTime = Date.now() - data.initialTimeStamp; - if (holdTime < Gesture.HOLD_DELAY + if (holdTime < Gesture.HOLD_DELAY && Math.abs(data.initialPageX - arrays.tail(data.rollingPageX)!) < 30 && Math.abs(data.initialPageY - arrays.tail(data.rollingPageY)!) < 30) { - const evt = this.newGestureEvent(EventType.Tap, data.initialTarget); - evt.pageX = arrays.tail(data.rollingPageX)!; - evt.pageY = arrays.tail(data.rollingPageY)!; - this.dispatchEvent(evt); + const evt = this.newGestureEvent(EventType.Tap, data.initialTarget); + evt.pageX = arrays.tail(data.rollingPageX)!; + evt.pageY = arrays.tail(data.rollingPageY)!; + this.dispatchEvent(evt); - } else if (holdTime >= Gesture.HOLD_DELAY + } else if (holdTime >= Gesture.HOLD_DELAY && Math.abs(data.initialPageX - arrays.tail(data.rollingPageX)!) < 30 && Math.abs(data.initialPageY - arrays.tail(data.rollingPageY)!) < 30) { - const evt = this.newGestureEvent(EventType.Contextmenu, data.initialTarget); - evt.pageX = arrays.tail(data.rollingPageX)!; - evt.pageY = arrays.tail(data.rollingPageY)!; - this.dispatchEvent(evt); + const evt = this.newGestureEvent(EventType.Contextmenu, data.initialTarget); + evt.pageX = arrays.tail(data.rollingPageX)!; + evt.pageY = arrays.tail(data.rollingPageY)!; + this.dispatchEvent(evt); - } else if (activeTouchCount === 1) { - const finalX = arrays.tail(data.rollingPageX)!; - const finalY = arrays.tail(data.rollingPageY)!; + } else if (activeTouchCount === 1) { + const finalX = arrays.tail(data.rollingPageX)!; + const finalY = arrays.tail(data.rollingPageY)!; - const deltaT = arrays.tail(data.rollingTimestamps)! - data.rollingTimestamps[0]; - const deltaX = finalX - data.rollingPageX[0]; - const deltaY = finalY - data.rollingPageY[0]; + const deltaT = arrays.tail(data.rollingTimestamps)! - data.rollingTimestamps[0]; + const deltaX = finalX - data.rollingPageX[0]; + const deltaY = finalY - data.rollingPageY[0]; - const dispatchTo = [...this.targets].filter(t => data.initialTarget instanceof Node && t.contains(data.initialTarget)); - this.inertia(targetWindow, dispatchTo, timestamp, - Math.abs(deltaX) / deltaT, - deltaX > 0 ? 1 : -1, - finalX, - Math.abs(deltaY) / deltaT, - deltaY > 0 ? 1 : -1, - finalY - ); - } + const dispatchTo = [...this.targets].filter(t => data.initialTarget instanceof Node && t.contains(data.initialTarget)); + this.inertia(targetWindow, dispatchTo, timestamp, + Math.abs(deltaX) / deltaT, + deltaX > 0 ? 1 : -1, + finalX, + Math.abs(deltaY) / deltaT, + deltaY > 0 ? 1 : -1, + finalY + ); + } - this.dispatchEvent(this.newGestureEvent(EventType.End, data.initialTarget)); - delete this.activeTouches[touch.identifier]; - } + this.dispatchEvent(this.newGestureEvent(EventType.End, data.initialTarget)); + delete this.activeTouches[touch.identifier]; + } - if (this.dispatched) { - e.preventDefault(); - e.stopPropagation(); - this.dispatched = false; - } - } + if (this.dispatched) { + e.preventDefault(); + e.stopPropagation(); + this.dispatched = false; + } + } - private newGestureEvent(type: string, initialTarget?: EventTarget): GestureEvent { - const event = document.createEvent('CustomEvent') as unknown as GestureEvent; - event.initEvent(type, false, true); - event.initialTarget = initialTarget; - event.tapCount = 0; - return event; - } + private newGestureEvent(type: string, initialTarget?: EventTarget): GestureEvent { + const event = document.createEvent('CustomEvent') as unknown as GestureEvent; + event.initEvent(type, false, true); + event.initialTarget = initialTarget; + event.tapCount = 0; + return event; + } - private dispatchEvent(event: GestureEvent): void { - if (event.type === EventType.Tap) { - const currentTime = (new Date()).getTime(); - let setTapCount = 0; - if (currentTime - this._lastSetTapCountTime > Gesture.CLEAR_TAP_COUNT_TIME) { - setTapCount = 1; - } else { - setTapCount = 2; - } + private dispatchEvent(event: GestureEvent): void { + if (event.type === EventType.Tap) { + const currentTime = (new Date()).getTime(); + let setTapCount = 0; + if (currentTime - this._lastSetTapCountTime > Gesture.CLEAR_TAP_COUNT_TIME) { + setTapCount = 1; + } else { + setTapCount = 2; + } - this._lastSetTapCountTime = currentTime; - event.tapCount = setTapCount; - } else if (event.type === EventType.Change || event.type === EventType.Contextmenu) { - this._lastSetTapCountTime = 0; - } + this._lastSetTapCountTime = currentTime; + event.tapCount = setTapCount; + } else if (event.type === EventType.Change || event.type === EventType.Contextmenu) { + this._lastSetTapCountTime = 0; + } - if (event.initialTarget instanceof Node) { - for (const ignoreTarget of this.ignoreTargets) { - if (ignoreTarget.contains(event.initialTarget)) { - return; - } - } + if (event.initialTarget instanceof Node) { + for (const ignoreTarget of this.ignoreTargets) { + if (ignoreTarget.contains(event.initialTarget)) { + return; + } + } - const targets: [number, HTMLElement][] = []; - for (const target of this.targets) { - if (target.contains(event.initialTarget)) { - let depth = 0; - let now: Node | null = event.initialTarget; - while (now && now !== target) { - depth++; - now = now.parentElement; - } - targets.push([depth, target]); - } - } + const targets: [number, HTMLElement][] = []; + for (const target of this.targets) { + if (target.contains(event.initialTarget)) { + let depth = 0; + let now: Node | null = event.initialTarget; + while (now && now !== target) { + depth++; + now = now.parentElement; + } + targets.push([depth, target]); + } + } - targets.sort((a, b) => a[0] - b[0]); + targets.sort((a, b) => a[0] - b[0]); - for (const [_, target] of targets) { - target.dispatchEvent(event); - this.dispatched = true; - } - } - } + for (const [_, target] of targets) { + target.dispatchEvent(event); + this.dispatched = true; + } + } + } - private inertia(targetWindow: Window, dispatchTo: readonly EventTarget[], t1: number, vX: number, dirX: number, x: number, vY: number, dirY: number, y: number): void { - this.handle = DomUtils.scheduleAtNextAnimationFrame(targetWindow, () => { - const now = Date.now(); + private inertia(targetWindow: Window, dispatchTo: ReadonlyArray, t1: number, vX: number, dirX: number, x: number, vY: number, dirY: number, y: number): void { + this.handle = DomUtils.scheduleAtNextAnimationFrame(targetWindow, () => { + const now = Date.now(); - const deltaT = now - t1; - let delta_pos_x = 0, delta_pos_y = 0; - let stopped = true; + const deltaT = now - t1; + let delta_pos_x = 0; let delta_pos_y = 0; + let stopped = true; - vX += Gesture.SCROLL_FRICTION * deltaT; - vY += Gesture.SCROLL_FRICTION * deltaT; + vX += Gesture.SCROLL_FRICTION * deltaT; + vY += Gesture.SCROLL_FRICTION * deltaT; - if (vX > 0) { - stopped = false; - delta_pos_x = dirX * vX * deltaT; - } + if (vX > 0) { + stopped = false; + delta_pos_x = dirX * vX * deltaT; + } - if (vY > 0) { - stopped = false; - delta_pos_y = dirY * vY * deltaT; - } + if (vY > 0) { + stopped = false; + delta_pos_y = dirY * vY * deltaT; + } - const evt = this.newGestureEvent(EventType.Change); - evt.translationX = delta_pos_x; - evt.translationY = delta_pos_y; - dispatchTo.forEach(d => d.dispatchEvent(evt)); + const evt = this.newGestureEvent(EventType.Change); + evt.translationX = delta_pos_x; + evt.translationY = delta_pos_y; + dispatchTo.forEach(d => d.dispatchEvent(evt)); - if (!stopped) { - this.inertia(targetWindow, dispatchTo, now, vX, dirX, x + delta_pos_x, vY, dirY, y + delta_pos_y); - } - }); - } + if (!stopped) { + this.inertia(targetWindow, dispatchTo, now, vX, dirX, x + delta_pos_x, vY, dirY, y + delta_pos_y); + } + }); + } - private onTouchMove(e: TouchEvent): void { - const timestamp = Date.now(); + private onTouchMove(e: TouchEvent): void { + const timestamp = Date.now(); - for (let i = 0, len = e.changedTouches.length; i < len; i++) { + for (let i = 0, len = e.changedTouches.length; i < len; i++) { - const touch = e.changedTouches.item(i); + const touch = e.changedTouches.item(i); - if (!this.activeTouches.hasOwnProperty(String(touch.identifier))) { - console.warn('end of an UNKNOWN touch', touch); - continue; - } + if (!this.activeTouches.hasOwnProperty(String(touch.identifier))) { + console.warn('end of an UNKNOWN touch', touch); + continue; + } - const data = this.activeTouches[touch.identifier]; + const data = this.activeTouches[touch.identifier]; - const evt = this.newGestureEvent(EventType.Change, data.initialTarget); - evt.translationX = touch.pageX - arrays.tail(data.rollingPageX)!; - evt.translationY = touch.pageY - arrays.tail(data.rollingPageY)!; - evt.pageX = touch.pageX; - evt.pageY = touch.pageY; - this.dispatchEvent(evt); + const evt = this.newGestureEvent(EventType.Change, data.initialTarget); + evt.translationX = touch.pageX - arrays.tail(data.rollingPageX)!; + evt.translationY = touch.pageY - arrays.tail(data.rollingPageY)!; + evt.pageX = touch.pageX; + evt.pageY = touch.pageY; + this.dispatchEvent(evt); - if (data.rollingPageX.length > 3) { - data.rollingPageX.shift(); - data.rollingPageY.shift(); - data.rollingTimestamps.shift(); - } + if (data.rollingPageX.length > 3) { + data.rollingPageX.shift(); + data.rollingPageY.shift(); + data.rollingTimestamps.shift(); + } - data.rollingPageX.push(touch.pageX); - data.rollingPageY.push(touch.pageY); - data.rollingTimestamps.push(timestamp); - } + data.rollingPageX.push(touch.pageX); + data.rollingPageY.push(touch.pageY); + data.rollingTimestamps.push(timestamp); + } - if (this.dispatched) { - e.preventDefault(); - e.stopPropagation(); - this.dispatched = false; - } - } + if (this.dispatched) { + e.preventDefault(); + e.stopPropagation(); + this.dispatched = false; + } + } } diff --git a/src/browser/scrollable/verticalScrollbar.ts b/src/browser/scrollable/verticalScrollbar.ts index d155a0c8..42f62231 100644 --- a/src/browser/scrollable/verticalScrollbar.ts +++ b/src/browser/scrollable/verticalScrollbar.ts @@ -10,77 +10,77 @@ import { INewScrollPosition, Scrollable, ScrollbarVisibility, ScrollEvent } from export class VerticalScrollbar extends AbstractScrollbar { - constructor(scrollable: Scrollable, options: ScrollableElementResolvedOptions, host: ScrollbarHost) { - const scrollDimensions = scrollable.getScrollDimensions(); - const scrollPosition = scrollable.getCurrentScrollPosition(); - super({ - lazyRender: options.lazyRender, - host: host, - scrollbarState: new ScrollbarState( - (options.verticalHasArrows ? options.arrowSize : 0), - (options.vertical === ScrollbarVisibility.Hidden ? 0 : options.verticalScrollbarSize), - 0, - scrollDimensions.height, - scrollDimensions.scrollHeight, - scrollPosition.scrollTop - ), - visibility: options.vertical, - extraScrollbarClassName: 'vertical', - scrollable: scrollable, - scrollByPage: options.scrollByPage - }); + constructor(scrollable: Scrollable, options: ScrollableElementResolvedOptions, host: ScrollbarHost) { + const scrollDimensions = scrollable.getScrollDimensions(); + const scrollPosition = scrollable.getCurrentScrollPosition(); + super({ + lazyRender: options.lazyRender, + host: host, + scrollbarState: new ScrollbarState( + (options.verticalHasArrows ? options.arrowSize : 0), + (options.vertical === ScrollbarVisibility.Hidden ? 0 : options.verticalScrollbarSize), + 0, + scrollDimensions.height, + scrollDimensions.scrollHeight, + scrollPosition.scrollTop + ), + visibility: options.vertical, + extraScrollbarClassName: 'vertical', + scrollable: scrollable, + scrollByPage: options.scrollByPage + }); - if (options.verticalHasArrows) { - throw new Error('horizontalHasArrows is not supported in xterm.js'); - } + if (options.verticalHasArrows) { + throw new Error('horizontalHasArrows is not supported in xterm.js'); + } - this._createSlider(0, Math.floor((options.verticalScrollbarSize - options.verticalSliderSize) / 2), options.verticalSliderSize, undefined); - } + this._createSlider(0, Math.floor((options.verticalScrollbarSize - options.verticalSliderSize) / 2), options.verticalSliderSize, undefined); + } - protected _updateSlider(sliderSize: number, sliderPosition: number): void { - this.slider.setHeight(sliderSize); - this.slider.setTop(sliderPosition); - } + protected _updateSlider(sliderSize: number, sliderPosition: number): void { + this.slider.setHeight(sliderSize); + this.slider.setTop(sliderPosition); + } - protected _renderDomNode(largeSize: number, smallSize: number): void { - this.domNode.setWidth(smallSize); - this.domNode.setHeight(largeSize); - this.domNode.setRight(0); - this.domNode.setTop(0); - } + protected _renderDomNode(largeSize: number, smallSize: number): void { + this.domNode.setWidth(smallSize); + this.domNode.setHeight(largeSize); + this.domNode.setRight(0); + this.domNode.setTop(0); + } - public onDidScroll(e: ScrollEvent): boolean { - this._shouldRender = this._onElementScrollSize(e.scrollHeight) || this._shouldRender; - this._shouldRender = this._onElementScrollPosition(e.scrollTop) || this._shouldRender; - this._shouldRender = this._onElementSize(e.height) || this._shouldRender; - return this._shouldRender; - } + public onDidScroll(e: ScrollEvent): boolean { + this._shouldRender = this._onElementScrollSize(e.scrollHeight) || this._shouldRender; + this._shouldRender = this._onElementScrollPosition(e.scrollTop) || this._shouldRender; + this._shouldRender = this._onElementSize(e.height) || this._shouldRender; + return this._shouldRender; + } - protected _pointerDownRelativePosition(offsetX: number, offsetY: number): number { - return offsetY; - } + protected _pointerDownRelativePosition(offsetX: number, offsetY: number): number { + return offsetY; + } - protected _sliderPointerPosition(e: ISimplifiedPointerEvent): number { - return e.pageY; - } + protected _sliderPointerPosition(e: ISimplifiedPointerEvent): number { + return e.pageY; + } - protected _sliderOrthogonalPointerPosition(e: ISimplifiedPointerEvent): number { - return e.pageX; - } + protected _sliderOrthogonalPointerPosition(e: ISimplifiedPointerEvent): number { + return e.pageX; + } - protected _updateScrollbarSize(size: number): void { - this.slider.setWidth(size); - } + protected _updateScrollbarSize(size: number): void { + this.slider.setWidth(size); + } - public writeScrollPosition(target: INewScrollPosition, scrollPosition: number): void { - target.scrollTop = scrollPosition; - } + public writeScrollPosition(target: INewScrollPosition, scrollPosition: number): void { + target.scrollTop = scrollPosition; + } - public updateOptions(options: ScrollableElementResolvedOptions): void { - this.updateScrollbarSize(options.vertical === ScrollbarVisibility.Hidden ? 0 : options.verticalScrollbarSize); - this._scrollbarState.setOppositeScrollbarSize(0); - this._visibilityController.setVisibility(options.vertical); - this._scrollByPage = options.scrollByPage; - } + public updateOptions(options: ScrollableElementResolvedOptions): void { + this.updateScrollbarSize(options.vertical === ScrollbarVisibility.Hidden ? 0 : options.verticalScrollbarSize); + this._scrollbarState.setOppositeScrollbarSize(0); + this._visibilityController.setVisibility(options.vertical); + this._scrollByPage = options.scrollByPage; + } } diff --git a/src/browser/scrollable/widget.ts b/src/browser/scrollable/widget.ts index 5102cc8e..fa721796 100644 --- a/src/browser/scrollable/widget.ts +++ b/src/browser/scrollable/widget.ts @@ -11,47 +11,47 @@ import { Disposable, IDisposable } from './lifecycle'; export abstract class Widget extends Disposable { - protected onclick(domNode: HTMLElement, listener: (e: IMouseEvent) => void): void { - this._register(dom.addDisposableListener(domNode, dom.EventType.CLICK, (e: MouseEvent) => listener(new StandardMouseEvent(dom.getWindow(domNode), e)))); - } + protected onclick(domNode: HTMLElement, listener: (e: IMouseEvent) => void): void { + this._register(dom.addDisposableListener(domNode, dom.EventType.CLICK, (e: MouseEvent) => listener(new StandardMouseEvent(dom.getWindow(domNode), e)))); + } - protected onmousedown(domNode: HTMLElement, listener: (e: IMouseEvent) => void): void { - this._register(dom.addDisposableListener(domNode, dom.EventType.MOUSE_DOWN, (e: MouseEvent) => listener(new StandardMouseEvent(dom.getWindow(domNode), e)))); - } + protected onmousedown(domNode: HTMLElement, listener: (e: IMouseEvent) => void): void { + this._register(dom.addDisposableListener(domNode, dom.EventType.MOUSE_DOWN, (e: MouseEvent) => listener(new StandardMouseEvent(dom.getWindow(domNode), e)))); + } - protected onmouseover(domNode: HTMLElement, listener: (e: IMouseEvent) => void): void { - this._register(dom.addDisposableListener(domNode, dom.EventType.MOUSE_OVER, (e: MouseEvent) => listener(new StandardMouseEvent(dom.getWindow(domNode), e)))); - } + protected onmouseover(domNode: HTMLElement, listener: (e: IMouseEvent) => void): void { + this._register(dom.addDisposableListener(domNode, dom.EventType.MOUSE_OVER, (e: MouseEvent) => listener(new StandardMouseEvent(dom.getWindow(domNode), e)))); + } - protected onmouseleave(domNode: HTMLElement, listener: (e: IMouseEvent) => void): void { - this._register(dom.addDisposableListener(domNode, dom.EventType.MOUSE_LEAVE, (e: MouseEvent) => listener(new StandardMouseEvent(dom.getWindow(domNode), e)))); - } + protected onmouseleave(domNode: HTMLElement, listener: (e: IMouseEvent) => void): void { + this._register(dom.addDisposableListener(domNode, dom.EventType.MOUSE_LEAVE, (e: MouseEvent) => listener(new StandardMouseEvent(dom.getWindow(domNode), e)))); + } - protected onkeydown(domNode: HTMLElement, listener: (e: IKeyboardEvent) => void): void { - this._register(dom.addDisposableListener(domNode, dom.EventType.KEY_DOWN, (e: KeyboardEvent) => listener(new StandardKeyboardEvent(e)))); - } + protected onkeydown(domNode: HTMLElement, listener: (e: IKeyboardEvent) => void): void { + this._register(dom.addDisposableListener(domNode, dom.EventType.KEY_DOWN, (e: KeyboardEvent) => listener(new StandardKeyboardEvent(e)))); + } - protected onkeyup(domNode: HTMLElement, listener: (e: IKeyboardEvent) => void): void { - this._register(dom.addDisposableListener(domNode, dom.EventType.KEY_UP, (e: KeyboardEvent) => listener(new StandardKeyboardEvent(e)))); - } + protected onkeyup(domNode: HTMLElement, listener: (e: IKeyboardEvent) => void): void { + this._register(dom.addDisposableListener(domNode, dom.EventType.KEY_UP, (e: KeyboardEvent) => listener(new StandardKeyboardEvent(e)))); + } - protected oninput(domNode: HTMLElement, listener: (e: Event) => void): void { - this._register(dom.addDisposableListener(domNode, dom.EventType.INPUT, listener)); - } + protected oninput(domNode: HTMLElement, listener: (e: Event) => void): void { + this._register(dom.addDisposableListener(domNode, dom.EventType.INPUT, listener)); + } - protected onblur(domNode: HTMLElement, listener: (e: Event) => void): void { - this._register(dom.addDisposableListener(domNode, dom.EventType.BLUR, listener)); - } + protected onblur(domNode: HTMLElement, listener: (e: Event) => void): void { + this._register(dom.addDisposableListener(domNode, dom.EventType.BLUR, listener)); + } - protected onfocus(domNode: HTMLElement, listener: (e: Event) => void): void { - this._register(dom.addDisposableListener(domNode, dom.EventType.FOCUS, listener)); - } + protected onfocus(domNode: HTMLElement, listener: (e: Event) => void): void { + this._register(dom.addDisposableListener(domNode, dom.EventType.FOCUS, listener)); + } - protected onchange(domNode: HTMLElement, listener: (e: Event) => void): void { - this._register(dom.addDisposableListener(domNode, dom.EventType.CHANGE, listener)); - } + protected onchange(domNode: HTMLElement, listener: (e: Event) => void): void { + this._register(dom.addDisposableListener(domNode, dom.EventType.CHANGE, listener)); + } - protected ignoreGesture(domNode: HTMLElement): IDisposable { - return Gesture.ignoreTarget(domNode); - } + protected ignoreGesture(domNode: HTMLElement): IDisposable { + return Gesture.ignoreTarget(domNode); + } } diff --git a/src/browser/scrollable/window.ts b/src/browser/scrollable/window.ts index 3a377a85..141f1330 100644 --- a/src/browser/scrollable/window.ts +++ b/src/browser/scrollable/window.ts @@ -4,11 +4,11 @@ *--------------------------------------------------------------------------------------------*/ export type CodeWindow = Window & typeof globalThis & { - readonly vscodeWindowId: number; + readonly vscodeWindowId: number; }; export function ensureCodeWindow(targetWindow: Window, fallbackWindowId: number): asserts targetWindow is CodeWindow { } -// eslint-disable-next-line no-restricted-globals + export const mainWindow = (typeof window === 'object' ? window : globalThis) as CodeWindow;