From bcc69dfb3d84bf11a700791a3004aa45a58c72cb Mon Sep 17 00:00:00 2001 From: Artem Goncharov Date: Tue, 14 Jun 2022 03:47:36 -0700 Subject: [PATCH] Back out "PointerEvents: Don't dispatch when no listeners for hover events" because hover events stopped working in felios apps in headsets Summary: Changelog: [Internal][Changed] The diff I'm backing out accidentally made Hover events in Felios apps that use RN under the hood stopped working in headsets (Oculus, Arcata). So we can't test our apps properly without these events. We, with the diff author Luna tried to fix that but it turned out to be not easy so we decided to revert the commit in order to unblock experiences teams. Original commit changeset: d6b5c32ae50b Original Phabricator Diff: D36601638 (https://github.com/facebook/react-native/commit/40769f2212dcd85cba2e54973179c7de445499a4) (Note: this ignores all push blocking failures!) Reviewed By: arhelmus Differential Revision: D37135208 fbshipit-source-id: 4f7d5f168b795690e951ce7063ae3feec3338772 --- .../react/uimanager/JSPointerDispatcher.java | 124 ++++++------------ 1 file changed, 41 insertions(+), 83 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 a37ba3fe15a..0d7922ed01d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSPointerDispatcher.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSPointerDispatcher.java @@ -111,13 +111,7 @@ public class JSPointerDispatcher { if (!supportsHover) { dispatchNonBubblingEventForPathWhenListened( - EVENT.ENTER, - EVENT.ENTER_CAPTURE, - hitPath, - eventDispatcher, - surfaceId, - motionEvent, - false); + EVENT.ENTER, EVENT.ENTER_CAPTURE, hitPath, eventDispatcher, surfaceId, motionEvent); } boolean listeningForDown = @@ -202,13 +196,7 @@ public class JSPointerDispatcher { if (!supportsHover) { dispatchNonBubblingEventForPathWhenListened( - EVENT.LEAVE, - EVENT.LEAVE_CAPTURE, - hitPath, - eventDispatcher, - surfaceId, - motionEvent, - false); + EVENT.LEAVE, EVENT.LEAVE_CAPTURE, hitPath, eventDispatcher, surfaceId, motionEvent); } return; } @@ -239,28 +227,22 @@ public class JSPointerDispatcher { return false; } - /** - * Dispatch event only if ancestor is listening to relevant capture event. This should only be - * relevant for ENTER/LEAVE events that need to be dispatched along every relevant view in the hit - * path. - * - * @param pointerEventType - Should only be ENTER/LEAVE events - * @param hitPath - ViewTargets ordered from target -> root - * @param dispatcher - * @param surfaceId - * @param motionEvent - * @param forceDispatch - Ignore if ancestor is listening and force the event to be dispatched + /* + Dispatch event only if ancestor is listening to relevant event. + This should only be relevant for ENTER/LEAVE events. + @param hitPath - ordered from inner target to root */ + + /** Dispatch non-bubbling event along the hit path only when relevant listeners */ private static void dispatchNonBubblingEventForPathWhenListened( EVENT event, EVENT captureEvent, List hitPath, EventDispatcher dispatcher, int surfaceId, - MotionEvent motionEvent, - boolean forceDispatch) { + MotionEvent motionEvent) { - boolean ancestorListening = forceDispatch; + boolean ancestorListening = false; String eventName = PointerEventHelper.getDispatchableEventName(event); if (eventName == null) { return; @@ -330,72 +312,54 @@ public class JSPointerDispatcher { // hitState is list ordered from inner child -> parent tag // Traverse hitState back-to-front to find the first divergence with mLastHitState // FIXME: this may generate incorrect events when view collapsing changes the hierarchy - boolean nonDivergentListeningToEnter = false; - boolean nonDivergentListeningToLeave = false; - int firstDivergentIndexFromBack = 0; - while (firstDivergentIndexFromBack < Math.min(hitPath.size(), mLastHitPath.size()) + int firstDivergentIndex = 0; + while (firstDivergentIndex < Math.min(hitPath.size(), mLastHitPath.size()) && hitPath - .get(hitPath.size() - 1 - firstDivergentIndexFromBack) - .equals(mLastHitPath.get(mLastHitPath.size() - 1 - firstDivergentIndexFromBack))) { - - // Track if any non-diverging views are listening to enter/leave - View nonDivergentViewTargetView = - hitPath.get(hitPath.size() - 1 - firstDivergentIndexFromBack).getView(); - if (!nonDivergentListeningToEnter - && PointerEventHelper.isListening(nonDivergentViewTargetView, EVENT.ENTER_CAPTURE)) { - nonDivergentListeningToEnter = true; - } - if (!nonDivergentListeningToLeave - && PointerEventHelper.isListening(nonDivergentViewTargetView, EVENT.LEAVE_CAPTURE)) { - nonDivergentListeningToLeave = true; - } - - firstDivergentIndexFromBack++; + .get(hitPath.size() - 1 - firstDivergentIndex) + .equals(mLastHitPath.get(mLastHitPath.size() - 1 - firstDivergentIndex))) { + firstDivergentIndex++; } - boolean hasDiverged = - firstDivergentIndexFromBack < Math.max(hitPath.size(), mLastHitPath.size()); + boolean hasDiverged = firstDivergentIndex < Math.max(hitPath.size(), mLastHitPath.size()); + // Fire all relevant enter events if (hasDiverged) { // If something has changed in either enter/exit, let's start a new coalescing key mTouchEventCoalescingKeyHelper.incrementCoalescingKey(mHoverInteractionKey); - List enterViewTargets = - hitPath.subList(0, hitPath.size() - firstDivergentIndexFromBack); + List enterViewTargets = hitPath.subList(0, hitPath.size() - firstDivergentIndex); if (enterViewTargets.size() > 0) { - dispatchNonBubblingEventForPathWhenListened( - EVENT.ENTER, - EVENT.ENTER_CAPTURE, - enterViewTargets, - eventDispatcher, - surfaceId, - motionEvent, - nonDivergentListeningToEnter); + // root -> child + for (int i = enterViewTargets.size(); i-- > 0; ) { + eventDispatcher.dispatchEvent( + PointerEvent.obtain( + PointerEventHelper.POINTER_ENTER, + surfaceId, + enterViewTargets.get(i).getViewId(), + motionEvent)); + } } + // Fire all relevant exit events List exitViewTargets = - mLastHitPath.subList(0, mLastHitPath.size() - firstDivergentIndexFromBack); + mLastHitPath.subList(0, mLastHitPath.size() - firstDivergentIndex); if (exitViewTargets.size() > 0) { // child -> root - dispatchNonBubblingEventForPathWhenListened( - EVENT.LEAVE, - EVENT.LEAVE_CAPTURE, - enterViewTargets, - eventDispatcher, - surfaceId, - motionEvent, - nonDivergentListeningToLeave); + for (ViewTarget exitViewTarget : exitViewTargets) { + eventDispatcher.dispatchEvent( + PointerEvent.obtain( + PointerEventHelper.POINTER_LEAVE, + surfaceId, + exitViewTarget.getViewId(), + motionEvent)); + } } } int coalescingKey = mTouchEventCoalescingKeyHelper.getCoalescingKey(mHoverInteractionKey); - boolean listeningToMove = - isAnyoneListeningForBubblingEvent(hitPath, EVENT.MOVE, EVENT.MOVE_CAPTURE); - if (listeningToMove) { - eventDispatcher.dispatchEvent( - PointerEvent.obtain( - PointerEventHelper.POINTER_MOVE, surfaceId, targetTag, motionEvent, coalescingKey)); - } + eventDispatcher.dispatchEvent( + PointerEvent.obtain( + PointerEventHelper.POINTER_MOVE, surfaceId, targetTag, motionEvent, coalescingKey)); mLastHitPath = hitPath; mLastEventCoordinates[0] = x; @@ -425,13 +389,7 @@ public class JSPointerDispatcher { } dispatchNonBubblingEventForPathWhenListened( - EVENT.LEAVE, - EVENT.LEAVE_CAPTURE, - hitPath, - eventDispatcher, - surfaceId, - motionEvent, - false); + EVENT.LEAVE, EVENT.LEAVE_CAPTURE, hitPath, eventDispatcher, surfaceId, motionEvent); mTouchEventCoalescingKeyHelper.removeCoalescingKey(mDownStartTime); mDownStartTime = TouchEvent.UNSET;