-
Notifications
You must be signed in to change notification settings - Fork 151
Description
Environment
react-native -v: 0.68.57-microsoft.0
npm ls react-native-macos: 0.68.57
node -v: v16.17.1
npm -v: 8.15.0
yarn --version: 1.22.19
xcodebuild -version: Xcode 14.1 Build version 14B47bSteps to reproduce the bug
This issue only manifests if the RCTRootView is not at the origin of the NSWindow. To repro this bug, I modified packages/rn-tester/RNTester-macOS/ViewController.m adding [rootView setFrameOrigin:(NSPoint){0,-100}]; at the end of viewDidLoad.
Then in RNTester go to the "Pressable" page. When you click on "Pressable" in the ListView you have to be very careful to not move the mouse in between mouse down and mouse up (the bug manifests in the ListView as well)
In the "Pressable" page, click on the first "Press Me" button and notice that it flickers from "Pressed!" back to "Press Me".
If you press and drag up, once you get about 100 points above the "Press Me" button it will change to "Pressed!".
Expected Behavior
onPress events should work properly regardless of where the RCTRootView is positioned on the window.
Here is the correct behavior with a potential fix applied:
Actual Behavior
In the "Pressable" page, click on the first "Press Me" button and notice that it flickers from "Pressed!" back to "Press Me".
If you press and drag up, once you get about 100 points above the "Press Me" button it will change to "Pressed!".
Reproducible Demo
No response
Additional context
If the RCTRootView is not positioned at the origin of the NSWindow, then touch.pageX/pageY events will not have the correct coordinates. This can make it difficult for a user to click on Touchable and Pressable components unless there are no mouse moves between the mouse down and the mouse up events. The touch down and up events use the touch.locationX/locationY which are computed correctly, but after a touch down if the user move the mouse the touch.pageX/pageY coordinates are used and if the RCTRootView is not at the window origin, these coordinates will be offset. The result is the user will see touch feedback for a moment and then it disappears.
A potential fix is to change React/Base/RCTTouchHandler.m, modifying the line 231:
- CGPoint rootViewLocation = CGPointMake(location.x, CGRectGetHeight(self.view.window.frame) - location.y);
+ RCTAssert(_cachedRootView, @"We were unable to find a root view for the touch");
+ CGPoint rootViewLocation = [_cachedRootView.window.contentView convertPoint:location toView:_cachedRootView];
