diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSPointerDispatcher.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSPointerDispatcher.java index 4d61f51c56f358..d65ecbea8bcfbc 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSPointerDispatcher.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSPointerDispatcher.java @@ -50,6 +50,8 @@ public class JSPointerDispatcher { private int mLastButtonState = 0; private final ViewGroup mRootViewGroup; + private static final int[] sRootScreenCoords = {0, 0}; + // Set globally for hover interactions, referenced for coalescing hover events public JSPointerDispatcher(ViewGroup viewGroup) { @@ -255,10 +257,21 @@ private void onDown( } } + private float[] eventCoordsToScreenCoords(float[] eventCoords) { + float[] screenCoords = new float[2]; + mRootViewGroup.getLocationOnScreen(sRootScreenCoords); + + screenCoords[0] = eventCoords[0] + sRootScreenCoords[0]; + screenCoords[1] = eventCoords[1] + sRootScreenCoords[1]; + + return screenCoords; + } + private PointerEventState createEventState(int activePointerId, MotionEvent motionEvent) { Map offsetByPointerId = new HashMap(); Map> hitPathByPointerId = new HashMap>(); Map eventCoordinatesByPointerId = new HashMap(); + Map screenCoordinatesByPointerId = new HashMap(); for (int index = 0; index < motionEvent.getPointerCount(); index++) { float[] offsetCoordinates = new float[2]; float[] eventCoordinates = new float[] {motionEvent.getX(index), motionEvent.getY(index)}; @@ -270,6 +283,7 @@ private PointerEventState createEventState(int activePointerId, MotionEvent moti offsetByPointerId.put(pointerId, offsetCoordinates); hitPathByPointerId.put(pointerId, hitPath); eventCoordinatesByPointerId.put(pointerId, eventCoordinates); + screenCoordinatesByPointerId.put(pointerId, eventCoordsToScreenCoords(eventCoordinates)); } int surfaceId = UIManagerHelper.getSurfaceId(mRootViewGroup); @@ -282,6 +296,7 @@ private PointerEventState createEventState(int activePointerId, MotionEvent moti offsetByPointerId, hitPathByPointerId, eventCoordinatesByPointerId, + screenCoordinatesByPointerId, mHoveringPointerIds); // Creates a copy of hovering pointer ids, as they may be updated } @@ -673,6 +688,8 @@ private int[] getChildOffsetRelativeToRoot(View childView) { private PointerEventState normalizeToRoot(PointerEventState original, float rootX, float rootY) { Map newOffsets = new HashMap<>(original.getOffsetByPointerId()); Map newEventCoords = new HashMap<>(original.getEventCoordinatesByPointerId()); + Map newScreenCoords = + new HashMap<>(original.getScreenCoordinatesByPointerId()); float[] rootOffset = {rootX, rootY}; for (Map.Entry offsetEntry : newOffsets.entrySet()) { @@ -684,6 +701,11 @@ private PointerEventState normalizeToRoot(PointerEventState original, float root eventCoordsEntry.setValue(zeroOffset); } + float[] screenCoords = eventCoordsToScreenCoords(rootOffset); + for (Map.Entry screenCoordsEntry : newScreenCoords.entrySet()) { + screenCoordsEntry.setValue(screenCoords); + } + return new PointerEventState( original.getPrimaryPointerId(), original.getActivePointerId(), @@ -692,6 +714,7 @@ private PointerEventState normalizeToRoot(PointerEventState original, float root newOffsets, new HashMap<>(original.getHitPathByPointerId()), newEventCoords, + newScreenCoords, new HashSet<>(original.getHoveringPointerIds())); } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/PointerEvent.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/PointerEvent.java index d0f221d127de7c..66f3c1bdcfc12c 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/PointerEvent.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/PointerEvent.java @@ -215,6 +215,12 @@ private WritableMap createW3CPointerEvent(int index) { pointerEvent.putDouble("clientX", clientX); pointerEvent.putDouble("clientY", clientY); + float[] screenCoords = mEventState.getScreenCoordinatesByPointerId().get(pointerId); + double screenX = PixelUtil.toDIPFromPixel(screenCoords[0]); + double screenY = PixelUtil.toDIPFromPixel(screenCoords[1]); + pointerEvent.putDouble("screenX", screenX); + pointerEvent.putDouble("screenY", screenY); + // x,y values are aliases of clientX, clientY pointerEvent.putDouble("x", clientX); pointerEvent.putDouble("y", clientY); @@ -338,6 +344,7 @@ public static class PointerEventState { private Map mOffsetByPointerId; private Map> mHitPathByPointerId; private Map mEventCoordinatesByPointerId; + private Map mScreenCoordinatesByPointerId; private Set mHoveringPointerIds; public PointerEventState( @@ -348,6 +355,7 @@ public PointerEventState( Map offsetByPointerId, Map> hitPathByPointerId, Map eventCoordinatesByPointerId, + Map screenCoordinatesByPointerId, Set hoveringPointerIds) { mPrimaryPointerId = primaryPointerId; mActivePointerId = activePointerId; @@ -356,6 +364,7 @@ public PointerEventState( mOffsetByPointerId = offsetByPointerId; mHitPathByPointerId = hitPathByPointerId; mEventCoordinatesByPointerId = eventCoordinatesByPointerId; + mScreenCoordinatesByPointerId = screenCoordinatesByPointerId; mHoveringPointerIds = new HashSet<>(hoveringPointerIds); } @@ -395,6 +404,10 @@ public final Map getEventCoordinatesByPointerId() { return mEventCoordinatesByPointerId; } + public final Map getScreenCoordinatesByPointerId() { + return mScreenCoordinatesByPointerId; + } + public final List getHitPathForActivePointer() { return mHitPathByPointerId.get(mActivePointerId); }