Skip to content

Commit

Permalink
fix: handle mouse up not fired outside of window
Browse files Browse the repository at this point in the history
  • Loading branch information
oscarlorentzon committed Mar 15, 2021
1 parent b562a0b commit 0e34309
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 23 deletions.
44 changes: 24 additions & 20 deletions spec/helper/EventHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,31 @@ export class EventHelper {
return new KeyboardEvent(typeArg, eventInitDict);
}

public static createMouseEvent(eventType: string, params: MouseEventInit, target?: EventTarget): MouseEvent {
const mouseEvent: MouseEvent = document.createEvent("MouseEvent");

mouseEvent.initMouseEvent(
public static createMouseEvent(
eventType: string,
params: MouseEventInit,
target?: EventTarget): MouseEvent {
return new MouseEvent(
eventType,
params.bubbles !== undefined ? params.bubbles : true,
params.cancelable !== undefined ? params.cancelable : true,
window,
params.detail !== undefined ? params.detail : 0,
params.screenX !== undefined ? params.screenX : 0,
params.screenY !== undefined ? params.screenY : 0,
params.clientX !== undefined ? params.clientX : 0,
params.clientY !== undefined ? params.clientY : 0,
!!params.ctrlKey,
!!params.altKey,
!!params.shiftKey,
!!params.metaKey,
params.button !== undefined ? params.button : 0,
!!target ? target : document.createElement("div"));

return mouseEvent;
{
bubbles: params.bubbles !== undefined ?
params.bubbles : true,
cancelable: params.cancelable !== undefined ?
params.cancelable : true,
detail: params.detail !== undefined ? params.detail : 0,
screenX: params.screenX !== undefined ? params.screenX : 0,
screenY: params.screenY !== undefined ? params.screenY : 0,
clientX: params.clientX !== undefined ? params.clientX : 0,
clientY: params.clientY !== undefined ? params.clientY : 0,
ctrlKey: !!params.ctrlKey,
altKey: !!params.altKey,
shiftKey: !!params.shiftKey,
metaKey: !!params.metaKey,
button: params.button !== undefined ? params.button : 0,
buttons: params.buttons !== undefined ? params.button : 1,
relatedTarget: !!target ?
target : document.createElement("div"),
});
}

public static createTouchEvent(eventType: string, shiftKey?: boolean): TouchEvent {
Expand Down
36 changes: 33 additions & 3 deletions src/viewer/MouseService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,22 @@ import { IMouseClaim } from "./interfaces/IMouseClaim";
import { IMouseDeferPixels } from "./interfaces/IMouseDeferPixels";
import { SubscriptionHolder } from "../utils/SubscriptionHolder";

type Button = 0 | 2;

// MouseEvent.button
const LEFT_BUTTON: Button = 0;
const RIGHT_BUTTON: Button = 2;

// MouseEvent.buttons
const BUTTONS_MAP = {
[LEFT_BUTTON]: 1,
[RIGHT_BUTTON]: 2
};

interface FirefoxBrowser {
InstallTrigger: undefined;
}

const LEFT_BUTTON = 0;
const RIGHT_BUTTON = 2;

export class MouseService {
private _activeSubject$: BehaviorSubject<boolean>;
private _active$: Observable<boolean>;
Expand Down Expand Up @@ -86,6 +95,7 @@ export class MouseService {
private _wheelOwner$: Observable<string>;

private _windowBlur$: Observable<FocusEvent>;

private _subscriptions: SubscriptionHolder = new SubscriptionHolder();

constructor(
Expand Down Expand Up @@ -218,6 +228,11 @@ export class MouseService {

const dragStop$: Observable<MouseEvent | FocusEvent> = observableMerge(
this._windowBlur$,
this._documentMouseMove$.pipe(
filter(
(e: MouseEvent): boolean => {
return this._buttonReleased(e, LEFT_BUTTON);
})),
this._documentMouseUp$.pipe(
filter(
(e: MouseEvent): boolean => {
Expand Down Expand Up @@ -247,6 +262,11 @@ export class MouseService {
const rightDragStop$: Observable<MouseEvent | FocusEvent> =
observableMerge(
this._windowBlur$,
this._documentMouseMove$.pipe(
filter(
(e: MouseEvent): boolean => {
return this._buttonReleased(e, RIGHT_BUTTON);
})),
this._documentMouseUp$.pipe(
filter(
(e: MouseEvent): boolean => {
Expand Down Expand Up @@ -611,4 +631,14 @@ export class MouseService {
}
return event.button;
}

private _buttonReleased(e: MouseEvent, button: Button): boolean {
// Right button `mouseup` is not fired in
// Chrome on Mac outside the window or iframe. If
// the button is no longer pressed during move
// it may have been released and drag stop
// should be emitted.
const flag = BUTTONS_MAP[button];
return e.buttons === undefined || (e.buttons & flag) !== flag;
}
}

0 comments on commit 0e34309

Please sign in to comment.