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 a37ba3fe15..0d7922ed01 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;