not-react-native-macos 0.87.1-rc.2 → 0.87.1-rc.4

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.
Files changed (24) hide show
  1. package/Libraries/Components/View/ViewPropTypes.js +58 -0
  2. package/Libraries/NativeComponent/BaseViewConfig.macos.js +66 -11
  3. package/Libraries/NativeComponent/ViewConfigIgnore.js +5 -1
  4. package/Libraries/StyleSheet/PlatformColorValueTypes.macos.js +147 -10
  5. package/Libraries/StyleSheet/PlatformColorValueTypesMacOS.js +34 -0
  6. package/Libraries/StyleSheet/PlatformColorValueTypesMacOS.macos.js +55 -0
  7. package/Libraries/Utilities/Platform.macos.js +78 -11
  8. package/React/Base/RCTConvert.mm +49 -0
  9. package/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +150 -0
  10. package/ReactCommon/React-Fabric.podspec +9 -0
  11. package/ReactCommon/react/renderer/components/view/platform/macos/react/renderer/components/view/HostPlatformTouch.h +16 -0
  12. package/ReactCommon/react/renderer/components/view/platform/macos/react/renderer/components/view/HostPlatformViewEventEmitter.cpp +39 -0
  13. package/ReactCommon/react/renderer/components/view/platform/macos/react/renderer/components/view/HostPlatformViewEventEmitter.h +39 -0
  14. package/ReactCommon/react/renderer/components/view/platform/macos/react/renderer/components/view/HostPlatformViewEvents.h +59 -0
  15. package/ReactCommon/react/renderer/components/view/platform/macos/react/renderer/components/view/HostPlatformViewProps.cpp +113 -0
  16. package/ReactCommon/react/renderer/components/view/platform/macos/react/renderer/components/view/HostPlatformViewProps.h +66 -0
  17. package/ReactCommon/react/renderer/components/view/platform/macos/react/renderer/components/view/HostPlatformViewTraitsInitializer.h +37 -0
  18. package/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/HostPlatformColor.h +6 -0
  19. package/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/HostPlatformColor.mm +31 -0
  20. package/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/PlatformColorParser.mm +34 -0
  21. package/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/RCTPlatformColorUtils.mm +23 -0
  22. package/index.js +10 -0
  23. package/macos/UIKitCompat/UIKit/UIColor.m +7 -1
  24. package/package.json +1 -1
@@ -55,6 +55,13 @@ const CGFloat BACKGROUND_COLOR_ZPOSITION = -1024.0f;
55
55
  NSMutableSet<NSString *> *_accessibilityOrderNativeIDs;
56
56
  RCTSwiftUIContainerViewWrapper *_swiftUIWrapper;
57
57
  BOOL _focusable;
58
+ #if TARGET_OS_OSX // [macOS
59
+ // AppKit reads these rather than being told them, so they are answered from
60
+ // stored values by the overrides further down.
61
+ BOOL _allowsVibrancy;
62
+ BOOL _mouseDownCanMoveWindow;
63
+ NSTrackingArea *_mouseTrackingArea;
64
+ #endif // macOS]
58
65
  }
59
66
 
60
67
  #ifdef RCT_DYNAMIC_FRAMEWORKS
@@ -69,6 +76,10 @@ const CGFloat BACKGROUND_COLOR_ZPOSITION = -1024.0f;
69
76
  if (self = [super initWithFrame:frame]) {
70
77
  _props = ViewShadowNode::defaultSharedProps();
71
78
  _reactSubviews = [NSMutableArray new];
79
+ #if TARGET_OS_OSX // [macOS] mirror HostPlatformViewProps' defaults
80
+ _mouseDownCanMoveWindow = YES;
81
+ _allowsVibrancy = NO;
82
+ #endif // macOS]
72
83
  #if !TARGET_OS_TV
73
84
  self.multipleTouchEnabled = YES;
74
85
  #endif
@@ -608,9 +619,148 @@ static BOOL RCTLayerTransformCollapsesAxis(CALayer *layer)
608
619
 
609
620
  _needsInvalidateLayer = _needsInvalidateLayer || needsInvalidateLayer;
610
621
 
622
+ #if TARGET_OS_OSX // [macOS
623
+ [self _updateMacOSProps:oldViewProps newProps:newViewProps];
624
+ #endif // macOS]
625
+
611
626
  _props = std::static_pointer_cast<const ViewProps>(props);
612
627
  }
613
628
 
629
+ #if TARGET_OS_OSX // [macOS
630
+ /**
631
+ * The props AppKit has and UIKit does not. They are declared in
632
+ * HostPlatformViewProps, so `ViewProps` already carries them on this platform.
633
+ */
634
+ - (void)_updateMacOSProps:(const ViewProps &)oldViewProps newProps:(const ViewProps &)newViewProps
635
+ {
636
+ if (oldViewProps.tooltip != newViewProps.tooltip) {
637
+ self.toolTip = newViewProps.tooltip.has_value() ? RCTNSStringFromString(*newViewProps.tooltip) : nil;
638
+ }
639
+
640
+ if (oldViewProps.acceptsFirstMouse != newViewProps.acceptsFirstMouse) {
641
+ self.acceptsFirstMouse = newViewProps.acceptsFirstMouse;
642
+ }
643
+
644
+ if (oldViewProps.mouseDownCanMoveWindow != newViewProps.mouseDownCanMoveWindow) {
645
+ _mouseDownCanMoveWindow = newViewProps.mouseDownCanMoveWindow;
646
+ }
647
+
648
+ if (oldViewProps.enableFocusRing != newViewProps.enableFocusRing) {
649
+ self.enableFocusRing = newViewProps.enableFocusRing;
650
+ }
651
+
652
+ // -allowsVibrancy and -canBecomeKeyView are read by AppKit rather than set,
653
+ // so the values are stored and the overrides below answer from them.
654
+ if (oldViewProps.allowsVibrancy != newViewProps.allowsVibrancy) {
655
+ _allowsVibrancy = newViewProps.allowsVibrancy;
656
+ self.needsDisplay = YES;
657
+ }
658
+
659
+ if (oldViewProps.focusable != newViewProps.focusable) {
660
+ _focusable = newViewProps.focusable;
661
+ }
662
+
663
+ if (oldViewProps.hostPlatformEvents != newViewProps.hostPlatformEvents) {
664
+ [self _updateMouseTracking:newViewProps.hostPlatformEvents.wantsMouseTracking()];
665
+ }
666
+ }
667
+
668
+ /**
669
+ * A view only tracks the mouse while something is listening. Tracking every
670
+ * view would cost a dispatch per view per mouse move.
671
+ */
672
+ - (void)_updateMouseTracking:(BOOL)wanted
673
+ {
674
+ if (wanted == (_mouseTrackingArea != nil)) {
675
+ return;
676
+ }
677
+
678
+ if (!wanted) {
679
+ [self removeTrackingArea:_mouseTrackingArea];
680
+ _mouseTrackingArea = nil;
681
+ return;
682
+ }
683
+
684
+ _mouseTrackingArea = [[NSTrackingArea alloc]
685
+ initWithRect:NSZeroRect
686
+ options:NSTrackingMouseEnteredAndExited | NSTrackingActiveInKeyWindow | NSTrackingInVisibleRect
687
+ owner:self
688
+ userInfo:nil];
689
+ [self addTrackingArea:_mouseTrackingArea];
690
+ }
691
+
692
+ - (HostPlatformViewEventEmitter::MouseEvent)_mouseEventFromNSEvent:(NSEvent *)event
693
+ {
694
+ NSPoint inWindow = event.locationInWindow;
695
+ NSPoint inView = [self convertPoint:inWindow fromView:nil];
696
+ NSPoint onScreen = self.window != nil ? [self.window convertPointToScreen:inWindow] : inWindow;
697
+
698
+ HostPlatformViewEventEmitter::MouseEvent mouseEvent = {};
699
+ mouseEvent.clientX = inView.x;
700
+ mouseEvent.clientY = inView.y;
701
+ mouseEvent.pageX = inWindow.x;
702
+ mouseEvent.pageY = inWindow.y;
703
+ mouseEvent.screenX = onScreen.x;
704
+ mouseEvent.screenY = onScreen.y;
705
+ return mouseEvent;
706
+ }
707
+
708
+ - (void)mouseEntered:(NSEvent *)event
709
+ {
710
+ [super mouseEntered:event];
711
+ if (_eventEmitter != nullptr) {
712
+ _eventEmitter->onMouseEnter([self _mouseEventFromNSEvent:event]);
713
+ }
714
+ }
715
+
716
+ - (void)mouseExited:(NSEvent *)event
717
+ {
718
+ [super mouseExited:event];
719
+ if (_eventEmitter != nullptr) {
720
+ _eventEmitter->onMouseLeave([self _mouseEventFromNSEvent:event]);
721
+ }
722
+ }
723
+
724
+ - (void)mouseUp:(NSEvent *)event
725
+ {
726
+ [super mouseUp:event];
727
+ const auto &viewProps = static_cast<const ViewProps &>(*_props);
728
+ if (_eventEmitter != nullptr && event.clickCount == 2 &&
729
+ viewProps.hostPlatformEvents[HostPlatformViewEvents::Offset::DoubleClick]) {
730
+ _eventEmitter->onDoubleClick([self _mouseEventFromNSEvent:event]);
731
+ }
732
+ }
733
+
734
+ - (void)rightMouseUp:(NSEvent *)event
735
+ {
736
+ [super rightMouseUp:event];
737
+ const auto &viewProps = static_cast<const ViewProps &>(*_props);
738
+ if (_eventEmitter != nullptr && viewProps.hostPlatformEvents[HostPlatformViewEvents::Offset::AuxClick]) {
739
+ _eventEmitter->onAuxClick([self _mouseEventFromNSEvent:event]);
740
+ }
741
+ }
742
+
743
+ - (BOOL)allowsVibrancy
744
+ {
745
+ return _allowsVibrancy;
746
+ }
747
+
748
+ - (BOOL)mouseDownCanMoveWindow
749
+ {
750
+ return _mouseDownCanMoveWindow;
751
+ }
752
+
753
+ - (BOOL)canBecomeKeyView
754
+ {
755
+ return _focusable;
756
+ }
757
+
758
+ - (BOOL)acceptsFirstResponder
759
+ {
760
+ return _focusable || [super acceptsFirstResponder];
761
+ }
762
+ #endif // macOS]
763
+
614
764
  - (void)updateEventEmitter:(const EventEmitter::Shared &)eventEmitter
615
765
  {
616
766
  assert(std::dynamic_pointer_cast<const ViewEventEmitter>(eventEmitter));
@@ -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,39 @@
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
+ return payload;
24
+ }
25
+
26
+ #define RCT_MACOS_MOUSE_EVENT(name) \
27
+ void HostPlatformViewEventEmitter::name(const MouseEvent &event) const \
28
+ { \
29
+ dispatchEvent(#name, [event](jsi::Runtime &runtime) { \
30
+ return mouseEventPayload(runtime, event); \
31
+ }); \
32
+ }
33
+
34
+ RCT_MACOS_MOUSE_EVENT(onMouseEnter)
35
+ RCT_MACOS_MOUSE_EVENT(onMouseLeave)
36
+ RCT_MACOS_MOUSE_EVENT(onDoubleClick)
37
+ RCT_MACOS_MOUSE_EVENT(onAuxClick)
38
+
39
+ } // namespace facebook::react
@@ -0,0 +1,39 @@
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 events AppKit can report and UIKit cannot.
9
+
10
+ #pragma once
11
+
12
+ #include <react/renderer/components/view/BaseViewEventEmitter.h>
13
+
14
+ namespace facebook::react {
15
+
16
+ class HostPlatformViewEventEmitter : public BaseViewEventEmitter {
17
+ public:
18
+ using BaseViewEventEmitter::BaseViewEventEmitter;
19
+
20
+ /**
21
+ * A mouse crossing into or out of the view. There is no touch equivalent, so
22
+ * these have no counterpart in BaseViewEventEmitter.
23
+ */
24
+ struct MouseEvent {
25
+ Float clientX{};
26
+ Float clientY{};
27
+ Float screenX{};
28
+ Float screenY{};
29
+ Float pageX{};
30
+ Float pageY{};
31
+ };
32
+
33
+ void onMouseEnter(const MouseEvent &event) const;
34
+ void onMouseLeave(const MouseEvent &event) const;
35
+ void onDoubleClick(const MouseEvent &event) const;
36
+ void onAuxClick(const MouseEvent &event) const;
37
+ };
38
+
39
+ } // namespace facebook::react
@@ -0,0 +1,59 @@
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
+ };
31
+
32
+ constexpr bool operator[](Offset offset) const
33
+ {
34
+ return bits[static_cast<std::size_t>(offset)];
35
+ }
36
+
37
+ std::bitset<8>::reference operator[](Offset offset)
38
+ {
39
+ return bits[static_cast<std::size_t>(offset)];
40
+ }
41
+
42
+ /** True when any macOS mouse handler is present. */
43
+ bool wantsMouseTracking() const
44
+ {
45
+ return (*this)[Offset::MouseEnter] || (*this)[Offset::MouseLeave];
46
+ }
47
+ };
48
+
49
+ inline bool operator==(const HostPlatformViewEvents &lhs, const HostPlatformViewEvents &rhs)
50
+ {
51
+ return lhs.bits == rhs.bits;
52
+ }
53
+
54
+ inline bool operator!=(const HostPlatformViewEvents &lhs, const HostPlatformViewEvents &rhs)
55
+ {
56
+ return lhs.bits != rhs.bits;
57
+ }
58
+
59
+ } // namespace facebook::react
@@ -0,0 +1,113 @@
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
+
37
+ #undef RCT_MACOS_CONVERT_EVENT
38
+
39
+ return result;
40
+ }
41
+
42
+ // Two parsing paths exist and both have to be fed. With the iterator setter
43
+ // feature flag on, props arrive one at a time through setProp and the
44
+ // constructor just carries the previous value forward; with it off, the
45
+ // constructor parses the whole RawProps map itself.
46
+ #define RCT_MACOS_PROP(name) \
47
+ name(ReactNativeFeatureFlags::enableCppPropsIteratorSetter() \
48
+ ? sourceProps.name \
49
+ : convertRawProp(context, rawProps, #name, sourceProps.name, {}))
50
+
51
+ HostPlatformViewProps::HostPlatformViewProps(
52
+ const PropsParserContext &context,
53
+ const HostPlatformViewProps &sourceProps,
54
+ const RawProps &rawProps)
55
+ : BaseViewProps(context, sourceProps, rawProps),
56
+ hostPlatformEvents(
57
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
58
+ ? sourceProps.hostPlatformEvents
59
+ : convertRawProp(context, rawProps, sourceProps.hostPlatformEvents, {})),
60
+ RCT_MACOS_PROP(focusable),
61
+ RCT_MACOS_PROP(enableFocusRing),
62
+ RCT_MACOS_PROP(tooltip),
63
+ RCT_MACOS_PROP(acceptsFirstMouse),
64
+ RCT_MACOS_PROP(allowsVibrancy),
65
+ RCT_MACOS_PROP(mouseDownCanMoveWindow)
66
+ {
67
+ }
68
+
69
+ #undef RCT_MACOS_PROP
70
+
71
+ void HostPlatformViewProps::setProp(
72
+ const PropsParserContext &context,
73
+ RawPropsPropNameHash hash,
74
+ const char *propName,
75
+ const RawValue &value)
76
+ {
77
+ // Every Props struct must call super unconditionally: several structs can
78
+ // share the same raw value, and skipping the call drops it for all of them.
79
+ BaseViewProps::setProp(context, hash, propName, value);
80
+
81
+ static auto defaults = HostPlatformViewProps{};
82
+
83
+ // An `onX` prop is stored as a bit rather than a value: all the view needs to
84
+ // know is whether anything is listening.
85
+ #define RCT_MACOS_EVENT_CASE(eventType) \
86
+ case CONSTEXPR_RAW_PROPS_KEY_HASH("on" #eventType): { \
87
+ const auto offset = HostPlatformViewEvents::Offset::eventType; \
88
+ HostPlatformViewEvents defaultEvents{}; \
89
+ bool listening = defaultEvents[offset]; \
90
+ if (value.hasValue()) { \
91
+ fromRawValue(context, value, listening); \
92
+ } \
93
+ hostPlatformEvents[offset] = listening; \
94
+ return; \
95
+ }
96
+
97
+ switch (hash) {
98
+ RCT_MACOS_EVENT_CASE(MouseEnter);
99
+ RCT_MACOS_EVENT_CASE(MouseLeave);
100
+ RCT_MACOS_EVENT_CASE(DoubleClick);
101
+ RCT_MACOS_EVENT_CASE(AuxClick);
102
+ RAW_SET_PROP_SWITCH_CASE_BASIC(focusable);
103
+ RAW_SET_PROP_SWITCH_CASE_BASIC(enableFocusRing);
104
+ RAW_SET_PROP_SWITCH_CASE_BASIC(tooltip);
105
+ RAW_SET_PROP_SWITCH_CASE_BASIC(acceptsFirstMouse);
106
+ RAW_SET_PROP_SWITCH_CASE_BASIC(allowsVibrancy);
107
+ RAW_SET_PROP_SWITCH_CASE_BASIC(mouseDownCanMoveWindow);
108
+ }
109
+
110
+ #undef RCT_MACOS_EVENT_CASE
111
+ }
112
+
113
+ } // namespace facebook::react
@@ -0,0 +1,66 @@
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] The props a Mac view has and an iOS one does not.
9
+ //
10
+ // React Native reaches platform-specific view props through this class -- see
11
+ // the sibling directories under components/view/platform. Adding them here
12
+ // means no shared C++ changes at all, and the names match
13
+ // microsoft/react-native-macos so code written against that fork type-checks
14
+ // and behaves the same.
15
+
16
+ #pragma once
17
+
18
+ #include <react/renderer/components/view/BaseViewProps.h>
19
+ #include <react/renderer/core/PropsParserContext.h>
20
+
21
+ #include <optional>
22
+ #include <string>
23
+
24
+ #include "HostPlatformViewEvents.h"
25
+
26
+ namespace facebook::react {
27
+
28
+ class HostPlatformViewProps : public BaseViewProps {
29
+ public:
30
+ HostPlatformViewProps() = default;
31
+ HostPlatformViewProps(
32
+ const PropsParserContext &context,
33
+ const HostPlatformViewProps &sourceProps,
34
+ const RawProps &rawProps);
35
+
36
+ void
37
+ setProp(const PropsParserContext &context, RawPropsPropNameHash hash, const char *propName, const RawValue &value);
38
+
39
+ /** Which macOS-only handlers are attached; see HostPlatformViewEvents. */
40
+ HostPlatformViewEvents hostPlatformEvents{};
41
+
42
+ #pragma mark - Props
43
+
44
+ /** Participates in the key view loop, i.e. reachable by Tab. */
45
+ bool focusable{false};
46
+
47
+ /** Draws the focus ring while first responder. On by default, as in AppKit. */
48
+ bool enableFocusRing{true};
49
+
50
+ /** The view's help tag. std::nullopt leaves any inherited tooltip alone. */
51
+ std::optional<std::string> tooltip{};
52
+
53
+ /** Take the click that activates a background window, rather than swallowing it. */
54
+ bool acceptsFirstMouse{false};
55
+
56
+ /** Let the view sit in an NSVisualEffectView and blend with what is behind it. */
57
+ bool allowsVibrancy{false};
58
+
59
+ /**
60
+ * Whether dragging the view moves the window. AppKit's default is true, and
61
+ * that is kept here: a view that opts out is the interesting case.
62
+ */
63
+ bool mouseDownCanMoveWindow{true};
64
+ };
65
+
66
+ } // namespace facebook::react
@@ -0,0 +1,37 @@
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] Keyboard focus is a real thing on macOS, so unlike the shared C++
9
+ // initializer this reports `focusable` views as keyboard-focusable.
10
+
11
+ #pragma once
12
+
13
+ #include <react/renderer/components/view/ViewProps.h>
14
+ #include <react/renderer/core/ShadowNodeTraits.h>
15
+
16
+ namespace facebook::react::HostPlatformViewTraitsInitializer {
17
+
18
+ inline bool formsStackingContext(const ViewProps & /*props*/)
19
+ {
20
+ return false;
21
+ }
22
+
23
+ inline bool formsView(const ViewProps &props)
24
+ {
25
+ // These all need a backing NSView, so a view carrying any of them must not be
26
+ // flattened away: a focusable view has to join the key view loop, a tooltip
27
+ // has to attach to something, and mouse tracking needs an NSTrackingArea
28
+ // owner. Flattening is otherwise invisible -- the handler simply never fires.
29
+ return props.focusable || props.tooltip.has_value() || props.hostPlatformEvents.bits.any();
30
+ }
31
+
32
+ inline bool isKeyboardFocusable(const ViewProps &props)
33
+ {
34
+ return props.focusable;
35
+ }
36
+
37
+ } // namespace facebook::react::HostPlatformViewTraitsInitializer
@@ -30,6 +30,12 @@ struct Color {
30
30
 
31
31
  static Color createSemanticColor(std::vector<std::string> &semanticItems);
32
32
 
33
+ #if TARGET_OS_OSX // [macOS] Wrap an already-resolved NSColor. AppKit derives some
34
+ // colours from others -- colorWithSystemEffect: -- so the parser needs a way
35
+ // to hand back a colour it built itself. macOS]
36
+ static Color createFromHostPlatformColor(std::shared_ptr<void> hostPlatformColor);
37
+ #endif
38
+
33
39
  std::shared_ptr<void> getUIColor() const
34
40
  {
35
41
  return uiColor_;
@@ -95,6 +95,13 @@ int32_t ColorFromColorComponents(const facebook::react::ColorComponents &compone
95
95
  int32_t ColorFromUIColor(UIColor *color)
96
96
  {
97
97
  CGFloat rgba[4];
98
+ #if TARGET_OS_OSX // [macOS] catalog colours need converting first; see Color::getChannel
99
+ NSColor *rgbColor = [color colorUsingColorSpace:NSColorSpace.sRGBColorSpace];
100
+ if (rgbColor == nil) {
101
+ return 0;
102
+ }
103
+ color = rgbColor;
104
+ #endif // macOS]
98
105
  [color getRed:&rgba[0] green:&rgba[1] blue:&rgba[2] alpha:&rgba[3]];
99
106
  return ColorFromColorComponents(
100
107
  {.red = (float)rgba[0], .green = (float)rgba[1], .blue = (float)rgba[2], .alpha = (float)rgba[3]});
@@ -226,6 +233,23 @@ float Color::getChannel(int channelId) const
226
233
  {
227
234
  CGFloat rgba[4];
228
235
  UIColor *color = (__bridge UIColor *)getUIColor().get();
236
+ #if TARGET_OS_OSX // [macOS
237
+ // AppKit's named colours -- everything PlatformColor() resolves to, plus the
238
+ // system palette -- live in the Catalog colour space, and asking one for its
239
+ // RGBA components without converting first raises:
240
+ //
241
+ // -getRed:green:blue:alpha: not valid for the NSColor Catalog color
242
+ //
243
+ // sRGB is the right target: it is what the components are interpreted as
244
+ // everywhere else in the renderer.
245
+ NSColor *rgbColor = [color colorUsingColorSpace:NSColorSpace.sRGBColorSpace];
246
+ if (rgbColor == nil) {
247
+ // A pattern or otherwise unconvertible colour. Treat it as transparent
248
+ // rather than raising, which would take the whole app down.
249
+ return 0;
250
+ }
251
+ color = rgbColor;
252
+ #endif // macOS]
229
253
  [color getRed:&rgba[0] green:&rgba[1] blue:&rgba[2] alpha:&rgba[3]];
230
254
  return static_cast<float>(rgba[channelId]);
231
255
  }
@@ -235,6 +259,13 @@ std::size_t Color::getUIColorHash() const
235
259
  return uiColorHashValue_;
236
260
  }
237
261
 
262
+ #if TARGET_OS_OSX // [macOS
263
+ Color Color::createFromHostPlatformColor(std::shared_ptr<void> hostPlatformColor)
264
+ {
265
+ return Color(std::move(hostPlatformColor));
266
+ }
267
+ #endif // macOS]
268
+
238
269
  Color Color::createSemanticColor(std::vector<std::string> &semanticItems)
239
270
  {
240
271
  auto semanticColor = RCTPlatformColorFromSemanticItems(semanticItems);
@@ -63,6 +63,40 @@ SharedColor parsePlatformColor(const ContextContainer &contextContainer, int32_t
63
63
  items.at("dynamic").hasType<std::unordered_map<std::string, RawValue>>()) {
64
64
  auto dynamicItems = (std::unordered_map<std::string, RawValue>)items.at("dynamic");
65
65
  return RCTPlatformColorComponentsFromDynamicItems(contextContainer, surfaceId, dynamicItems);
66
+ #if TARGET_OS_OSX // [macOS
67
+ } else if (
68
+ items.find("colorWithSystemEffect") != items.end() &&
69
+ items.at("colorWithSystemEffect").hasType<std::unordered_map<std::string, RawValue>>()) {
70
+ // AppKit derives the pressed / disabled / rollover variant of a colour
71
+ // rather than making the caller supply it. UIKit has no equivalent, so
72
+ // this arm only exists here.
73
+ auto effectItems = (std::unordered_map<std::string, RawValue>)items.at("colorWithSystemEffect");
74
+ if (effectItems.count("baseColor") == 0u || effectItems.count("systemEffect") == 0u) {
75
+ return clearColor();
76
+ }
77
+
78
+ SharedColor baseSharedColor;
79
+ fromRawValue(contextContainer, surfaceId, effectItems.at("baseColor"), baseSharedColor);
80
+ auto effectName = (std::string)effectItems.at("systemEffect");
81
+
82
+ static const std::unordered_map<std::string, NSColorSystemEffect> effects = {
83
+ {"none", NSColorSystemEffectNone},
84
+ {"pressed", NSColorSystemEffectPressed},
85
+ {"deepPressed", NSColorSystemEffectDeepPressed},
86
+ {"disabled", NSColorSystemEffectDisabled},
87
+ {"rollover", NSColorSystemEffectRollover}};
88
+
89
+ auto effect = effects.find(effectName);
90
+ if (effect == effects.end()) {
91
+ return clearColor();
92
+ }
93
+
94
+ NSColor *baseColor = RCTPlatformColorFromColor(*baseSharedColor);
95
+ if (baseColor == nil) {
96
+ return clearColor();
97
+ }
98
+ return SharedColor(Color::createFromHostPlatformColor(wrapManagedObject([baseColor colorWithSystemEffect:effect->second])));
99
+ #endif // macOS]
66
100
  }
67
101
  }
68
102