Stop sending PointerEvents when view is native gesture handling

Summary:
Changelog: [Internal] - Stop dispatching pointer events when a child view has indicated it wants to handle a native gesture.

In discussion and alignment with web standards, we've decided to not dispatch any pointer events during a native gesture.

Currently, on ACTION_HOVER_MOVE, we remove child views of the native gesture handling view and continue dispatching onPointerMove for ancestor views. This change removes this logic and won't dispatch a onPointerMove event at all.

For all other MotionEvent actions, this is already the case.

Also adding an example in RNTester that involves a scrollView (which handles gestures during scrolling)

Reviewed By: javache

Differential Revision: D39377157

fbshipit-source-id: cb0a719f67136e31b68d6f6e794fee10b256bf21
This commit is contained in:
Luna Wei
2022-09-12 12:17:21 -07:00
committed by Facebook GitHub Bot
parent 9929eadcb4
commit 5198d56f28
4 changed files with 193 additions and 118 deletions
@@ -228,14 +228,6 @@ public class JSPointerDispatcher {
TouchTargetHelper.ViewTarget activeViewTarget = hitPath.get(0);
int activeTargetTag = activeViewTarget.getViewId();
if (action == MotionEvent.ACTION_HOVER_MOVE) {
onMove(motionEvent, eventDispatcher, surfaceId, hitPath, targetCoordinates);
return;
}
// TODO(luwe) - Update this to properly handle native gesture handling for non-hover move events
// If the touch was intercepted by a child, we've already sent a cancel event to JS for this
// gesture, so we shouldn't send any more pointer events related to it.
if (mChildHandlingNativeGesture != -1) {
return;
}
@@ -246,6 +238,11 @@ public class JSPointerDispatcher {
onDown(
activeTargetTag, hitPath, surfaceId, motionEvent, eventDispatcher, targetCoordinates);
break;
case MotionEvent.ACTION_HOVER_MOVE:
// TODO(luwe) - converge this with ACTION_MOVE
onMove(
activeTargetTag, motionEvent, eventDispatcher, surfaceId, hitPath, targetCoordinates);
break;
case MotionEvent.ACTION_MOVE:
// TODO(luwe) - converge this with ACTION_HOVER_MOVE
int coalescingKey = mTouchEventCoalescingKeyHelper.getCoalescingKey(mDownStartTime);
@@ -343,6 +340,7 @@ public class JSPointerDispatcher {
// called on hover_move motion events only
private void onMove(
int targetTag,
MotionEvent motionEvent,
EventDispatcher eventDispatcher,
int surfaceId,
@@ -383,24 +381,6 @@ public class JSPointerDispatcher {
mTouchEventCoalescingKeyHelper.addCoalescingKey(mHoverInteractionKey);
}
// If child is handling, eliminate target tags under handling child
if (mChildHandlingNativeGesture > 0) {
int index = 0;
for (ViewTarget viewTarget : hitPath) {
if (viewTarget.getViewId() == mChildHandlingNativeGesture) {
hitPath.subList(0, index).clear();
break;
}
index++;
}
}
int targetTag = hitPath.isEmpty() ? -1 : hitPath.get(0).getViewId();
// If targetTag is empty, we should bail?
if (targetTag == -1) {
return;
}
// hitState is list ordered from inner child -> parent tag
// Traverse hitState back-to-front to find the first divergence with lastHitPath
// FIXME: this may generate incorrect events when view collapsing changes the hierarchy
@@ -552,6 +532,8 @@ public class JSPointerDispatcher {
mPrimaryPointerId));
}
// TODO(luwe) - Need to fire pointer out here as well:
// https://w3c.github.io/pointerevents/#dfn-suppress-a-pointer-event-stream
List<ViewTarget> leaveViewTargets =
filterByShouldDispatch(hitPath, EVENT.LEAVE, EVENT.LEAVE_CAPTURE, false);