Skip to content

Commit 71506ce

Browse files
vincentriemerfacebook-github-bot
authored andcommitted
Add basic emitting of click event (#36616)
Summary: Pull Request resolved: #36616 Changelog: [iOS][Internal] - Add basic emitting of click event This diff adds the basic implementation of click event emitting, particularlly focused on ensuring clicks are only fired if the pointer interaction ends within the same tree "branch" of elements as which it started. Reviewed By: yungsters Differential Revision: D44148427 fbshipit-source-id: 9e91c32fe0e1ca8a5c50e72cd819625294e070f4
1 parent a6690bf commit 71506ce

File tree

1 file changed

+66
-1
lines changed

1 file changed

+66
-1
lines changed

packages/react-native/React/Fabric/RCTSurfacePointerHandler.mm

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,26 @@ typedef NS_ENUM(NSInteger, RCTPointerEventType) {
2424
RCTPointerEventTypeCancel,
2525
};
2626

27+
static BOOL AllTouchesAreCancelledOrEnded(NSSet<UITouch *> *touches)
28+
{
29+
for (UITouch *touch in touches) {
30+
if (touch.phase == UITouchPhaseBegan || touch.phase == UITouchPhaseMoved || touch.phase == UITouchPhaseStationary) {
31+
return NO;
32+
}
33+
}
34+
return YES;
35+
}
36+
37+
static BOOL AnyTouchesChanged(NSSet<UITouch *> *touches)
38+
{
39+
for (UITouch *touch in touches) {
40+
if (touch.phase == UITouchPhaseBegan || touch.phase == UITouchPhaseMoved) {
41+
return YES;
42+
}
43+
}
44+
return NO;
45+
}
46+
2747
struct ActivePointer {
2848
/*
2949
* Pointer ID
@@ -349,7 +369,9 @@ static void UpdateActivePointerWithUITouch(
349369
UIEvent *uiEvent,
350370
UIView *rootComponentView)
351371
{
352-
activePointer.componentView = FindClosestFabricManagedTouchableView(uiTouch.view);
372+
CGPoint location = [uiTouch locationInView:rootComponentView];
373+
UIView *hitTestedView = [rootComponentView hitTest:location withEvent:nil];
374+
activePointer.componentView = FindClosestFabricManagedTouchableView(hitTestedView);
353375

354376
activePointer.clientPoint = [uiTouch locationInView:rootComponentView];
355377
activePointer.screenPoint = [rootComponentView convertPoint:activePointer.clientPoint
@@ -396,6 +418,22 @@ static BOOL IsAnyViewInPathListeningToEvent(NSOrderedSet<RCTReactTaggedView *> *
396418
return NO;
397419
}
398420

421+
/**
422+
* Given an ActivePointer determine if it is still within the same event target tree as
423+
* the one which initiated the pointer gesture.
424+
*/
425+
static BOOL IsPointerWithinInitialTree(ActivePointer activePointer)
426+
{
427+
NSOrderedSet<RCTReactTaggedView *> *initialViewSet =
428+
GetTouchableViewsInPathToRoot(activePointer.initialComponentView);
429+
for (RCTReactTaggedView *canidateTaggedView in initialViewSet) {
430+
if (canidateTaggedView.tag == activePointer.componentView.tag) {
431+
return YES;
432+
}
433+
}
434+
return NO;
435+
}
436+
399437
/**
400438
* Surprisingly, `__unsafe_unretained id` pointers are not regular pointers
401439
* and `std::hash<>` cannot hash them.
@@ -526,6 +564,8 @@ - (void)_registerTouches:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
526564
activePointer.shouldLeaveWhenReleased = YES;
527565
}
528566

567+
activePointer.initialComponentView = FindClosestFabricManagedTouchableView(touch.view);
568+
529569
UpdateActivePointerWithUITouch(activePointer, touch, event, _rootComponentView);
530570

531571
_activePointers.emplace(touch, activePointer);
@@ -618,6 +658,11 @@ - (void)_dispatchActivePointers:(std::vector<ActivePointer>)activePointers event
618658
}
619659
case RCTPointerEventTypeEnd: {
620660
eventEmitter->onPointerUp(pointerEvent);
661+
662+
if (pointerEvent.isPrimary && pointerEvent.button == 0 && IsPointerWithinInitialTree(activePointer)) {
663+
eventEmitter->onClick(pointerEvent);
664+
}
665+
621666
if (activePointer.shouldLeaveWhenReleased) {
622667
[self handleIncomingPointerEvent:pointerEvent onView:nil];
623668
}
@@ -641,6 +686,12 @@ - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
641686

642687
[self _registerTouches:touches withEvent:event];
643688
[self _dispatchActivePointers:[self _activePointersFromTouches:touches] eventType:RCTPointerEventTypeStart];
689+
690+
if (self.state == UIGestureRecognizerStatePossible) {
691+
self.state = UIGestureRecognizerStateBegan;
692+
} else if (self.state == UIGestureRecognizerStateBegan) {
693+
self.state = UIGestureRecognizerStateChanged;
694+
}
644695
}
645696

646697
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
@@ -649,6 +700,8 @@ - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
649700

650701
[self _updateTouches:touches withEvent:event];
651702
[self _dispatchActivePointers:[self _activePointersFromTouches:touches] eventType:RCTPointerEventTypeMove];
703+
704+
self.state = UIGestureRecognizerStateChanged;
652705
}
653706

654707
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
@@ -658,6 +711,12 @@ - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
658711
[self _updateTouches:touches withEvent:event];
659712
[self _dispatchActivePointers:[self _activePointersFromTouches:touches] eventType:RCTPointerEventTypeEnd];
660713
[self _unregisterTouches:touches];
714+
715+
if (AllTouchesAreCancelledOrEnded(event.allTouches)) {
716+
self.state = UIGestureRecognizerStateEnded;
717+
} else if (AnyTouchesChanged(event.allTouches)) {
718+
self.state = UIGestureRecognizerStateChanged;
719+
}
661720
}
662721

663722
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
@@ -667,6 +726,12 @@ - (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
667726
[self _updateTouches:touches withEvent:event];
668727
[self _dispatchActivePointers:[self _activePointersFromTouches:touches] eventType:RCTPointerEventTypeCancel];
669728
[self _unregisterTouches:touches];
729+
730+
if (AllTouchesAreCancelledOrEnded(event.allTouches)) {
731+
self.state = UIGestureRecognizerStateCancelled;
732+
} else if (AnyTouchesChanged(event.allTouches)) {
733+
self.state = UIGestureRecognizerStateChanged;
734+
}
670735
}
671736

672737
- (void)reset

0 commit comments

Comments
 (0)