96 lines
2.4 KiB
TypeScript
96 lines
2.4 KiB
TypeScript
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
|
|
import * as dom from './dom';
|
|
import { DisposableStore, IDisposable, toDisposable } from './lifecycle';
|
|
|
|
export interface IPointerMoveCallback {
|
|
(event: PointerEvent): void;
|
|
}
|
|
|
|
export interface IOnStopCallback {
|
|
(browserEvent?: PointerEvent | KeyboardEvent): void;
|
|
}
|
|
|
|
export class GlobalPointerMoveMonitor implements IDisposable {
|
|
|
|
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 stopMonitoring(invokeStopCallback: boolean, browserEvent?: PointerEvent | KeyboardEvent): void {
|
|
if (!this.isMonitoring()) {
|
|
return;
|
|
}
|
|
|
|
this._hooks.clear();
|
|
this._pointerMoveCallback = null;
|
|
const onStopCallback = this._onStopCallback;
|
|
this._onStopCallback = null;
|
|
|
|
if (invokeStopCallback && onStopCallback) {
|
|
onStopCallback(browserEvent);
|
|
}
|
|
}
|
|
|
|
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;
|
|
|
|
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);
|
|
}
|
|
|
|
this._hooks.add(dom.addDisposableListener(
|
|
eventSource,
|
|
dom.EventType.POINTER_MOVE,
|
|
(e) => {
|
|
if (e.buttons !== initialButtons) {
|
|
this.stopMonitoring(true);
|
|
return;
|
|
}
|
|
|
|
e.preventDefault();
|
|
this._pointerMoveCallback!(e);
|
|
}
|
|
));
|
|
|
|
this._hooks.add(dom.addDisposableListener(
|
|
eventSource,
|
|
dom.EventType.POINTER_UP,
|
|
(e: PointerEvent) => this.stopMonitoring(true)
|
|
));
|
|
}
|
|
}
|