Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,24 @@ open class GestureHandler {
}
}

/**
* The view whose coordinate space should be used when reporting event positions to JS.
*
* Handlers attached via the V3 NativeDetector are registered against the DetectorView
* which never carries user-applied transforms — those live on the detector's single child.
* Descending one level keeps reported coordinates consistent with V2 and the V3
* InterceptingGestureDetector path. For all other attachment styles this is just [view].
*/
val coordinateView: View?
get() {
val v = view
Comment thread
m-bert marked this conversation as resolved.
return if (v is RNGestureHandlerDetectorView && v.isNotEmpty()) {
v.getChildAt(0)
} else {
v
}
}
Comment thread
j-piasecki marked this conversation as resolved.

var state = STATE_UNDETERMINED
private set
var x = 0f
Expand Down Expand Up @@ -387,42 +405,13 @@ open class GestureHandler {

numberOfPointers = adaptedTransformedEvent.pointerCount

// TODO: this is likely wrong, and the transformed event itself should be
// in the coordinate system of the child view, but I'm not sure of the
// consequences
val detectorView = hostDetectorView
if (detectorView != null && view == detectorView && detectorView.isNotEmpty()) {
val outPoint = PointF()
var foundChild = false

for (i in 0 until detectorView.childCount) {
val child = detectorView.getChildAt(i)
GestureHandlerOrchestrator.transformPointToChildViewCoords(
adaptedTransformedEvent.x,
adaptedTransformedEvent.y,
detectorView,
child,
outPoint,
)
if (isWithinBounds(child, outPoint.x, outPoint.y)) {
x = outPoint.x
y = outPoint.y
isWithinBounds = true
foundChild = true
break
}
}

if (!foundChild) {
x = adaptedTransformedEvent.x
y = adaptedTransformedEvent.y
isWithinBounds = false
}
} else {
x = adaptedTransformedEvent.x
y = adaptedTransformedEvent.y
isWithinBounds = isWithinBounds(view, x, y)
}
x = adaptedTransformedEvent.x
y = adaptedTransformedEvent.y
// The orchestrator transforms incoming events into the coordinate space of the detector's
// child (when the handler is attached to a NativeDetector wrapper), so bounds-checking must
// also use that child rather than the wrapper, otherwise hit-testing would ignore the user's
// transforms applied to the visible view.
isWithinBounds = isWithinBounds(coordinateView, x, y)

if (shouldCancelWhenOutside) {
if (!isWithinBounds && (state == STATE_ACTIVE || state == STATE_BEGAN)) {
Expand Down Expand Up @@ -872,7 +861,7 @@ open class GestureHandler {
* This method modifies and transforms the received point.
*/
protected fun transformPoint(point: PointF): PointF =
orchestrator?.transformPointToViewCoords(this.view, point) ?: run {
orchestrator?.transformPointToViewCoords(coordinateView, point) ?: run {
point.x = Float.NaN
point.y = Float.NaN
point
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ class GestureHandlerOrchestrator(
}

val action = sourceEvent.actionMasked
val event = transformEventToViewCoords(handler.view, MotionEvent.obtain(sourceEvent))
val event = transformEventToViewCoords(handler.coordinateView, MotionEvent.obtain(sourceEvent))

if (handler.needsPointerData) {
handler.updatePointerData(event, sourceEvent)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ - (void)updateConfig:(NSDictionary *)config
- (RNGestureHandlerEventExtraData *)eventExtraData:(RNForceTouchGestureRecognizer *)recognizer
{
return [RNGestureHandlerEventExtraData forForce:recognizer.force
forPosition:[recognizer locationInView:recognizer.view]
forPosition:[recognizer locationInView:self.coordinateView]
withAbsolutePosition:[recognizer locationInView:recognizer.view.window]
withNumberOfTouches:recognizer.numberOfTouches
withPointerType:_pointerType];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ - (void)setCurrentPointerType:(RNGestureHandlerPointerType)pointerType

- (RNGestureHandlerEventExtraData *)eventExtraData:(UIGestureRecognizer *)recognizer
{
return [RNGestureHandlerEventExtraData forPosition:[recognizer locationInView:recognizer.view]
return [RNGestureHandlerEventExtraData forPosition:[recognizer locationInView:self.coordinateView]
withAbsolutePosition:[recognizer locationInView:recognizer.view.window]
withPointerType:_pointerType];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer

- (RNGestureHandlerEventExtraData *)eventExtraData:(UIGestureRecognizer *)recognizer
{
return [RNGestureHandlerEventExtraData forPosition:[recognizer locationInView:recognizer.view]
return [RNGestureHandlerEventExtraData forPosition:[recognizer locationInView:self.coordinateView]
withAbsolutePosition:[recognizer locationInView:recognizer.view.window]
withNumberOfTouches:recognizer.numberOfTouches
withDuration:[(RNBetterLongPressGestureRecognizer *)recognizer getDuration]
Expand All @@ -298,7 +298,7 @@ - (RNGestureHandlerEventExtraData *)eventExtraData:(UIGestureRecognizer *)recogn

- (RNGestureHandlerEventExtraData *)eventExtraData:(NSGestureRecognizer *)recognizer
{
return [RNGestureHandlerEventExtraData forPosition:[recognizer locationInView:recognizer.view]
return [RNGestureHandlerEventExtraData forPosition:[recognizer locationInView:self.coordinateView]
withAbsolutePosition:[recognizer locationInView:recognizer.view.window.contentView]
withNumberOfTouches:1
withDuration:[(RNBetterLongPressGestureRecognizer *)recognizer getDuration]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,7 @@ - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
#if TARGET_OS_OSX
- (RNGestureHandlerEventExtraData *)eventExtraData:(NSPanGestureRecognizer *)recognizer
{
return [RNGestureHandlerEventExtraData forPan:[recognizer locationInView:recognizer.view]
return [RNGestureHandlerEventExtraData forPan:[recognizer locationInView:self.coordinateView]
withAbsolutePosition:[recognizer locationInView:recognizer.view.window.contentView]
withTranslation:[recognizer translationInView:recognizer.view.window.contentView]
withVelocity:[recognizer velocityInView:recognizer.view.window.contentView]
Expand All @@ -466,7 +466,7 @@ - (RNGestureHandlerEventExtraData *)eventExtraData:(UIPanGestureRecognizer *)rec
RNBetterPanGestureRecognizer *panRecognizer = (RNBetterPanGestureRecognizer *)recognizer;

return [RNGestureHandlerEventExtraData
forPan:[recognizer locationInView:recognizer.view]
forPan:[recognizer locationInView:self.coordinateView]
withAbsolutePosition:[recognizer locationInView:recognizer.view.window]
withTranslation:[recognizer translationInView:recognizer.view.window]
withVelocity:[recognizer velocityInView:recognizer.view.window]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ - (instancetype)initWithTag:(NSNumber *)tag
- (RNGestureHandlerEventExtraData *)eventExtraData:(NSMagnificationGestureRecognizer *)recognizer
{
return [RNGestureHandlerEventExtraData forPinch:recognizer.magnification
withFocalPoint:[recognizer locationInView:recognizer.view]
withFocalPoint:[recognizer locationInView:self.coordinateView]
withVelocity:((RNBetterPinchRecognizer *)recognizer).velocity
withNumberOfTouches:2
withPointerType:RNGestureHandlerMouse];
Expand All @@ -177,20 +177,21 @@ - (RNGestureHandlerEventExtraData *)eventExtraData:(UIPinchGestureRecognizer *)r
{
CGPoint focalPoint;
NSUInteger numberOfTouches = recognizer.numberOfTouches;
RNGHUIView *coordinateView = self.coordinateView;

if (numberOfTouches > 0) {
CGPoint accumulatedPoint = CGPointZero;

for (int i = 0; i < numberOfTouches; i++) {
CGPoint location = [recognizer locationOfTouch:i inView:recognizer.view];
CGPoint location = [recognizer locationOfTouch:i inView:coordinateView];
accumulatedPoint.x += location.x;
accumulatedPoint.y += location.y;
}

focalPoint = CGPointMake(accumulatedPoint.x / numberOfTouches, accumulatedPoint.y / numberOfTouches);
} else {
// Trackpad pinch gestures may report 0 touches - use the recognizer's location instead
focalPoint = [recognizer locationInView:recognizer.view];
focalPoint = [recognizer locationInView:coordinateView];
}

return [RNGestureHandlerEventExtraData forPinch:recognizer.scale
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ - (instancetype)initWithTag:(NSNumber *)tag
- (RNGestureHandlerEventExtraData *)eventExtraData:(NSRotationGestureRecognizer *)recognizer
{
return [RNGestureHandlerEventExtraData forRotation:-recognizer.rotation
withAnchorPoint:[recognizer locationInView:recognizer.view]
withAnchorPoint:[recognizer locationInView:self.coordinateView]
withVelocity:((RNBetterRotationRecognizer *)recognizer).velocity
withNumberOfTouches:2
withPointerType:RNGestureHandlerMouse];
Expand All @@ -170,7 +170,7 @@ - (RNGestureHandlerEventExtraData *)eventExtraData:(NSRotationGestureRecognizer
- (RNGestureHandlerEventExtraData *)eventExtraData:(UIRotationGestureRecognizer *)recognizer
{
return [RNGestureHandlerEventExtraData forRotation:recognizer.rotation
withAnchorPoint:[recognizer locationInView:recognizer.view]
withAnchorPoint:[recognizer locationInView:self.coordinateView]
withVelocity:recognizer.velocity
withNumberOfTouches:recognizer.numberOfTouches
withPointerType:_pointerType];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,15 @@
@property (nonatomic, copy, nullable) NSNumber *viewTag;
@property (nonatomic, readonly) RNGestureHandlerState lastState;

/**
The view whose coordinate space should be used when reporting event positions to JS.
Handlers attached via the V3 NativeDetector are bound to the `RNGestureHandlerDetector` wrapper,
which never carries user-applied transforms — those live on the detector's single subview.
Descending one level keeps reported coordinates consistent with V2 and the V3
InterceptingGestureDetector path. For all other attachment styles this is just `recognizer.view`.
Comment thread
j-piasecki marked this conversation as resolved.
Outdated
*/
@property (nonatomic, readonly, nullable) RNGHUIView *coordinateView;

- (BOOL)isViewParagraphComponent:(nullable RNGHUIView *)view;
- (nonnull RNGHUIView *)chooseViewForInteraction:(nonnull UIGestureRecognizer *)recognizer;
- (void)bindToView:(nonnull RNGHUIView *)view;
Expand Down
14 changes: 12 additions & 2 deletions packages/react-native-gesture-handler/apple/RNGestureHandler.mm
Original file line number Diff line number Diff line change
Expand Up @@ -286,12 +286,12 @@ - (void)unbindFromView
- (RNGestureHandlerEventExtraData *)eventExtraData:(UIGestureRecognizer *)recognizer
{
#if TARGET_OS_OSX
return [RNGestureHandlerEventExtraData forPosition:[recognizer locationInView:recognizer.view]
return [RNGestureHandlerEventExtraData forPosition:[recognizer locationInView:self.coordinateView]
withAbsolutePosition:[recognizer locationInView:recognizer.view.window.contentView]
withNumberOfTouches:1
withPointerType:RNGestureHandlerMouse];
#else
return [RNGestureHandlerEventExtraData forPosition:[recognizer locationInView:recognizer.view]
return [RNGestureHandlerEventExtraData forPosition:[recognizer locationInView:self.coordinateView]
withAbsolutePosition:[recognizer locationInView:recognizer.view.window]
withNumberOfTouches:recognizer.numberOfTouches
withPointerType:_pointerType];
Expand All @@ -307,6 +307,16 @@ - (RNGHUIView *)chooseViewForInteraction:(UIGestureRecognizer *)recognizer
return [self isViewParagraphComponent:recognizer.view] ? recognizer.view.subviews[0] : recognizer.view;
}

- (RNGHUIView *)coordinateView
{
RNGHUIView *recognizerView = _recognizer.view;
if ([self usesNativeOrVirtualDetector] && recognizerView == self.hostDetectorView &&
recognizerView.subviews.count > 0) {
Comment thread
j-piasecki marked this conversation as resolved.
Outdated
return recognizerView.subviews[0];
}
return recognizerView;
Comment thread
m-bert marked this conversation as resolved.
}

- (BOOL)shouldSuppressActiveEvent:(RNGestureHandlerEventExtraData *)extraData
{
return NO;
Expand Down
Loading