From e8a778d494ec66d31554e83f6eb5226c5f8195d6 Mon Sep 17 00:00:00 2001 From: Luna Wei Date: Tue, 13 Sep 2022 16:11:35 -0700 Subject: [PATCH] Add buttons Summary: Changelog: [Internal] Add support for buttons/button property according to W3C PointerEvent spec Reviewed By: vincentriemer Differential Revision: D39460411 fbshipit-source-id: 3544a9b00e870a6028e37417ca9e4de5af62ef70 --- .../react/uimanager/JSPointerDispatcher.java | 51 +++++++++++-------- .../react/uimanager/events/PointerEvent.java | 22 ++++++-- .../uimanager/events/PointerEventHelper.java | 23 +++++++++ 3 files changed, 71 insertions(+), 25 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSPointerDispatcher.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSPointerDispatcher.java index 897f5a21785..6a2c7b18651 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSPointerDispatcher.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSPointerDispatcher.java @@ -44,6 +44,7 @@ public class JSPointerDispatcher { private int mChildHandlingNativeGesture = -1; private int mPrimaryPointerId = UNSET_POINTER_ID; + private int mLastButtonState = 0; private long mDownStartTime = TouchEvent.UNSET; private long mHoverInteractionKey = TouchEvent.UNSET; private final ViewGroup mRootViewGroup; @@ -101,7 +102,8 @@ public class JSPointerDispatcher { activeTargetTag, motionEvent, targetCoordinates, - mPrimaryPointerId)); + mPrimaryPointerId, + mLastButtonState)); } if (!supportsHover) { @@ -115,7 +117,8 @@ public class JSPointerDispatcher { activeTargetTag, motionEvent, targetCoordinates, - mPrimaryPointerId)); + mPrimaryPointerId, + mLastButtonState)); } List leaveViewTargets = @@ -169,7 +172,8 @@ public class JSPointerDispatcher { activeTargetTag, motionEvent, targetCoordinates, - mPrimaryPointerId)); + mPrimaryPointerId, + mLastButtonState)); } List enterViewTargets = @@ -196,23 +200,19 @@ public class JSPointerDispatcher { activeTargetTag, motionEvent, targetCoordinates, - mPrimaryPointerId)); + mPrimaryPointerId, + mLastButtonState)); } } public void handleMotionEvent(MotionEvent motionEvent, EventDispatcher eventDispatcher) { - int action = motionEvent.getActionMasked(); - - // Ignore hover enter/exit because we determine this ourselves - if (action == MotionEvent.ACTION_HOVER_EXIT || action == MotionEvent.ACTION_HOVER_ENTER) { + // Don't fire any pointer events if child view is handling native gesture + if (mChildHandlingNativeGesture != -1) { return; } - int surfaceId = UIManagerHelper.getSurfaceId(mRootViewGroup); - // Only relevant for POINTER_UP/POINTER_DOWN actions, otherwise 0 int actionIndex = motionEvent.getActionIndex(); - float[] targetCoordinates = new float[2]; List hitPath = TouchTargetHelper.findTargetPathAndCoordinatesForTouch( @@ -225,13 +225,12 @@ public class JSPointerDispatcher { return; } + int action = motionEvent.getActionMasked(); + int surfaceId = UIManagerHelper.getSurfaceId(mRootViewGroup); + TouchTargetHelper.ViewTarget activeViewTarget = hitPath.get(0); int activeTargetTag = activeViewTarget.getViewId(); - if (mChildHandlingNativeGesture != -1) { - return; - } - switch (action) { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_POINTER_DOWN: @@ -258,7 +257,8 @@ public class JSPointerDispatcher { motionEvent, targetCoordinates, coalescingKey, - mPrimaryPointerId)); + mPrimaryPointerId, + mLastButtonState)); } break; case MotionEvent.ACTION_UP: @@ -274,6 +274,8 @@ public class JSPointerDispatcher { "Warning : Motion Event was ignored. Action=" + action + " Target=" + activeTargetTag); return; } + + mLastButtonState = motionEvent.getButtonState(); } private static boolean isAnyoneListeningForBubblingEvent( @@ -334,7 +336,13 @@ public class JSPointerDispatcher { int viewId = viewTarget.getViewId(); dispatcher.dispatchEvent( PointerEvent.obtain( - eventName, surfaceId, viewId, motionEvent, targetCoordinates, mPrimaryPointerId)); + eventName, + surfaceId, + viewId, + motionEvent, + targetCoordinates, + mPrimaryPointerId, + mLastButtonState)); } } @@ -427,7 +435,8 @@ public class JSPointerDispatcher { lastTargetTag, motionEvent, targetCoordinates, - mPrimaryPointerId)); + mPrimaryPointerId, + mLastButtonState)); } // target -> root @@ -459,7 +468,8 @@ public class JSPointerDispatcher { targetTag, motionEvent, targetCoordinates, - mPrimaryPointerId)); + mPrimaryPointerId, + mLastButtonState)); } // target -> root @@ -529,7 +539,8 @@ public class JSPointerDispatcher { targetTag, motionEvent, targetCoordinates, - mPrimaryPointerId)); + mPrimaryPointerId, + mLastButtonState)); } // TODO(luwe) - Need to fire pointer out here as well: diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/PointerEvent.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/PointerEvent.java index e968826a7e2..a30dd8a7449 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/PointerEvent.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/PointerEvent.java @@ -32,7 +32,8 @@ public class PointerEvent extends Event { int viewTag, MotionEvent motionEventToCopy, float[] offsetCoords, - int primaryPointerId) { + int primaryPointerId, + int lastButtonState) { PointerEvent event = EVENTS_POOL.acquire(); if (event == null) { event = new PointerEvent(); @@ -44,7 +45,8 @@ public class PointerEvent extends Event { Assertions.assertNotNull(motionEventToCopy), offsetCoords, 0, - primaryPointerId); + primaryPointerId, + lastButtonState); return event; } @@ -55,7 +57,8 @@ public class PointerEvent extends Event { MotionEvent motionEventToCopy, float[] offsetCoords, int coalescingKey, - int primaryPointerId) { + int primaryPointerId, + int lastButtonState) { PointerEvent event = EVENTS_POOL.acquire(); if (event == null) { event = new PointerEvent(); @@ -67,7 +70,8 @@ public class PointerEvent extends Event { Assertions.assertNotNull(motionEventToCopy), offsetCoords, coalescingKey, - primaryPointerId); + primaryPointerId, + lastButtonState); return event; } @@ -78,6 +82,7 @@ public class PointerEvent extends Event { private float mOffsetY; private @Nullable List mPointersEventData; private int mPrimaryPointerId; + private int mLastButtonState; private void init( String eventName, @@ -86,7 +91,8 @@ public class PointerEvent extends Event { MotionEvent motionEventToCopy, float[] offsetCoords, int coalescingKey, - int primaryPointerId) { + int primaryPointerId, + int lastButtonState) { super.init(surfaceId, viewTag, motionEventToCopy.getEventTime()); mEventName = eventName; @@ -95,6 +101,7 @@ public class PointerEvent extends Event { mOffsetX = offsetCoords[0]; mOffsetY = offsetCoords[1]; mPrimaryPointerId = primaryPointerId; + mLastButtonState = lastButtonState; } private PointerEvent() {} @@ -209,6 +216,11 @@ public class PointerEvent extends Event { pointerEvent.putDouble("tiltY", 0); } + int buttonState = mMotionEvent.getButtonState(); + pointerEvent.putInt("buttons", buttonState); + pointerEvent.putInt( + "button", PointerEventHelper.getButtonChange(mLastButtonState, buttonState)); + return pointerEvent; } diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/PointerEventHelper.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/PointerEventHelper.java index ea7c69409cd..e281ad33a1f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/PointerEventHelper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/PointerEventHelper.java @@ -76,6 +76,29 @@ public class PointerEventHelper { } } + // https://w3c.github.io/pointerevents/#the-button-property + public static int getButtonChange(int lastButtonState, int currentButtonState) { + int changedMask = currentButtonState ^ lastButtonState; + if (changedMask == 0) { + return -1; + } + + switch (changedMask) { + case MotionEvent.BUTTON_PRIMARY: // left button, touch/pen contact + return 0; + case MotionEvent.BUTTON_TERTIARY: // middle mouse + return 1; + case MotionEvent.BUTTON_SECONDARY: // rightbutton, Pen barrel button + return 2; + case MotionEvent.BUTTON_BACK: + return 3; + case MotionEvent.BUTTON_FORWARD: + return 4; + // TOD0 - Pen eraser button maps to what? + } + return -1; + } + public static boolean isPrimary(int pointerId, int primaryPointerId, MotionEvent event) { if (supportsHover(event)) { return true;