Skip to content

Commit

Permalink
Back out "Back out "PointerEvents: Don't dispatch when no listeners f…
Browse files Browse the repository at this point in the history
…or hover events" because hover events stopped working in felios apps in headsets"

Summary: Changelog: [Internal] - Reland pointer event dispatch optimization. Have a fix in followup commit.

Reviewed By: vincentriemer

Differential Revision: D37348771

fbshipit-source-id: 495dda301849255ddc2b35cc5ef9054f10f77ce8
  • Loading branch information
Luna Wei authored and facebook-github-bot committed Jun 23, 2022
1 parent b5f1b3d commit 15d9aa0
Showing 1 changed file with 83 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,13 @@ public void handleMotionEvent(MotionEvent motionEvent, EventDispatcher eventDisp

if (!supportsHover) {
dispatchNonBubblingEventForPathWhenListened(
EVENT.ENTER, EVENT.ENTER_CAPTURE, hitPath, eventDispatcher, surfaceId, motionEvent);
EVENT.ENTER,
EVENT.ENTER_CAPTURE,
hitPath,
eventDispatcher,
surfaceId,
motionEvent,
false);
}

boolean listeningForDown =
Expand Down Expand Up @@ -196,7 +202,13 @@ public void handleMotionEvent(MotionEvent motionEvent, EventDispatcher eventDisp

if (!supportsHover) {
dispatchNonBubblingEventForPathWhenListened(
EVENT.LEAVE, EVENT.LEAVE_CAPTURE, hitPath, eventDispatcher, surfaceId, motionEvent);
EVENT.LEAVE,
EVENT.LEAVE_CAPTURE,
hitPath,
eventDispatcher,
surfaceId,
motionEvent,
false);
}
return;
}
Expand Down Expand Up @@ -227,22 +239,28 @@ private static boolean isAnyoneListeningForBubblingEvent(
return false;
}

/*
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 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 non-bubbling event along the hit path only when relevant listeners */
private static void dispatchNonBubblingEventForPathWhenListened(
EVENT event,
EVENT captureEvent,
List<ViewTarget> hitPath,
EventDispatcher dispatcher,
int surfaceId,
MotionEvent motionEvent) {
MotionEvent motionEvent,
boolean forceDispatch) {

boolean ancestorListening = false;
boolean ancestorListening = forceDispatch;
String eventName = PointerEventHelper.getDispatchableEventName(event);
if (eventName == null) {
return;
Expand Down Expand Up @@ -312,54 +330,72 @@ private void handleHoverEvent(
// 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
int firstDivergentIndex = 0;
while (firstDivergentIndex < Math.min(hitPath.size(), mLastHitPath.size())
boolean nonDivergentListeningToEnter = false;
boolean nonDivergentListeningToLeave = false;
int firstDivergentIndexFromBack = 0;
while (firstDivergentIndexFromBack < Math.min(hitPath.size(), mLastHitPath.size())
&& hitPath
.get(hitPath.size() - 1 - firstDivergentIndex)
.equals(mLastHitPath.get(mLastHitPath.size() - 1 - firstDivergentIndex))) {
firstDivergentIndex++;
.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++;
}

boolean hasDiverged = firstDivergentIndex < Math.max(hitPath.size(), mLastHitPath.size());
boolean hasDiverged =
firstDivergentIndexFromBack < 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<ViewTarget> enterViewTargets = hitPath.subList(0, hitPath.size() - firstDivergentIndex);
List<ViewTarget> enterViewTargets =
hitPath.subList(0, hitPath.size() - firstDivergentIndexFromBack);
if (enterViewTargets.size() > 0) {
// root -> child
for (int i = enterViewTargets.size(); i-- > 0; ) {
eventDispatcher.dispatchEvent(
PointerEvent.obtain(
PointerEventHelper.POINTER_ENTER,
surfaceId,
enterViewTargets.get(i).getViewId(),
motionEvent));
}
dispatchNonBubblingEventForPathWhenListened(
EVENT.ENTER,
EVENT.ENTER_CAPTURE,
enterViewTargets,
eventDispatcher,
surfaceId,
motionEvent,
nonDivergentListeningToEnter);
}

// Fire all relevant exit events
List<ViewTarget> exitViewTargets =
mLastHitPath.subList(0, mLastHitPath.size() - firstDivergentIndex);
mLastHitPath.subList(0, mLastHitPath.size() - firstDivergentIndexFromBack);
if (exitViewTargets.size() > 0) {
// child -> root
for (ViewTarget exitViewTarget : exitViewTargets) {
eventDispatcher.dispatchEvent(
PointerEvent.obtain(
PointerEventHelper.POINTER_LEAVE,
surfaceId,
exitViewTarget.getViewId(),
motionEvent));
}
dispatchNonBubblingEventForPathWhenListened(
EVENT.LEAVE,
EVENT.LEAVE_CAPTURE,
enterViewTargets,
eventDispatcher,
surfaceId,
motionEvent,
nonDivergentListeningToLeave);
}
}

int coalescingKey = mTouchEventCoalescingKeyHelper.getCoalescingKey(mHoverInteractionKey);
eventDispatcher.dispatchEvent(
PointerEvent.obtain(
PointerEventHelper.POINTER_MOVE, surfaceId, targetTag, motionEvent, coalescingKey));
boolean listeningToMove =
isAnyoneListeningForBubblingEvent(hitPath, EVENT.MOVE, EVENT.MOVE_CAPTURE);
if (listeningToMove) {
eventDispatcher.dispatchEvent(
PointerEvent.obtain(
PointerEventHelper.POINTER_MOVE, surfaceId, targetTag, motionEvent, coalescingKey));
}

mLastHitPath = hitPath;
mLastEventCoordinates[0] = x;
Expand Down Expand Up @@ -389,7 +425,13 @@ private void dispatchCancelEvent(
}

dispatchNonBubblingEventForPathWhenListened(
EVENT.LEAVE, EVENT.LEAVE_CAPTURE, hitPath, eventDispatcher, surfaceId, motionEvent);
EVENT.LEAVE,
EVENT.LEAVE_CAPTURE,
hitPath,
eventDispatcher,
surfaceId,
motionEvent,
false);

mTouchEventCoalescingKeyHelper.removeCoalescingKey(mDownStartTime);
mDownStartTime = TouchEvent.UNSET;
Expand Down

0 comments on commit 15d9aa0

Please sign in to comment.