From 33d6091cac5ed2f8cef06d4740c8b42fcd107271 Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Tue, 9 Feb 2021 08:08:09 -0800 Subject: [PATCH] Fabric: Using `SurfaceHandler` on iOS Summary: This diff migrates iOS renderer to using SurfaceHandler directly instead of calling Scheduler methods. Major changes: * RCTFabricSurface only stores a SurfaceHandler and platform-specific parts (such as a UIView instance and TouchHandler); all other pieces of state are stored in SurfaceHandler object. * All the state changes initiated from RCTFabricSurface are performed via calling corresponding methods on SurfaceHandler (bypassing RCTSurfacePresenter, RCTScheduler, Scheduler, and UIManager). * Every RCTSurfaceHandler is responsible for observing `UIContentSizeCategoryDidChangeNotification` and communicating the change down to SurfaceHandler. (Besides code simplifications it's more correct because on iOS the DPI actually depends on a particular UIScreen/UIWindow associated with UIView and *not* global for the whole app.) Changelog: [Internal] Fabric-specific internal change. Reviewed By: sammy-SC Differential Revision: D24290778 fbshipit-source-id: 62b600c3f1b2e66a7513481404af941ef8b78bec --- React/Fabric/RCTScheduler.h | 20 +- React/Fabric/RCTScheduler.mm | 41 +--- React/Fabric/RCTSurfacePresenter.h | 24 +-- React/Fabric/RCTSurfacePresenter.mm | 141 ++---------- React/Fabric/Surface/RCTFabricSurface.h | 8 +- React/Fabric/Surface/RCTFabricSurface.mm | 263 +++++++++++------------ 6 files changed, 154 insertions(+), 343 deletions(-) diff --git a/React/Fabric/RCTScheduler.h b/React/Fabric/RCTScheduler.h index 55670daca64..6eca003c033 100644 --- a/React/Fabric/RCTScheduler.h +++ b/React/Fabric/RCTScheduler.h @@ -14,6 +14,7 @@ #import #import #import +#import #import NS_ASSUME_NONNULL_BEGIN @@ -47,26 +48,13 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithToolbox:(facebook::react::SchedulerToolbox)toolbox; -- (void)startSurfaceWithSurfaceId:(facebook::react::SurfaceId)surfaceId - moduleName:(NSString *)moduleName - initialProps:(NSDictionary *)initialProps - layoutConstraints:(facebook::react::LayoutConstraints)layoutConstraints - layoutContext:(facebook::react::LayoutContext)layoutContext; - -- (void)stopSurfaceWithSurfaceId:(facebook::react::SurfaceId)surfaceId; - -- (CGSize)measureSurfaceWithLayoutConstraints:(facebook::react::LayoutConstraints)layoutConstraints - layoutContext:(facebook::react::LayoutContext)layoutContext - surfaceId:(facebook::react::SurfaceId)surfaceId; - -- (void)constraintSurfaceLayoutWithLayoutConstraints:(facebook::react::LayoutConstraints)layoutConstraints - layoutContext:(facebook::react::LayoutContext)layoutContext - surfaceId:(facebook::react::SurfaceId)surfaceId; +- (void)registerSurface:(facebook::react::SurfaceHandler const &)surfaceHandler; +- (void)unregisterSurface:(facebook::react::SurfaceHandler const &)surfaceHandler; - (facebook::react::ComponentDescriptor const *)findComponentDescriptorByHandle_DO_NOT_USE_THIS_IS_BROKEN: (facebook::react::ComponentHandle)handle; -- (facebook::react::MountingCoordinator::Shared)mountingCoordinatorWithSurfaceId:(facebook::react::SurfaceId)surfaceId; +- (void)setupAnimationDriver:(facebook::react::SurfaceHandler const &)surfaceHandler; - (void)onAnimationStarted; diff --git a/React/Fabric/RCTScheduler.mm b/React/Fabric/RCTScheduler.mm index 3e7281be63c..b9d38d6cd86 100644 --- a/React/Fabric/RCTScheduler.mm +++ b/React/Fabric/RCTScheduler.mm @@ -139,43 +139,14 @@ class LayoutAnimationDelegateProxy : public LayoutAnimationStatusDelegate, publi _animationDriver = nullptr; } -- (void)startSurfaceWithSurfaceId:(SurfaceId)surfaceId - moduleName:(NSString *)moduleName - initialProps:(NSDictionary *)initialProps - layoutConstraints:(LayoutConstraints)layoutConstraints - layoutContext:(LayoutContext)layoutContext +- (void)registerSurface:(facebook::react::SurfaceHandler const &)surfaceHandler { - SystraceSection s("-[RCTScheduler startSurfaceWithSurfaceId:...]"); - - auto props = convertIdToFollyDynamic(initialProps); - _scheduler->startSurface(surfaceId, RCTStringFromNSString(moduleName), props, layoutConstraints, layoutContext); - - _scheduler->findMountingCoordinator(surfaceId)->setMountingOverrideDelegate(_animationDriver); - - _scheduler->renderTemplateToSurface( - surfaceId, props.getDefault("navigationConfig").getDefault("initialUITemplate", "").getString()); + _scheduler->registerSurface(surfaceHandler); } -- (void)stopSurfaceWithSurfaceId:(SurfaceId)surfaceId +- (void)unregisterSurface:(facebook::react::SurfaceHandler const &)surfaceHandler { - SystraceSection s("-[RCTScheduler stopSurfaceWithSurfaceId:]"); - _scheduler->stopSurface(surfaceId); -} - -- (CGSize)measureSurfaceWithLayoutConstraints:(LayoutConstraints)layoutConstraints - layoutContext:(LayoutContext)layoutContext - surfaceId:(SurfaceId)surfaceId -{ - SystraceSection s("-[RCTScheduler measureSurfaceWithLayoutConstraints:]"); - return RCTCGSizeFromSize(_scheduler->measureSurface(surfaceId, layoutConstraints, layoutContext)); -} - -- (void)constraintSurfaceLayoutWithLayoutConstraints:(LayoutConstraints)layoutConstraints - layoutContext:(LayoutContext)layoutContext - surfaceId:(SurfaceId)surfaceId -{ - SystraceSection s("-[RCTScheduler constraintSurfaceLayoutWithLayoutConstraints:]"); - _scheduler->constraintSurfaceLayout(surfaceId, layoutConstraints, layoutContext); + _scheduler->unregisterSurface(surfaceHandler); } - (ComponentDescriptor const *)findComponentDescriptorByHandle_DO_NOT_USE_THIS_IS_BROKEN:(ComponentHandle)handle @@ -183,9 +154,9 @@ class LayoutAnimationDelegateProxy : public LayoutAnimationStatusDelegate, publi return _scheduler->findComponentDescriptorByHandle_DO_NOT_USE_THIS_IS_BROKEN(handle); } -- (MountingCoordinator::Shared)mountingCoordinatorWithSurfaceId:(SurfaceId)surfaceId +- (void)setupAnimationDriver:(facebook::react::SurfaceHandler const &)surfaceHandler { - return _scheduler->findMountingCoordinator(surfaceId); + surfaceHandler.getMountingCoordinator()->setMountingOverrideDelegate(_animationDriver); } - (void)onAnimationStarted diff --git a/React/Fabric/RCTSurfacePresenter.h b/React/Fabric/RCTSurfacePresenter.h index 6293ef6167c..0053a376ee1 100644 --- a/React/Fabric/RCTSurfacePresenter.h +++ b/React/Fabric/RCTSurfacePresenter.h @@ -11,6 +11,7 @@ #import #import #import +#import #import NS_ASSUME_NONNULL_BEGIN @@ -45,34 +46,25 @@ NS_ASSUME_NONNULL_BEGIN @interface RCTSurfacePresenter (Surface) -/** +/* * Surface uses these methods to register itself in the Presenter. */ - (void)registerSurface:(RCTFabricSurface *)surface; - (void)unregisterSurface:(RCTFabricSurface *)surface; -- (void)setProps:(NSDictionary *)props surface:(RCTFabricSurface *)surface; +@property (readonly) RCTMountingManager *mountingManager; - (nullable RCTFabricSurface *)surfaceForRootTag:(ReactTag)rootTag; -/** - * Measures the Surface with given constraints. - */ -- (CGSize)sizeThatFitsMinimumSize:(CGSize)minimumSize - maximumSize:(CGSize)maximumSize - surface:(RCTFabricSurface *)surface; - -/** - * Sets `minimumSize` and `maximumSize` layout constraints for the Surface. - */ -- (void)setMinimumSize:(CGSize)minimumSize maximumSize:(CGSize)maximumSize surface:(RCTFabricSurface *)surface; - - (BOOL)synchronouslyUpdateViewOnUIThread:(NSNumber *)reactTag props:(NSDictionary *)props; -- (BOOL)synchronouslyWaitSurface:(RCTFabricSurface *)surface timeout:(NSTimeInterval)timeout; +- (void)setupAnimationDriverWithSurfaceHandler:(facebook::react::SurfaceHandler const &)surfaceHandler; +/* + * Deprecated. + * Use `RCTMountingTransactionObserverCoordinator` instead. + */ - (void)addObserver:(id)observer; - - (void)removeObserver:(id)observer; /* diff --git a/React/Fabric/RCTSurfacePresenter.mm b/React/Fabric/RCTSurfacePresenter.mm index e982243d62e..bd11901c67f 100644 --- a/React/Fabric/RCTSurfacePresenter.mm +++ b/React/Fabric/RCTSurfacePresenter.mm @@ -40,25 +40,6 @@ using namespace facebook::react; -static inline LayoutConstraints RCTGetLayoutConstraintsForSize(CGSize minimumSize, CGSize maximumSize) -{ - return { - .minimumSize = RCTSizeFromCGSize(minimumSize), - .maximumSize = RCTSizeFromCGSize(maximumSize), - .layoutDirection = RCTLayoutDirection([[RCTI18nUtil sharedInstance] isRTL]), - }; -} - -static inline LayoutContext RCTGetLayoutContext(CGPoint viewportOffset) -{ - return { - .pointScaleFactor = RCTScreenScale(), - .swapLeftAndRightInRTL = - [[RCTI18nUtil sharedInstance] isRTL] && [[RCTI18nUtil sharedInstance] doLeftAndRightSwapInRTL], - .fontSizeMultiplier = RCTFontSizeMultiplier(), - .viewportOffset = RCTPointFromCGPoint(viewportOffset)}; -} - static dispatch_queue_t RCTGetBackgroundQueue() { static dispatch_queue_t queue; @@ -119,16 +100,16 @@ static BackgroundExecutor RCTGetBackgroundExecutor() _observers = [NSMutableArray array]; _scheduler = [self _createScheduler]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(_handleContentSizeCategoryDidChangeNotification:) - name:UIContentSizeCategoryDidChangeNotification - object:nil]; } return self; } +- (RCTMountingManager *)mountingManager +{ + return _mountingManager; +} + - (RCTScheduler *_Nullable)_scheduler { std::lock_guard lock(_schedulerAccessMutex); @@ -163,10 +144,10 @@ static BackgroundExecutor RCTGetBackgroundExecutor() - (void)registerSurface:(RCTFabricSurface *)surface { - RCTScheduler *scheduler = [self _scheduler]; [_surfaceRegistry registerSurface:surface]; + RCTScheduler *scheduler = [self _scheduler]; if (scheduler) { - [self _startSurface:surface scheduler:scheduler]; + [scheduler registerSurface:surface.surfaceHandler]; } } @@ -174,54 +155,16 @@ static BackgroundExecutor RCTGetBackgroundExecutor() { RCTScheduler *scheduler = [self _scheduler]; if (scheduler) { - [self _stopSurface:surface scheduler:scheduler]; + [scheduler unregisterSurface:surface.surfaceHandler]; } [_surfaceRegistry unregisterSurface:surface]; } -- (void)setProps:(NSDictionary *)props surface:(RCTFabricSurface *)surface -{ - RCTScheduler *scheduler = [self _scheduler]; - if (scheduler) { - [self _stopSurface:surface scheduler:scheduler]; - [self _startSurface:surface scheduler:scheduler]; - } -} - - (RCTFabricSurface *)surfaceForRootTag:(ReactTag)rootTag { return [_surfaceRegistry surfaceForRootTag:rootTag]; } -- (CGSize)sizeThatFitsMinimumSize:(CGSize)minimumSize - maximumSize:(CGSize)maximumSize - surface:(RCTFabricSurface *)surface -{ - RCTScheduler *scheduler = [self _scheduler]; - if (!scheduler) { - return minimumSize; - } - LayoutContext layoutContext = RCTGetLayoutContext(surface.viewportOffset); - LayoutConstraints layoutConstraints = RCTGetLayoutConstraintsForSize(minimumSize, maximumSize); - return [scheduler measureSurfaceWithLayoutConstraints:layoutConstraints - layoutContext:layoutContext - surfaceId:surface.rootTag]; -} - -- (void)setMinimumSize:(CGSize)minimumSize maximumSize:(CGSize)maximumSize surface:(RCTFabricSurface *)surface -{ - RCTScheduler *scheduler = [self _scheduler]; - if (!scheduler) { - return; - } - - LayoutContext layoutContext = RCTGetLayoutContext(surface.viewportOffset); - LayoutConstraints layoutConstraints = RCTGetLayoutConstraintsForSize(minimumSize, maximumSize); - [scheduler constraintSurfaceLayoutWithLayoutConstraints:layoutConstraints - layoutContext:layoutContext - surfaceId:surface.rootTag]; -} - - (UIView *)findComponentViewWithTag_DO_NOT_USE_DEPRECATED:(NSInteger)tag { UIView *componentView = @@ -253,22 +196,9 @@ static BackgroundExecutor RCTGetBackgroundExecutor() return YES; } -- (BOOL)synchronouslyWaitSurface:(RCTFabricSurface *)surface timeout:(NSTimeInterval)timeout +- (void)setupAnimationDriverWithSurfaceHandler:(facebook::react::SurfaceHandler const &)surfaceHandler { - RCTScheduler *scheduler = [self _scheduler]; - if (!scheduler) { - return NO; - } - - auto mountingCoordinator = [scheduler mountingCoordinatorWithSurfaceId:surface.rootTag]; - - if (!mountingCoordinator->waitForTransaction(std::chrono::duration(timeout))) { - return NO; - } - - [_mountingManager scheduleTransaction:mountingCoordinator]; - - return YES; + [[self _scheduler] setupAnimationDriver:surfaceHandler]; } - (BOOL)suspend @@ -377,39 +307,12 @@ static BackgroundExecutor RCTGetBackgroundExecutor() return scheduler; } -- (void)_startSurface:(RCTFabricSurface *)surface scheduler:(RCTScheduler *)scheduler -{ - RCTMountingManager *mountingManager = _mountingManager; - RCTExecuteOnMainQueue(^{ - [mountingManager attachSurfaceToView:surface.view surfaceId:surface.rootTag]; - }); - - LayoutContext layoutContext = RCTGetLayoutContext(surface.viewportOffset); - - LayoutConstraints layoutConstraints = RCTGetLayoutConstraintsForSize(surface.minimumSize, surface.maximumSize); - - [scheduler startSurfaceWithSurfaceId:surface.rootTag - moduleName:surface.moduleName - initialProps:surface.properties - layoutConstraints:layoutConstraints - layoutContext:layoutContext]; -} - -- (void)_stopSurface:(RCTFabricSurface *)surface scheduler:(RCTScheduler *)scheduler -{ - [scheduler stopSurfaceWithSurfaceId:surface.rootTag]; - - RCTMountingManager *mountingManager = _mountingManager; - RCTExecuteOnMainQueue(^{ - [mountingManager detachSurfaceFromView:surface.view surfaceId:surface.rootTag]; - }); -} - - (void)_startAllSurfacesWithScheduler:(RCTScheduler *)scheduler { [_surfaceRegistry enumerateWithBlock:^(NSEnumerator *enumerator) { for (RCTFabricSurface *surface in enumerator) { - [self _startSurface:surface scheduler:scheduler]; + [scheduler registerSurface:surface.surfaceHandler]; + [surface start]; } }]; } @@ -418,24 +321,8 @@ static BackgroundExecutor RCTGetBackgroundExecutor() { [_surfaceRegistry enumerateWithBlock:^(NSEnumerator *enumerator) { for (RCTFabricSurface *surface in enumerator) { - [self _stopSurface:surface scheduler:scheduler]; - } - }]; -} - -- (void)_handleContentSizeCategoryDidChangeNotification:(NSNotification *)notification -{ - RCTScheduler *scheduler = [self _scheduler]; - - [_surfaceRegistry enumerateWithBlock:^(NSEnumerator *enumerator) { - for (RCTFabricSurface *surface in enumerator) { - LayoutContext layoutContext = RCTGetLayoutContext(surface.viewportOffset); - - LayoutConstraints layoutConstraints = RCTGetLayoutConstraintsForSize(surface.minimumSize, surface.maximumSize); - - [scheduler constraintSurfaceLayoutWithLayoutConstraints:layoutConstraints - layoutContext:layoutContext - surfaceId:surface.rootTag]; + [surface stop]; + [scheduler unregisterSurface:surface.surfaceHandler]; } }]; } diff --git a/React/Fabric/Surface/RCTFabricSurface.h b/React/Fabric/Surface/RCTFabricSurface.h index 1c3e4af43f7..77b3c906cc7 100644 --- a/React/Fabric/Surface/RCTFabricSurface.h +++ b/React/Fabric/Surface/RCTFabricSurface.h @@ -8,6 +8,7 @@ #import #import #import +#import NS_ASSUME_NONNULL_BEGIN @@ -128,12 +129,7 @@ NS_ASSUME_NONNULL_BEGIN @interface RCTFabricSurface (Internal) -/** - * Sets and clears given stage flags (bitmask). - * Returns `YES` if the actual state was changed. - */ -- (BOOL)_setStage:(RCTSurfaceStage)stage; -- (BOOL)_unsetStage:(RCTSurfaceStage)stage; +- (facebook::react::SurfaceHandler const &)surfaceHandler; @end diff --git a/React/Fabric/Surface/RCTFabricSurface.mm b/React/Fabric/Surface/RCTFabricSurface.mm index 616945339cd..1ddda245055 100644 --- a/React/Fabric/Surface/RCTFabricSurface.mm +++ b/React/Fabric/Surface/RCTFabricSurface.mm @@ -10,6 +10,10 @@ #import #import +#import +#import +#import +#import #import #import #import @@ -23,26 +27,19 @@ using namespace facebook::react; @implementation RCTFabricSurface { - // Immutable __weak RCTSurfacePresenter *_surfacePresenter; - NSString *_moduleName; - // Protected by the `_mutex` - std::mutex _mutex; - RCTSurfaceStage _stage; - NSDictionary *_properties; - CGSize _minimumSize; - CGSize _maximumSize; - CGPoint _viewportOffset; - CGSize _intrinsicSize; + // `SurfaceHandler` is a thread-safe object, so we don't need additional synchronization. + // Objective-C++ classes cannot have instance variables without default constructors, + // hence we wrap a value into `optional` to workaround it. + better::optional _surfaceHandler; - // The Main thread only + // Can be accessed from the main thread only. RCTSurfaceView *_Nullable _view; RCTSurfaceTouchHandler *_Nullable _touchHandler; } @synthesize delegate = _delegate; -@synthesize rootTag = _rootTag; - (instancetype)initWithSurfacePresenter:(RCTSurfacePresenter *)surfacePresenter moduleName:(NSString *)moduleName @@ -50,15 +47,19 @@ using namespace facebook::react; { if (self = [super init]) { _surfacePresenter = surfacePresenter; - _moduleName = moduleName; - _properties = [initialProperties copy]; - _rootTag = [RCTAllocateRootViewTag() integerValue]; - _minimumSize = CGSizeZero; + _surfaceHandler = + SurfaceHandler{RCTStringFromNSString(moduleName), (SurfaceId)[RCTAllocateRootViewTag() integerValue]}; + _surfaceHandler->setProps(convertIdToFollyDynamic(initialProperties)); - _maximumSize = CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX); + [_surfacePresenter registerSurface:self]; - _stage = RCTSurfaceStageSurfaceDidInitialize; + [self _updateLayoutContext]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(handleContentSizeCategoryDidChangeNotification:) + name:UIContentSizeCategoryDidChangeNotification + object:nil]; } return self; @@ -67,40 +68,48 @@ using namespace facebook::react; - (void)resetWithSurfacePresenter:(RCTSurfacePresenter *)surfacePresenter { _surfacePresenter = surfacePresenter; - _stage = RCTSurfaceStageSurfaceDidInitialize; _view = nil; } +- (void)dealloc +{ + [_surfacePresenter unregisterSurface:self]; +} + +#pragma mark - Life-cycle management + - (BOOL)start { - if (![self _setStage:RCTSurfaceStageRunning]) { - return NO; - } + _surfaceHandler->start(); + [self _propagateStageChange]; - [_surfacePresenter registerSurface:self]; + RCTExecuteOnMainQueue(^{ + [self->_surfacePresenter.mountingManager attachSurfaceToView:self.view + surfaceId:self->_surfaceHandler->getSurfaceId()]; + }); + + [_surfacePresenter setupAnimationDriverWithSurfaceHandler:*_surfaceHandler]; return YES; } - (BOOL)stop { - if (![self _unsetStage:RCTSurfaceStageRunning]) { - return NO; - } + _surfaceHandler->stop(); + [self _propagateStageChange]; + + RCTExecuteOnMainQueue(^{ + [self->_surfacePresenter.mountingManager detachSurfaceFromView:self.view + surfaceId:self->_surfaceHandler->getSurfaceId()]; + }); - [_surfacePresenter unregisterSurface:self]; return YES; } -- (void)dealloc -{ - [self stop]; -} - #pragma mark - Immutable Properties (no need to enforce synchronization) - (NSString *)moduleName { - return _moduleName; + return RCTNSStringFromString(_surfaceHandler->getModuleName()); } #pragma mark - Main-Threaded Routines @@ -122,49 +131,13 @@ using namespace facebook::react; - (RCTSurfaceStage)stage { - std::lock_guard lock(_mutex); - return _stage; + return _surfaceHandler->getStatus() == SurfaceHandler::Status::Running ? RCTSurfaceStageRunning + : RCTSurfaceStagePreparing; } -- (BOOL)_setStage:(RCTSurfaceStage)stage +- (void)_propagateStageChange { - return [self _setStage:stage setOrUnset:YES]; -} - -- (BOOL)_unsetStage:(RCTSurfaceStage)stage -{ - return [self _setStage:stage setOrUnset:NO]; -} - -- (BOOL)_setStage:(RCTSurfaceStage)stage setOrUnset:(BOOL)setOrUnset -{ - RCTSurfaceStage updatedStage; - { - std::lock_guard lock(_mutex); - - if (setOrUnset) { - updatedStage = (RCTSurfaceStage)(_stage | stage); - } else { - updatedStage = (RCTSurfaceStage)(_stage & ~stage); - } - - if (updatedStage == _stage) { - return NO; - } - - _stage = updatedStage; - } - - [self _propagateStageChange:updatedStage]; - return YES; -} - -- (void)_propagateStageChange:(RCTSurfaceStage)stage -{ - // Updating the `view` - RCTExecuteOnMainQueue(^{ - self->_view.stage = stage; - }); + RCTSurfaceStage stage = self.stage; // Notifying the `delegate` id delegate = self.delegate; @@ -173,114 +146,113 @@ using namespace facebook::react; } } +- (void)_updateLayoutContext +{ + auto layoutConstraints = _surfaceHandler->getLayoutConstraints(); + auto layoutContext = _surfaceHandler->getLayoutContext(); + + layoutContext.pointScaleFactor = RCTScreenScale(); + layoutContext.swapLeftAndRightInRTL = + [[RCTI18nUtil sharedInstance] isRTL] && [[RCTI18nUtil sharedInstance] doLeftAndRightSwapInRTL]; + layoutContext.fontSizeMultiplier = RCTFontSizeMultiplier(); + + _surfaceHandler->constraintLayout(layoutConstraints, layoutContext); +} + #pragma mark - Properties Management - (NSDictionary *)properties { - std::lock_guard lock(_mutex); - return _properties; + return convertFollyDynamicToId(_surfaceHandler->getProps()); } - (void)setProperties:(NSDictionary *)properties { - { - std::lock_guard lock(_mutex); - - if ([properties isEqualToDictionary:_properties]) { - return; - } - - _properties = [properties copy]; - } - - [_surfacePresenter setProps:properties surface:self]; + _surfaceHandler->setProps(convertIdToFollyDynamic(properties)); } #pragma mark - Layout -- (CGSize)sizeThatFitsMinimumSize:(CGSize)minimumSize maximumSize:(CGSize)maximumSize -{ - return [_surfacePresenter sizeThatFitsMinimumSize:minimumSize maximumSize:maximumSize surface:self]; -} - -#pragma mark - Size Constraints - -- (void)setSize:(CGSize)size -{ - [self setMinimumSize:size maximumSize:size viewportOffset:_viewportOffset]; -} - - (void)setMinimumSize:(CGSize)minimumSize maximumSize:(CGSize)maximumSize viewportOffset:(CGPoint)viewportOffset { - { - std::lock_guard lock(_mutex); - if (CGSizeEqualToSize(minimumSize, _minimumSize) && CGSizeEqualToSize(maximumSize, _maximumSize) && - CGPointEqualToPoint(viewportOffset, _viewportOffset)) { - return; - } + auto layoutConstraints = _surfaceHandler->getLayoutConstraints(); + auto layoutContext = _surfaceHandler->getLayoutContext(); - _maximumSize = maximumSize; - _minimumSize = minimumSize; - _viewportOffset = viewportOffset; + layoutConstraints.minimumSize = RCTSizeFromCGSize(minimumSize); + layoutConstraints.maximumSize = RCTSizeFromCGSize(maximumSize); + + if (!isnan(viewportOffset.x) && !isnan(viewportOffset.y)) { + layoutContext.viewportOffset = RCTPointFromCGPoint(viewportOffset); } - [_surfacePresenter setMinimumSize:minimumSize maximumSize:maximumSize surface:self]; + _surfaceHandler->constraintLayout(layoutConstraints, layoutContext); } - (void)setMinimumSize:(CGSize)minimumSize maximumSize:(CGSize)maximumSize { - [self setMinimumSize:minimumSize maximumSize:maximumSize viewportOffset:_viewportOffset]; + [self setMinimumSize:minimumSize maximumSize:maximumSize viewportOffset:CGPointMake(NAN, NAN)]; +} + +- (void)setSize:(CGSize)size +{ + [self setMinimumSize:size maximumSize:size]; +} + +- (CGSize)sizeThatFitsMinimumSize:(CGSize)minimumSize maximumSize:(CGSize)maximumSize +{ + auto layoutConstraints = _surfaceHandler->getLayoutConstraints(); + auto layoutContext = _surfaceHandler->getLayoutContext(); + + layoutConstraints.minimumSize = RCTSizeFromCGSize(minimumSize); + layoutConstraints.maximumSize = RCTSizeFromCGSize(maximumSize); + + return RCTCGSizeFromSize(_surfaceHandler->measure(layoutConstraints, layoutContext)); } - (CGSize)minimumSize { - std::lock_guard lock(_mutex); - return _minimumSize; + return RCTCGSizeFromSize(_surfaceHandler->getLayoutConstraints().minimumSize); } - (CGSize)maximumSize { - std::lock_guard lock(_mutex); - return _maximumSize; + return RCTCGSizeFromSize(_surfaceHandler->getLayoutConstraints().maximumSize); } - (CGPoint)viewportOffset { - std::lock_guard lock(_mutex); - return _viewportOffset; -} - -#pragma mark - intrinsicSize - -- (void)setIntrinsicSize:(CGSize)intrinsicSize -{ - { - std::lock_guard lock(_mutex); - if (CGSizeEqualToSize(intrinsicSize, _intrinsicSize)) { - return; - } - - _intrinsicSize = intrinsicSize; - } - - // Notifying `delegate` - id delegate = self.delegate; - if ([delegate respondsToSelector:@selector(surface:didChangeIntrinsicSize:)]) { - [delegate surface:(RCTSurface *)(id)self didChangeIntrinsicSize:intrinsicSize]; - } -} - -- (CGSize)intrinsicSize -{ - std::lock_guard lock(_mutex); - return _intrinsicSize; + return RCTCGPointFromPoint(_surfaceHandler->getLayoutContext().viewportOffset); } #pragma mark - Synchronous Waiting - (BOOL)synchronouslyWaitFor:(NSTimeInterval)timeout { - return [_surfacePresenter synchronouslyWaitSurface:self timeout:timeout]; + auto mountingCoordinator = _surfaceHandler->getMountingCoordinator(); + + if (!mountingCoordinator) { + return NO; + } + + if (!mountingCoordinator->waitForTransaction(std::chrono::duration(timeout))) { + return NO; + } + + [_surfacePresenter.mountingManager scheduleTransaction:mountingCoordinator]; + + return YES; +} + +- (void)handleContentSizeCategoryDidChangeNotification:(NSNotification *)notification +{ + [self _updateLayoutContext]; +} + +#pragma mark - Private + +- (SurfaceHandler const &)surfaceHandler; +{ + return *_surfaceHandler; } #pragma mark - Deprecated @@ -296,7 +268,12 @@ using namespace facebook::react; - (NSNumber *)rootViewTag { - return @(_rootTag); + return @(_surfaceHandler->getSurfaceId()); +} + +- (NSInteger)rootTag +{ + return (NSInteger)(_surfaceHandler->getSurfaceId()); } @end