Skip to content

Commit c49d7b2

Browse files
authored
chore: revert "Add onMouseEnter and onMouseLeave to Text" (#2709)
This reverts commit 10b1cd8. ## Summary: The reverted commit moved mouse tracking and handling from `RCTView` to `RCTUIView`. Unfortunately, this includes adding some paper-isms to `RCTUIView`, which is also used by Fabric. We don't use this feature internally anymore, so let's just remove it. In Fabric, it should be much easier to add mouse Tracking to Text since everything is an RCTViewComponentView. ## Test Plan: CI should pass
1 parent 69fe24f commit c49d7b2

File tree

13 files changed

+184
-448
lines changed

13 files changed

+184
-448
lines changed

packages/react-native/Libraries/Text/Text.d.ts

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -102,20 +102,9 @@ export interface TextPropsAndroid {
102102
android_hyphenationFrequency?: 'normal' | 'none' | 'full' | undefined;
103103
}
104104

105-
// [macOS
106-
export interface TextPropsMacOS {
107-
enableFocusRing?: boolean | undefined;
108-
focusable?: boolean | undefined;
109-
onMouseEnter?: ((event: MouseEvent) => void) | undefined;
110-
onMouseLeave?: ((event: MouseEvent) => void) | undefined;
111-
tooltip?: string | undefined;
112-
}
113-
// macOS]
114-
115105
// https://reactnative.dev/docs/text#props
116106
export interface TextProps
117107
extends TextPropsIOS,
118-
TextPropsMacOS, // [macOS]
119108
TextPropsAndroid,
120109
AccessibilityProps {
121110
/**

packages/react-native/Libraries/Text/Text/RCTTextShadowView.mm

Lines changed: 10 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -85,24 +85,16 @@ - (void)uiManagerWillPerformMounting
8585

8686
NSNumber *tag = self.reactTag;
8787
NSMutableArray<NSNumber *> *descendantViewTags = [NSMutableArray new];
88-
NSMutableArray<NSNumber *> *virtualSubviewTags = [NSMutableArray new]; // [macOS]
89-
90-
// [macOS - Enumerate embedded shadow views and virtual subviews in one loop
91-
[textStorage enumerateAttributesInRange:NSMakeRange(0, textStorage.length)
92-
options:0
93-
usingBlock:^(NSDictionary<NSAttributedStringKey, id> *_Nonnull attrs, NSRange range, __unused BOOL * _Nonnull stop) {
94-
id embeddedViewAttribute = attrs[RCTBaseTextShadowViewEmbeddedShadowViewAttributeName];
95-
if ([embeddedViewAttribute isKindOfClass:[RCTShadowView class]]) {
96-
RCTShadowView *embeddedShadowView = (RCTShadowView *)embeddedViewAttribute;
97-
[descendantViewTags addObject:embeddedShadowView.reactTag];
98-
}
88+
[textStorage enumerateAttribute:RCTBaseTextShadowViewEmbeddedShadowViewAttributeName
89+
inRange:NSMakeRange(0, textStorage.length)
90+
options:0
91+
usingBlock:^(RCTShadowView *shadowView, NSRange range, __unused BOOL *stop) {
92+
if (!shadowView) {
93+
return;
94+
}
9995

100-
id tagAttribute = attrs[RCTTextAttributesTagAttributeName];
101-
if ([tagAttribute isKindOfClass:[NSNumber class]] && ![tagAttribute isEqualToNumber:tag]) {
102-
[virtualSubviewTags addObject:tagAttribute];
103-
}
104-
}];
105-
// macOS]
96+
[descendantViewTags addObject:shadowView.reactTag];
97+
}];
10698

10799
[_bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary<NSNumber *, RCTPlatformView *> *viewRegistry) { // [macOS]
108100
RCTTextView *textView = (RCTTextView *)viewRegistry[tag];
@@ -121,25 +113,11 @@ - (void)uiManagerWillPerformMounting
121113
[descendantViews addObject:descendantView];
122114
}];
123115

124-
// [macOS
125-
NSMutableArray<RCTVirtualTextView *> *virtualSubviews = [NSMutableArray arrayWithCapacity:virtualSubviewTags.count];
126-
[virtualSubviewTags
127-
enumerateObjectsUsingBlock:^(NSNumber *_Nonnull virtualSubviewTag, NSUInteger index, BOOL *_Nonnull stop) {
128-
RCTPlatformView *virtualSubview = viewRegistry[virtualSubviewTag];
129-
if ([virtualSubview isKindOfClass:[RCTVirtualTextView class]]) {
130-
[virtualSubviews addObject:(RCTVirtualTextView *)virtualSubview];
131-
}
132-
}];
133-
// macOS]
134-
135116
// Removing all references to Shadow Views to avoid unnecessary retaining.
136117
[textStorage removeAttribute:RCTBaseTextShadowViewEmbeddedShadowViewAttributeName
137118
range:NSMakeRange(0, textStorage.length)];
138119

139-
[textView setTextStorage:textStorage
140-
contentFrame:contentFrame
141-
descendantViews:descendantViews
142-
virtualSubviews:virtualSubviews]; // [macOS]
120+
[textView setTextStorage:textStorage contentFrame:contentFrame descendantViews:descendantViews];
143121
}];
144122
}
145123

packages/react-native/Libraries/Text/Text/RCTTextView.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
#import <React/RCTComponent.h>
99
#import <React/RCTEventDispatcher.h> // [macOS]
10-
#import <React/RCTVirtualTextView.h> // [macOS]
1110

1211
#import <React/RCTUIKit.h> // [macOS]
1312

@@ -23,13 +22,6 @@ NS_ASSUME_NONNULL_BEGIN
2322
contentFrame:(CGRect)contentFrame
2423
descendantViews:(NSArray<RCTPlatformView *> *)descendantViews; // [macOS]
2524

26-
// [macOS
27-
- (void)setTextStorage:(NSTextStorage *)textStorage
28-
contentFrame:(CGRect)contentFrame
29-
descendantViews:(NSArray<RCTPlatformView *> *)descendantViews
30-
virtualSubviews:(NSArray<RCTVirtualTextView *> *_Nullable)virtualSubviews;
31-
// macOS]
32-
3325
/**
3426
* (Experimental and unused for Paper) Pointer event handlers.
3527
*/

packages/react-native/Libraries/Text/Text/RCTTextView.mm

Lines changed: 0 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
#endif // [macOS]
1313

1414
#import <React/RCTAssert.h> // [macOS]
15-
#import <React/RCTUIManager.h> // [macOS]
1615
#import <React/RCTUtils.h>
1716
#import <React/UIView+React.h>
1817
#import <React/RCTFocusChangeEvent.h> // [macOS]
@@ -61,8 +60,6 @@ @implementation RCTTextView {
6160

6261
id<RCTEventDispatcherProtocol> _eventDispatcher; // [macOS]
6362
NSArray<RCTUIView *> *_Nullable _descendantViews; // [macOS]
64-
NSArray<RCTVirtualTextView *> *_Nullable _virtualSubviews; // [macOS]
65-
RCTUIView *_Nullable _currentHoveredSubview; // [macOS]
6663
NSTextStorage *_Nullable _textStorage;
6764
CGRect _contentFrame;
6865
}
@@ -100,7 +97,6 @@ - (instancetype)initWithFrame:(CGRect)frame
10097
_textView.layoutManager.usesFontLeading = NO;
10198
_textStorage = _textView.textStorage;
10299
[self addSubview:_textView];
103-
_currentHoveredSubview = nil;
104100
#endif // macOS]
105101
RCTUIViewSetContentModeRedraw(self); // [macOS]
106102
}
@@ -164,20 +160,6 @@ - (void)setTextStorage:(NSTextStorage *)textStorage
164160
contentFrame:(CGRect)contentFrame
165161
descendantViews:(NSArray<RCTPlatformView *> *)descendantViews // [macOS]
166162
{
167-
// [macOS - to keep track of virtualSubviews as well
168-
[self setTextStorage:textStorage
169-
contentFrame:contentFrame
170-
descendantViews:descendantViews
171-
virtualSubviews:nil];
172-
}
173-
174-
- (void)setTextStorage:(NSTextStorage *)textStorage
175-
contentFrame:(CGRect)contentFrame
176-
descendantViews:(NSArray<RCTPlatformView *> *)descendantViews
177-
virtualSubviews:(NSArray<RCTVirtualTextView *> *)virtualSubviews
178-
{
179-
// macOS]
180-
181163
// This lets the textView own its text storage on macOS
182164
// We update and replace the text container `_textView.textStorage.attributedString` when text/layout changes
183165
#if !TARGET_OS_OSX // [macOS]
@@ -220,8 +202,6 @@ - (void)setTextStorage:(NSTextStorage *)textStorage
220202
[self addSubview:view];
221203
}
222204

223-
_virtualSubviews = virtualSubviews; // [macOS]
224-
225205
[self setNeedsDisplay];
226206
}
227207

@@ -423,21 +403,6 @@ - (void)handleLongPress:(UILongPressGestureRecognizer *)gesture
423403

424404
#else // [macOS
425405

426-
- (BOOL)hasMouseHoverEvent
427-
{
428-
if ([super hasMouseHoverEvent]) {
429-
return YES;
430-
}
431-
432-
// We only care about virtual subviews here.
433-
// Embedded views (e.g., <Text> <View /> </Text>) handle mouse hover events themselves.
434-
NSUInteger indexOfChildWithMouseHoverEvent = [_virtualSubviews indexOfObjectPassingTest:^BOOL(RCTVirtualTextView *_Nonnull childView, NSUInteger idx, BOOL *_Nonnull stop) {
435-
*stop = [childView hasMouseHoverEvent];
436-
return *stop;
437-
}];
438-
return indexOfChildWithMouseHoverEvent != NSNotFound;
439-
}
440-
441406
- (NSView *)hitTest:(NSPoint)point
442407
{
443408
// We will forward mouse click events to the NSTextView ourselves to prevent NSTextView from swallowing events that may be handled in JS (e.g. long press).
@@ -452,110 +417,6 @@ - (NSView *)hitTest:(NSPoint)point
452417
return isTextViewClick ? self : hitView;
453418
}
454419

455-
- (NSNumber *)reactTagAtMouseLocationFromEvent:(NSEvent *)event
456-
{
457-
NSPoint locationInSelf = [self convertPoint:event.locationInWindow fromView:nil];
458-
NSPoint locationInInnerTextView = [self convertPoint:locationInSelf toView:_textView]; // This is needed if the parent <Text> view has padding
459-
return [self reactTagAtPoint:locationInInnerTextView];
460-
}
461-
462-
- (void)mouseEntered:(NSEvent *)event
463-
{
464-
// superclass invokes self.onMouseEnter, so do this first
465-
[super mouseEntered:event];
466-
467-
[self updateHoveredSubviewWithEvent:event];
468-
}
469-
470-
- (void)mouseExited:(NSEvent *)event
471-
{
472-
[self updateHoveredSubviewWithEvent:event];
473-
474-
// superclass invokes self.onMouseLeave, so do this last
475-
[super mouseExited:event];
476-
}
477-
478-
- (void)mouseMoved:(NSEvent *)event
479-
{
480-
[super mouseMoved:event];
481-
[self updateHoveredSubviewWithEvent:event];
482-
}
483-
484-
- (void)updateHoveredSubviewWithEvent:(NSEvent *)event
485-
{
486-
RCTUIView *hoveredView = nil;
487-
488-
if ([event type] != NSEventTypeMouseExited && _virtualSubviews != nil) {
489-
NSNumber *reactTagOfHoveredView = [self reactTagAtMouseLocationFromEvent:event];
490-
491-
if (reactTagOfHoveredView == nil) {
492-
// This happens if we hover over an embedded view, which will handle its own mouse events
493-
return;
494-
}
495-
496-
if ([reactTagOfHoveredView isEqualToNumber:self.reactTag]) {
497-
// We're hovering over the root Text element
498-
hoveredView = self;
499-
} else {
500-
// Maybe we're hovering over a child Text element?
501-
NSUInteger index = [_virtualSubviews indexOfObjectPassingTest:^BOOL(RCTVirtualTextView *_Nonnull view, NSUInteger idx, BOOL *_Nonnull stop) {
502-
*stop = [[view reactTag] isEqualToNumber:reactTagOfHoveredView];
503-
return *stop;
504-
}];
505-
if (index != NSNotFound) {
506-
hoveredView = _virtualSubviews[index];
507-
}
508-
}
509-
}
510-
511-
if (_currentHoveredSubview == hoveredView) {
512-
return;
513-
}
514-
515-
// self will always be an ancestor of any views we pass in here, so it serves as a good default option.
516-
// Also, if we do set from/to nil, we have to call the relevant events on the entire subtree.
517-
RCTUIManager *uiManager = [[_eventDispatcher bridge] uiManager];
518-
RCTShadowView *oldShadowView = [uiManager shadowViewForReactTag:[(_currentHoveredSubview ?: self) reactTag]];
519-
RCTShadowView *newShadowView = [uiManager shadowViewForReactTag:[(hoveredView ?: self) reactTag]];
520-
521-
// Find the common ancestor between the two shadow views
522-
RCTShadowView *commonAncestor = [oldShadowView ancestorSharedWithShadowView:newShadowView];
523-
524-
for (RCTShadowView *exitedShadowView = oldShadowView; exitedShadowView != commonAncestor && exitedShadowView != nil; exitedShadowView = [exitedShadowView reactSuperview]) {
525-
RCTPlatformView *exitedView = [uiManager viewForReactTag:[exitedShadowView reactTag]];
526-
if (![exitedView isKindOfClass:[RCTUIView class]]) {
527-
RCTLogError(@"Unexpected view of type %@ found in hierarchy, must be RCTUIView or subclass", [exitedView class]);
528-
continue;
529-
}
530-
531-
RCTUIView *exitedReactView = (RCTUIView *)exitedView;
532-
[self sendMouseEventWithBlock:[exitedReactView onMouseLeave]
533-
locationInfo:[self locationInfoFromEvent:event]
534-
modifierFlags:event.modifierFlags
535-
additionalData:nil];
536-
}
537-
538-
// We cache these so we can call them from outermost to innermost
539-
NSMutableArray<RCTUIView *> *enteredViewHierarchy = [NSMutableArray new];
540-
for (RCTShadowView *enteredShadowView = newShadowView; enteredShadowView != commonAncestor && enteredShadowView != nil; enteredShadowView = [enteredShadowView reactSuperview]) {
541-
RCTPlatformView *enteredView = [uiManager viewForReactTag:[enteredShadowView reactTag]];
542-
if (![enteredView isKindOfClass:[RCTUIView class]]) {
543-
RCTLogError(@"Unexpected view of type %@ found in hierarchy, must be RCTUIView or subclass", [enteredView class]);
544-
continue;
545-
}
546-
547-
[enteredViewHierarchy addObject:(RCTUIView *)enteredView];
548-
}
549-
for (NSInteger i = [enteredViewHierarchy count] - 1; i >= 0; i--) {
550-
[self sendMouseEventWithBlock:[[enteredViewHierarchy objectAtIndex:i] onMouseEnter]
551-
locationInfo:[self locationInfoFromEvent:event]
552-
modifierFlags:event.modifierFlags
553-
additionalData:nil];
554-
}
555-
556-
_currentHoveredSubview = hoveredView;
557-
}
558-
559420
- (void)rightMouseDown:(NSEvent *)event
560421
{
561422

packages/react-native/Libraries/Text/TextProps.js

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -146,20 +146,6 @@ export type TextPropsMacOS = {
146146
* @platform macos
147147
*/
148148
enableFocusRing?: ?boolean,
149-
150-
/**
151-
* This event is called when the mouse hovers over this component.
152-
*
153-
* @platform macos
154-
*/
155-
onMouseEnter?: ?(event: MouseEvent) => void,
156-
157-
/**
158-
* This event is called when the mouse moves off of this component.
159-
*
160-
* @platform macos
161-
*/
162-
onMouseLeave?: ?(event: MouseEvent) => void,
163149
};
164150
// macOS]
165151

packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8289,8 +8289,6 @@ export type TextPropsMacOS = {
82898289
tooltip?: ?string,
82908290
focusable?: ?boolean,
82918291
enableFocusRing?: ?boolean,
8292-
onMouseEnter?: ?(event: MouseEvent) => void,
8293-
onMouseLeave?: ?(event: MouseEvent) => void,
82948292
};
82958293
type TextBaseProps = $ReadOnly<{
82968294
accessible?: ?boolean,

packages/react-native/React/Base/RCTUIKit.h

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,6 @@ NS_ASSUME_NONNULL_END
117117

118118
#import <AppKit/AppKit.h>
119119

120-
#import <React/RCTComponent.h>
121-
122120
NS_ASSUME_NONNULL_BEGIN
123121

124122
//
@@ -400,16 +398,6 @@ void UIBezierPathAppendPath(UIBezierPath *path, UIBezierPath *appendPath);
400398

401399
- (void)setNeedsDisplay;
402400

403-
// Methods related to mouse events
404-
- (BOOL)hasMouseHoverEvent;
405-
- (NSDictionary*)locationInfoFromDraggingLocation:(NSPoint)locationInWindow;
406-
- (NSDictionary*)locationInfoFromEvent:(NSEvent*)event;
407-
408-
- (void)sendMouseEventWithBlock:(RCTDirectEventBlock)block
409-
locationInfo:(NSDictionary*)locationInfo
410-
modifierFlags:(NSEventModifierFlags)modifierFlags
411-
additionalData:(NSDictionary* __nullable)additionalData;
412-
413401
// FUTURE: When Xcode 14 is no longer supported (CI is building with Xcode 15), we can remove this override since it's now declared on NSView
414402
@property BOOL clipsToBounds;
415403
@property (nonatomic, copy) NSColor *backgroundColor;
@@ -433,20 +421,6 @@ void UIBezierPathAppendPath(UIBezierPath *path, UIBezierPath *appendPath);
433421
*/
434422
@property (nonatomic, assign) BOOL enableFocusRing;
435423

436-
// Mouse events
437-
@property (nonatomic, copy) RCTDirectEventBlock onMouseEnter;
438-
@property (nonatomic, copy) RCTDirectEventBlock onMouseLeave;
439-
@property (nonatomic, copy) RCTDirectEventBlock onDragEnter;
440-
@property (nonatomic, copy) RCTDirectEventBlock onDragLeave;
441-
@property (nonatomic, copy) RCTDirectEventBlock onDrop;
442-
443-
@property (nonatomic, copy) RCTBubblingEventBlock onResponderGrant;
444-
@property (nonatomic, copy) RCTBubblingEventBlock onResponderMove;
445-
@property (nonatomic, copy) RCTBubblingEventBlock onResponderRelease;
446-
@property (nonatomic, copy) RCTBubblingEventBlock onResponderTerminate;
447-
@property (nonatomic, copy) RCTBubblingEventBlock onResponderTerminationRequest;
448-
@property (nonatomic, copy) RCTBubblingEventBlock onStartShouldSetResponder;
449-
450424
@end
451425

452426
// UIScrollView

0 commit comments

Comments
 (0)