From 93990172d62e5941a347601e7a3f0363f74c8a7f Mon Sep 17 00:00:00 2001 From: Saad Najmi Date: Wed, 20 Nov 2024 16:24:41 -0800 Subject: [PATCH 1/2] refactor(paper): remove macOS specific transform handling code --- packages/react-native/React/Views/RCTView.h | 1 - packages/react-native/React/Views/RCTView.m | 16 +++------------- packages/react-native/React/Views/UIView+React.h | 7 ------- packages/react-native/React/Views/UIView+React.m | 11 ----------- 4 files changed, 3 insertions(+), 32 deletions(-) diff --git a/packages/react-native/React/Views/RCTView.h b/packages/react-native/React/Views/RCTView.h index 86556d1a07e059..8947d0d16ab562 100644 --- a/packages/react-native/React/Views/RCTView.h +++ b/packages/react-native/React/Views/RCTView.h @@ -161,7 +161,6 @@ extern const UIAccessibilityTraits SwitchAccessibilityTrait; /** * macOS Properties */ -@property (nonatomic, assign) CATransform3D transform3D; // `allowsVibrancy` is readonly on NSView, so let's create a new property to make it assignable // that we can set through JS and the getter for `allowsVibrancy` can read in RCTView. diff --git a/packages/react-native/React/Views/RCTView.m b/packages/react-native/React/Views/RCTView.m index 9fc3fbf413895d..533b12b0f5b4bf 100644 --- a/packages/react-native/React/Views/RCTView.m +++ b/packages/react-native/React/Views/RCTView.m @@ -179,7 +179,6 @@ - (instancetype)initWithFrame:(CGRect)frame _hitTestEdgeInsets = UIEdgeInsetsZero; _cursor = RCTCursorAuto; #if TARGET_OS_OSX // [macOS - _transform3D = CATransform3DIdentity; _shadowColor = nil; _mouseDownCanMoveWindow = YES; #endif // macOS] @@ -1187,20 +1186,19 @@ - (void)displayLayer:(CALayer *)layer #else // [macOS RCTUIColor *backgroundColor = _backgroundColor; #endif // macOS] - + #if TARGET_OS_OSX // [macOS - CATransform3D transform = [self transform3D]; + CATransform3D transform = [[self layer] transform]; CGPoint anchorPoint = [layer anchorPoint]; if (CGPointEqualToPoint(anchorPoint, CGPointZero) && !CATransform3DEqualToTransform(transform, CATransform3DIdentity)) { // https://developer.apple.com/documentation/quartzcore/calayer/1410817-anchorpoint // This compensates for the fact that layer.anchorPoint is {0, 0} instead of {0.5, 0.5} on macOS for some reason. CATransform3D originAdjust = CATransform3DTranslate(CATransform3DIdentity, self.frame.size.width / 2, self.frame.size.height / 2, 0); transform = CATransform3DConcat(CATransform3DConcat(CATransform3DInvert(originAdjust), transform), originAdjust); - // Enable edge antialiasing in perspective transforms - [layer setAllowsEdgeAntialiasing:!(transform.m34 == 0.0f)]; } [layer setTransform:transform]; #endif // macOS] + if (useIOSBorderRendering) { layer.cornerRadius = cornerRadii.topLeftHorizontal; layer.borderColor = borderColors.left.CGColor; @@ -1251,14 +1249,6 @@ - (void)displayLayer:(CALayer *)layer [self updateClippingForLayer:layer]; } -#if TARGET_OS_OSX // [macOS -- (void)updateReactTransformInternal:(CATransform3D)transform -{ - [self setTransform3D:transform]; - [self setNeedsDisplay]; -} -#endif // macOS] - static BOOL RCTLayerHasShadow(CALayer *layer) { return layer.shadowOpacity * CGColorGetAlpha(layer.shadowColor) > 0; diff --git a/packages/react-native/React/Views/UIView+React.h b/packages/react-native/React/Views/UIView+React.h index 8f169f12055a72..bdde9b9ca89113 100644 --- a/packages/react-native/React/Views/UIView+React.h +++ b/packages/react-native/React/Views/UIView+React.h @@ -84,13 +84,6 @@ typedef struct { - (void)reactSetFrame:(CGRect)frame; -#if TARGET_OS_OSX // [macOS -/** - * Used by macOS to propagate transform changes internally. - */ -- (void)updateReactTransformInternal:(CATransform3D)transform; -#endif // macOS] - /** * This method finds and returns the containing view controller for the view. */ diff --git a/packages/react-native/React/Views/UIView+React.m b/packages/react-native/React/Views/UIView+React.m index a3bc056e921a40..cda5a77398bd7b 100644 --- a/packages/react-native/React/Views/UIView+React.m +++ b/packages/react-native/React/Views/UIView+React.m @@ -306,21 +306,10 @@ static void updateTransform(RCTPlatformView *view) // [macOS] transform = view.reactTransform; } -#if !TARGET_OS_OSX // [macOS] view.layer.transform = transform; // Enable edge antialiasing in rotation, skew, or perspective transforms view.layer.allowsEdgeAntialiasing = transform.m12 != 0.0f || transform.m21 != 0.0f || transform.m34 != 0.0f; -#else // [macOS - [view updateReactTransformInternal:transform]; -#endif // macOS] -} - -#if TARGET_OS_OSX // [macOS -- (void)updateReactTransformInternal:(CATransform3D)transform -{ - // Do nothing, this will get overridden by RCTView and other subclasses as needed. } -#endif // macOS] - (UIViewController *)reactViewController { From 04287f4c735c4833027ba75c2d38a530adc02a03 Mon Sep 17 00:00:00 2001 From: Nick Lefever Date: Wed, 25 Oct 2023 02:54:49 +0200 Subject: [PATCH 2/2] [fabric] Adapt transforms to CALayer top-left anchor point Summary: On macOS, Core Animation layers have their anchor point set to (0,0) which is the top-left. On iOS the anchor point is set to (0.5, 0.5) which matches the center. Transforms assigned to views are built based on having the anchor point at the center. This diff updates the transform matrix to apply to transform from the center. Test Plan: Check zoom/rotation animations in Zeratul. | Before | After | |--| | https://pxl.cl/3G8HG | https://pxl.cl/3G8HQ | Reviewers: shawndempsey, #rn-desktop Reviewed By: shawndempsey Differential Revision: https://phabricator.intern.facebook.com/D50628807 Tasks: T161413049 --- .../Mounting/ComponentViews/View/RCTViewComponentView.mm | 9 +++++++++ .../React/Fabric/Mounting/RCTMountingManager.mm | 6 ++++++ 2 files changed, 15 insertions(+) diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm index 1f5dbd7f8f7e91..035bcc2245f317 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm @@ -332,6 +332,15 @@ - (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared & ![_propKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN containsObject:@"transform"]) { auto newTransform = newViewProps.resolveTransform(_layoutMetrics); CATransform3D caTransform = RCTCATransform3DFromTransformMatrix(newTransform); +#if TARGET_OS_OSX // [macOS + CGPoint anchorPoint = self.layer.anchorPoint; + if (CGPointEqualToPoint(anchorPoint, CGPointZero) && !CATransform3DEqualToTransform(caTransform, CATransform3DIdentity)) { + // https://developer.apple.com/documentation/quartzcore/calayer/1410817-anchorpoint + // This compensates for the fact that layer.anchorPoint is {0, 0} instead of {0.5, 0.5} on macOS for some reason. + CATransform3D originAdjust = CATransform3DTranslate(CATransform3DIdentity, self.frame.size.width / 2, self.frame.size.height / 2, 0); + caTransform = CATransform3DConcat(CATransform3DConcat(CATransform3DInvert(originAdjust), caTransform), originAdjust); + } +#endif // macOS] self.layer.transform = caTransform; // Enable edge antialiasing in rotation, skew, or perspective transforms diff --git a/packages/react-native/React/Fabric/Mounting/RCTMountingManager.mm b/packages/react-native/React/Fabric/Mounting/RCTMountingManager.mm index cf0e64585b1ed2..ded9d1d45cedad 100644 --- a/packages/react-native/React/Fabric/Mounting/RCTMountingManager.mm +++ b/packages/react-native/React/Fabric/Mounting/RCTMountingManager.mm @@ -309,6 +309,12 @@ - (void)synchronouslyUpdateViewOnUIThread:(ReactTag)reactTag layoutMetrics.frame.size.width = componentView.layer.bounds.size.width; layoutMetrics.frame.size.height = componentView.layer.bounds.size.height; CATransform3D newTransform = RCTCATransform3DFromTransformMatrix(newViewProps.resolveTransform(layoutMetrics)); +#if TARGET_OS_OSX // [macOS] + if (CGPointEqualToPoint(componentView.layer.anchorPoint, CGPointZero) && !CATransform3DEqualToTransform(newTransform, CATransform3DIdentity)) { + CATransform3D originAdjust = CATransform3DTranslate(CATransform3DIdentity, componentView.frame.size.width / 2, componentView.frame.size.height / 2, 0); + newTransform = CATransform3DConcat(CATransform3DConcat(CATransform3DInvert(originAdjust), newTransform), originAdjust); + } +#endif // macOS] if (!CATransform3DEqualToTransform(newTransform, componentView.layer.transform)) { componentView.layer.transform = newTransform; }