From 19fab5952c51dbcb993eeaadf0c1a9b4add250f0 Mon Sep 17 00:00:00 2001 From: Shawn Dempsey Date: Fri, 20 Jan 2023 17:17:33 -0800 Subject: [PATCH 01/27] [Fabric] Shim RCTSwitchComponentView --- .../ComponentViews/Switch/RCTSwitchComponentView.mm | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm b/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm index 59eaeb218c77ff..77220e6d7a452f 100644 --- a/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm @@ -34,9 +34,16 @@ - (instancetype)initWithFrame:(CGRect)frame _switchView = [[RCTUISwitch alloc] initWithFrame:self.bounds]; // [macOS] +#if !TARGET_OS_OSX // [macOS] [_switchView addTarget:self action:@selector(onChange:) forControlEvents:UIControlEventValueChanged]; +#endif +#if !TARGET_OS_OSX // [macOS] self.contentView = _switchView; +#else // [macOS + self.contentView = [[RCTUIView alloc] initWithFrame:frame]; + [self.contentView addSubview:_switchView]; +#endif // macOS] } return self; @@ -72,6 +79,7 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & _switchView.enabled = !newSwitchProps.disabled; } +#if !TARGET_OS_OSX // [macOS] // `tintColor` if (oldSwitchProps.tintColor != newSwitchProps.tintColor) { _switchView.tintColor = RCTUIColorFromSharedColor(newSwitchProps.tintColor); @@ -86,6 +94,7 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & if (oldSwitchProps.thumbTintColor != newSwitchProps.thumbTintColor) { _switchView.thumbTintColor = RCTUIColorFromSharedColor(newSwitchProps.thumbTintColor); } +#endif [super updateProps:props oldProps:oldProps]; } From a41fb9d69ad6824404dd830febe6f3d0fe8e46d8 Mon Sep 17 00:00:00 2001 From: Shawn Dempsey Date: Fri, 20 Jan 2023 17:47:17 -0800 Subject: [PATCH 02/27] Add missing tags --- .../Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm b/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm index 77220e6d7a452f..dd9b3776e41e0c 100644 --- a/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm @@ -36,7 +36,7 @@ - (instancetype)initWithFrame:(CGRect)frame #if !TARGET_OS_OSX // [macOS] [_switchView addTarget:self action:@selector(onChange:) forControlEvents:UIControlEventValueChanged]; -#endif +#endif // [macOS] #if !TARGET_OS_OSX // [macOS] self.contentView = _switchView; @@ -94,7 +94,7 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & if (oldSwitchProps.thumbTintColor != newSwitchProps.thumbTintColor) { _switchView.thumbTintColor = RCTUIColorFromSharedColor(newSwitchProps.thumbTintColor); } -#endif +#endif // [macOS] [super updateProps:props oldProps:oldProps]; } From 24aeaaac752b6217784a48d913d5b909fe65ba23 Mon Sep 17 00:00:00 2001 From: Shawn Dempsey Date: Fri, 20 Jan 2023 18:22:52 -0800 Subject: [PATCH 03/27] [Fabric] Shim RCTImage --- .../ComponentViews/Image/RCTImageComponentView.mm | 11 +++++++++++ .../ComponentViews/View/RCTViewComponentView.mm | 12 +++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm b/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm index 9d7b67f07d4dea..bf8cb84372e90b 100644 --- a/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm @@ -31,14 +31,21 @@ - (instancetype)initWithFrame:(CGRect)frame _props = defaultProps; _imageView = [RCTUIImageViewAnimated new]; +#if !TARGET_OS_OSX // [macOS] _imageView.clipsToBounds = YES; _imageView.contentMode = RCTContentModeFromImageResizeMode(defaultProps->resizeMode); +#endif // [macOS] _imageView.layer.minificationFilter = kCAFilterTrilinear; _imageView.layer.magnificationFilter = kCAFilterTrilinear; _imageResponseObserverProxy = RCTImageResponseObserverProxy(self); +#if !TARGET_OS_OSX // [macOS] self.contentView = _imageView; +#else // [macOS + self.contentView = [RCTUIView new]; + [self.contentView addSubview:_imageView]; +#endif // macOS] } return self; @@ -56,6 +63,7 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & auto const &oldImageProps = *std::static_pointer_cast(_props); auto const &newImageProps = *std::static_pointer_cast(props); +#if !TARGET_OS_OSX // [macOS] // `resizeMode` if (oldImageProps.resizeMode != newImageProps.resizeMode) { _imageView.contentMode = RCTContentModeFromImageResizeMode(newImageProps.resizeMode); @@ -65,6 +73,7 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & if (oldImageProps.tintColor != newImageProps.tintColor) { _imageView.tintColor = RCTUIColorFromSharedColor(newImageProps.tintColor); } +#endif // [macOS] [super updateProps:props oldProps:oldProps]; } @@ -132,6 +141,7 @@ - (void)didReceiveImage:(UIImage *)image metadata:(id)metadata fromObserver:(voi const auto &imageProps = *std::static_pointer_cast(_props); +#if !TARGET_OS_OSX // [macOS] if (imageProps.tintColor) { image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; } @@ -144,6 +154,7 @@ - (void)didReceiveImage:(UIImage *)image metadata:(id)metadata fromObserver:(voi image = [image resizableImageWithCapInsets:RCTUIEdgeInsetsFromEdgeInsets(imageProps.capInsets) resizingMode:UIImageResizingModeStretch]; } +#endif // [macOS] if (imageProps.blurRadius > __FLT_EPSILON__) { // Blur on a background thread to avoid blocking interaction. diff --git a/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm b/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm index 8d9b4fe9637c4d..b8ac211e126b13 100644 --- a/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm @@ -6,6 +6,7 @@ */ #import "RCTViewComponentView.h" +#import // [macOS] - prevent compiler error on invocation of CAShapeLayer #import #import @@ -626,9 +627,14 @@ - (void)invalidateLayer CGRect contentsCenter = CGRect{ CGPoint{imageCapInsets.left / imageSize.width, imageCapInsets.top / imageSize.height}, CGSize{(CGFloat)1.0 / imageSize.width, (CGFloat)1.0 / imageSize.height}}; - - _borderLayer.contents = (id)image.CGImage; - _borderLayer.contentsScale = image.scale; + +#if !TARGET_OS_OSX // [macOS] + _borderLayer.contents = (id)image.CGImage; + _borderLayer.contentsScale = image.scale; +#else // [macOS + _borderLayer.contents = [image layerContentsForContentsScale:scaleFactor]; + _borderLayer.contentsScale = [[NSScreen mainScreen] backingScaleFactor]; +#endif // macOS] BOOL isResizable = !UIEdgeInsetsEqualToEdgeInsets(image.capInsets, UIEdgeInsetsZero); if (isResizable) { From 072141f207ccc93b54f01b0bfffffcf270329022 Mon Sep 17 00:00:00 2001 From: Shawn Dempsey Date: Mon, 23 Jan 2023 16:53:11 -0800 Subject: [PATCH 04/27] Shim RCTTextInput --- .../TextInput/RCTTextInputComponentView.mm | 62 +++++++++++-------- .../TextInput/RCTTextInputUtils.h | 21 ++++--- .../TextInput/RCTTextInputUtils.mm | 8 ++- 3 files changed, 57 insertions(+), 34 deletions(-) diff --git a/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm b/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm index 0fee0499389bde..c5cebbf6615d77 100644 --- a/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm @@ -30,7 +30,11 @@ @interface RCTTextInputComponentView () *_backedTextInputView; // [macOS] +#if !TARGET_OS_OSX // [macOS] + RCTUIView *_backedTextInputView; +#else // [macOS + RCTUITextView *_backedTextInputView; +#endif // macOS] NSUInteger _mostRecentEventCount; NSAttributedString *_lastStringStateWasUpdatedWith; @@ -67,7 +71,11 @@ - (instancetype)initWithFrame:(CGRect)frame _props = defaultProps; auto &props = *defaultProps; +#if !TARGET_OS_OSX // [macOS] _backedTextInputView = props.traits.multiline ? [RCTUITextView new] : [RCTUITextField new]; +#else // [macOS + _backedTextInputView = [RCTUITextView new]; +#endif // macOS] _backedTextInputView.textInputDelegate = self; _ignoreNextTextInputCall = NO; _comingFromJS = NO; @@ -478,25 +486,23 @@ - (void)setTextAndSelection:(NSInteger)eventCount - (void)setDefaultInputAccessoryView { +#if !TARGET_OS_OSX // [macOS] // InputAccessoryView component sets the inputAccessoryView when inputAccessoryViewID exists if (_backedTextInputView.inputAccessoryViewID) { if (_backedTextInputView.isFirstResponder) { -#if !TARGET_OS_OSX // [macOS] [_backedTextInputView reloadInputViews]; -#endif // [macOS] } return; } -#if !TARGET_OS_OSX // [macOS] UIKeyboardType keyboardType = _backedTextInputView.keyboardType; // These keyboard types (all are number pads) don't have a "Done" button by default, // so we create an `inputAccessoryView` with this button for them. BOOL shouldHaveInputAccesoryView = - (keyboardType == UIKeyboardTypeNumberPad || keyboardType == UIKeyboardTypePhonePad || - keyboardType == UIKeyboardTypeDecimalPad || keyboardType == UIKeyboardTypeASCIICapableNumberPad) && - _backedTextInputView.returnKeyType == UIReturnKeyDone; + (keyboardType == UIKeyboardTypeNumberPad || keyboardType == UIKeyboardTypePhonePad || + keyboardType == UIKeyboardTypeDecimalPad || keyboardType == UIKeyboardTypeASCIICapableNumberPad) && + _backedTextInputView.returnKeyType == UIReturnKeyDone; if ((_backedTextInputView.inputAccessoryView != nil) == shouldHaveInputAccesoryView) { return; @@ -506,32 +512,30 @@ - (void)setDefaultInputAccessoryView UIToolbar *toolbarView = [UIToolbar new]; [toolbarView sizeToFit]; UIBarButtonItem *flexibleSpace = - [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; + [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; UIBarButtonItem *doneButton = - [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone - target:self - action:@selector(handleInputAccessoryDoneButton)]; + [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone + target:self + action:@selector(handleInputAccessoryDoneButton)]; toolbarView.items = @[ flexibleSpace, doneButton ]; _backedTextInputView.inputAccessoryView = toolbarView; } else { _backedTextInputView.inputAccessoryView = nil; } -#endif // [macOS] - + if (_backedTextInputView.isFirstResponder) { -#if !TARGET_OS_OSX // [macOS] [_backedTextInputView reloadInputViews]; -#endif // [macOS] } +#endif // [macOS] } - (void)handleInputAccessoryDoneButton { - if ([self textInputShouldReturn]) { #if !TARGET_OS_OSX // [macOS] + if ([self textInputShouldReturn]) { [_backedTextInputView endEditing:YES]; -#endif // [macOS] } +#endif // [macOS] } #pragma mark - Other @@ -633,7 +637,11 @@ - (void)_setAttributedString:(NSAttributedString *)attributedString - (void)_setMultiline:(BOOL)multiline { [_backedTextInputView removeFromSuperview]; - RCTUIView *backedTextInputView = multiline ? [RCTUITextView new] : [RCTUITextField new]; // [macOS] +#if !TARGET_OS_OSX // [macOS] + RCTUIView *backedTextInputView = multiline ? [RCTUITextView new] : [RCTUITextField new]; +#else // [macOS + RCTUITextView *backedTextInputView = [RCTUITextView new]; +#endif // macOS] backedTextInputView.frame = _backedTextInputView.frame; RCTCopyBackedTextInput(_backedTextInputView, backedTextInputView); _backedTextInputView = backedTextInputView; @@ -663,17 +671,19 @@ - (BOOL)_textOf:(NSAttributedString *)newText equals:(NSAttributedString *)oldTe }]; BOOL shouldFallbackToBareTextComparison = - [_backedTextInputView.textInputMode.primaryLanguage isEqualToString:@"dictation"] || #if !TARGET_OS_OSX // [macOS] - [_backedTextInputView.textInputMode.primaryLanguage isEqualToString:@"ko-KR"] || - _backedTextInputView.markedTextRange || _backedTextInputView.isSecureTextEntry || fontHasBeenUpdatedBySystem; + [_backedTextInputView.textInputMode.primaryLanguage isEqualToString:@"dictation"] || + [_backedTextInputView.textInputMode.primaryLanguage isEqualToString:@"ko-KR"] || + _backedTextInputView.markedTextRange || + _backedTextInputView.isSecureTextEntry || #else // [macOS - // There are multiple Korean input sources (2-Set, 3-Set, etc). Check substring instead instead - [[[self.backedTextInputView inputContext] selectedKeyboardInputSource] containsString:@"com.apple.inputmethod.Korean"] || - [self.backedTextInputView hasMarkedText] || - [self.backedTextInputView isKindOfClass:[NSSecureTextField class]] || - fontHasBeenUpdatedBySystem; + // There are multiple Korean input sources (2-Set, 3-Set, etc). Check substring instead instead + [[[_backedTextInputView inputContext] selectedKeyboardInputSource] containsString:@"com.apple.inputmethod.Korean"] || + [_backedTextInputView hasMarkedText] || + [_backedTextInputView isKindOfClass:[NSSecureTextField class]] || #endif // macOS] + fontHasBeenUpdatedBySystem; + if (shouldFallbackToBareTextComparison) { return ([newText.string isEqualToString:oldText.string]); } else { diff --git a/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputUtils.h b/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputUtils.h index da452fcf21086b..869ae06fef07a1 100644 --- a/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputUtils.h +++ b/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputUtils.h @@ -4,10 +4,11 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ +#import #import // [macOS] - -#import +#import // [macOS] +#import // [macOS] #import #import @@ -15,10 +16,16 @@ NS_ASSUME_NONNULL_BEGIN void RCTCopyBackedTextInput( - RCTUIView *fromTextInput, // [macOS] - RCTUIView *toTextInput); // [macOS] - -#if !TARGET_OS_OSX // [macOS] +#if !TARGET_OS_OSX // [macOS] + RCTUIView *fromTextInput, + RCTUIView *toTextInput +#else // [macOS + RCTUITextView *fromTextInput, + RCTUITextView *toTextInput +#endif // macOS] +); + +#if !TARGET_OS_OSX // [macOS] UITextAutocorrectionType RCTUITextAutocorrectionTypeFromOptionalBool(std::optional autoCorrect); UITextAutocapitalizationType RCTUITextAutocapitalizationTypeFromAutocapitalizationType( @@ -41,6 +48,6 @@ UITextContentType RCTUITextContentTypeFromString(std::string const &contentType) API_AVAILABLE(ios(12.0)) UITextInputPasswordRules *RCTUITextInputPasswordRulesFromString(std::string const &passwordRules); -#endif // [macOS] +#endif // [macOS] NS_ASSUME_NONNULL_END diff --git a/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputUtils.mm b/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputUtils.mm index 2a3936934a5403..e7258109b5a556 100644 --- a/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputUtils.mm +++ b/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputUtils.mm @@ -19,8 +19,14 @@ } void RCTCopyBackedTextInput( +#if !TARGET_OS_OSX // [macOS] RCTUIView *fromTextInput, - RCTUIView *toTextInput) // [macOS] + RCTUIView *toTextInput +#else // [macOS + RCTUITextView *fromTextInput, + RCTUITextView *toTextInput +#endif // macOS] +) { toTextInput.attributedText = RCTSanitizeAttributedString(fromTextInput.attributedText); toTextInput.placeholder = fromTextInput.placeholder; From 5ffd7622f408849a05a06cb918ca15a593304f6a Mon Sep 17 00:00:00 2001 From: Shawn Dempsey Date: Mon, 23 Jan 2023 17:48:25 -0800 Subject: [PATCH 05/27] Shim RCTSurfaceTouchHandler --- React/Base/RCTUIKit.h | 4 +- React/Fabric/RCTSurfaceTouchHandler.mm | 61 ++++++++++++++++++-------- 2 files changed, 45 insertions(+), 20 deletions(-) diff --git a/React/Base/RCTUIKit.h b/React/Base/RCTUIKit.h index 0514b236114210..cba5a4441752d4 100644 --- a/React/Base/RCTUIKit.h +++ b/React/Base/RCTUIKit.h @@ -61,7 +61,7 @@ UIKIT_STATIC_INLINE CGPathRef UIBezierPathCreateCGPathRef(UIBezierPath *path) // // UIView -#define RCTPlatformView UIView +#define RCTPlatformView UIView #define RCTUIView UIView #define RCTUIScrollView UIScrollView @@ -484,6 +484,8 @@ NS_ASSUME_NONNULL_END // fabric component types // +#define RCTUITouch UITouch // [macOS] + // RCTUISlider #if !TARGET_OS_OSX diff --git a/React/Fabric/RCTSurfaceTouchHandler.mm b/React/Fabric/RCTSurfaceTouchHandler.mm index b6c033f6cc0a34..c125aa4f0bfc59 100644 --- a/React/Fabric/RCTSurfaceTouchHandler.mm +++ b/React/Fabric/RCTSurfaceTouchHandler.mm @@ -7,6 +7,7 @@ #import "RCTSurfaceTouchHandler.h" +#import // [macOS] #import #import @@ -79,10 +80,11 @@ bool operator()(const ActiveTouch &lhs, const ActiveTouch &rhs) const static void UpdateActiveTouchWithUITouch( ActiveTouch &activeTouch, - UITouch *uiTouch, + RCTUITouch *uiTouch, // [macOS] RCTUIView *rootComponentView, CGPoint rootViewOriginOffset) // [macOS] { +#if !TARGET_OS_OSX // [macOS] CGPoint offsetPoint = [uiTouch locationInView:activeTouch.componentView]; CGPoint screenPoint = [uiTouch locationInView:uiTouch.window]; CGPoint pagePoint = [uiTouch locationInView:rootComponentView]; @@ -97,12 +99,14 @@ static void UpdateActiveTouchWithUITouch( if (RCTForceTouchAvailable()) { activeTouch.touch.force = RCTZeroIfNaN(uiTouch.force / uiTouch.maximumPossibleForce); } +#endif // [macOS] } static ActiveTouch CreateTouchWithUITouch(UITouch *uiTouch, RCTUIView *rootComponentView, CGPoint rootViewOriginOffset) // [macOS] { ActiveTouch activeTouch = {}; +#if !TARGET_OS_OSX // [macOS] // Find closest Fabric-managed touchable view RCTUIView *componentView = uiTouch.view; // [macOS] while (componentView) { @@ -117,25 +121,30 @@ static ActiveTouch CreateTouchWithUITouch(UITouch *uiTouch, RCTUIView *rootCompo } UpdateActiveTouchWithUITouch(activeTouch, uiTouch, rootComponentView, rootViewOriginOffset); +#endif // [macOS] return activeTouch; } -static BOOL AllTouchesAreCancelledOrEnded(NSSet *touches) +static BOOL AllTouchesAreCancelledOrEnded(NSSet *touches) // [macOS] { - for (UITouch *touch in touches) { + for (RCTUITouch *touch in touches) { // [macOS] +#if !TARGET_OS_OSX // [macOS] if (touch.phase == UITouchPhaseBegan || touch.phase == UITouchPhaseMoved || touch.phase == UITouchPhaseStationary) { return NO; } +#endif // [macOS] } return YES; } -static BOOL AnyTouchesChanged(NSSet *touches) +static BOOL AnyTouchesChanged(NSSet *touches) // [macOS] { - for (UITouch *touch in touches) { + for (RCTUITouch *touch in touches) { // [macOS] +#if !TARGET_OS_OSX // [macOS] if (touch.phase == UITouchPhaseBegan || touch.phase == UITouchPhaseMoved) { return YES; } +#endif // [macOS] } return NO; } @@ -158,8 +167,8 @@ @interface RCTSurfaceTouchHandler () @end @implementation RCTSurfaceTouchHandler { - std::unordered_map<__unsafe_unretained UITouch *, ActiveTouch, PointerHasher<__unsafe_unretained UITouch *>> - _activeTouches; + std::unordered_map<__unsafe_unretained RCTUITouch *, ActiveTouch, PointerHasher<__unsafe_unretained RCTUITouch *>> + _activeTouches; // [macOS] /* * We hold the view weakly to prevent a retain cycle. @@ -175,9 +184,11 @@ - (instancetype)init // to be used as a top level event delegated recognizer. // Otherwise, lower-level components not built using React Native, // will fail to recognize gestures. +#if !TARGET_OS_OSX // [macOS] self.cancelsTouchesInView = NO; self.delaysTouchesBegan = NO; // This is default value. self.delaysTouchesEnded = NO; +#endif // [macOS] self.delegate = self; } @@ -204,18 +215,18 @@ - (void)detachFromView:(RCTUIView *)view // [macOS] _rootComponentView = nil; } -- (void)_registerTouches:(NSSet *)touches +- (void)_registerTouches:(NSSet *)touches // [macOS] { - for (UITouch *touch in touches) { + for (RCTUITouch *touch in touches) { // [macOS] auto activeTouch = CreateTouchWithUITouch(touch, _rootComponentView, _viewOriginOffset); activeTouch.touch.identifier = _identifierPool.dequeue(); _activeTouches.emplace(touch, activeTouch); } } -- (void)_updateTouches:(NSSet *)touches +- (void)_updateTouches:(NSSet *)touches // [macOS] { - for (UITouch *touch in touches) { + for (RCTUITouch *touch in touches) { // [macOS] auto iterator = _activeTouches.find(touch); assert(iterator != _activeTouches.end() && "Inconsistency between local and UIKit touch registries"); if (iterator == _activeTouches.end()) { @@ -226,9 +237,9 @@ - (void)_updateTouches:(NSSet *)touches } } -- (void)_unregisterTouches:(NSSet *)touches +- (void)_unregisterTouches:(NSSet *)touches // [macOS] { - for (UITouch *touch in touches) { + for (RCTUITouch *touch in touches) { // [macOS] auto iterator = _activeTouches.find(touch); assert(iterator != _activeTouches.end() && "Inconsistency between local and UIKit touch registries"); if (iterator == _activeTouches.end()) { @@ -240,12 +251,12 @@ - (void)_unregisterTouches:(NSSet *)touches } } -- (std::vector)_activeTouchesFromTouches:(NSSet *)touches +- (std::vector)_activeTouchesFromTouches:(NSSet *)touches // [macOS] { std::vector activeTouches; activeTouches.reserve(touches.count); - for (UITouch *touch in touches) { + for (RCTUITouch *touch in touches) { // [macOS] auto iterator = _activeTouches.find(touch); assert(iterator != _activeTouches.end() && "Inconsistency between local and UIKit touch registries"); if (iterator == _activeTouches.end()) { @@ -314,8 +325,9 @@ - (void)_dispatchActiveTouches:(std::vector)activeTouches eventType #pragma mark - `UIResponder`-ish touch-delivery methods -- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event // [macOS] { +#if !TARGET_OS_OSX // [macOS] [super touchesBegan:touches withEvent:event]; [self _registerTouches:touches]; @@ -326,20 +338,24 @@ - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event } else if (self.state == UIGestureRecognizerStateBegan) { self.state = UIGestureRecognizerStateChanged; } +#endif // [macOS] } -- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event // [macOS] { +#if !TARGET_OS_OSX // [macOS] [super touchesMoved:touches withEvent:event]; [self _updateTouches:touches]; [self _dispatchActiveTouches:[self _activeTouchesFromTouches:touches] eventType:RCTTouchEventTypeTouchMove]; self.state = UIGestureRecognizerStateChanged; +#endif // [macOS] } -- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event // [macOS] { +#if !TARGET_OS_OSX // [macOS] [super touchesEnded:touches withEvent:event]; [self _updateTouches:touches]; @@ -351,10 +367,12 @@ - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event } else if (AnyTouchesChanged(event.allTouches)) { self.state = UIGestureRecognizerStateChanged; } +#endif // [macOS] } -- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event +- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event // [macOS] { +#if !TARGET_OS_OSX // [macOS] [super touchesCancelled:touches withEvent:event]; [self _updateTouches:touches]; @@ -366,6 +384,7 @@ - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event } else if (AnyTouchesChanged(event.allTouches)) { self.state = UIGestureRecognizerStateChanged; } +#endif // [macOS] } - (void)reset @@ -395,9 +414,13 @@ - (BOOL)canPreventGestureRecognizer:(__unused UIGestureRecognizer *)preventedGes - (BOOL)canBePreventedByGestureRecognizer:(UIGestureRecognizer *)preventingGestureRecognizer { +#if !TARGET_OS_OSX // [macOS] // We fail in favour of other external gesture recognizers. // iOS will ask `delegate`'s opinion about this gesture recognizer little bit later. return ![preventingGestureRecognizer.view isDescendantOfView:self.view]; +#else // [macOS + return NO; +#endif // macOS] } #pragma mark - UIGestureRecognizerDelegate From 5ce9035577827accbe245c2a3dbe3db3d5489dcf Mon Sep 17 00:00:00 2001 From: Shawn Dempsey Date: Mon, 23 Jan 2023 18:01:30 -0800 Subject: [PATCH 06/27] Shim NSTouch in RCTUIKit --- React/Base/RCTUIKit.h | 4 +++- React/Fabric/RCTSurfaceTouchHandler.mm | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/React/Base/RCTUIKit.h b/React/Base/RCTUIKit.h index cba5a4441752d4..7f6af770bb0e0f 100644 --- a/React/Base/RCTUIKit.h +++ b/React/Base/RCTUIKit.h @@ -484,7 +484,9 @@ NS_ASSUME_NONNULL_END // fabric component types // -#define RCTUITouch UITouch // [macOS] +// RCTUITouch + +#define RCTUITouch NSTouch // [macOS] // RCTUISlider diff --git a/React/Fabric/RCTSurfaceTouchHandler.mm b/React/Fabric/RCTSurfaceTouchHandler.mm index c125aa4f0bfc59..01ec9be572122e 100644 --- a/React/Fabric/RCTSurfaceTouchHandler.mm +++ b/React/Fabric/RCTSurfaceTouchHandler.mm @@ -102,7 +102,7 @@ static void UpdateActiveTouchWithUITouch( #endif // [macOS] } -static ActiveTouch CreateTouchWithUITouch(UITouch *uiTouch, RCTUIView *rootComponentView, CGPoint rootViewOriginOffset) // [macOS] +static ActiveTouch CreateTouchWithUITouch(RCTUITouch *uiTouch, RCTUIView *rootComponentView, CGPoint rootViewOriginOffset) // [macOS] { ActiveTouch activeTouch = {}; From f83ff505d3a620f05919c3a0a21719bd7fc44113 Mon Sep 17 00:00:00 2001 From: Shawn Dempsey Date: Mon, 23 Jan 2023 21:05:24 -0800 Subject: [PATCH 07/27] Shim RCTComponentViewDescriptor --- React/Fabric/Mounting/RCTComponentViewDescriptor.h | 2 +- React/Fabric/Mounting/RCTComponentViewRegistry.mm | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/React/Fabric/Mounting/RCTComponentViewDescriptor.h b/React/Fabric/Mounting/RCTComponentViewDescriptor.h index b59fb32748d283..a287b11e68ff3a 100644 --- a/React/Fabric/Mounting/RCTComponentViewDescriptor.h +++ b/React/Fabric/Mounting/RCTComponentViewDescriptor.h @@ -22,7 +22,7 @@ class RCTComponentViewDescriptor final { * Associated (and owned) native view instance. */ __strong RCTUIView *view = nil; // [macOS] - + NSInteger tag = 0; // default is 0 // [macOS] /* * Indicates a requirement to call on the view methods from * `RCTMountingTransactionObserving` protocol. diff --git a/React/Fabric/Mounting/RCTComponentViewRegistry.mm b/React/Fabric/Mounting/RCTComponentViewRegistry.mm index e08a3c199dcb69..d21aebc749503c 100644 --- a/React/Fabric/Mounting/RCTComponentViewRegistry.mm +++ b/React/Fabric/Mounting/RCTComponentViewRegistry.mm @@ -83,7 +83,11 @@ - (void)preallocateViewComponents @"RCTComponentViewRegistry: Attempt to dequeue already registered component."); auto componentViewDescriptor = [self _dequeueComponentViewWithComponentHandle:componentHandle]; +#if !TARGET_OS_OSX // [macOS] componentViewDescriptor.view.tag = tag; +#else // [macOS + componentViewDescriptor.tag = tag; +#endif // macOS] auto it = _registry.insert({tag, componentViewDescriptor}); return it.first->second; } @@ -98,7 +102,11 @@ - (void)enqueueComponentViewWithComponentHandle:(ComponentHandle)componentHandle _registry.find(tag) != _registry.end(), @"RCTComponentViewRegistry: Attempt to enqueue unregistered component."); _registry.erase(tag); +#if !TARGET_OS_OSX // [macOS] componentViewDescriptor.view.tag = 0; +#else // [macOS + componentViewDescriptor.tag = 0; +#endif // macOS] [self _enqueueComponentViewWithComponentHandle:componentHandle componentViewDescriptor:componentViewDescriptor]; } From 729d54a86902b9bce5ff3967c68eec2d258b2724 Mon Sep 17 00:00:00 2001 From: Shawn Dempsey Date: Mon, 23 Jan 2023 21:55:40 -0800 Subject: [PATCH 08/27] Fix RCTLegacyViewManagerInteropComponentView --- .../RCTLegacyViewManagerInteropComponentView.mm | 6 +++--- React/Fabric/Mounting/RCTComponentViewRegistry.mm | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropComponentView.mm b/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropComponentView.mm index 26fdcf49318622..ea90c5c1f9d84c 100644 --- a/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropComponentView.mm @@ -43,7 +43,7 @@ - (instancetype)initWithFrame:(CGRect)frame - (RCTUIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event // [macOS] { - RCTUIView *result = [super hitTest:point withEvent:event]; // [macOS] + RCTUIView *result = (RCTUIView *)[super hitTest:point withEvent:event]; // [macOS] if (result == _adapter.paperView) { return self; @@ -197,9 +197,9 @@ - (void)finalizeUpdates:(RNComponentViewUpdateMask)updateMask for (NSDictionary *mountInstruction in _viewsToBeMounted) { NSNumber *index = mountInstruction[kRCTLegacyInteropChildIndexKey]; - UIView *childView = mountInstruction[kRCTLegacyInteropChildComponentKey]; + RCTUIView *childView = mountInstruction[kRCTLegacyInteropChildComponentKey]; // [macOS] if ([childView isKindOfClass:[RCTLegacyViewManagerInteropComponentView class]]) { - UIView *target = ((RCTLegacyViewManagerInteropComponentView *)childView).contentView; + RCTUIView *target = ((RCTLegacyViewManagerInteropComponentView *)childView).contentView; // [macOS] [_adapter.paperView insertReactSubview:target atIndex:index.integerValue]; } else { [_adapter.paperView insertReactSubview:childView atIndex:index.integerValue]; diff --git a/React/Fabric/Mounting/RCTComponentViewRegistry.mm b/React/Fabric/Mounting/RCTComponentViewRegistry.mm index e08a3c199dcb69..23d305641f17f8 100644 --- a/React/Fabric/Mounting/RCTComponentViewRegistry.mm +++ b/React/Fabric/Mounting/RCTComponentViewRegistry.mm @@ -40,7 +40,9 @@ - (instancetype)init dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // Calling this a bit later, when the main thread is probably idle while JavaScript thread is busy. +#if !TARGET_OS_OSX // [macOS] [self preallocateViewComponents]; +#endif // [macOS] }); } From 958a0583a43511b709bfb630e4f890909f7a7e90 Mon Sep 17 00:00:00 2001 From: Shawn Dempsey Date: Mon, 23 Jan 2023 22:37:33 -0800 Subject: [PATCH 09/27] Fix Fabric crash setting frame --- React/Fabric/Mounting/UIView+ComponentViewProtocol.mm | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/React/Fabric/Mounting/UIView+ComponentViewProtocol.mm b/React/Fabric/Mounting/UIView+ComponentViewProtocol.mm index 9d7b3717683e70..936779e8eddb13 100644 --- a/React/Fabric/Mounting/UIView+ComponentViewProtocol.mm +++ b/React/Fabric/Mounting/UIView+ComponentViewProtocol.mm @@ -103,7 +103,11 @@ - (void)updateLayoutMetrics:(LayoutMetrics const &)layoutMetrics } else { // Note: Changing `frame` when `layer.transform` is not the `identity transform` is undefined behavior. // Therefore, we must use `center` and `bounds`. +#if !TARGET_OS_OSX // [macOS] self.center = CGPoint{CGRectGetMidX(frame), CGRectGetMidY(frame)}; +#else // [macOS + self.frame = frame; +#endif // macOS] self.bounds = CGRect{CGPointZero, frame.size}; } } From 21bb1e400876c1eb6a37cffdaf0d52f6996c1e4f Mon Sep 17 00:00:00 2001 From: Shawn Dempsey Date: Mon, 23 Jan 2023 22:37:45 -0800 Subject: [PATCH 10/27] Fix crash w/ first responder --- .../ComponentViews/TextInput/RCTTextInputComponentView.mm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm b/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm index 0fee0499389bde..af4ab21632214e 100644 --- a/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm @@ -85,7 +85,9 @@ - (void)didMoveToWindow if (self.window && !_didMoveToWindow) { auto const &props = *std::static_pointer_cast(_props); if (props.autoFocus) { +#if !TARGET_OS_OSX // [macOS] [_backedTextInputView becomeFirstResponder]; +#endif // [macOS] } _didMoveToWindow = YES; } From 816ff1a39d4eb47653a09b5779c3eb377e5fc4c5 Mon Sep 17 00:00:00 2001 From: Shawn Dempsey Date: Mon, 23 Jan 2023 22:39:20 -0800 Subject: [PATCH 11/27] Fix RCTFindTextInputWithNativeId --- .../InputAccessory/RCTInputAccessoryComponentView.mm | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/React/Fabric/Mounting/ComponentViews/InputAccessory/RCTInputAccessoryComponentView.mm b/React/Fabric/Mounting/ComponentViews/InputAccessory/RCTInputAccessoryComponentView.mm index 364ea6c26b3773..af1604677acbe5 100644 --- a/React/Fabric/Mounting/ComponentViews/InputAccessory/RCTInputAccessoryComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/InputAccessory/RCTInputAccessoryComponentView.mm @@ -66,8 +66,12 @@ - (void)didMoveToWindow if (self.window && !_textInput) { if (self.nativeId) { +#if !TARGET_OS_OSX // [macOS] _textInput = RCTFindTextInputWithNativeId(self.window, self.nativeId); _textInput.inputAccessoryView = _contentView; +#else // [macOS + _textInput = RCTFindTextInputWithNativeId(self.window.contentView, self.nativeId); +#endif // macOS] } else { _textInput = RCTFindTextInputWithNativeId(_contentView, nil); } From 26a271381178b96b3dae0b1f07807f641a038a42 Mon Sep 17 00:00:00 2001 From: Shawn Dempsey Date: Mon, 23 Jan 2023 22:57:10 -0800 Subject: [PATCH 12/27] Shim macOS scale utils --- React/Base/RCTUtils.m | 22 ++++++++++++++++++- .../View/RCTViewComponentView.mm | 3 ++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/React/Base/RCTUtils.m b/React/Base/RCTUtils.m index 934cff2bf21bb4..a26b348da6efb5 100644 --- a/React/Base/RCTUtils.m +++ b/React/Base/RCTUtils.m @@ -358,7 +358,21 @@ CGSize RCTScreenSize() return size; } -#endif // [macOS] +#else // [macOS +CGFloat RCTScreenScale() +{ + return [NSScreen mainScreen].backingScaleFactor; +} + +CGFloat RCTFontSizeMultiplier() { + return 1.0; +} + +CGSize RCTScreenSize() +{ + return [NSScreen mainScreen].frame.size; +} +#endif // macOS] #if !TARGET_OS_OSX // [macOS] CGSize RCTViewportSize() @@ -385,6 +399,12 @@ CGFloat RCTFloorPixelValue(CGFloat value) return floor(value * scale) / scale; } #else // [macOS +CGSize RCTViewportSize() +{ + NSScreen* screen = [NSScreen mainScreen]; + return screen ? screen.frame.size : RCTScreenSize(); +} + CGFloat RCTRoundPixelValue(CGFloat value, CGFloat scale) { return round(value * scale) / scale; diff --git a/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm b/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm index b8ac211e126b13..4c17c1da39ea81 100644 --- a/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm @@ -15,6 +15,7 @@ #import #import #import +#import #import #import #import @@ -633,7 +634,7 @@ - (void)invalidateLayer _borderLayer.contentsScale = image.scale; #else // [macOS _borderLayer.contents = [image layerContentsForContentsScale:scaleFactor]; - _borderLayer.contentsScale = [[NSScreen mainScreen] backingScaleFactor]; + _borderLayer.contentsScale = RCTScreenScale(); #endif // macOS] BOOL isResizable = !UIEdgeInsetsEqualToEdgeInsets(image.capInsets, UIEdgeInsetsZero); From f17846de39a976ee6f82ff72dc668d0fe96a4530 Mon Sep 17 00:00:00 2001 From: Shawn Dempsey Date: Mon, 23 Jan 2023 23:02:22 -0800 Subject: [PATCH 13/27] Shim RCTUITouch -> NSEvent --- React/Base/RCTUIKit.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/React/Base/RCTUIKit.h b/React/Base/RCTUIKit.h index 7f6af770bb0e0f..b118faa824d8eb 100644 --- a/React/Base/RCTUIKit.h +++ b/React/Base/RCTUIKit.h @@ -64,8 +64,8 @@ UIKIT_STATIC_INLINE CGPathRef UIBezierPathCreateCGPathRef(UIBezierPath *path) #define RCTPlatformView UIView #define RCTUIView UIView #define RCTUIScrollView UIScrollView - #define RCTPlatformWindow UIWindow +#define RCTUITouch UITouch // [macOS] UIKIT_STATIC_INLINE RCTPlatformView *RCTUIViewHitTestWithEvent(RCTPlatformView *view, CGPoint point, __unused UIEvent *__nullable event) { @@ -485,8 +485,7 @@ NS_ASSUME_NONNULL_END // // RCTUITouch - -#define RCTUITouch NSTouch // [macOS] +#define RCTUITouch NSEvent // [macOS] // RCTUISlider From 0a4b20248f093ea46d359d249910bba966e7c73b Mon Sep 17 00:00:00 2001 From: Shawn Dempsey Date: Tue, 24 Jan 2023 10:15:49 -0800 Subject: [PATCH 14/27] [Fabric] Fix UIKit Shim --- React/Base/RCTUIKit.h | 6 ++ React/Base/macOS/RCTUIKit.m | 112 ++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+) diff --git a/React/Base/RCTUIKit.h b/React/Base/RCTUIKit.h index 0514b236114210..9652217de888b6 100644 --- a/React/Base/RCTUIKit.h +++ b/React/Base/RCTUIKit.h @@ -316,6 +316,7 @@ NS_INLINE NSEdgeInsets UIEdgeInsetsMake(CGFloat top, CGFloat left, CGFloat botto // These types have the same purpose but may differ semantically. Use with care! #define UIEvent NSEvent +#define RCTUITouch NSEvent // UIGestureRecognizer #define UIGestureRecognizer NSGestureRecognizer @@ -509,6 +510,11 @@ NS_ASSUME_NONNULL_END typedef UILabel RCTUILabel; #else @interface RCTUILabel : NSTextField +NS_ASSUME_NONNULL_BEGIN +@property(nonatomic, copy) NSString* _Nullable text; +@property(nonatomic, assign) NSInteger numberOfLines; +@property(nonatomic, assign) NSTextAlignment textAlignment; +NS_ASSUME_NONNULL_END @end #endif diff --git a/React/Base/macOS/RCTUIKit.m b/React/Base/macOS/RCTUIKit.m index 0f00e983023ec7..1593137d45c392 100644 --- a/React/Base/macOS/RCTUIKit.m +++ b/React/Base/macOS/RCTUIKit.m @@ -13,6 +13,9 @@ #import +#import +#import + static char RCTGraphicsContextSizeKey; // @@ -631,5 +634,114 @@ - (void)setOn:(BOOL)on animated:(BOOL)animated { self.state = on ? NSControlStateValueOn : NSControlStateValueOff; } +@end + +// RCTUIActivityIndicatorView + +@interface RCTUIActivityIndicatorView () +@property (nonatomic, readwrite, getter=isAnimating) BOOL animating; +@end + +@implementation RCTUIActivityIndicatorView {} + +- (instancetype)initWithFrame:(CGRect)frame +{ + if ((self = [super initWithFrame:frame])) { + self.displayedWhenStopped = NO; + self.style = NSProgressIndicatorStyleSpinning; + } + return self; +} + +- (void)startAnimating +{ + // `wantsLayer` gets reset after the animation is stopped. We have to + // reset it in order for CALayer filters to take effect. + [self setWantsLayer:YES]; + [self startAnimation:self]; +} + +- (void)stopAnimating +{ + [self stopAnimation:self]; +} + +- (void)startAnimation:(id)sender +{ + [super startAnimation:sender]; + self.animating = YES; +} + +- (void)stopAnimation:(id)sender +{ + [super stopAnimation:sender]; + self.animating = NO; +} + +- (void)setActivityIndicatorViewStyle:(UIActivityIndicatorViewStyle)activityIndicatorViewStyle +{ + _activityIndicatorViewStyle = activityIndicatorViewStyle; + + switch (activityIndicatorViewStyle) { + case UIActivityIndicatorViewStyleWhiteLarge: + self.controlSize = NSControlSizeRegular; + break; + case UIActivityIndicatorViewStyleWhite: + self.controlSize = NSControlSizeSmall; + break; + default: + break; + } +} + +- (void)setColor:(RCTUIColor*)color +{ + if (_color != color) { + _color = color; + [self setNeedsDisplay:YES]; + } +} + +- (void)updateLayer +{ + [super updateLayer]; + if (_color != nil) { + CGFloat r, g, b, a; + [[_color colorUsingColorSpace:[NSColorSpace genericRGBColorSpace]] getRed:&r green:&g blue:&b alpha:&a]; + + CIFilter *colorPoly = [CIFilter filterWithName:@"CIColorPolynomial"]; + [colorPoly setDefaults]; + + CIVector *redVector = [CIVector vectorWithX:r Y:0 Z:0 W:0]; + CIVector *greenVector = [CIVector vectorWithX:g Y:0 Z:0 W:0]; + CIVector *blueVector = [CIVector vectorWithX:b Y:0 Z:0 W:0]; + [colorPoly setValue:redVector forKey:@"inputRedCoefficients"]; + [colorPoly setValue:greenVector forKey:@"inputGreenCoefficients"]; + [colorPoly setValue:blueVector forKey:@"inputBlueCoefficients"]; + + [[self layer] setFilters:@[colorPoly]]; + } else { + [[self layer] setFilters:nil]; + } +} + +- (void)setHidesWhenStopped:(BOOL)hidesWhenStopped +{ + self.displayedWhenStopped = !hidesWhenStopped; +} + +- (BOOL)hidesWhenStopped +{ + return !self.displayedWhenStopped; +} + +- (void)setHidden:(BOOL)hidden +{ + if ([self hidesWhenStopped] && ![self isAnimating]) { + [super setHidden:YES]; + } else { + [super setHidden:hidden]; + } +} @end From b6d48ea8f1767a7c02069ee1c745ffc9263364b7 Mon Sep 17 00:00:00 2001 From: Shawn Dempsey Date: Tue, 24 Jan 2023 10:18:52 -0800 Subject: [PATCH 15/27] [Fabric] Fix RCTUILabel shim --- .../RCTUnimplementedNativeComponentView.mm | 4 ++++ .../RCTUnimplementedViewComponentView.mm | 14 +++++--------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/React/Fabric/Mounting/ComponentViews/UnimplementedComponent/RCTUnimplementedNativeComponentView.mm b/React/Fabric/Mounting/ComponentViews/UnimplementedComponent/RCTUnimplementedNativeComponentView.mm index a8729c2e2ca91e..faadaa282b521a 100644 --- a/React/Fabric/Mounting/ComponentViews/UnimplementedComponent/RCTUnimplementedNativeComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/UnimplementedComponent/RCTUnimplementedNativeComponentView.mm @@ -34,7 +34,11 @@ - (instancetype)initWithFrame:(CGRect)frame _label.textAlignment = NSTextAlignmentCenter; _label.textColor = [RCTUIColor whiteColor]; // [macOS] +#if !TARGET_OS_OSX // [macOS] self.contentView = _label; +#else // [macOS + [self.contentView addSubview:_label]; +#endif // macOS] } return self; diff --git a/React/Fabric/Mounting/ComponentViews/UnimplementedView/RCTUnimplementedViewComponentView.mm b/React/Fabric/Mounting/ComponentViews/UnimplementedView/RCTUnimplementedViewComponentView.mm index cb67b03893780b..d38d80fcee00d3 100644 --- a/React/Fabric/Mounting/ComponentViews/UnimplementedView/RCTUnimplementedViewComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/UnimplementedView/RCTUnimplementedViewComponentView.mm @@ -29,19 +29,15 @@ - (instancetype)initWithFrame:(CGRect)frame if (self = [super initWithFrame:frame]) { static auto const defaultProps = std::make_shared(); _props = defaultProps; - - _label = [[RCTUILabel alloc] initWithFrame:self.bounds]; // [macOS] - _label.backgroundColor = [RCTUIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:0.3]; // [macOS] + + _label = [[RCTUILabel alloc] initWithFrame:self.bounds]; + _label.backgroundColor = [RCTUIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:0.3]; _label.lineBreakMode = NSLineBreakByCharWrapping; -#if !TARGET_OS_OSX // [macOS] _label.numberOfLines = 0; _label.textAlignment = NSTextAlignmentCenter; -#else // [macOS - _label.alignment = NSTextAlignmentCenter; -#endif // macOS] - _label.textColor = [RCTUIColor whiteColor]; // [macOS] - _label.allowsDefaultTighteningForTruncation = YES; + _label.textColor = [RCTUIColor whiteColor]; #if !TARGET_OS_OSX // [macOS] + _label.allowsDefaultTighteningForTruncation = YES; _label.adjustsFontSizeToFitWidth = YES; #endif // [macOS] From 238d2c0fa0a0a4e9d8c0feb21b4a94a02371152a Mon Sep 17 00:00:00 2001 From: Shawn Dempsey Date: Tue, 24 Jan 2023 10:19:13 -0800 Subject: [PATCH 16/27] [Fabric] Fix RCTSliderComponent shim --- .../Mounting/ComponentViews/Slider/RCTSliderComponentView.mm | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/React/Fabric/Mounting/ComponentViews/Slider/RCTSliderComponentView.mm b/React/Fabric/Mounting/ComponentViews/Slider/RCTSliderComponentView.mm index 1ea87f8bfc2d83..d75821e698f8e8 100644 --- a/React/Fabric/Mounting/ComponentViews/Slider/RCTSliderComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/Slider/RCTSliderComponentView.mm @@ -64,7 +64,12 @@ - (instancetype)initWithFrame:(CGRect)frame _maximumTrackImageResponseObserverProxy = RCTImageResponseObserverProxy(self); _thumbImageResponseObserverProxy = RCTImageResponseObserverProxy(self); +#if !TARGET_OS_OSX // [macOS] self.contentView = _sliderView; +#else // [macOS + self.contentView = [RCTUIView new]; + [self.contentView addSubview:_sliderView]; +#endif // macOS] } return self; From bae1e1abafd4dbbc5feee90ab9eaa6c19297c560 Mon Sep 17 00:00:00 2001 From: Shawn Dempsey Date: Tue, 24 Jan 2023 10:21:19 -0800 Subject: [PATCH 17/27] [Fabric] Disable UIApplicationWillTerminateNotification on macOS --- React/Fabric/RCTSurfacePresenter.mm | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/React/Fabric/RCTSurfacePresenter.mm b/React/Fabric/RCTSurfacePresenter.mm index 340fc1eacd5c8f..d99b2959bb71b2 100644 --- a/React/Fabric/RCTSurfacePresenter.mm +++ b/React/Fabric/RCTSurfacePresenter.mm @@ -98,13 +98,12 @@ - (instancetype)initWithContextContainer:(ContextContainer::Shared)contextContai _scheduler = [self _createScheduler]; - auto reactNativeConfig = _contextContainer->at>("ReactNativeConfig"); - if (reactNativeConfig->getBool("react_native_new_architecture:suspend_before_app_termination")) { - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(_applicationWillTerminate) - name:UIApplicationWillTerminateNotification - object:nil]; - } +#if !TARGET_OS_OSX // [macOS] + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(_applicationWillTerminate) + name:UIApplicationWillTerminateNotification + object:nil]; +#endif // [macOS] } return self; From f5e827835923573acff6f2289d38fbbfc4f3e92b Mon Sep 17 00:00:00 2001 From: Shawn Dempsey Date: Tue, 24 Jan 2023 10:39:35 -0800 Subject: [PATCH 18/27] [Fabric] Don't check alpha for NSView --- .../Mounting/ComponentViews/View/RCTViewComponentView.mm | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm b/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm index 8d9b4fe9637c4d..6bc64e6baf6300 100644 --- a/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm @@ -454,7 +454,11 @@ - (RCTUIView *)betterHitTest:(CGPoint)point withEvent:(UIEvent *)event // [macOS // * Taking `layer.zIndex` field into an account is not required because // lists of `ShadowView`s are already sorted based on `zIndex` prop. +#if !TARGET_OS_OSX // [macOS] if (!self.userInteractionEnabled || self.hidden || self.alpha < 0.01) { +#else // [macOS + if (!self.userInteractionEnabled || self.hidden) { +#endif // macOS] return nil; } From 7796cc7d77981b0ff6ac183cf1ec38da61dbaf3f Mon Sep 17 00:00:00 2001 From: Shawn Dempsey Date: Tue, 24 Jan 2023 11:04:45 -0800 Subject: [PATCH 19/27] [Fabric] Add missing tags --- .../ComponentViews/Switch/RCTSwitchComponentView.mm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm b/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm index dd9b3776e41e0c..da265911a48e52 100644 --- a/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm @@ -82,17 +82,17 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & #if !TARGET_OS_OSX // [macOS] // `tintColor` if (oldSwitchProps.tintColor != newSwitchProps.tintColor) { - _switchView.tintColor = RCTUIColorFromSharedColor(newSwitchProps.tintColor); + _switchView.tintColor = RCTUIColorFromSharedColor(newSwitchProps.tintColor); // [macOS] } // `onTintColor if (oldSwitchProps.onTintColor != newSwitchProps.onTintColor) { - _switchView.onTintColor = RCTUIColorFromSharedColor(newSwitchProps.onTintColor); + _switchView.onTintColor = RCTUIColorFromSharedColor(newSwitchProps.onTintColor); // [macOS] } // `thumbTintColor` if (oldSwitchProps.thumbTintColor != newSwitchProps.thumbTintColor) { - _switchView.thumbTintColor = RCTUIColorFromSharedColor(newSwitchProps.thumbTintColor); + _switchView.thumbTintColor = RCTUIColorFromSharedColor(newSwitchProps.thumbTintColor); // [macOS] } #endif // [macOS] From b1d9c7aa9efdf3814c2c091449ec6af73d92f040 Mon Sep 17 00:00:00 2001 From: Shawn Dempsey Date: Tue, 24 Jan 2023 11:08:38 -0800 Subject: [PATCH 20/27] [Fabric] Remove double import --- .../Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm | 1 - 1 file changed, 1 deletion(-) diff --git a/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm b/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm index 4c17c1da39ea81..38e8d4851f527a 100644 --- a/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm @@ -6,7 +6,6 @@ */ #import "RCTViewComponentView.h" -#import // [macOS] - prevent compiler error on invocation of CAShapeLayer #import #import From 719b5cb84ff171ab1a6ab4d7e948956de029102c Mon Sep 17 00:00:00 2001 From: Shawn Dempsey Date: Tue, 24 Jan 2023 11:22:02 -0800 Subject: [PATCH 21/27] [Fabric] Fix RCTTouchEvent Shim --- React/Base/RCTUIKit.h | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/React/Base/RCTUIKit.h b/React/Base/RCTUIKit.h index b118faa824d8eb..c66f67d9b02cec 100644 --- a/React/Base/RCTUIKit.h +++ b/React/Base/RCTUIKit.h @@ -65,7 +65,6 @@ UIKIT_STATIC_INLINE CGPathRef UIBezierPathCreateCGPathRef(UIBezierPath *path) #define RCTUIView UIView #define RCTUIScrollView UIScrollView #define RCTPlatformWindow UIWindow -#define RCTUITouch UITouch // [macOS] UIKIT_STATIC_INLINE RCTPlatformView *RCTUIViewHitTestWithEvent(RCTPlatformView *view, CGPoint point, __unused UIEvent *__nullable event) { @@ -484,9 +483,6 @@ NS_ASSUME_NONNULL_END // fabric component types // -// RCTUITouch -#define RCTUITouch NSEvent // [macOS] - // RCTUISlider #if !TARGET_OS_OSX @@ -548,3 +544,12 @@ NS_ASSUME_NONNULL_END @end #endif + +// RCTUITouch + +#if !TARGET_OS_OSX +typedef UITouch RCTUITouch; +#else +@interface RCTUITouch : NSEvent +@end +#endif From d4265bb61b505243b417487459ff76849516e46d Mon Sep 17 00:00:00 2001 From: Shawn Dempsey <96719+shwanton@users.noreply.github.com> Date: Tue, 24 Jan 2023 11:31:01 -0800 Subject: [PATCH 22/27] Update React/Fabric/Mounting/RCTComponentViewDescriptor.h Co-authored-by: Saad Najmi --- React/Fabric/Mounting/RCTComponentViewDescriptor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/React/Fabric/Mounting/RCTComponentViewDescriptor.h b/React/Fabric/Mounting/RCTComponentViewDescriptor.h index a287b11e68ff3a..62e3a5041837f5 100644 --- a/React/Fabric/Mounting/RCTComponentViewDescriptor.h +++ b/React/Fabric/Mounting/RCTComponentViewDescriptor.h @@ -22,7 +22,7 @@ class RCTComponentViewDescriptor final { * Associated (and owned) native view instance. */ __strong RCTUIView *view = nil; // [macOS] - NSInteger tag = 0; // default is 0 // [macOS] + NSInteger tag = 0; // [macOS] default is 0 /* * Indicates a requirement to call on the view methods from * `RCTMountingTransactionObserving` protocol. From dfb4cd85347731e6d1eb7ce451cb5db2c8981ea7 Mon Sep 17 00:00:00 2001 From: Shawn Dempsey Date: Tue, 24 Jan 2023 11:52:19 -0800 Subject: [PATCH 23/27] [Fabric] Remove duplicate RCTUITouch def --- React/Base/RCTUIKit.h | 1 - 1 file changed, 1 deletion(-) diff --git a/React/Base/RCTUIKit.h b/React/Base/RCTUIKit.h index 78efd861e6a2b7..edc2530e459ca1 100644 --- a/React/Base/RCTUIKit.h +++ b/React/Base/RCTUIKit.h @@ -315,7 +315,6 @@ NS_INLINE NSEdgeInsets UIEdgeInsetsMake(CGFloat top, CGFloat left, CGFloat botto // These types have the same purpose but may differ semantically. Use with care! #define UIEvent NSEvent -#define RCTUITouch NSEvent // UIGestureRecognizer #define UIGestureRecognizer NSGestureRecognizer From 3f79c794c9a21e7eb1c57f64daeb85fc8da8b7f3 Mon Sep 17 00:00:00 2001 From: Shawn Dempsey Date: Tue, 24 Jan 2023 11:52:19 -0800 Subject: [PATCH 24/27] [Fabric] Remove duplicate RCTUITouch def --- React/Base/RCTUIKit.h | 1 - 1 file changed, 1 deletion(-) diff --git a/React/Base/RCTUIKit.h b/React/Base/RCTUIKit.h index 9652217de888b6..988e97ca5bd095 100644 --- a/React/Base/RCTUIKit.h +++ b/React/Base/RCTUIKit.h @@ -316,7 +316,6 @@ NS_INLINE NSEdgeInsets UIEdgeInsetsMake(CGFloat top, CGFloat left, CGFloat botto // These types have the same purpose but may differ semantically. Use with care! #define UIEvent NSEvent -#define RCTUITouch NSEvent // UIGestureRecognizer #define UIGestureRecognizer NSGestureRecognizer From c24946cc673bd2d371c9d909e6a7c9be095ceb42 Mon Sep 17 00:00:00 2001 From: Shawn Dempsey Date: Tue, 24 Jan 2023 12:24:02 -0800 Subject: [PATCH 25/27] [Fabric] Fix whitespace --- .../UnimplementedView/RCTUnimplementedViewComponentView.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/React/Fabric/Mounting/ComponentViews/UnimplementedView/RCTUnimplementedViewComponentView.mm b/React/Fabric/Mounting/ComponentViews/UnimplementedView/RCTUnimplementedViewComponentView.mm index d38d80fcee00d3..0ea1257092f302 100644 --- a/React/Fabric/Mounting/ComponentViews/UnimplementedView/RCTUnimplementedViewComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/UnimplementedView/RCTUnimplementedViewComponentView.mm @@ -29,7 +29,7 @@ - (instancetype)initWithFrame:(CGRect)frame if (self = [super initWithFrame:frame]) { static auto const defaultProps = std::make_shared(); _props = defaultProps; - + _label = [[RCTUILabel alloc] initWithFrame:self.bounds]; _label.backgroundColor = [RCTUIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:0.3]; _label.lineBreakMode = NSLineBreakByCharWrapping; From 3c937f76824cde9dae4f9704194f0cc7f030aaa2 Mon Sep 17 00:00:00 2001 From: Shawn Dempsey Date: Tue, 24 Jan 2023 12:32:56 -0800 Subject: [PATCH 26/27] [Fabric] Enable fabric macOS builds on CI --- .ado/apple-pr.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.ado/apple-pr.yml b/.ado/apple-pr.yml index eb6c1b6556b93e..2cd923b1a674b4 100644 --- a/.ado/apple-pr.yml +++ b/.ado/apple-pr.yml @@ -80,15 +80,15 @@ jobs: xcode_destination: 'platform=macOS,arch=x86_64' xcode_actions: 'build' use_fabric: '0' + 'macOS Fabric Debug': + packager_platform: 'macos' + xcode_sdk: macosx + xcode_scheme: 'RNTester-macOS' + xcode_configuration: 'Debug' + xcode_destination: 'platform=macOS,arch=x86_64' + xcode_actions: 'build test' + use_fabric: '1' # Disable failing job - # 'macOS Fabric Debug': - # packager_platform: 'macos' - # xcode_sdk: macosx - # xcode_scheme: 'RNTester-macOS' - # xcode_configuration: 'Debug' - # xcode_destination: 'platform=macOS,arch=x86_64' - # xcode_actions: 'build test' - # use_fabric: '1' # 'macOS Fabric Release': # packager_platform: 'macos' # xcode_sdk: macosx From 604fc9dbdcba98fb45c7d1e10fe22d3535968fb5 Mon Sep 17 00:00:00 2001 From: Shawn Dempsey Date: Tue, 24 Jan 2023 15:58:16 -0800 Subject: [PATCH 27/27] [Fabric] Add missing tag --- .../Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm b/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm index 38e8d4851f527a..34d972375acf0c 100644 --- a/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm @@ -14,7 +14,7 @@ #import #import #import -#import +#import // [macOS] #import #import #import