12
12
#endif // [macOS]
13
13
14
14
#import < React/RCTAssert.h> // [macOS]
15
- #import < React/RCTUIManager.h> // [macOS]
16
15
#import < React/RCTUtils.h>
17
16
#import < React/UIView+React.h>
18
17
#import < React/RCTFocusChangeEvent.h> // [macOS]
@@ -61,8 +60,6 @@ @implementation RCTTextView {
61
60
62
61
id <RCTEventDispatcherProtocol> _eventDispatcher; // [macOS]
63
62
NSArray <RCTUIView *> *_Nullable _descendantViews; // [macOS]
64
- NSArray <RCTVirtualTextView *> *_Nullable _virtualSubviews; // [macOS]
65
- RCTUIView *_Nullable _currentHoveredSubview; // [macOS]
66
63
NSTextStorage *_Nullable _textStorage;
67
64
CGRect _contentFrame;
68
65
}
@@ -100,7 +97,6 @@ - (instancetype)initWithFrame:(CGRect)frame
100
97
_textView.layoutManager .usesFontLeading = NO ;
101
98
_textStorage = _textView.textStorage ;
102
99
[self addSubview: _textView];
103
- _currentHoveredSubview = nil ;
104
100
#endif // macOS]
105
101
RCTUIViewSetContentModeRedraw (self); // [macOS]
106
102
}
@@ -164,20 +160,6 @@ - (void)setTextStorage:(NSTextStorage *)textStorage
164
160
contentFrame : (CGRect)contentFrame
165
161
descendantViews : (NSArray <RCTPlatformView *> *)descendantViews // [macOS]
166
162
{
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
-
181
163
// This lets the textView own its text storage on macOS
182
164
// We update and replace the text container `_textView.textStorage.attributedString` when text/layout changes
183
165
#if !TARGET_OS_OSX // [macOS]
@@ -220,8 +202,6 @@ - (void)setTextStorage:(NSTextStorage *)textStorage
220
202
[self addSubview: view];
221
203
}
222
204
223
- _virtualSubviews = virtualSubviews; // [macOS]
224
-
225
205
[self setNeedsDisplay ];
226
206
}
227
207
@@ -423,21 +403,6 @@ - (void)handleLongPress:(UILongPressGestureRecognizer *)gesture
423
403
424
404
#else // [macOS
425
405
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
-
441
406
- (NSView *)hitTest : (NSPoint )point
442
407
{
443
408
// 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
452
417
return isTextViewClick ? self : hitView;
453
418
}
454
419
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
-
559
420
- (void )rightMouseDown : (NSEvent *)event
560
421
{
561
422
0 commit comments