From bcb58089c4723a005326cb7a8b44e349c6a9a451 Mon Sep 17 00:00:00 2001 From: Luna Wei Date: Tue, 20 Sep 2022 12:01:07 -0700 Subject: [PATCH] Create PointerEventState Summary: Changelog: [Internal] - A refactor to pass the object PointerEventState containing relevant state / and also properties for pointerEvent objects Reviewed By: vincentriemer Differential Revision: D39626285 fbshipit-source-id: e2ff5313ef03d7d2d36c35ca459950ec07650df2 --- .../react/uimanager/JSPointerDispatcher.java | 202 +++++++----------- .../react/uimanager/PointerEventState.java | 19 ++ .../react/uimanager/events/PointerEvent.java | 71 ++---- 3 files changed, 121 insertions(+), 171 deletions(-) create mode 100644 ReactAndroid/src/main/java/com/facebook/react/uimanager/PointerEventState.java 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 4446f256370a7f..8206ebd883dd13 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSPointerDispatcher.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSPointerDispatcher.java @@ -59,11 +59,7 @@ public void onChildStartedNativeGesture( return; } - float[] targetCoordinates = new float[2]; - List hitPath = - TouchTargetHelper.findTargetPathAndCoordinatesForTouch( - motionEvent.getX(), motionEvent.getY(), mRootViewGroup, targetCoordinates); - dispatchCancelEvent(hitPath, motionEvent, eventDispatcher, targetCoordinates); + dispatchCancelEvent(motionEvent, eventDispatcher); mChildHandlingNativeGesture = childView.getId(); } @@ -74,24 +70,17 @@ public void onChildEndedNativeGesture() { private void onUp( int activeTargetTag, - List hitPath, - int surfaceId, + PointerEventState eventState, MotionEvent motionEvent, - EventDispatcher eventDispatcher, - float[] targetCoordinates) { + List hitPath, + EventDispatcher eventDispatcher) { boolean supportsHover = PointerEventHelper.supportsHover(motionEvent); boolean listeningForUp = isAnyoneListeningForBubblingEvent(hitPath, EVENT.UP, EVENT.UP_CAPTURE); if (listeningForUp) { eventDispatcher.dispatchEvent( PointerEvent.obtain( - PointerEventHelper.POINTER_UP, - surfaceId, - activeTargetTag, - motionEvent, - targetCoordinates, - mPrimaryPointerId, - mLastButtonState)); + PointerEventHelper.POINTER_UP, activeTargetTag, eventState, motionEvent)); } if (!supportsHover) { @@ -100,13 +89,7 @@ private void onUp( if (listeningForOut) { eventDispatcher.dispatchEvent( PointerEvent.obtain( - PointerEventHelper.POINTER_OUT, - surfaceId, - activeTargetTag, - motionEvent, - targetCoordinates, - mPrimaryPointerId, - mLastButtonState)); + PointerEventHelper.POINTER_OUT, activeTargetTag, eventState, motionEvent)); } List leaveViewTargets = @@ -115,11 +98,10 @@ private void onUp( // target -> root dispatchEventForViewTargets( PointerEventHelper.POINTER_LEAVE, - leaveViewTargets, - eventDispatcher, - surfaceId, + eventState, motionEvent, - targetCoordinates); + leaveViewTargets, + eventDispatcher); int activePointerId = motionEvent.getPointerId(motionEvent.getActionIndex()); mLastHitPathByPointerId.remove(activePointerId); @@ -141,11 +123,10 @@ private short getCoalescingKey() { private void onDown( int activeTargetTag, - List hitPath, - int surfaceId, + PointerEventState eventState, MotionEvent motionEvent, - EventDispatcher eventDispatcher, - float[] targetCoordinates) { + List hitPath, + EventDispatcher eventDispatcher) { incrementCoalescingKey(); boolean supportsHover = PointerEventHelper.supportsHover(motionEvent); @@ -156,13 +137,7 @@ private void onDown( if (listeningForOver) { eventDispatcher.dispatchEvent( PointerEvent.obtain( - PointerEventHelper.POINTER_OVER, - surfaceId, - activeTargetTag, - motionEvent, - targetCoordinates, - mPrimaryPointerId, - mLastButtonState)); + PointerEventHelper.POINTER_OVER, activeTargetTag, eventState, motionEvent)); } List enterViewTargets = @@ -172,11 +147,10 @@ private void onDown( Collections.reverse(enterViewTargets); dispatchEventForViewTargets( PointerEventHelper.POINTER_ENTER, - enterViewTargets, - eventDispatcher, - surfaceId, + eventState, motionEvent, - targetCoordinates); + enterViewTargets, + eventDispatcher); } boolean listeningForDown = @@ -184,13 +158,7 @@ private void onDown( if (listeningForDown) { eventDispatcher.dispatchEvent( PointerEvent.obtain( - PointerEventHelper.POINTER_DOWN, - surfaceId, - activeTargetTag, - motionEvent, - targetCoordinates, - mPrimaryPointerId, - mLastButtonState)); + PointerEventHelper.POINTER_DOWN, activeTargetTag, eventState, motionEvent)); } } @@ -215,26 +183,31 @@ public void handleMotionEvent(MotionEvent motionEvent, EventDispatcher eventDisp } int action = motionEvent.getActionMasked(); - int surfaceId = UIManagerHelper.getSurfaceId(mRootViewGroup); TouchTargetHelper.ViewTarget activeViewTarget = hitPath.get(0); int activeTargetTag = activeViewTarget.getViewId(); + if (action == MotionEvent.ACTION_DOWN) { + mPrimaryPointerId = motionEvent.getPointerId(0); + } + + PointerEventState eventState = new PointerEventState(); + eventState.primaryPointerId = mPrimaryPointerId; + eventState.buttons = motionEvent.getButtonState(); + eventState.button = + PointerEventHelper.getButtonChange(mLastButtonState, motionEvent.getButtonState()); + eventState.offsetCoords = targetCoordinates; + eventState.surfaceId = UIManagerHelper.getSurfaceId(mRootViewGroup); + switch (action) { case MotionEvent.ACTION_DOWN: - mPrimaryPointerId = motionEvent.getPointerId(0); - onDown( - activeTargetTag, hitPath, surfaceId, motionEvent, eventDispatcher, targetCoordinates); - break; case MotionEvent.ACTION_POINTER_DOWN: - onDown( - activeTargetTag, hitPath, surfaceId, motionEvent, eventDispatcher, targetCoordinates); + onDown(activeTargetTag, eventState, motionEvent, hitPath, eventDispatcher); break; case MotionEvent.ACTION_HOVER_MOVE: // TODO(luwe) - converge this with ACTION_MOVE // HOVER_MOVE may occur before DOWN. Add its downTime as a coalescing key - onMove( - activeTargetTag, motionEvent, eventDispatcher, surfaceId, hitPath, targetCoordinates); + onMove(activeTargetTag, eventState, motionEvent, hitPath, eventDispatcher); break; case MotionEvent.ACTION_MOVE: // TODO(luwe) - converge this with ACTION_HOVER_MOVE @@ -244,22 +217,19 @@ public void handleMotionEvent(MotionEvent motionEvent, EventDispatcher eventDisp eventDispatcher.dispatchEvent( PointerEvent.obtain( PointerEventHelper.POINTER_MOVE, - surfaceId, activeTargetTag, + eventState, motionEvent, - targetCoordinates, - getCoalescingKey(), - mPrimaryPointerId, - mLastButtonState)); + getCoalescingKey())); } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: incrementCoalescingKey(); - onUp(activeTargetTag, hitPath, surfaceId, motionEvent, eventDispatcher, targetCoordinates); + onUp(activeTargetTag, eventState, motionEvent, hitPath, eventDispatcher); break; case MotionEvent.ACTION_CANCEL: - dispatchCancelEvent(hitPath, motionEvent, eventDispatcher, targetCoordinates); + dispatchCancelEvent(eventState, hitPath, motionEvent, eventDispatcher); break; default: FLog.w( @@ -319,34 +289,24 @@ private static List filterByShouldDispatch( private void dispatchEventForViewTargets( String eventName, - List viewTargets, - EventDispatcher dispatcher, - int surfaceId, + PointerEventState eventState, MotionEvent motionEvent, - float[] targetCoordinates) { + List viewTargets, + EventDispatcher dispatcher) { for (ViewTarget viewTarget : viewTargets) { int viewId = viewTarget.getViewId(); - dispatcher.dispatchEvent( - PointerEvent.obtain( - eventName, - surfaceId, - viewId, - motionEvent, - targetCoordinates, - mPrimaryPointerId, - mLastButtonState)); + dispatcher.dispatchEvent(PointerEvent.obtain(eventName, viewId, eventState, motionEvent)); } } // called on hover_move motion events only private void onMove( int targetTag, + PointerEventState eventState, MotionEvent motionEvent, - EventDispatcher eventDispatcher, - int surfaceId, List hitPath, - float[] targetCoordinates) { + EventDispatcher eventDispatcher) { int action = motionEvent.getActionMasked(); if (action != MotionEvent.ACTION_HOVER_MOVE) { @@ -417,13 +377,7 @@ private void onMove( if (listeningForOut) { eventDispatcher.dispatchEvent( PointerEvent.obtain( - PointerEventHelper.POINTER_OUT, - surfaceId, - lastTargetTag, - motionEvent, - targetCoordinates, - mPrimaryPointerId, - mLastButtonState)); + PointerEventHelper.POINTER_OUT, lastTargetTag, eventState, motionEvent)); } // target -> root @@ -437,11 +391,10 @@ private void onMove( // We want to dispatch from target -> root, so no need to reverse dispatchEventForViewTargets( PointerEventHelper.POINTER_LEAVE, - leaveViewTargets, - eventDispatcher, - surfaceId, + eventState, motionEvent, - targetCoordinates); + leaveViewTargets, + eventDispatcher); } } @@ -450,13 +403,7 @@ private void onMove( if (listeningForOver) { eventDispatcher.dispatchEvent( PointerEvent.obtain( - PointerEventHelper.POINTER_OVER, - surfaceId, - targetTag, - motionEvent, - targetCoordinates, - mPrimaryPointerId, - mLastButtonState)); + PointerEventHelper.POINTER_OVER, targetTag, eventState, motionEvent)); } // target -> root @@ -472,11 +419,10 @@ private void onMove( Collections.reverse(enterViewTargets); dispatchEventForViewTargets( PointerEventHelper.POINTER_ENTER, - enterViewTargets, - eventDispatcher, - surfaceId, + eventState, motionEvent, - targetCoordinates); + enterViewTargets, + eventDispatcher); } } @@ -486,32 +432,49 @@ private void onMove( eventDispatcher.dispatchEvent( PointerEvent.obtain( PointerEventHelper.POINTER_MOVE, - surfaceId, targetTag, + eventState, motionEvent, - targetCoordinates, - getCoalescingKey(), - mPrimaryPointerId, - mLastButtonState)); + getCoalescingKey())); } mLastHitPathByPointerId.put(activePointerId, hitPath); mLastEventCoodinatesByPointerId.put(activePointerId, new float[] {x, y}); } + private void dispatchCancelEvent(MotionEvent motionEvent, EventDispatcher eventDispatcher) { + Assertions.assertCondition( + mChildHandlingNativeGesture == -1, + "Expected to not have already sent a cancel for this gesture"); + + float[] targetCoordinates = new float[2]; + List hitPath = + TouchTargetHelper.findTargetPathAndCoordinatesForTouch( + motionEvent.getX(), motionEvent.getY(), mRootViewGroup, targetCoordinates); + + PointerEventState eventState = new PointerEventState(); + + eventState.primaryPointerId = mPrimaryPointerId; + eventState.buttons = motionEvent.getButtonState(); + eventState.button = + PointerEventHelper.getButtonChange(mLastButtonState, motionEvent.getButtonState()); + eventState.offsetCoords = targetCoordinates; + eventState.surfaceId = UIManagerHelper.getSurfaceId(mRootViewGroup); + + dispatchCancelEvent(eventState, hitPath, motionEvent, eventDispatcher); + } + private void dispatchCancelEvent( + PointerEventState eventState, List hitPath, MotionEvent motionEvent, - EventDispatcher eventDispatcher, - float[] targetCoordinates) { + EventDispatcher eventDispatcher) { // This means the gesture has already ended, via some other CANCEL or UP event. This is not // expected to happen very often as it would mean some child View has decided to intercept the // touch stream and start a native gesture only upon receiving the UP/CANCEL event. - Assertions.assertCondition( mChildHandlingNativeGesture == -1, "Expected to not have already sent a cancel for this gesture"); - int surfaceId = UIManagerHelper.getSurfaceId(mRootViewGroup); if (!hitPath.isEmpty()) { boolean listeningForCancel = @@ -521,13 +484,7 @@ private void dispatchCancelEvent( Assertions.assertNotNull(eventDispatcher) .dispatchEvent( PointerEvent.obtain( - PointerEventHelper.POINTER_CANCEL, - surfaceId, - targetTag, - motionEvent, - targetCoordinates, - mPrimaryPointerId, - mLastButtonState)); + PointerEventHelper.POINTER_CANCEL, targetTag, eventState, motionEvent)); } // TODO(luwe) - Need to fire pointer out here as well: @@ -538,11 +495,10 @@ private void dispatchCancelEvent( // dispatch from target -> root dispatchEventForViewTargets( PointerEventHelper.POINTER_LEAVE, - leaveViewTargets, - eventDispatcher, - surfaceId, + eventState, motionEvent, - targetCoordinates); + leaveViewTargets, + eventDispatcher); incrementCoalescingKey(); mPrimaryPointerId = UNSET_POINTER_ID; diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/PointerEventState.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/PointerEventState.java new file mode 100644 index 00000000000000..0a23011d456090 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/PointerEventState.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.uimanager; + +public class PointerEventState { + + public PointerEventState() {} + + public int primaryPointerId; + public int buttons; + public int button; + public float[] offsetCoords; + public int surfaceId; +} 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 7e190b83f1a050..d2a3eda421d50f 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 @@ -15,6 +15,7 @@ import com.facebook.react.bridge.ReactSoftExceptionLogger; import com.facebook.react.bridge.WritableMap; import com.facebook.react.uimanager.PixelUtil; +import com.facebook.react.uimanager.PointerEventState; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -28,80 +29,55 @@ public class PointerEvent extends Event { public static PointerEvent obtain( String eventName, - int surfaceId, - int viewTag, - MotionEvent motionEventToCopy, - float[] offsetCoords, - int primaryPointerId, - int lastButtonState) { + int targetTag, + PointerEventState eventState, + MotionEvent motionEventToCopy) { PointerEvent event = EVENTS_POOL.acquire(); if (event == null) { event = new PointerEvent(); } event.init( - eventName, - surfaceId, - viewTag, - Assertions.assertNotNull(motionEventToCopy), - offsetCoords, - (short) 0, - primaryPointerId, - lastButtonState); + eventName, targetTag, eventState, Assertions.assertNotNull(motionEventToCopy), (short) 0); return event; } public static PointerEvent obtain( String eventName, - int surfaceId, - int viewTag, + int targetTag, + PointerEventState eventState, MotionEvent motionEventToCopy, - float[] offsetCoords, - short coalescingKey, - int primaryPointerId, - int lastButtonState) { + short coalescingKey) { PointerEvent event = EVENTS_POOL.acquire(); if (event == null) { event = new PointerEvent(); } event.init( eventName, - surfaceId, - viewTag, + targetTag, + eventState, Assertions.assertNotNull(motionEventToCopy), - offsetCoords, - coalescingKey, - primaryPointerId, - lastButtonState); + coalescingKey); return event; } private @Nullable MotionEvent mMotionEvent; private @Nullable String mEventName; private short mCoalescingKey = UNSET_COALESCING_KEY; - private float mOffsetX; - private float mOffsetY; private @Nullable List mPointersEventData; - private int mPrimaryPointerId; - private int mLastButtonState; + private PointerEventState mEventState; private void init( String eventName, - int surfaceId, - int viewTag, + int targetTag, + PointerEventState eventState, MotionEvent motionEventToCopy, - float[] offsetCoords, - short coalescingKey, - int primaryPointerId, - int lastButtonState) { + short coalescingKey) { - super.init(surfaceId, viewTag, motionEventToCopy.getEventTime()); + super.init(eventState.surfaceId, targetTag, motionEventToCopy.getEventTime()); mEventName = eventName; mMotionEvent = MotionEvent.obtain(motionEventToCopy); mCoalescingKey = coalescingKey; - mOffsetX = offsetCoords[0]; - mOffsetY = offsetCoords[1]; - mPrimaryPointerId = primaryPointerId; - mLastButtonState = lastButtonState; + mEventState = eventState; } private PointerEvent() {} @@ -184,7 +160,8 @@ private WritableMap createPointerEventData(int index) { pointerEvent.putString("pointerType", pointerType); pointerEvent.putBoolean( - "isPrimary", PointerEventHelper.isPrimary(pointerId, mPrimaryPointerId, mMotionEvent)); + "isPrimary", + PointerEventHelper.isPrimary(pointerId, mEventState.primaryPointerId, mMotionEvent)); // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent // Client refers to upper left edge of the content area (viewport) @@ -203,8 +180,8 @@ private WritableMap createPointerEventData(int index) { pointerEvent.putDouble("pageY", clientY); // Offset refers to upper left edge of the target view - pointerEvent.putDouble("offsetX", PixelUtil.toDIPFromPixel(mOffsetX)); - pointerEvent.putDouble("offsetY", PixelUtil.toDIPFromPixel(mOffsetY)); + pointerEvent.putDouble("offsetX", PixelUtil.toDIPFromPixel(mEventState.offsetCoords[0])); + pointerEvent.putDouble("offsetY", PixelUtil.toDIPFromPixel(mEventState.offsetCoords[1])); pointerEvent.putInt("target", this.getViewTag()); pointerEvent.putDouble("timestamp", this.getTimestampMs()); @@ -216,10 +193,8 @@ private WritableMap createPointerEventData(int index) { pointerEvent.putDouble("tiltY", 0); } - int buttonState = mMotionEvent.getButtonState(); - pointerEvent.putInt("buttons", buttonState); - pointerEvent.putInt( - "button", PointerEventHelper.getButtonChange(mLastButtonState, buttonState)); + pointerEvent.putInt("buttons", mEventState.buttons); + pointerEvent.putInt("button", mEventState.button); return pointerEvent; }