Path: blob/main/src/vs/base/browser/globalPointerMoveMonitor.ts
3292 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import * as dom from './dom.js';6import { DisposableStore, IDisposable, toDisposable } from '../common/lifecycle.js';78export interface IPointerMoveCallback {9(event: PointerEvent): void;10}1112export interface IOnStopCallback {13(browserEvent?: PointerEvent | KeyboardEvent): void;14}1516export class GlobalPointerMoveMonitor implements IDisposable {1718private readonly _hooks = new DisposableStore();19private _pointerMoveCallback: IPointerMoveCallback | null = null;20private _onStopCallback: IOnStopCallback | null = null;2122public dispose(): void {23this.stopMonitoring(false);24this._hooks.dispose();25}2627public stopMonitoring(invokeStopCallback: boolean, browserEvent?: PointerEvent | KeyboardEvent): void {28if (!this.isMonitoring()) {29// Not monitoring30return;31}3233// Unhook34this._hooks.clear();35this._pointerMoveCallback = null;36const onStopCallback = this._onStopCallback;37this._onStopCallback = null;3839if (invokeStopCallback && onStopCallback) {40onStopCallback(browserEvent);41}42}4344public isMonitoring(): boolean {45return !!this._pointerMoveCallback;46}4748public startMonitoring(49initialElement: Element,50pointerId: number,51initialButtons: number,52pointerMoveCallback: IPointerMoveCallback,53onStopCallback: IOnStopCallback54): void {55if (this.isMonitoring()) {56this.stopMonitoring(false);57}58this._pointerMoveCallback = pointerMoveCallback;59this._onStopCallback = onStopCallback;6061let eventSource: Element | Window = initialElement;6263try {64initialElement.setPointerCapture(pointerId);65this._hooks.add(toDisposable(() => {66try {67initialElement.releasePointerCapture(pointerId);68} catch (err) {69// See https://github.com/microsoft/vscode/issues/16173170//71// `releasePointerCapture` sometimes fails when being invoked with the exception:72// DOMException: Failed to execute 'releasePointerCapture' on 'Element':73// No active pointer with the given id is found.74//75// There's no need to do anything in case of failure76}77}));78} catch (err) {79// See https://github.com/microsoft/vscode/issues/14458480// See https://github.com/microsoft/vscode/issues/14694781// `setPointerCapture` sometimes fails when being invoked82// from a `mousedown` listener on macOS and Windows83// and it always fails on Linux with the exception:84// DOMException: Failed to execute 'setPointerCapture' on 'Element':85// No active pointer with the given id is found.86// In case of failure, we bind the listeners on the window87eventSource = dom.getWindow(initialElement);88}8990this._hooks.add(dom.addDisposableListener(91eventSource,92dom.EventType.POINTER_MOVE,93(e) => {94if (e.buttons !== initialButtons) {95// Buttons state has changed in the meantime96this.stopMonitoring(true);97return;98}99100e.preventDefault();101this._pointerMoveCallback!(e);102}103));104105this._hooks.add(dom.addDisposableListener(106eventSource,107dom.EventType.POINTER_UP,108(e: PointerEvent) => this.stopMonitoring(true)109));110}111}112113114