Skip to content

Commit dff7ce8

Browse files
Nick LefeverSaadnajmi
authored andcommitted
[fabric] Add mouse enter/leave tracking on scroll
Summary: This diff adds a bounds change observer to the wrapping clip view, allowing to be notified when the view position is changing because a parent scroll view is being scrolled. This allows the view to evaluate the new cursor position and check if mouse enter/leave events have to be emitted. Test Plan: * Run Zeratul with Fabric enabled. * Scroll the messages view without moving the cursor position and check that enter/leave tracking is working as expected. https://pxl.cl/4jSxh Reviewers: shawndempsey, #rn-desktop Reviewed By: shawndempsey Differential Revision: https://phabricator.intern.facebook.com/D53529018 Tasks: T154617556
1 parent 0327eed commit dff7ce8

File tree

1 file changed

+34
-0
lines changed

1 file changed

+34
-0
lines changed

packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ @implementation RCTViewComponentView {
5050
BOOL _isJSResponder;
5151
BOOL _removeClippedSubviews;
5252
BOOL _hasMouseOver; // [macOS]
53+
BOOL _hasClipViewBoundsObserver; // [macOS]
5354
NSTrackingArea *_trackingArea; // [macOS]
5455
NSMutableArray<RCTUIView *> *_reactSubviews; // [macOS]
5556
NSSet<NSString *> *_Nullable _propKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN;
@@ -649,6 +650,7 @@ - (void)finalizeUpdates:(RNComponentViewUpdateMask)updateMask
649650
[self invalidateLayer];
650651

651652
[self updateTrackingAreas];
653+
[self updateClipViewBoundsObserverIfNeeded];
652654
}
653655

654656
- (void)prepareForRecycle
@@ -1720,6 +1722,38 @@ - (void)updateMouseOverIfNeeded
17201722
}
17211723
}
17221724

1725+
- (void)updateClipViewBoundsObserverIfNeeded
1726+
{
1727+
// Subscribe to view bounds changed notification so that the view can be notified when a
1728+
// scroll event occurs either due to trackpad/gesture based scrolling or a scrollwheel event
1729+
// both of which would not cause the mouseExited to be invoked.
1730+
1731+
NSClipView *clipView = self.window ? self.enclosingScrollView.contentView : nil;
1732+
1733+
BOOL hasMouseEventHandler = _props->macOSViewEvents[facebook::react::MacOSViewEvents::Offset::MouseEnter] ||
1734+
_props->macOSViewEvents[facebook::react::MacOSViewEvents::Offset::MouseLeave];
1735+
1736+
if (_hasClipViewBoundsObserver && (!clipView || !hasMouseEventHandler)) {
1737+
_hasClipViewBoundsObserver = NO;
1738+
[[NSNotificationCenter defaultCenter] removeObserver:self
1739+
name:NSViewBoundsDidChangeNotification
1740+
object:nil];
1741+
} else if (!_hasClipViewBoundsObserver && clipView && hasMouseEventHandler) {
1742+
_hasClipViewBoundsObserver = YES;
1743+
[[NSNotificationCenter defaultCenter] addObserver:self
1744+
selector:@selector(updateMouseOverIfNeeded)
1745+
name:NSViewBoundsDidChangeNotification
1746+
object:clipView];
1747+
[self updateMouseOverIfNeeded];
1748+
}
1749+
}
1750+
1751+
- (void)viewDidMoveToWindow
1752+
{
1753+
[self updateClipViewBoundsObserverIfNeeded];
1754+
[super viewDidMoveToWindow];
1755+
}
1756+
17231757
- (void)updateTrackingAreas
17241758
{
17251759
if (_trackingArea) {

0 commit comments

Comments
 (0)