Skip to content

Commit 7ccb292

Browse files
vincentriemerfacebook-github-bot
authored andcommitted
Apply pointer entering/leaving tracking to touch-initiated pointer events
Summary: Changelog: [iOS][Internal] - Apply pointer entering/leaving tracking to touch-initiated pointer events This diff takes the refactoring done in the previous diff in this stack and applies it to the pointer events which are converted from discrete touch events. In addition this adds a check when an ActiveTouch is created to see if the pointer in question was hovering before the touch started or not, which is stored and leveraged once the touch is lifted to determine if we should treat the pointer as leaving the screen entirely or not. Reviewed By: lunaleaps Differential Revision: D38762330 fbshipit-source-id: 08452783e01bf5944c57b94a292805b2d69d4384
1 parent 4c408de commit 7ccb292

File tree

1 file changed

+45
-14
lines changed

1 file changed

+45
-14
lines changed

React/Fabric/RCTSurfaceTouchHandler.mm

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,12 @@ typedef NS_ENUM(NSInteger, RCTTouchEventType) {
101101
*/
102102
int button;
103103

104+
/*
105+
* Informs the event system that when the touch is released it should be treated as the
106+
* pointer leaving the screen entirely.
107+
*/
108+
bool shouldLeaveWhenReleased;
109+
104110
/*
105111
* A component view on which the touch was begun.
106112
*/
@@ -550,10 +556,16 @@ - (void)_registerTouches:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
550556
_primaryTouchPointerId = activeTouch.touch.identifier;
551557
activeTouch.isPrimary = true;
552558
}
553-
554559
activeTouch.button = 0;
555560
}
556561

562+
// If the pointer has not been marked as hovering over views before the touch started, we register
563+
// that the activeTouch should not maintain its hovered state once the pointer has been lifted.
564+
auto currentlyHoveredViews = [_currentlyHoveredViewsPerPointer objectForKey:@(activeTouch.touch.identifier)];
565+
if (currentlyHoveredViews == nil || [currentlyHoveredViews count] == 0) {
566+
activeTouch.shouldLeaveWhenReleased = YES;
567+
}
568+
557569
_activeTouches.emplace(touch, activeTouch);
558570
}
559571
}
@@ -639,20 +651,39 @@ - (void)_dispatchActiveTouches:(std::vector<ActiveTouch>)activeTouches eventType
639651
// emit w3c pointer events
640652
if (RCTGetDispatchW3CPointerEvents()) {
641653
PointerEvent pointerEvent = CreatePointerEventFromActiveTouch(activeTouch, eventType);
642-
switch (eventType) {
643-
case RCTTouchEventTypeTouchStart:
644-
activeTouch.eventEmitter->onPointerDown(pointerEvent);
645-
break;
646-
case RCTTouchEventTypeTouchMove:
647-
activeTouch.eventEmitter->onPointerMove(pointerEvent);
648-
break;
649-
case RCTTouchEventTypeTouchEnd:
650-
activeTouch.eventEmitter->onPointerUp(pointerEvent);
651-
break;
652-
case RCTTouchEventTypeTouchCancel:
653-
activeTouch.eventEmitter->onPointerCancel(pointerEvent);
654-
break;
654+
655+
UIView *targetView = nil;
656+
bool shouldLeave = (eventType == RCTTouchEventTypeTouchEnd && activeTouch.shouldLeaveWhenReleased) ||
657+
eventType == RCTTouchEventTypeTouchCancel;
658+
if (!shouldLeave) {
659+
CGPoint clientLocation = CGPointMake(pointerEvent.clientPoint.x, pointerEvent.clientPoint.y);
660+
targetView = FindClosestFabricManagedTouchableView([_rootComponentView hitTest:clientLocation withEvent:nil]);
655661
}
662+
663+
PointerHandler handler = ^(NSOrderedSet<RCTReactTaggedView *> *eventPathViews) {
664+
switch (eventType) {
665+
case RCTTouchEventTypeTouchStart:
666+
activeTouch.eventEmitter->onPointerDown(pointerEvent);
667+
break;
668+
case RCTTouchEventTypeTouchMove: {
669+
bool hasMoveEventListeners =
670+
IsAnyViewInPathListeningToEvent(eventPathViews, ViewEvents::Offset::PointerMove) ||
671+
IsAnyViewInPathListeningToEvent(eventPathViews, ViewEvents::Offset::PointerMoveCapture);
672+
if (hasMoveEventListeners) {
673+
activeTouch.eventEmitter->onPointerMove(pointerEvent);
674+
}
675+
break;
676+
}
677+
case RCTTouchEventTypeTouchEnd:
678+
activeTouch.eventEmitter->onPointerUp(pointerEvent);
679+
break;
680+
case RCTTouchEventTypeTouchCancel:
681+
activeTouch.eventEmitter->onPointerCancel(pointerEvent);
682+
break;
683+
}
684+
};
685+
686+
[self handleIncomingPointerEvent:pointerEvent onView:targetView withHandler:handler];
656687
}
657688
}
658689

0 commit comments

Comments
 (0)