mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Add basic emitting of click event (#36616)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/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
This commit is contained in:
committed by
Facebook GitHub Bot
parent
a6690bfb7b
commit
71506cefbf
@@ -24,6 +24,26 @@ typedef NS_ENUM(NSInteger, RCTPointerEventType) {
|
||||
RCTPointerEventTypeCancel,
|
||||
};
|
||||
|
||||
static BOOL AllTouchesAreCancelledOrEnded(NSSet<UITouch *> *touches)
|
||||
{
|
||||
for (UITouch *touch in touches) {
|
||||
if (touch.phase == UITouchPhaseBegan || touch.phase == UITouchPhaseMoved || touch.phase == UITouchPhaseStationary) {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
static BOOL AnyTouchesChanged(NSSet<UITouch *> *touches)
|
||||
{
|
||||
for (UITouch *touch in touches) {
|
||||
if (touch.phase == UITouchPhaseBegan || touch.phase == UITouchPhaseMoved) {
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
struct ActivePointer {
|
||||
/*
|
||||
* Pointer ID
|
||||
@@ -349,7 +369,9 @@ static void UpdateActivePointerWithUITouch(
|
||||
UIEvent *uiEvent,
|
||||
UIView *rootComponentView)
|
||||
{
|
||||
activePointer.componentView = FindClosestFabricManagedTouchableView(uiTouch.view);
|
||||
CGPoint location = [uiTouch locationInView:rootComponentView];
|
||||
UIView *hitTestedView = [rootComponentView hitTest:location withEvent:nil];
|
||||
activePointer.componentView = FindClosestFabricManagedTouchableView(hitTestedView);
|
||||
|
||||
activePointer.clientPoint = [uiTouch locationInView:rootComponentView];
|
||||
activePointer.screenPoint = [rootComponentView convertPoint:activePointer.clientPoint
|
||||
@@ -396,6 +418,22 @@ static BOOL IsAnyViewInPathListeningToEvent(NSOrderedSet<RCTReactTaggedView *> *
|
||||
return NO;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an ActivePointer determine if it is still within the same event target tree as
|
||||
* the one which initiated the pointer gesture.
|
||||
*/
|
||||
static BOOL IsPointerWithinInitialTree(ActivePointer activePointer)
|
||||
{
|
||||
NSOrderedSet<RCTReactTaggedView *> *initialViewSet =
|
||||
GetTouchableViewsInPathToRoot(activePointer.initialComponentView);
|
||||
for (RCTReactTaggedView *canidateTaggedView in initialViewSet) {
|
||||
if (canidateTaggedView.tag == activePointer.componentView.tag) {
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
/**
|
||||
* Surprisingly, `__unsafe_unretained id` pointers are not regular pointers
|
||||
* and `std::hash<>` cannot hash them.
|
||||
@@ -526,6 +564,8 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithTarget : (id)target action : (SEL)act
|
||||
activePointer.shouldLeaveWhenReleased = YES;
|
||||
}
|
||||
|
||||
activePointer.initialComponentView = FindClosestFabricManagedTouchableView(touch.view);
|
||||
|
||||
UpdateActivePointerWithUITouch(activePointer, touch, event, _rootComponentView);
|
||||
|
||||
_activePointers.emplace(touch, activePointer);
|
||||
@@ -618,6 +658,11 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithTarget : (id)target action : (SEL)act
|
||||
}
|
||||
case RCTPointerEventTypeEnd: {
|
||||
eventEmitter->onPointerUp(pointerEvent);
|
||||
|
||||
if (pointerEvent.isPrimary && pointerEvent.button == 0 && IsPointerWithinInitialTree(activePointer)) {
|
||||
eventEmitter->onClick(pointerEvent);
|
||||
}
|
||||
|
||||
if (activePointer.shouldLeaveWhenReleased) {
|
||||
[self handleIncomingPointerEvent:pointerEvent onView:nil];
|
||||
}
|
||||
@@ -641,6 +686,12 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithTarget : (id)target action : (SEL)act
|
||||
|
||||
[self _registerTouches:touches withEvent:event];
|
||||
[self _dispatchActivePointers:[self _activePointersFromTouches:touches] eventType:RCTPointerEventTypeStart];
|
||||
|
||||
if (self.state == UIGestureRecognizerStatePossible) {
|
||||
self.state = UIGestureRecognizerStateBegan;
|
||||
} else if (self.state == UIGestureRecognizerStateBegan) {
|
||||
self.state = UIGestureRecognizerStateChanged;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
|
||||
@@ -649,6 +700,8 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithTarget : (id)target action : (SEL)act
|
||||
|
||||
[self _updateTouches:touches withEvent:event];
|
||||
[self _dispatchActivePointers:[self _activePointersFromTouches:touches] eventType:RCTPointerEventTypeMove];
|
||||
|
||||
self.state = UIGestureRecognizerStateChanged;
|
||||
}
|
||||
|
||||
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
|
||||
@@ -658,6 +711,12 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithTarget : (id)target action : (SEL)act
|
||||
[self _updateTouches:touches withEvent:event];
|
||||
[self _dispatchActivePointers:[self _activePointersFromTouches:touches] eventType:RCTPointerEventTypeEnd];
|
||||
[self _unregisterTouches:touches];
|
||||
|
||||
if (AllTouchesAreCancelledOrEnded(event.allTouches)) {
|
||||
self.state = UIGestureRecognizerStateEnded;
|
||||
} else if (AnyTouchesChanged(event.allTouches)) {
|
||||
self.state = UIGestureRecognizerStateChanged;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
|
||||
@@ -667,6 +726,12 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithTarget : (id)target action : (SEL)act
|
||||
[self _updateTouches:touches withEvent:event];
|
||||
[self _dispatchActivePointers:[self _activePointersFromTouches:touches] eventType:RCTPointerEventTypeCancel];
|
||||
[self _unregisterTouches:touches];
|
||||
|
||||
if (AllTouchesAreCancelledOrEnded(event.allTouches)) {
|
||||
self.state = UIGestureRecognizerStateCancelled;
|
||||
} else if (AnyTouchesChanged(event.allTouches)) {
|
||||
self.state = UIGestureRecognizerStateChanged;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)reset
|
||||
|
||||
Reference in New Issue
Block a user