not-react-native-macos 0.87.1-rc.3 → 0.87.1-rc.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Libraries/Components/View/ViewPropTypes.js +91 -0
- package/Libraries/NativeComponent/BaseViewConfig.macos.js +68 -11
- package/Libraries/NativeComponent/ViewConfigIgnore.js +5 -1
- package/Libraries/StyleSheet/PlatformColorValueTypes.macos.js +147 -10
- package/Libraries/StyleSheet/PlatformColorValueTypesMacOS.js +34 -0
- package/Libraries/StyleSheet/PlatformColorValueTypesMacOS.macos.js +55 -0
- package/Libraries/Types/CoreEventTypes.js +11 -0
- package/React/Base/RCTConvert.mm +49 -0
- package/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +294 -0
- package/ReactCommon/React-Fabric.podspec +9 -0
- package/ReactCommon/react/renderer/components/view/platform/macos/react/renderer/components/view/HostPlatformTouch.h +16 -0
- package/ReactCommon/react/renderer/components/view/platform/macos/react/renderer/components/view/HostPlatformViewEventEmitter.cpp +74 -0
- package/ReactCommon/react/renderer/components/view/platform/macos/react/renderer/components/view/HostPlatformViewEventEmitter.h +52 -0
- package/ReactCommon/react/renderer/components/view/platform/macos/react/renderer/components/view/HostPlatformViewEvents.h +61 -0
- package/ReactCommon/react/renderer/components/view/platform/macos/react/renderer/components/view/HostPlatformViewProps.cpp +121 -0
- package/ReactCommon/react/renderer/components/view/platform/macos/react/renderer/components/view/HostPlatformViewProps.h +76 -0
- package/ReactCommon/react/renderer/components/view/platform/macos/react/renderer/components/view/HostPlatformViewTraitsInitializer.h +38 -0
- package/ReactCommon/react/renderer/components/view/platform/macos/react/renderer/components/view/KeyEvent.h +100 -0
- package/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/HostPlatformColor.h +6 -0
- package/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/HostPlatformColor.mm +31 -0
- package/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/PlatformColorParser.mm +34 -0
- package/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/RCTPlatformColorUtils.mm +23 -0
- package/index.js +10 -0
- package/macos/UIKitCompat/UIKit/UIColor.m +7 -1
- package/package.json +1 -1
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
#import <CoreGraphics/CoreGraphics.h>
|
|
12
12
|
#import <QuartzCore/QuartzCore.h>
|
|
13
|
+
#import <algorithm> // [macOS] std::find, for matching a press against keyDownEvents
|
|
13
14
|
#import <objc/runtime.h>
|
|
14
15
|
#import <ranges>
|
|
15
16
|
|
|
@@ -55,6 +56,13 @@ const CGFloat BACKGROUND_COLOR_ZPOSITION = -1024.0f;
|
|
|
55
56
|
NSMutableSet<NSString *> *_accessibilityOrderNativeIDs;
|
|
56
57
|
RCTSwiftUIContainerViewWrapper *_swiftUIWrapper;
|
|
57
58
|
BOOL _focusable;
|
|
59
|
+
#if TARGET_OS_OSX // [macOS
|
|
60
|
+
// AppKit reads these rather than being told them, so they are answered from
|
|
61
|
+
// stored values by the overrides further down.
|
|
62
|
+
BOOL _allowsVibrancy;
|
|
63
|
+
BOOL _mouseDownCanMoveWindow;
|
|
64
|
+
NSTrackingArea *_mouseTrackingArea;
|
|
65
|
+
#endif // macOS]
|
|
58
66
|
}
|
|
59
67
|
|
|
60
68
|
#ifdef RCT_DYNAMIC_FRAMEWORKS
|
|
@@ -69,6 +77,10 @@ const CGFloat BACKGROUND_COLOR_ZPOSITION = -1024.0f;
|
|
|
69
77
|
if (self = [super initWithFrame:frame]) {
|
|
70
78
|
_props = ViewShadowNode::defaultSharedProps();
|
|
71
79
|
_reactSubviews = [NSMutableArray new];
|
|
80
|
+
#if TARGET_OS_OSX // [macOS] mirror HostPlatformViewProps' defaults
|
|
81
|
+
_mouseDownCanMoveWindow = YES;
|
|
82
|
+
_allowsVibrancy = NO;
|
|
83
|
+
#endif // macOS]
|
|
72
84
|
#if !TARGET_OS_TV
|
|
73
85
|
self.multipleTouchEnabled = YES;
|
|
74
86
|
#endif
|
|
@@ -608,9 +620,275 @@ static BOOL RCTLayerTransformCollapsesAxis(CALayer *layer)
|
|
|
608
620
|
|
|
609
621
|
_needsInvalidateLayer = _needsInvalidateLayer || needsInvalidateLayer;
|
|
610
622
|
|
|
623
|
+
#if TARGET_OS_OSX // [macOS
|
|
624
|
+
[self _updateMacOSProps:oldViewProps newProps:newViewProps];
|
|
625
|
+
#endif // macOS]
|
|
626
|
+
|
|
611
627
|
_props = std::static_pointer_cast<const ViewProps>(props);
|
|
612
628
|
}
|
|
613
629
|
|
|
630
|
+
#if TARGET_OS_OSX // [macOS
|
|
631
|
+
/**
|
|
632
|
+
* The props AppKit has and UIKit does not. They are declared in
|
|
633
|
+
* HostPlatformViewProps, so `ViewProps` already carries them on this platform.
|
|
634
|
+
*/
|
|
635
|
+
- (void)_updateMacOSProps:(const ViewProps &)oldViewProps newProps:(const ViewProps &)newViewProps
|
|
636
|
+
{
|
|
637
|
+
if (oldViewProps.tooltip != newViewProps.tooltip) {
|
|
638
|
+
self.toolTip = newViewProps.tooltip.has_value() ? RCTNSStringFromString(*newViewProps.tooltip) : nil;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
if (oldViewProps.acceptsFirstMouse != newViewProps.acceptsFirstMouse) {
|
|
642
|
+
self.acceptsFirstMouse = newViewProps.acceptsFirstMouse;
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
if (oldViewProps.mouseDownCanMoveWindow != newViewProps.mouseDownCanMoveWindow) {
|
|
646
|
+
_mouseDownCanMoveWindow = newViewProps.mouseDownCanMoveWindow;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
if (oldViewProps.enableFocusRing != newViewProps.enableFocusRing) {
|
|
650
|
+
self.enableFocusRing = newViewProps.enableFocusRing;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
// -allowsVibrancy and -canBecomeKeyView are read by AppKit rather than set,
|
|
654
|
+
// so the values are stored and the overrides below answer from them.
|
|
655
|
+
if (oldViewProps.allowsVibrancy != newViewProps.allowsVibrancy) {
|
|
656
|
+
_allowsVibrancy = newViewProps.allowsVibrancy;
|
|
657
|
+
self.needsDisplay = YES;
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
if (oldViewProps.focusable != newViewProps.focusable) {
|
|
661
|
+
_focusable = newViewProps.focusable;
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
if (oldViewProps.hostPlatformEvents != newViewProps.hostPlatformEvents) {
|
|
665
|
+
[self _updateMouseTracking:newViewProps.hostPlatformEvents.wantsMouseTracking()];
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
/**
|
|
670
|
+
* A view only tracks the mouse while something is listening. Tracking every
|
|
671
|
+
* view would cost a dispatch per view per mouse move.
|
|
672
|
+
*/
|
|
673
|
+
- (void)_updateMouseTracking:(BOOL)wanted
|
|
674
|
+
{
|
|
675
|
+
if (wanted == (_mouseTrackingArea != nil)) {
|
|
676
|
+
return;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
if (!wanted) {
|
|
680
|
+
[self removeTrackingArea:_mouseTrackingArea];
|
|
681
|
+
_mouseTrackingArea = nil;
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
_mouseTrackingArea = [[NSTrackingArea alloc]
|
|
686
|
+
initWithRect:NSZeroRect
|
|
687
|
+
options:NSTrackingMouseEnteredAndExited | NSTrackingActiveInKeyWindow | NSTrackingInVisibleRect
|
|
688
|
+
owner:self
|
|
689
|
+
userInfo:nil];
|
|
690
|
+
[self addTrackingArea:_mouseTrackingArea];
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
- (HostPlatformViewEventEmitter::MouseEvent)_mouseEventFromNSEvent:(NSEvent *)event
|
|
694
|
+
{
|
|
695
|
+
NSPoint inWindow = event.locationInWindow;
|
|
696
|
+
NSPoint inView = [self convertPoint:inWindow fromView:nil];
|
|
697
|
+
NSPoint onScreen = self.window != nil ? [self.window convertPointToScreen:inWindow] : inWindow;
|
|
698
|
+
|
|
699
|
+
HostPlatformViewEventEmitter::MouseEvent mouseEvent = {};
|
|
700
|
+
mouseEvent.clientX = inView.x;
|
|
701
|
+
mouseEvent.clientY = inView.y;
|
|
702
|
+
mouseEvent.pageX = inWindow.x;
|
|
703
|
+
mouseEvent.pageY = inWindow.y;
|
|
704
|
+
mouseEvent.screenX = onScreen.x;
|
|
705
|
+
mouseEvent.screenY = onScreen.y;
|
|
706
|
+
return mouseEvent;
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
- (void)mouseEntered:(NSEvent *)event
|
|
710
|
+
{
|
|
711
|
+
[super mouseEntered:event];
|
|
712
|
+
if (_eventEmitter != nullptr) {
|
|
713
|
+
_eventEmitter->onMouseEnter([self _mouseEventFromNSEvent:event]);
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
- (void)mouseExited:(NSEvent *)event
|
|
718
|
+
{
|
|
719
|
+
[super mouseExited:event];
|
|
720
|
+
if (_eventEmitter != nullptr) {
|
|
721
|
+
_eventEmitter->onMouseLeave([self _mouseEventFromNSEvent:event]);
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
- (void)mouseUp:(NSEvent *)event
|
|
726
|
+
{
|
|
727
|
+
[super mouseUp:event];
|
|
728
|
+
const auto &viewProps = static_cast<const ViewProps &>(*_props);
|
|
729
|
+
if (_eventEmitter != nullptr && event.clickCount == 2 &&
|
|
730
|
+
viewProps.hostPlatformEvents[HostPlatformViewEvents::Offset::DoubleClick]) {
|
|
731
|
+
_eventEmitter->onDoubleClick([self _mouseEventFromNSEvent:event]);
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
- (void)rightMouseUp:(NSEvent *)event
|
|
736
|
+
{
|
|
737
|
+
[super rightMouseUp:event];
|
|
738
|
+
const auto &viewProps = static_cast<const ViewProps &>(*_props);
|
|
739
|
+
if (_eventEmitter != nullptr && viewProps.hostPlatformEvents[HostPlatformViewEvents::Offset::AuxClick]) {
|
|
740
|
+
_eventEmitter->onAuxClick([self _mouseEventFromNSEvent:event]);
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
#pragma mark - Keyboard Events
|
|
745
|
+
|
|
746
|
+
/**
|
|
747
|
+
* The W3C `key` name for a press, per https://www.w3.org/TR/uievents-key/.
|
|
748
|
+
*
|
|
749
|
+
* `charactersIgnoringModifiers` already gives the right answer for anything
|
|
750
|
+
* printable. The cases below are the ones where it gives a private-use unichar
|
|
751
|
+
* (the arrows, the function keys) or a control character (Return, Delete)
|
|
752
|
+
* instead of a name. Tab and Escape are matched on keyCode rather than
|
|
753
|
+
* character because AppKit reports them as \t and \e, which would otherwise
|
|
754
|
+
* arrive as those literal characters.
|
|
755
|
+
*
|
|
756
|
+
* Naming follows the cross-platform reconciliation react-native-windows and
|
|
757
|
+
* react-native-macos both use, so a key handler is portable between them.
|
|
758
|
+
*/
|
|
759
|
+
static NSString *RCTKeyFromNSEvent(NSEvent *event)
|
|
760
|
+
{
|
|
761
|
+
NSString *characters = event.charactersIgnoringModifiers;
|
|
762
|
+
unichar code = characters.length > 0 ? [characters characterAtIndex:0] : 0;
|
|
763
|
+
|
|
764
|
+
switch (event.keyCode) {
|
|
765
|
+
case 48:
|
|
766
|
+
return @"Tab";
|
|
767
|
+
case 53:
|
|
768
|
+
return @"Escape";
|
|
769
|
+
default:
|
|
770
|
+
break;
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
switch (code) {
|
|
774
|
+
case NSEnterCharacter:
|
|
775
|
+
case NSNewlineCharacter:
|
|
776
|
+
case NSCarriageReturnCharacter:
|
|
777
|
+
return @"Enter";
|
|
778
|
+
case NSLeftArrowFunctionKey:
|
|
779
|
+
return @"ArrowLeft";
|
|
780
|
+
case NSRightArrowFunctionKey:
|
|
781
|
+
return @"ArrowRight";
|
|
782
|
+
case NSUpArrowFunctionKey:
|
|
783
|
+
return @"ArrowUp";
|
|
784
|
+
case NSDownArrowFunctionKey:
|
|
785
|
+
return @"ArrowDown";
|
|
786
|
+
case NSBackspaceCharacter:
|
|
787
|
+
case NSDeleteCharacter:
|
|
788
|
+
return @"Backspace";
|
|
789
|
+
case NSDeleteFunctionKey:
|
|
790
|
+
return @"Delete";
|
|
791
|
+
case NSHomeFunctionKey:
|
|
792
|
+
return @"Home";
|
|
793
|
+
case NSEndFunctionKey:
|
|
794
|
+
return @"End";
|
|
795
|
+
case NSPageUpFunctionKey:
|
|
796
|
+
return @"PageUp";
|
|
797
|
+
case NSPageDownFunctionKey:
|
|
798
|
+
return @"PageDown";
|
|
799
|
+
default:
|
|
800
|
+
break;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
if (code >= NSF1FunctionKey && code <= NSF12FunctionKey) {
|
|
804
|
+
return [NSString stringWithFormat:@"F%u", (unsigned)(code - NSF1FunctionKey + 1)];
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
return characters;
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
/**
|
|
811
|
+
* Emits the press and reports whether the view claimed it.
|
|
812
|
+
*
|
|
813
|
+
* Claiming matters because AppKit interprets an unclaimed key itself once the
|
|
814
|
+
* responder chain is done with it: Tab moves focus, Escape cancels, anything
|
|
815
|
+
* else beeps. A view says which keys it means to act on through `keyDownEvents`
|
|
816
|
+
* / `keyUpEvents`, and only those suppress the default behaviour. Listening via
|
|
817
|
+
* `onKeyDown` alone deliberately does not, so observing a key does not change
|
|
818
|
+
* what it does.
|
|
819
|
+
*/
|
|
820
|
+
- (BOOL)_handleKeyboardEvent:(NSEvent *)event
|
|
821
|
+
{
|
|
822
|
+
NSEventModifierFlags flags = event.modifierFlags;
|
|
823
|
+
KeyEvent keyEvent = {
|
|
824
|
+
.key = RCTStringFromNSString(RCTKeyFromNSEvent(event)),
|
|
825
|
+
.altKey = static_cast<bool>(flags & NSEventModifierFlagOption),
|
|
826
|
+
.ctrlKey = static_cast<bool>(flags & NSEventModifierFlagControl),
|
|
827
|
+
.shiftKey = static_cast<bool>(flags & NSEventModifierFlagShift),
|
|
828
|
+
.metaKey = static_cast<bool>(flags & NSEventModifierFlagCommand),
|
|
829
|
+
.capsLockKey = static_cast<bool>(flags & NSEventModifierFlagCapsLock),
|
|
830
|
+
.numericPadKey = static_cast<bool>(flags & NSEventModifierFlagNumericPad),
|
|
831
|
+
.helpKey = static_cast<bool>(flags & NSEventModifierFlagHelp),
|
|
832
|
+
.functionKey = static_cast<bool>(flags & NSEventModifierFlagFunction),
|
|
833
|
+
};
|
|
834
|
+
|
|
835
|
+
BOOL isKeyDown = event.type == NSEventTypeKeyDown;
|
|
836
|
+
const auto &viewProps = static_cast<const ViewProps &>(*_props);
|
|
837
|
+
|
|
838
|
+
// Calling super walks the responder chain, which is the view hierarchy, so
|
|
839
|
+
// every ancestor view would emit the same press. Fabric bubbles the event
|
|
840
|
+
// through the shadow tree on its own, so only the innermost view should emit.
|
|
841
|
+
// The flag rides on the NSEvent because that is the one object the whole
|
|
842
|
+
// chain shares.
|
|
843
|
+
static const char kEmittedKey = 0;
|
|
844
|
+
if (_eventEmitter != nullptr && !((NSNumber *)objc_getAssociatedObject(event, &kEmittedKey)).boolValue) {
|
|
845
|
+
if (isKeyDown) {
|
|
846
|
+
_eventEmitter->onKeyDown(keyEvent);
|
|
847
|
+
} else {
|
|
848
|
+
_eventEmitter->onKeyUp(keyEvent);
|
|
849
|
+
}
|
|
850
|
+
objc_setAssociatedObject(event, &kEmittedKey, @YES, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
const auto &handled = isKeyDown ? viewProps.keyDownEvents : viewProps.keyUpEvents;
|
|
854
|
+
return std::find(handled.cbegin(), handled.cend(), keyEvent) != handled.cend();
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
- (void)keyDown:(NSEvent *)event
|
|
858
|
+
{
|
|
859
|
+
if (![self _handleKeyboardEvent:event]) {
|
|
860
|
+
[super keyDown:event];
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
- (void)keyUp:(NSEvent *)event
|
|
865
|
+
{
|
|
866
|
+
if (![self _handleKeyboardEvent:event]) {
|
|
867
|
+
[super keyUp:event];
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
- (BOOL)allowsVibrancy
|
|
872
|
+
{
|
|
873
|
+
return _allowsVibrancy;
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
- (BOOL)mouseDownCanMoveWindow
|
|
877
|
+
{
|
|
878
|
+
return _mouseDownCanMoveWindow;
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
- (BOOL)canBecomeKeyView
|
|
882
|
+
{
|
|
883
|
+
return _focusable;
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
- (BOOL)acceptsFirstResponder
|
|
887
|
+
{
|
|
888
|
+
return _focusable || [super acceptsFirstResponder];
|
|
889
|
+
}
|
|
890
|
+
#endif // macOS]
|
|
891
|
+
|
|
614
892
|
- (void)updateEventEmitter:(const EventEmitter::Shared &)eventEmitter
|
|
615
893
|
{
|
|
616
894
|
assert(std::dynamic_pointer_cast<const ViewEventEmitter>(eventEmitter));
|
|
@@ -1772,7 +2050,16 @@ static NSString *RCTRecursiveAccessibilityLabel(UIView *view)
|
|
|
1772
2050
|
|
|
1773
2051
|
- (void)focus
|
|
1774
2052
|
{
|
|
2053
|
+
#if TARGET_OS_OSX // [macOS] On AppKit -becomeFirstResponder is the window
|
|
2054
|
+
// notifying the view that it happened, not the view asking. Sending it
|
|
2055
|
+
// directly changes nothing: -makeFirstResponder: is the request. Without
|
|
2056
|
+
// this, `focusable` views never receive key events, because nothing ever
|
|
2057
|
+
// makes them first responder -- AppKit moves focus on Tab only, and only
|
|
2058
|
+
// when Full Keyboard Access is on.
|
|
2059
|
+
[self.window makeFirstResponder:self];
|
|
2060
|
+
#else // [macOS]
|
|
1775
2061
|
[self becomeFirstResponder];
|
|
2062
|
+
#endif // [macOS]
|
|
1776
2063
|
|
|
1777
2064
|
#if TARGET_OS_TV
|
|
1778
2065
|
RCTSurfaceHostingProxyRootView *rootView = [self containingRootView];
|
|
@@ -1788,7 +2075,14 @@ static NSString *RCTRecursiveAccessibilityLabel(UIView *view)
|
|
|
1788
2075
|
|
|
1789
2076
|
- (void)blur
|
|
1790
2077
|
{
|
|
2078
|
+
#if TARGET_OS_OSX // [macOS] Symmetrically: resigning is granted by the window,
|
|
2079
|
+
// and only if this view still holds the focus.
|
|
2080
|
+
if (self.window.firstResponder == self) {
|
|
2081
|
+
[self.window makeFirstResponder:nil];
|
|
2082
|
+
}
|
|
2083
|
+
#else // [macOS]
|
|
1791
2084
|
[self resignFirstResponder];
|
|
2085
|
+
#endif // [macOS]
|
|
1792
2086
|
}
|
|
1793
2087
|
|
|
1794
2088
|
- (BOOL)becomeFirstResponder
|
|
@@ -102,6 +102,10 @@ Pod::Spec.new do |s|
|
|
|
102
102
|
"\"$(PODS_TARGET_SRCROOT)/react/renderer/components/legacyviewmanagerinterop/platform/ios\"",
|
|
103
103
|
"\"$(PODS_TARGET_SRCROOT)/react/renderer/components/text/platform/cxx\"",
|
|
104
104
|
"\"$(PODS_TARGET_SRCROOT)/react/renderer/components/textinput/platform/ios\"",
|
|
105
|
+
# [macOS] macOS has its own HostPlatformViewProps -- tooltip, focus ring,
|
|
106
|
+
# first mouse and the rest. Its directory has to come first so it wins
|
|
107
|
+
# over the shared C++ one. macOS]
|
|
108
|
+
"\"$(PODS_TARGET_SRCROOT)/react/renderer/components/view/platform/macos\"",
|
|
105
109
|
"\"$(PODS_TARGET_SRCROOT)/react/renderer/components/view/platform/cxx\"",
|
|
106
110
|
]
|
|
107
111
|
end
|
|
@@ -135,6 +139,11 @@ Pod::Spec.new do |s|
|
|
|
135
139
|
sss.dependency "React-renderercss"
|
|
136
140
|
sss.dependency "Yoga"
|
|
137
141
|
sss.source_files = podspec_sources(["react/renderer/components/view/*.{m,mm,cpp,h}", "react/renderer/components/view/platform/cxx/**/*.{m,mm,cpp,h}"], ["react/renderer/components/view/*.{h}", "react/renderer/components/view/platform/cxx/**/*.{h}"])
|
|
142
|
+
# [macOS] Swap the shared C++ host-platform view files for the macOS ones.
|
|
143
|
+
# Both define the same symbols, so this is a replacement, not an addition.
|
|
144
|
+
sss.osx.source_files = podspec_sources(["react/renderer/components/view/*.{m,mm,cpp,h}", "react/renderer/components/view/platform/macos/**/*.{m,mm,cpp,h}"], ["react/renderer/components/view/*.{h}", "react/renderer/components/view/platform/macos/**/*.{h}"])
|
|
145
|
+
sss.osx.exclude_files = "react/renderer/components/view/platform/cxx/**/*"
|
|
146
|
+
# macOS]
|
|
138
147
|
sss.header_dir = "react/renderer/components/view"
|
|
139
148
|
end
|
|
140
149
|
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// [macOS] Touch is the shared one; a mouse is reported through the same path.
|
|
9
|
+
|
|
10
|
+
#pragma once
|
|
11
|
+
|
|
12
|
+
#include <react/renderer/components/view/BaseTouch.h>
|
|
13
|
+
|
|
14
|
+
namespace facebook::react {
|
|
15
|
+
using HostPlatformTouch = BaseTouch;
|
|
16
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// [macOS] See HostPlatformViewEventEmitter.h.
|
|
9
|
+
|
|
10
|
+
#include "HostPlatformViewEventEmitter.h"
|
|
11
|
+
|
|
12
|
+
namespace facebook::react {
|
|
13
|
+
|
|
14
|
+
static jsi::Value mouseEventPayload(jsi::Runtime &runtime, const HostPlatformViewEventEmitter::MouseEvent &event)
|
|
15
|
+
{
|
|
16
|
+
auto payload = jsi::Object(runtime);
|
|
17
|
+
payload.setProperty(runtime, "clientX", event.clientX);
|
|
18
|
+
payload.setProperty(runtime, "clientY", event.clientY);
|
|
19
|
+
payload.setProperty(runtime, "screenX", event.screenX);
|
|
20
|
+
payload.setProperty(runtime, "screenY", event.screenY);
|
|
21
|
+
payload.setProperty(runtime, "pageX", event.pageX);
|
|
22
|
+
payload.setProperty(runtime, "pageY", event.pageY);
|
|
23
|
+
payload.setProperty(runtime, "altKey", event.altKey);
|
|
24
|
+
payload.setProperty(runtime, "ctrlKey", event.ctrlKey);
|
|
25
|
+
payload.setProperty(runtime, "shiftKey", event.shiftKey);
|
|
26
|
+
payload.setProperty(runtime, "metaKey", event.metaKey);
|
|
27
|
+
payload.setProperty(runtime, "button", event.button);
|
|
28
|
+
// Pressability's click guard reads this to tell a real mouse click apart from
|
|
29
|
+
// one synthesised by the responder system, which would otherwise fire onPress
|
|
30
|
+
// twice.
|
|
31
|
+
payload.setProperty(runtime, "pointerType", "mouse");
|
|
32
|
+
return payload;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
static jsi::Value keyEventPayload(jsi::Runtime &runtime, const KeyEvent &event)
|
|
36
|
+
{
|
|
37
|
+
auto payload = jsi::Object(runtime);
|
|
38
|
+
payload.setProperty(runtime, "key", jsi::String::createFromUtf8(runtime, event.key));
|
|
39
|
+
payload.setProperty(runtime, "altKey", event.altKey);
|
|
40
|
+
payload.setProperty(runtime, "ctrlKey", event.ctrlKey);
|
|
41
|
+
payload.setProperty(runtime, "shiftKey", event.shiftKey);
|
|
42
|
+
payload.setProperty(runtime, "metaKey", event.metaKey);
|
|
43
|
+
payload.setProperty(runtime, "capsLockKey", event.capsLockKey);
|
|
44
|
+
payload.setProperty(runtime, "numericPadKey", event.numericPadKey);
|
|
45
|
+
payload.setProperty(runtime, "helpKey", event.helpKey);
|
|
46
|
+
payload.setProperty(runtime, "functionKey", event.functionKey);
|
|
47
|
+
return payload;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
#define RCT_MACOS_MOUSE_EVENT(name) \
|
|
51
|
+
void HostPlatformViewEventEmitter::name(const MouseEvent &event) const \
|
|
52
|
+
{ \
|
|
53
|
+
dispatchEvent(#name, [event](jsi::Runtime &runtime) { \
|
|
54
|
+
return mouseEventPayload(runtime, event); \
|
|
55
|
+
}); \
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
RCT_MACOS_MOUSE_EVENT(onMouseEnter)
|
|
59
|
+
RCT_MACOS_MOUSE_EVENT(onMouseLeave)
|
|
60
|
+
RCT_MACOS_MOUSE_EVENT(onDoubleClick)
|
|
61
|
+
RCT_MACOS_MOUSE_EVENT(onAuxClick)
|
|
62
|
+
|
|
63
|
+
#define RCT_MACOS_KEY_EVENT(name) \
|
|
64
|
+
void HostPlatformViewEventEmitter::name(const KeyEvent &event) const \
|
|
65
|
+
{ \
|
|
66
|
+
dispatchEvent(#name, [event](jsi::Runtime &runtime) { \
|
|
67
|
+
return keyEventPayload(runtime, event); \
|
|
68
|
+
}); \
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
RCT_MACOS_KEY_EVENT(onKeyDown)
|
|
72
|
+
RCT_MACOS_KEY_EVENT(onKeyUp)
|
|
73
|
+
|
|
74
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// [macOS] Adds the pointer and key events AppKit can report and UIKit cannot.
|
|
9
|
+
|
|
10
|
+
#pragma once
|
|
11
|
+
|
|
12
|
+
#include <react/renderer/components/view/BaseViewEventEmitter.h>
|
|
13
|
+
|
|
14
|
+
#include "KeyEvent.h"
|
|
15
|
+
|
|
16
|
+
namespace facebook::react {
|
|
17
|
+
|
|
18
|
+
class HostPlatformViewEventEmitter : public BaseViewEventEmitter {
|
|
19
|
+
public:
|
|
20
|
+
using BaseViewEventEmitter::BaseViewEventEmitter;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* A mouse crossing into or out of the view. There is no touch equivalent, so
|
|
24
|
+
* these have no counterpart in BaseViewEventEmitter.
|
|
25
|
+
*/
|
|
26
|
+
struct MouseEvent {
|
|
27
|
+
Float clientX{};
|
|
28
|
+
Float clientY{};
|
|
29
|
+
Float screenX{};
|
|
30
|
+
Float screenY{};
|
|
31
|
+
Float pageX{};
|
|
32
|
+
Float pageY{};
|
|
33
|
+
|
|
34
|
+
bool altKey{false};
|
|
35
|
+
bool ctrlKey{false};
|
|
36
|
+
bool shiftKey{false};
|
|
37
|
+
bool metaKey{false};
|
|
38
|
+
|
|
39
|
+
/** DOM button numbering: 0 left, 1 middle, 2 right. */
|
|
40
|
+
int button{0};
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
void onMouseEnter(const MouseEvent &event) const;
|
|
44
|
+
void onMouseLeave(const MouseEvent &event) const;
|
|
45
|
+
void onDoubleClick(const MouseEvent &event) const;
|
|
46
|
+
void onAuxClick(const MouseEvent &event) const;
|
|
47
|
+
|
|
48
|
+
void onKeyDown(const KeyEvent &event) const;
|
|
49
|
+
void onKeyUp(const KeyEvent &event) const;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// [macOS] Which macOS-only handlers a view actually has.
|
|
9
|
+
//
|
|
10
|
+
// Installing an NSTrackingArea on every view to find out later would cost a
|
|
11
|
+
// mouse-moved dispatch per view per move. The props carry a bitset instead, so
|
|
12
|
+
// the view only tracks the mouse when something is listening -- the same
|
|
13
|
+
// arrangement BaseViewProps uses for pointer and responder events.
|
|
14
|
+
|
|
15
|
+
#pragma once
|
|
16
|
+
|
|
17
|
+
#include <bitset>
|
|
18
|
+
#include <cstddef>
|
|
19
|
+
|
|
20
|
+
namespace facebook::react {
|
|
21
|
+
|
|
22
|
+
struct HostPlatformViewEvents {
|
|
23
|
+
std::bitset<8> bits{};
|
|
24
|
+
|
|
25
|
+
enum class Offset : std::size_t {
|
|
26
|
+
MouseEnter = 0,
|
|
27
|
+
MouseLeave = 1,
|
|
28
|
+
DoubleClick = 2,
|
|
29
|
+
AuxClick = 3,
|
|
30
|
+
KeyDown = 4,
|
|
31
|
+
KeyUp = 5,
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
constexpr bool operator[](Offset offset) const
|
|
35
|
+
{
|
|
36
|
+
return bits[static_cast<std::size_t>(offset)];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
std::bitset<8>::reference operator[](Offset offset)
|
|
40
|
+
{
|
|
41
|
+
return bits[static_cast<std::size_t>(offset)];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** True when any macOS mouse handler is present. */
|
|
45
|
+
bool wantsMouseTracking() const
|
|
46
|
+
{
|
|
47
|
+
return (*this)[Offset::MouseEnter] || (*this)[Offset::MouseLeave];
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
inline bool operator==(const HostPlatformViewEvents &lhs, const HostPlatformViewEvents &rhs)
|
|
52
|
+
{
|
|
53
|
+
return lhs.bits == rhs.bits;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
inline bool operator!=(const HostPlatformViewEvents &lhs, const HostPlatformViewEvents &rhs)
|
|
57
|
+
{
|
|
58
|
+
return lhs.bits != rhs.bits;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// [macOS] See HostPlatformViewProps.h.
|
|
9
|
+
|
|
10
|
+
#include "HostPlatformViewProps.h"
|
|
11
|
+
|
|
12
|
+
#include <react/featureflags/ReactNativeFeatureFlags.h>
|
|
13
|
+
#include <react/renderer/core/propsConversions.h>
|
|
14
|
+
|
|
15
|
+
namespace facebook::react {
|
|
16
|
+
|
|
17
|
+
// The whole-map parsing path (feature flag off) needs a converter for the
|
|
18
|
+
// bitset, mirroring the one propsConversions.h provides for ViewEvents.
|
|
19
|
+
static inline HostPlatformViewEvents convertRawProp(
|
|
20
|
+
const PropsParserContext &context,
|
|
21
|
+
const RawProps &rawProps,
|
|
22
|
+
const HostPlatformViewEvents &sourceValue,
|
|
23
|
+
const HostPlatformViewEvents &defaultValue)
|
|
24
|
+
{
|
|
25
|
+
HostPlatformViewEvents result{};
|
|
26
|
+
using Offset = HostPlatformViewEvents::Offset;
|
|
27
|
+
|
|
28
|
+
#define RCT_MACOS_CONVERT_EVENT(name, offset) \
|
|
29
|
+
result[Offset::offset] = convertRawProp( \
|
|
30
|
+
context, rawProps, name, sourceValue[Offset::offset], defaultValue[Offset::offset])
|
|
31
|
+
|
|
32
|
+
RCT_MACOS_CONVERT_EVENT("onMouseEnter", MouseEnter);
|
|
33
|
+
RCT_MACOS_CONVERT_EVENT("onMouseLeave", MouseLeave);
|
|
34
|
+
RCT_MACOS_CONVERT_EVENT("onDoubleClick", DoubleClick);
|
|
35
|
+
RCT_MACOS_CONVERT_EVENT("onAuxClick", AuxClick);
|
|
36
|
+
RCT_MACOS_CONVERT_EVENT("onKeyDown", KeyDown);
|
|
37
|
+
RCT_MACOS_CONVERT_EVENT("onKeyUp", KeyUp);
|
|
38
|
+
|
|
39
|
+
#undef RCT_MACOS_CONVERT_EVENT
|
|
40
|
+
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Two parsing paths exist and both have to be fed. With the iterator setter
|
|
45
|
+
// feature flag on, props arrive one at a time through setProp and the
|
|
46
|
+
// constructor just carries the previous value forward; with it off, the
|
|
47
|
+
// constructor parses the whole RawProps map itself.
|
|
48
|
+
#define RCT_MACOS_PROP(name) \
|
|
49
|
+
name(ReactNativeFeatureFlags::enableCppPropsIteratorSetter() \
|
|
50
|
+
? sourceProps.name \
|
|
51
|
+
: convertRawProp(context, rawProps, #name, sourceProps.name, {}))
|
|
52
|
+
|
|
53
|
+
HostPlatformViewProps::HostPlatformViewProps(
|
|
54
|
+
const PropsParserContext &context,
|
|
55
|
+
const HostPlatformViewProps &sourceProps,
|
|
56
|
+
const RawProps &rawProps)
|
|
57
|
+
: BaseViewProps(context, sourceProps, rawProps),
|
|
58
|
+
hostPlatformEvents(
|
|
59
|
+
ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
|
|
60
|
+
? sourceProps.hostPlatformEvents
|
|
61
|
+
: convertRawProp(context, rawProps, sourceProps.hostPlatformEvents, {})),
|
|
62
|
+
RCT_MACOS_PROP(focusable),
|
|
63
|
+
RCT_MACOS_PROP(enableFocusRing),
|
|
64
|
+
RCT_MACOS_PROP(keyDownEvents),
|
|
65
|
+
RCT_MACOS_PROP(keyUpEvents),
|
|
66
|
+
RCT_MACOS_PROP(tooltip),
|
|
67
|
+
RCT_MACOS_PROP(acceptsFirstMouse),
|
|
68
|
+
RCT_MACOS_PROP(allowsVibrancy),
|
|
69
|
+
RCT_MACOS_PROP(mouseDownCanMoveWindow)
|
|
70
|
+
{
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
#undef RCT_MACOS_PROP
|
|
74
|
+
|
|
75
|
+
void HostPlatformViewProps::setProp(
|
|
76
|
+
const PropsParserContext &context,
|
|
77
|
+
RawPropsPropNameHash hash,
|
|
78
|
+
const char *propName,
|
|
79
|
+
const RawValue &value)
|
|
80
|
+
{
|
|
81
|
+
// Every Props struct must call super unconditionally: several structs can
|
|
82
|
+
// share the same raw value, and skipping the call drops it for all of them.
|
|
83
|
+
BaseViewProps::setProp(context, hash, propName, value);
|
|
84
|
+
|
|
85
|
+
static auto defaults = HostPlatformViewProps{};
|
|
86
|
+
|
|
87
|
+
// An `onX` prop is stored as a bit rather than a value: all the view needs to
|
|
88
|
+
// know is whether anything is listening.
|
|
89
|
+
#define RCT_MACOS_EVENT_CASE(eventType) \
|
|
90
|
+
case CONSTEXPR_RAW_PROPS_KEY_HASH("on" #eventType): { \
|
|
91
|
+
const auto offset = HostPlatformViewEvents::Offset::eventType; \
|
|
92
|
+
HostPlatformViewEvents defaultEvents{}; \
|
|
93
|
+
bool listening = defaultEvents[offset]; \
|
|
94
|
+
if (value.hasValue()) { \
|
|
95
|
+
fromRawValue(context, value, listening); \
|
|
96
|
+
} \
|
|
97
|
+
hostPlatformEvents[offset] = listening; \
|
|
98
|
+
return; \
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
switch (hash) {
|
|
102
|
+
RCT_MACOS_EVENT_CASE(MouseEnter);
|
|
103
|
+
RCT_MACOS_EVENT_CASE(MouseLeave);
|
|
104
|
+
RCT_MACOS_EVENT_CASE(DoubleClick);
|
|
105
|
+
RCT_MACOS_EVENT_CASE(AuxClick);
|
|
106
|
+
RCT_MACOS_EVENT_CASE(KeyDown);
|
|
107
|
+
RCT_MACOS_EVENT_CASE(KeyUp);
|
|
108
|
+
RAW_SET_PROP_SWITCH_CASE_BASIC(focusable);
|
|
109
|
+
RAW_SET_PROP_SWITCH_CASE_BASIC(enableFocusRing);
|
|
110
|
+
RAW_SET_PROP_SWITCH_CASE_BASIC(keyDownEvents);
|
|
111
|
+
RAW_SET_PROP_SWITCH_CASE_BASIC(keyUpEvents);
|
|
112
|
+
RAW_SET_PROP_SWITCH_CASE_BASIC(tooltip);
|
|
113
|
+
RAW_SET_PROP_SWITCH_CASE_BASIC(acceptsFirstMouse);
|
|
114
|
+
RAW_SET_PROP_SWITCH_CASE_BASIC(allowsVibrancy);
|
|
115
|
+
RAW_SET_PROP_SWITCH_CASE_BASIC(mouseDownCanMoveWindow);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
#undef RCT_MACOS_EVENT_CASE
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
} // namespace facebook::react
|