From 533ef2ca37d3b19fc909315f183e3f30dbf4b93d Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Thu, 12 Sep 2024 03:30:52 -0700 Subject: [PATCH] Mark HoverEvents as handled when pointer event dispatching is enabled (#46445) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/46445 Similarly to onTouchEvent, we should return true from onHoverEvent to signal to Android that the hover event is "handled" (because we've dispatched the event to JS). This is important to be able to distinguish multiple stacked React roots on top of each other. Changelog: [Android][Fixed] Hover events were dispatched incorrectly when multiple ReactRoots were layered. Reviewed By: mdvacca Differential Revision: D62529586 fbshipit-source-id: d007c44b8ef56989888eb9a993e1428bd0b72a7b --- .../react-native/ReactAndroid/api/ReactAndroid.api | 1 + .../facebook/react/uimanager/JSPointerDispatcher.java | 2 +- .../com/facebook/react/views/view/ReactViewGroup.java | 10 ++++++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index c2c39edc370b45..bfa6197e58eb35 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -8279,6 +8279,7 @@ public class com/facebook/react/views/view/ReactViewGroup : android/view/ViewGro public fun getZIndexMappedChildIndex (I)I public fun hasOverlappingRendering ()Z protected fun onAttachedToWindow ()V + public fun onHoverEvent (Landroid/view/MotionEvent;)Z public fun onInterceptTouchEvent (Landroid/view/MotionEvent;)Z protected fun onLayout (ZIIII)V protected fun onMeasure (II)V 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 ef22bd280dd96c..4215eb51b51324 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 @@ -38,7 +38,7 @@ public class JSPointerDispatcher { private static final int UNSELECTED_VIEW_TAG = -1; private static final int UNSET_POINTER_ID = -1; private static final float ONMOVE_EPSILON = 0.1f; - private static final String TAG = "POINTER EVENTS"; + private static final String TAG = "PointerEvents"; private Map> mLastHitPathByPointerId; private Map mLastEventCoordinatesByPointerId; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java index 5ec379de2d9004..57b1d8eeeae9b2 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java @@ -37,6 +37,7 @@ import com.facebook.react.bridge.UiThreadUtil; import com.facebook.react.common.annotations.UnstableReactNativeAPI; import com.facebook.react.common.annotations.VisibleForTesting; +import com.facebook.react.config.ReactFeatureFlags; import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags; import com.facebook.react.modules.i18nmanager.I18nUtil; import com.facebook.react.touch.OnInterceptTouchEventListener; @@ -309,6 +310,15 @@ public boolean onTouchEvent(MotionEvent ev) { return true; } + @Override + public boolean onHoverEvent(MotionEvent event) { + if (ReactFeatureFlags.dispatchPointerEvents) { + // Match the logic from onTouchEvent if pointer events are enabled + return PointerEvents.canBeTouchTarget(mPointerEvents); + } + return super.onHoverEvent(event); + } + @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) { // We do not dispatch the motion event if its children are not supposed to receive it