From a30f42f3fe5f08e9746864a7e6f7a15d15936a0f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20Bert?=
<63123542+m-bert@users.noreply.github.com>
Date: Tue, 16 Jan 2024 14:28:06 +0100
Subject: [PATCH] Add `mouseButton` prop (#2676)
## Description
After giving it some thought, we decided to add new modifier to our handlers - `mouseButton`. This way users will be able to choose mouse buttons that handler will respond to.
For now this prop is available on all handlers, but it is a topic for a short discussion.
I think it is also worth to mention, that right now all three mouse buttons work on web, so this prop will allow us to 'disable' all buttons except those provided as arguments.
This PR also adds two small examples (one for buttons and one for context menu) that can be used to test given prop on other platforms (when this functionality will be added)
## Test plan
Tested on example app.
---
example/src/App.tsx | 4 +
.../src/release_tests/contextMenu/index.tsx | 61 ++++++
.../src/release_tests/mouseButtons/index.tsx | 181 ++++++++++++++++++
src/components/DrawerLayout.tsx | 15 ++
src/handlers/gestureHandlerCommon.ts | 5 +
src/handlers/gestures/GestureDetector.tsx | 16 +-
src/handlers/gestures/gesture.ts | 6 +
src/index.ts | 1 +
src/web/handlers/FlingGestureHandler.ts | 4 +
src/web/handlers/GestureHandler.ts | 13 ++
src/web/handlers/LongPressGestureHandler.ts | 13 +-
src/web/handlers/PanGestureHandler.ts | 4 +
src/web/handlers/TapGestureHandler.ts | 4 +
src/web/interfaces.ts | 20 +-
src/web/tools/GestureHandlerDelegate.ts | 3 +
src/web/tools/GestureHandlerWebDelegate.ts | 39 ++++
src/web/tools/NodeManager.ts | 2 +
src/web/tools/PointerEventManager.ts | 20 +-
src/web/tools/TouchEventManager.ts | 2 -
19 files changed, 393 insertions(+), 20 deletions(-)
create mode 100644 example/src/release_tests/contextMenu/index.tsx
create mode 100644 example/src/release_tests/mouseButtons/index.tsx
diff --git a/example/src/App.tsx b/example/src/App.tsx
index ddf35567ff..a70007b47f 100644
--- a/example/src/App.tsx
+++ b/example/src/App.tsx
@@ -16,6 +16,8 @@ import { ComboWithGHScroll } from './release_tests/combo';
import { TouchablesIndex, TouchableExample } from './release_tests/touchables';
import Rows from './release_tests/rows';
import Fling from './release_tests/fling';
+import MouseButtons from './release_tests/mouseButtons';
+import ContextMenu from './release_tests/contextMenu';
import NestedTouchables from './release_tests/nestedTouchables';
import NestedButtons from './release_tests/nestedButtons';
import NestedGestureHandlerRootViewWithModal from './release_tests/nestedGHRootViewWithModal';
@@ -116,6 +118,8 @@ const EXAMPLES: ExamplesSection[] = [
{ name: 'Fling', component: Fling },
{ name: 'Combo', component: ComboWithGHScroll },
{ name: 'Touchables', component: TouchablesIndex as React.ComponentType },
+ { name: 'MouseButtons', component: MouseButtons },
+ { name: 'ContextMenu (web only)', component: ContextMenu },
{ name: 'Rounded buttons', component: RoundedButtons },
],
},
diff --git a/example/src/release_tests/contextMenu/index.tsx b/example/src/release_tests/contextMenu/index.tsx
new file mode 100644
index 0000000000..d89ed1a007
--- /dev/null
+++ b/example/src/release_tests/contextMenu/index.tsx
@@ -0,0 +1,61 @@
+import React from 'react';
+import { StyleSheet, View } from 'react-native';
+import {
+ Gesture,
+ GestureDetector,
+ MouseButton,
+} from 'react-native-gesture-handler';
+
+export default function ContextMenuExample() {
+ const p1 = Gesture.Pan().mouseButton(MouseButton.RIGHT);
+ const p2 = Gesture.Pan();
+ const p3 = Gesture.Pan();
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ justifyContent: 'space-around',
+ alignItems: 'center',
+ },
+
+ grandParent: {
+ width: 300,
+ height: 300,
+ backgroundColor: 'lightblue',
+ },
+
+ parent: {
+ width: 200,
+ height: 200,
+ backgroundColor: 'lightgreen',
+ },
+
+ child: {
+ width: 100,
+ height: 100,
+ backgroundColor: 'crimson',
+ },
+
+ box: {
+ display: 'flex',
+ justifyContent: 'space-around',
+ alignItems: 'center',
+ },
+});
diff --git a/example/src/release_tests/mouseButtons/index.tsx b/example/src/release_tests/mouseButtons/index.tsx
new file mode 100644
index 0000000000..8eafb46954
--- /dev/null
+++ b/example/src/release_tests/mouseButtons/index.tsx
@@ -0,0 +1,181 @@
+import React from 'react';
+import {
+ Gesture,
+ GestureDetector,
+ GestureType,
+ MouseButton,
+ Directions,
+ ScrollView,
+} from 'react-native-gesture-handler';
+import { StyleSheet, View, Text } from 'react-native';
+
+const COLORS = ['darkmagenta', 'darkgreen', 'darkblue', 'crimson', 'pink'];
+
+type TestProps = {
+ name: string;
+ gestureHandlers: GestureType[];
+};
+
+function Test({ name, gestureHandlers }: TestProps) {
+ return (
+
+ {name}
+
+ {gestureHandlers.map((handler, index) => {
+ return (
+
+
+
+ );
+ })}
+
+
+ );
+}
+
+function TapTests() {
+ const leftTap = Gesture.Tap()
+ .mouseButton(MouseButton.LEFT)
+ .onEnd(() => console.log('Tap with left'));
+
+ const middleTap = Gesture.Tap()
+ .mouseButton(MouseButton.MIDDLE)
+ .onEnd(() => console.log('Tap with middle'));
+
+ const rightTap = Gesture.Tap()
+ .mouseButton(MouseButton.RIGHT)
+ .onEnd(() => console.log('Tap with right'));
+
+ const leftRightTap = Gesture.Tap()
+ .mouseButton(MouseButton.LEFT | MouseButton.RIGHT)
+ .onEnd(() => console.log('Tap with left | right'));
+
+ const allTap = Gesture.Tap()
+ .mouseButton(MouseButton.ALL)
+ .onEnd(() => console.log('Tap with any button'));
+
+ const gestureHandlers = [leftTap, middleTap, rightTap, leftRightTap, allTap];
+
+ return ;
+}
+
+function PanTests() {
+ const leftPan = Gesture.Pan()
+ .mouseButton(MouseButton.LEFT)
+ .onChange(() => console.log('Panning with left'));
+
+ const middlePan = Gesture.Pan()
+ .mouseButton(MouseButton.MIDDLE)
+ .onChange(() => console.log('Panning with middle'));
+
+ const rightPan = Gesture.Pan()
+ .mouseButton(MouseButton.RIGHT)
+ .onChange(() => console.log('Panning with right'));
+
+ const leftRightPan = Gesture.Pan()
+ .mouseButton(MouseButton.LEFT | MouseButton.RIGHT)
+ .onChange(() => console.log('Panning with left | right'));
+
+ const allPan = Gesture.Pan()
+ .mouseButton(MouseButton.ALL)
+ .onChange(() => console.log('Panning with any button'));
+
+ const gestureHandlers = [leftPan, middlePan, rightPan, leftRightPan, allPan];
+
+ return ;
+}
+
+function LongPressTests() {
+ const leftLongPress = Gesture.LongPress()
+ .mouseButton(MouseButton.LEFT)
+ .onStart(() => console.log('LongPress with left'));
+
+ const middleLongPress = Gesture.LongPress()
+ .mouseButton(MouseButton.MIDDLE)
+ .onStart(() => console.log('LongPress with middle'));
+
+ const rightLongPress = Gesture.LongPress()
+ .mouseButton(MouseButton.RIGHT)
+ .onStart(() => console.log('LongPress with right'));
+
+ const leftRightLongPress = Gesture.LongPress()
+ .mouseButton(MouseButton.LEFT | MouseButton.RIGHT)
+ .onStart(() => console.log('LongPress with left | right'));
+
+ const allLongPress = Gesture.LongPress()
+ .mouseButton(MouseButton.ALL)
+ .onStart(() => console.log('LongPress with any button'));
+
+ const gestureHandlers = [
+ leftLongPress,
+ middleLongPress,
+ rightLongPress,
+ leftRightLongPress,
+ allLongPress,
+ ];
+
+ return ;
+}
+
+function FlingTests() {
+ const leftFling = Gesture.Fling()
+ .direction(Directions.LEFT | Directions.RIGHT)
+ .mouseButton(MouseButton.LEFT)
+ .onStart(() => console.log('Fling with left'));
+
+ const middleFling = Gesture.Fling()
+ .direction(Directions.LEFT | Directions.RIGHT)
+ .mouseButton(MouseButton.MIDDLE)
+ .onStart(() => console.log('Fling with middle'));
+
+ const rightFling = Gesture.Fling()
+ .direction(Directions.LEFT | Directions.RIGHT)
+ .mouseButton(MouseButton.RIGHT)
+ .onStart(() => console.log('Fling with right'));
+
+ const leftRightFling = Gesture.Fling()
+ .direction(Directions.LEFT | Directions.RIGHT)
+ .mouseButton(MouseButton.LEFT | MouseButton.RIGHT)
+ .onStart(() => console.log('Fling with left | right'));
+
+ const allFling = Gesture.Fling()
+ .direction(Directions.LEFT | Directions.RIGHT)
+ .mouseButton(MouseButton.ALL)
+ .onStart(() => console.log('Fling with any button'));
+
+ const gestureHandlers = [
+ leftFling,
+ middleFling,
+ rightFling,
+ leftRightFling,
+ allFling,
+ ];
+
+ return ;
+}
+
+export default function Buttons() {
+ return (
+
+
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ center: {
+ alignItems: 'center',
+ justifyContent: 'space-around',
+ },
+ box: {
+ width: 75,
+ height: 75,
+ },
+});
diff --git a/src/components/DrawerLayout.tsx b/src/components/DrawerLayout.tsx
index 479b3618bb..3d6148d851 100644
--- a/src/components/DrawerLayout.tsx
+++ b/src/components/DrawerLayout.tsx
@@ -38,6 +38,7 @@ import {
TapGestureHandlerEventPayload,
} from '../handlers/TapGestureHandler';
import { State } from '../State';
+import { MouseButton } from '../web/interfaces';
const DRAG_TOSS = 0.05;
@@ -173,6 +174,18 @@ export interface DrawerLayoutProps {
* Values: see CSS cursor values
*/
activeCursor?: ActiveCursor;
+
+ /**
+ * @default 'MouseButton.LEFT'
+ * Allows to choose which mouse button should underlying pan handler react to.
+ */
+ mouseButton?: MouseButton;
+
+ /**
+ * @default 'false if MouseButton.RIGHT is specified'
+ * Allows to enable/disable context menu.
+ */
+ enableContextMenu?: boolean;
}
export type DrawerLayoutState = {
@@ -700,6 +713,8 @@ export default class DrawerLayout extends Component<
// @ts-ignore could be fixed in handler types
userSelect={this.props.userSelect}
activeCursor={this.props.activeCursor}
+ mouseButton={this.props.mouseButton}
+ enableContextMenu={this.props.enableContextMenu}
ref={this.setPanGestureRef}
hitSlop={hitSlop}
activeOffsetX={gestureOrientation * minSwipeDistance!}
diff --git a/src/handlers/gestureHandlerCommon.ts b/src/handlers/gestureHandlerCommon.ts
index c4ba8c3ac7..5fb4889b91 100644
--- a/src/handlers/gestureHandlerCommon.ts
+++ b/src/handlers/gestureHandlerCommon.ts
@@ -12,6 +12,7 @@ import { handlerIDToTag } from './handlersRegistry';
import { toArray } from '../utils';
import RNGestureHandlerModule from '../RNGestureHandlerModule';
import { ghQueueMicrotask } from '../ghQueueMicrotask';
+import { MouseButton } from '../web/interfaces';
const commonProps = [
'id',
@@ -21,6 +22,8 @@ const commonProps = [
'cancelsTouchesInView',
'userSelect',
'activeCursor',
+ 'mouseButton',
+ 'enableContextMenu',
] as const;
const componentInteractionProps = [
@@ -149,6 +152,8 @@ export type CommonGestureConfig = {
hitSlop?: HitSlop;
userSelect?: UserSelect;
activeCursor?: ActiveCursor;
+ mouseButton?: MouseButton;
+ enableContextMenu?: boolean;
};
// Events payloads are types instead of interfaces due to TS limitation.
diff --git a/src/handlers/gestures/GestureDetector.tsx b/src/handlers/gestures/GestureDetector.tsx
index 0ce9b48e99..5f55b5eeab 100644
--- a/src/handlers/gestures/GestureDetector.tsx
+++ b/src/handlers/gestures/GestureDetector.tsx
@@ -605,10 +605,20 @@ const applyUserSelectProp = (
}
};
+const applyEnableContextMenuProp = (
+ enableContextMenu: boolean,
+ gesture: ComposedGesture | GestureType
+): void => {
+ for (const g of gesture.toGestureArray()) {
+ g.config.enableContextMenu = enableContextMenu;
+ }
+};
+
interface GestureDetectorProps {
gesture: ComposedGesture | GestureType;
- userSelect?: UserSelect;
children?: React.ReactNode;
+ userSelect?: UserSelect;
+ enableContextMenu?: boolean;
}
interface GestureDetectorState {
firstRender: boolean;
@@ -630,6 +640,10 @@ export const GestureDetector = (props: GestureDetectorProps) => {
applyUserSelectProp(props.userSelect, gestureConfig);
}
+ if (props.enableContextMenu !== undefined) {
+ applyEnableContextMenuProp(props.enableContextMenu, gestureConfig);
+ }
+
const gesture = gestureConfig.toGestureArray();
const useReanimatedHook = gesture.some((g) => g.shouldUseReanimated);
diff --git a/src/handlers/gestures/gesture.ts b/src/handlers/gestures/gesture.ts
index f9135ab4be..b1cec76983 100644
--- a/src/handlers/gestures/gesture.ts
+++ b/src/handlers/gestures/gesture.ts
@@ -17,6 +17,7 @@ import { RotationGestureHandlerEventPayload } from '../RotationGestureHandler';
import { TapGestureHandlerEventPayload } from '../TapGestureHandler';
import { NativeViewGestureHandlerPayload } from '../NativeViewGestureHandler';
import { isRemoteDebuggingEnabled } from '../../utils';
+import { MouseButton } from '../../web/interfaces';
export type GestureType =
| BaseGesture>
@@ -257,6 +258,11 @@ export abstract class BaseGesture<
return this;
}
+ mouseButton(mouseButton: MouseButton) {
+ this.config.mouseButton = mouseButton;
+ return this;
+ }
+
runOnJS(runOnJS: boolean) {
this.config.runOnJS = runOnJS;
return this;
diff --git a/src/index.ts b/src/index.ts
index 343998ca14..49fd999c64 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -2,6 +2,7 @@ import { initialize } from './init';
export { Directions } from './Directions';
export { State } from './State';
+export { MouseButton } from './web/interfaces';
export { default as gestureHandlerRootHOC } from './components/gestureHandlerRootHOC';
export { default as GestureHandlerRootView } from './components/GestureHandlerRootView';
export type {
diff --git a/src/web/handlers/FlingGestureHandler.ts b/src/web/handlers/FlingGestureHandler.ts
index 722b14029d..38a0a7aa38 100644
--- a/src/web/handlers/FlingGestureHandler.ts
+++ b/src/web/handlers/FlingGestureHandler.ts
@@ -83,6 +83,10 @@ export default class FlingGestureHandler extends GestureHandler {
}
protected onPointerDown(event: AdaptedEvent): void {
+ if (!this.isButtonInConfig(event.button)) {
+ return;
+ }
+
this.tracker.addToTracker(event);
this.keyPointer = event.pointerId;
diff --git a/src/web/handlers/GestureHandler.ts b/src/web/handlers/GestureHandler.ts
index 2c402829b6..3a15283060 100644
--- a/src/web/handlers/GestureHandler.ts
+++ b/src/web/handlers/GestureHandler.ts
@@ -10,6 +10,7 @@ import {
PointerType,
TouchEventType,
EventTypes,
+ MouseButton,
} from '../interfaces';
import EventManager from '../tools/EventManager';
import GestureHandlerOrchestrator from '../tools/GestureHandlerOrchestrator';
@@ -736,8 +737,20 @@ export default abstract class GestureHandler {
return false;
}
+ public isButtonInConfig(mouseButton: MouseButton | undefined) {
+ return (
+ !mouseButton ||
+ (!this.config.mouseButton && mouseButton === MouseButton.LEFT) ||
+ (this.config.mouseButton && mouseButton & this.config.mouseButton)
+ );
+ }
+
protected resetConfig(): void {}
+ public onDestroy(): void {
+ this.delegate.destroy(this.config);
+ }
+
//
// Getters and setters
//
diff --git a/src/web/handlers/LongPressGestureHandler.ts b/src/web/handlers/LongPressGestureHandler.ts
index d21815f314..7707b90aba 100644
--- a/src/web/handlers/LongPressGestureHandler.ts
+++ b/src/web/handlers/LongPressGestureHandler.ts
@@ -1,4 +1,3 @@
-import { Platform } from 'react-native';
import { State } from '../../State';
import { AdaptedEvent, Config } from '../interfaces';
@@ -22,11 +21,11 @@ export default class LongPressGestureHandler extends GestureHandler {
private activationTimeout: number | undefined;
public init(ref: number, propsRef: React.RefObject) {
- super.init(ref, propsRef);
-
- if (Platform.OS === 'web') {
- (this.delegate.getView() as HTMLElement).oncontextmenu = () => false;
+ if (this.config.enableContextMenu === undefined) {
+ this.config.enableContextMenu = false;
}
+
+ super.init(ref, propsRef);
}
protected transformNativeEvent() {
@@ -59,6 +58,10 @@ export default class LongPressGestureHandler extends GestureHandler {
}
protected onPointerDown(event: AdaptedEvent): void {
+ if (!this.isButtonInConfig(event.button)) {
+ return;
+ }
+
this.tracker.addToTracker(event);
super.onPointerDown(event);
this.tryBegin(event);
diff --git a/src/web/handlers/PanGestureHandler.ts b/src/web/handlers/PanGestureHandler.ts
index a6a180490e..43347401ec 100644
--- a/src/web/handlers/PanGestureHandler.ts
+++ b/src/web/handlers/PanGestureHandler.ts
@@ -211,6 +211,10 @@ export default class PanGestureHandler extends GestureHandler {
//EventsHandling
protected onPointerDown(event: AdaptedEvent): void {
+ if (!this.isButtonInConfig(event.button)) {
+ return;
+ }
+
this.tracker.addToTracker(event);
super.onPointerDown(event);
diff --git a/src/web/handlers/TapGestureHandler.ts b/src/web/handlers/TapGestureHandler.ts
index 92920e0d33..7aa52c3ba2 100644
--- a/src/web/handlers/TapGestureHandler.ts
+++ b/src/web/handlers/TapGestureHandler.ts
@@ -105,6 +105,10 @@ export default class TapGestureHandler extends GestureHandler {
//Handling Events
protected onPointerDown(event: AdaptedEvent): void {
+ if (!this.isButtonInConfig(event.button)) {
+ return;
+ }
+
this.tracker.addToTracker(event);
super.onPointerDown(event);
diff --git a/src/web/interfaces.ts b/src/web/interfaces.ts
index 96da2b0bc8..155ee59a43 100644
--- a/src/web/interfaces.ts
+++ b/src/web/interfaces.ts
@@ -37,6 +37,8 @@ export interface Config extends Record {
shouldCancelWhenOutside?: boolean;
userSelect?: UserSelect;
activeCursor?: ActiveCursor;
+ mouseButton?: MouseButton;
+ enableContextMenu?: boolean;
activateAfterLongPress?: number;
failOffsetXStart?: number;
@@ -122,22 +124,20 @@ export interface AdaptedEvent {
pointerId: number;
eventType: EventTypes;
pointerType: PointerType;
- buttons: number;
time: number;
+ button?: MouseButton;
allTouches?: TouchList;
changedTouches?: TouchList;
touchEventType?: TouchEventType;
}
-export enum MouseButtons {
- NONE,
- LEFT,
- RIGHT,
- LEFT_RIGHT,
- SCROLL,
- SCROLL_LEFT,
- SCROLL_RIGHT,
- SCROLL_LEFT_RIGHT,
+export enum MouseButton {
+ LEFT = 1,
+ MIDDLE = 2,
+ RIGHT = 4,
+ BUTTON_4 = 8,
+ BUTTON_5 = 16,
+ ALL = 31,
}
export enum EventTypes {
diff --git a/src/web/tools/GestureHandlerDelegate.ts b/src/web/tools/GestureHandlerDelegate.ts
index ac68196f98..259b1c52c9 100644
--- a/src/web/tools/GestureHandlerDelegate.ts
+++ b/src/web/tools/GestureHandlerDelegate.ts
@@ -1,4 +1,5 @@
import type GestureHandler from '../handlers/GestureHandler';
+import { Config } from '../interfaces';
export interface MeasureResult {
pageX: number;
@@ -20,4 +21,6 @@ export interface GestureHandlerDelegate {
onEnd(): void;
onCancel(): void;
onFail(): void;
+
+ destroy(config: Config): void;
}
diff --git a/src/web/tools/GestureHandlerWebDelegate.ts b/src/web/tools/GestureHandlerWebDelegate.ts
index 39d2052a1b..fad27df38c 100644
--- a/src/web/tools/GestureHandlerWebDelegate.ts
+++ b/src/web/tools/GestureHandlerWebDelegate.ts
@@ -9,6 +9,7 @@ import TouchEventManager from './TouchEventManager';
import { State } from '../../State';
import { isPointerInBounds } from '../utils';
import EventManager from './EventManager';
+import { Config, MouseButton } from '../interfaces';
export class GestureHandlerWebDelegate
implements GestureHandlerDelegate
@@ -37,6 +38,8 @@ export class GestureHandlerWebDelegate
const config = handler.getConfig();
+ this.addContextMenuListeners(config);
+
if (!config.userSelect) {
this.view.style['webkitUserSelect'] = 'none';
this.view.style['userSelect'] = 'none';
@@ -86,6 +89,38 @@ export class GestureHandlerWebDelegate
}
}
+ private shouldDisableContextMenu(config: Config) {
+ return (
+ (config.enableContextMenu === undefined &&
+ this.gestureHandler.isButtonInConfig(MouseButton.RIGHT)) ||
+ config.enableContextMenu === false
+ );
+ }
+
+ private addContextMenuListeners(config: Config): void {
+ if (this.shouldDisableContextMenu(config)) {
+ this.view.addEventListener('contextmenu', this.disableContextMenu);
+ } else if (config.enableContextMenu) {
+ this.view.addEventListener('contextmenu', this.enableContextMenu);
+ }
+ }
+
+ private removeContextMenuListeners(config: Config): void {
+ if (this.shouldDisableContextMenu(config)) {
+ this.view.removeEventListener('contextmenu', this.disableContextMenu);
+ } else if (config.enableContextMenu) {
+ this.view.removeEventListener('contextmenu', this.enableContextMenu);
+ }
+ }
+
+ private disableContextMenu(this: void, e: MouseEvent): void {
+ e.preventDefault();
+ }
+
+ private enableContextMenu(this: void, e: MouseEvent): void {
+ e.stopPropagation();
+ }
+
onBegin(): void {
// no-op for now
}
@@ -112,4 +147,8 @@ export class GestureHandlerWebDelegate
onFail(): void {
this.tryResetCursor();
}
+
+ public destroy(config: Config): void {
+ this.removeContextMenuListeners(config);
+ }
}
diff --git a/src/web/tools/NodeManager.ts b/src/web/tools/NodeManager.ts
index fd4a9c630c..ca452324e6 100644
--- a/src/web/tools/NodeManager.ts
+++ b/src/web/tools/NodeManager.ts
@@ -35,6 +35,8 @@ export default abstract class NodeManager {
return;
}
+ this.gestures[handlerTag].onDestroy();
+
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete this.gestures[handlerTag];
}
diff --git a/src/web/tools/PointerEventManager.ts b/src/web/tools/PointerEventManager.ts
index 0e6e03959c..2168752b6d 100644
--- a/src/web/tools/PointerEventManager.ts
+++ b/src/web/tools/PointerEventManager.ts
@@ -1,4 +1,9 @@
-import { AdaptedEvent, EventTypes, PointerType } from '../interfaces';
+import {
+ AdaptedEvent,
+ EventTypes,
+ MouseButton,
+ PointerType,
+} from '../interfaces';
import EventManager from './EventManager';
import { isPointerInBounds } from '../utils';
@@ -6,6 +11,17 @@ const POINTER_CAPTURE_EXCLUDE_LIST = new Set(['SELECT', 'INPUT']);
export default class PointerEventManager extends EventManager {
private trackedPointers = new Set();
+ private readonly mouseButtonsMapper = new Map();
+
+ constructor(view: HTMLElement) {
+ super(view);
+
+ this.mouseButtonsMapper.set(0, MouseButton.LEFT);
+ this.mouseButtonsMapper.set(1, MouseButton.MIDDLE);
+ this.mouseButtonsMapper.set(2, MouseButton.RIGHT);
+ this.mouseButtonsMapper.set(3, MouseButton.BUTTON_4);
+ this.mouseButtonsMapper.set(4, MouseButton.BUTTON_5);
+ }
public setListeners(): void {
this.view.addEventListener('pointerdown', (event: PointerEvent): void => {
@@ -192,7 +208,7 @@ export default class PointerEventManager extends EventManager {
pointerId: event.pointerId,
eventType: eventType,
pointerType: event.pointerType as PointerType,
- buttons: event.buttons,
+ button: this.mouseButtonsMapper.get(event.button),
time: event.timeStamp,
};
}
diff --git a/src/web/tools/TouchEventManager.ts b/src/web/tools/TouchEventManager.ts
index aabdd0bf62..d73c11dc3c 100644
--- a/src/web/tools/TouchEventManager.ts
+++ b/src/web/tools/TouchEventManager.ts
@@ -1,7 +1,6 @@
import {
AdaptedEvent,
EventTypes,
- MouseButtons,
PointerType,
TouchEventType,
} from '../interfaces';
@@ -157,7 +156,6 @@ export default class TouchEventManager extends EventManager {
pointerId: event.changedTouches[index].identifier,
eventType: eventType,
pointerType: PointerType.TOUCH,
- buttons: MouseButtons.NONE,
time: event.timeStamp,
allTouches: event.touches,
changedTouches: event.changedTouches,