From 8952e3158a8f46447efa681152cb454513ab4ac2 Mon Sep 17 00:00:00 2001 From: Nick Lefever Date: Wed, 8 Nov 2023 22:09:39 +0100 Subject: [PATCH 1/3] [fabric] Add conditional coordinate space conversion for native view hit testing Summary: Native views use the AppKit api for hit testing which requires the point to be in the superview coordinate system. This diff updates the hit testing in `RCTViewComponentView` to conditionally converts the point to the target view coordinate system only if the tested view is a react view. Test Plan: Run Zeratul with Fabric and select text inside message bubbles. The scroll view being a native view, the hit testing does not require a point conversion. With this change, the text selection works as expected. | Before | After | |--| | https://pxl.cl/3Mlpb | https://pxl.cl/3MllN | Reviewers: shawndempsey, #rn-desktop Reviewed By: shawndempsey Differential Revision: https://phabricator.intern.facebook.com/D51129375 Tags: uikit-diff --- .../ComponentViews/View/RCTViewComponentView.mm | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm index 1f5dbd7f8f7e91..2c18984619e2b4 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm @@ -18,6 +18,7 @@ #import // [macOS] #import #import +#import // [macOS] #import #import #import @@ -660,7 +661,16 @@ - (RCTUIView *)betterHitTest:(CGPoint)point withEvent:(UIEvent *)event // [macOS } for (RCTUIView *subview in [self.subviews reverseObjectEnumerator]) { // [macOS] - RCTUIView *hitView = [subview hitTest:[subview convertPoint:point fromView:self] withEvent:event]; // [macOS] + // Native macOS views require the point to be in the super view coordinate space for hit testing. [macOS] + CGPoint hitTestPoint = point; +#if TARGET_OS_OSX // [macOS + // Paper and Fabric components use the target view coordinate space for hit testing + if ([subview isKindOfClass:[RCTView class]] || [subview isKindOfClass:[RCTViewComponentView class]]) { + hitTestPoint = [subview convertPoint:point fromView:self]; + } +#endif // macOS] + + RCTUIView *hitView = [subview hitTest:hitTestPoint withEvent:event]; // [macOS] if (hitView) { return hitView; } From 10c973ab15b5c881f41340c3aee3f80bb06c5232 Mon Sep 17 00:00:00 2001 From: Saad Najmi Date: Thu, 21 Nov 2024 09:50:56 -0800 Subject: [PATCH 2/3] fix(fabric): don't import RCTView into RCTViewComponentView --- .../Mounting/ComponentViews/View/RCTViewComponentView.mm | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm index 2c18984619e2b4..e81b7275158f2a 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm @@ -18,7 +18,6 @@ #import // [macOS] #import #import -#import // [macOS] #import #import #import @@ -664,8 +663,8 @@ - (RCTUIView *)betterHitTest:(CGPoint)point withEvent:(UIEvent *)event // [macOS // Native macOS views require the point to be in the super view coordinate space for hit testing. [macOS] CGPoint hitTestPoint = point; #if TARGET_OS_OSX // [macOS - // Paper and Fabric components use the target view coordinate space for hit testing - if ([subview isKindOfClass:[RCTView class]] || [subview isKindOfClass:[RCTViewComponentView class]]) { + // Fabric components use the target view coordinate space for hit testing + if ([subview isKindOfClass:[RCTViewComponentView class]]) { hitTestPoint = [subview convertPoint:point fromView:self]; } #endif // macOS] From 953c92967b5f905af8ced0ff72a12515f0ef7ff8 Mon Sep 17 00:00:00 2001 From: Saad Najmi Date: Thu, 28 Nov 2024 15:53:57 -0800 Subject: [PATCH 3/3] refactor(fabric): Make the diff in `[RCTViewComponentView betterHitTest:withEvent:]` more transparent --- .../Mounting/ComponentViews/View/RCTViewComponentView.mm | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm index e81b7275158f2a..0ee88bcc58e916 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm @@ -660,16 +660,17 @@ - (RCTUIView *)betterHitTest:(CGPoint)point withEvent:(UIEvent *)event // [macOS } for (RCTUIView *subview in [self.subviews reverseObjectEnumerator]) { // [macOS] - // Native macOS views require the point to be in the super view coordinate space for hit testing. [macOS] +#if !TARGET_OS_OSX // [macOS] + RCTUIView *hitView = [subview hitTest:[subview convertPoint:point fromView:self] withEvent:event]; // [macOS] +#else // [macOS + // Native macOS views require the point to be in the super view coordinate space for hit testing. CGPoint hitTestPoint = point; -#if TARGET_OS_OSX // [macOS // Fabric components use the target view coordinate space for hit testing if ([subview isKindOfClass:[RCTViewComponentView class]]) { hitTestPoint = [subview convertPoint:point fromView:self]; } -#endif // macOS] - RCTUIView *hitView = [subview hitTest:hitTestPoint withEvent:event]; // [macOS] +#endif // macOS] if (hitView) { return hitView; }