diff --git a/engine/src/flutter/ci/licenses_golden/licenses_flutter b/engine/src/flutter/ci/licenses_golden/licenses_flutter index bcfc9aeac2..c20489d122 100644 --- a/engine/src/flutter/ci/licenses_golden/licenses_flutter +++ b/engine/src/flutter/ci/licenses_golden/licenses_flutter @@ -44564,8 +44564,6 @@ ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatf ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPluginTest.mm + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsController.h + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsController.mm + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPluginAppLifeCycleDelegate.mm + ../../../flutter/LICENSE @@ -44627,6 +44625,8 @@ ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/overlay_laye ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/overlay_layer_pool.mm + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.mm + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/platform_views_controller.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/platform_views_controller.mm + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/profiler_metrics_ios.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/profiler_metrics_ios.mm + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.h + ../../../flutter/LICENSE @@ -47500,8 +47500,6 @@ FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatfor FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPluginTest.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm -FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsController.h -FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsController.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPluginAppLifeCycleDelegate.mm @@ -47563,6 +47561,8 @@ FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/overlay_layer_ FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/overlay_layer_pool.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.mm +FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/platform_views_controller.h +FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/platform_views_controller.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/profiler_metrics_ios.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/profiler_metrics_ios.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.h diff --git a/engine/src/flutter/shell/platform/darwin/ios/BUILD.gn b/engine/src/flutter/shell/platform/darwin/ios/BUILD.gn index 4a0eeac21c..95f2dfa9ff 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/BUILD.gn +++ b/engine/src/flutter/shell/platform/darwin/ios/BUILD.gn @@ -80,8 +80,6 @@ source_set("flutter_framework_source") { "framework/Source/FlutterPlatformPlugin.h", "framework/Source/FlutterPlatformPlugin.mm", "framework/Source/FlutterPlatformViews.mm", - "framework/Source/FlutterPlatformViewsController.h", - "framework/Source/FlutterPlatformViewsController.mm", "framework/Source/FlutterPlatformViews_Internal.h", "framework/Source/FlutterPluginAppLifeCycleDelegate.mm", "framework/Source/FlutterRestorationPlugin.h", @@ -122,6 +120,8 @@ source_set("flutter_framework_source") { "framework/Source/overlay_layer_pool.mm", "framework/Source/platform_message_response_darwin.h", "framework/Source/platform_message_response_darwin.mm", + "framework/Source/platform_views_controller.h", + "framework/Source/platform_views_controller.mm", "framework/Source/profiler_metrics_ios.h", "framework/Source/profiler_metrics_ios.mm", "framework/Source/vsync_waiter_ios.h", diff --git a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm index eff08e6cc5..85f1ba5519 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm +++ b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm @@ -105,8 +105,6 @@ static constexpr int kNumProfilerSamplesPerSec = 5; @property(nonatomic, readonly, assign) BOOL allowHeadlessExecution; @property(nonatomic, readonly, assign) BOOL restorationEnabled; -@property(nonatomic, strong) FlutterPlatformViewsController* platformViewsController; - // Maintains a dictionary of plugin names that have registered with the engine. Used by // FlutterEngineRegistrar to implement a FlutterPluginRegistrar. @property(nonatomic, readonly) NSMutableDictionary* pluginPublications; @@ -152,6 +150,7 @@ static constexpr int kNumProfilerSamplesPerSec = 5; std::shared_ptr _threadHost; std::unique_ptr _shell; + std::shared_ptr _platformViewsController; flutter::IOSRenderingAPI _renderingApi; std::shared_ptr _profiler; @@ -212,7 +211,7 @@ static constexpr int kNumProfilerSamplesPerSec = 5; _pluginPublications = [[NSMutableDictionary alloc] init]; _registrars = [[NSMutableDictionary alloc] init]; - [self recreatePlatformViewsController]; + [self recreatePlatformViewController]; _binaryMessenger = [[FlutterBinaryMessengerRelay alloc] initWithParent:self]; _textureRegistry = [[FlutterTextureRegistryRelay alloc] initWithParent:self]; _connections.reset(new flutter::ConnectionCollection()); @@ -263,9 +262,9 @@ static constexpr int kNumProfilerSamplesPerSec = 5; object:nil]; } -- (void)recreatePlatformViewsController { +- (void)recreatePlatformViewController { _renderingApi = flutter::GetRenderingAPIForProcess(FlutterView.forceSoftwareRendering); - _platformViewsController = [[FlutterPlatformViewsController alloc] init]; + _platformViewsController.reset(new flutter::PlatformViewsController()); } - (flutter::IOSRenderingAPI)platformViewsRenderingAPI { @@ -453,7 +452,11 @@ static constexpr int kNumProfilerSamplesPerSec = 5; _shell.reset(); _profiler.reset(); _threadHost.reset(); - _platformViewsController = nil; + _platformViewsController.reset(); +} + +- (std::shared_ptr&)platformViewsController { + return _platformViewsController; } - (NSURL*)observatoryUrl { @@ -632,7 +635,7 @@ static constexpr int kNumProfilerSamplesPerSec = 5; [self.platformViewsChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) { if (weakSelf) { - [weakSelf.platformViewsController onMethodCall:call result:result]; + weakSelf.platformViewsController->OnMethodCall(call, result); } }]; @@ -774,11 +777,11 @@ static void SetEntryPoint(flutter::Settings* settings, NSString* entrypoint, NSS if (!strongSelf) { return std::unique_ptr(); } - [strongSelf recreatePlatformViewsController]; - strongSelf.platformViewsController.taskRunner = - shell.GetTaskRunners().GetPlatformTaskRunner(); + [strongSelf recreatePlatformViewController]; + strongSelf->_platformViewsController->SetTaskRunner( + shell.GetTaskRunners().GetPlatformTaskRunner()); return std::make_unique( - shell, strongSelf->_renderingApi, strongSelf.platformViewsController, + shell, strongSelf->_renderingApi, strongSelf->_platformViewsController, shell.GetTaskRunners(), shell.GetConcurrentWorkerTaskRunner(), shell.GetIsGpuDisabledSyncSwitch()); }; @@ -1100,7 +1103,7 @@ static void SetEntryPoint(flutter::Settings* settings, NSString* entrypoint, NSS // Have to check in the next run loop, because iOS requests the previous first responder to // resign before requesting the next view to become first responder. dispatch_async(dispatch_get_main_queue(), ^(void) { - long platform_view_id = [self.platformViewsController firstResponderPlatformViewId]; + long platform_view_id = self.platformViewsController->FindFirstResponderPlatformViewId(); if (platform_view_id == -1) { return; } @@ -1397,10 +1400,11 @@ static void SetEntryPoint(flutter::Settings* settings, NSString* entrypoint, NSS // create call is synchronous. flutter::Shell::CreateCallback on_create_platform_view = [result, context](flutter::Shell& shell) { - [result recreatePlatformViewsController]; - result.platformViewsController.taskRunner = shell.GetTaskRunners().GetPlatformTaskRunner(); + [result recreatePlatformViewController]; + result->_platformViewsController->SetTaskRunner( + shell.GetTaskRunners().GetPlatformTaskRunner()); return std::make_unique( - shell, context, result.platformViewsController, shell.GetTaskRunners()); + shell, context, result->_platformViewsController, shell.GetTaskRunners()); }; flutter::Shell::CreateCallback on_create_rasterizer = @@ -1495,9 +1499,8 @@ static void SetEntryPoint(flutter::Settings* settings, NSString* entrypoint, NSS withId:(NSString*)factoryId gestureRecognizersBlockingPolicy: (FlutterPlatformViewGestureRecognizersBlockingPolicy)gestureRecognizersBlockingPolicy { - [_flutterEngine.platformViewsController registerViewFactory:factory - withId:factoryId - gestureRecognizersBlockingPolicy:gestureRecognizersBlockingPolicy]; + [_flutterEngine platformViewsController]->RegisterViewFactory(factory, factoryId, + gestureRecognizersBlockingPolicy); } @end diff --git a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h index bb3beca9db..6f954adbcb 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h +++ b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h @@ -46,6 +46,7 @@ NS_ASSUME_NONNULL_BEGIN base64Encode:(bool)base64Encode; - (FlutterPlatformPlugin*)platformPlugin; +- (std::shared_ptr&)platformViewsController; - (FlutterTextInputPlugin*)textInputPlugin; - (FlutterRestorationPlugin*)restorationPlugin; - (void)launchEngine:(nullable NSString*)entrypoint @@ -80,7 +81,6 @@ NS_ASSUME_NONNULL_BEGIN userData:(nullable void*)userData; @property(nonatomic, readonly) FlutterDartProject* project; - @end NS_ASSUME_NONNULL_END diff --git a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index a0e140e6e4..ce38124365 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -518,7 +518,8 @@ static BOOL _preparedOnce = NO; @implementation FlutterTouchInterceptingView - (instancetype)initWithEmbeddedView:(UIView*)embeddedView - platformViewsController:(FlutterPlatformViewsController*)platformViewsController + platformViewsController: + (fml::WeakPtr)platformViewsController gestureRecognizersBlockingPolicy: (FlutterPlatformViewGestureRecognizersBlockingPolicy)blockingPolicy { self = [super initWithFrame:embeddedView.frame]; @@ -666,7 +667,7 @@ static BOOL _preparedOnce = NO; // outlives the FlutterViewController. And ForwardingGestureRecognizer is owned by a subview of // FlutterView, so the ForwardingGestureRecognizer never out lives FlutterViewController. // Therefore, `_platformViewsController` should never be nullptr. - __weak FlutterPlatformViewsController* _platformViewsController; + fml::WeakPtr _platformViewsController; // Counting the pointers that has started in one touch sequence. NSInteger _currentTouchPointersCount; // We can't dispatch events to the framework without this back pointer. @@ -677,12 +678,13 @@ static BOOL _preparedOnce = NO; } - (instancetype)initWithTarget:(id)target - platformViewsController:(FlutterPlatformViewsController*)platformViewsController { + platformViewsController: + (fml::WeakPtr)platformViewsController { self = [super initWithTarget:target action:nil]; if (self) { self.delegate = self; - FML_DCHECK(platformViewsController); - _platformViewsController = platformViewsController; + FML_DCHECK(platformViewsController.get() != nullptr); + _platformViewsController = std::move(platformViewsController); _currentTouchPointersCount = 0; } return self; @@ -690,7 +692,7 @@ static BOOL _preparedOnce = NO; - (ForwardingGestureRecognizer*)recreateRecognizerWithTarget:(id)target { return [[ForwardingGestureRecognizer alloc] initWithTarget:target - platformViewsController:_platformViewsController]; + platformViewsController:std::move(_platformViewsController)]; } - (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { @@ -699,7 +701,7 @@ static BOOL _preparedOnce = NO; // At the start of each gesture sequence, we reset the `_flutterViewController`, // so that all the touch events in the same sequence are forwarded to the same // `_flutterViewController`. - _flutterViewController = _platformViewsController.flutterViewController; + _flutterViewController = _platformViewsController->GetFlutterViewController(); } [_flutterViewController touchesBegan:touches withEvent:event]; _currentTouchPointersCount += touches.count; diff --git a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsController.h b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsController.h deleted file mode 100644 index 9ce3c7f8ac..0000000000 --- a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsController.h +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERPLATFORMVIEWSCONTROLLER_H_ -#define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERPLATFORMVIEWSCONTROLLER_H_ - -#include -#include -#include -#include - -#include "flutter/flow/surface.h" -#include "flutter/fml/task_runner.h" -#include "flutter/fml/trace_event.h" -#include "impeller/base/thread_safety.h" -#include "third_party/skia/include/core/SkRect.h" - -#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterChannels.h" -#import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterPlatformViews.h" -#import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterPlugin.h" -#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewResponder.h" -#import "flutter/shell/platform/darwin/ios/framework/Source/overlay_layer_pool.h" -#import "flutter/shell/platform/darwin/ios/ios_context.h" - -@class FlutterTouchInterceptingView; -@class FlutterClippingMaskViewPool; - -@interface FlutterPlatformViewsController : NSObject - -- (id)init NS_DESIGNATED_INITIALIZER; - -/// The task runner used to post rendering tasks to the platform thread. -@property(nonatomic, assign) const fml::RefPtr& taskRunner; - -/// The flutter view. -@property(nonatomic, weak) UIView* flutterView; - -/// @brief The flutter view controller. -@property(nonatomic, weak) UIViewController* flutterViewController; - -/// @brief Retrieve the view controller. -- (UIViewController*)flutterViewController; - -/// @brief set the factory used to construct embedded UI Views. -- (void)registerViewFactory:(NSObject*)factory - withId:(NSString*)factoryId - gestureRecognizersBlockingPolicy: - (FlutterPlatformViewGestureRecognizersBlockingPolicy)gestureRecognizerBlockingPolicy; - -/// @brief Mark the beginning of a frame and record the size of the onscreen. -- (void)beginFrameWithSize:(SkISize)frameSize; - -/// @brief Cancel the current frame, indicating that no platform views are composited. -/// -/// Additionally, reverts the composition order to its original state at the beginning of the -/// frame. -- (void)cancelFrame; - -/// @brief Record a platform view in the layer tree to be rendered, along with the positioning and -/// mutator parameters. -/// -/// Called from the raster thread. -- (void)prerollCompositeEmbeddedView:(int64_t)viewId - withParams:(std::unique_ptr)params; - -/// @brief Returns the`FlutterTouchInterceptingView` with the provided view_id. -/// -/// Returns nil if there is no platform view with the provided id. Called -/// from the platform thread. -- (FlutterTouchInterceptingView*)flutterTouchInterceptingViewForId:(int64_t)viewId; - -/// @brief Determine if thread merging is required after prerolling platform views. -/// -/// Called from the raster thread. -- (flutter::PostPrerollResult)postPrerollActionWithThreadMerger: - (const fml::RefPtr&)rasterThreadMerger - impellerEnabled:(BOOL)impellerEnabled; - -/// @brief Mark the end of a compositor frame. -/// -/// May determine changes are required to the thread merging state. -/// Called from the raster thread. -- (void)endFrameWithResubmit:(BOOL)shouldResubmitFrame - threadMerger:(const fml::RefPtr&)rasterThreadMerger - impellerEnabled:(BOOL)impellerEnabled; - -/// @brief Returns the Canvas for the overlay slice for the given platform view. -/// -/// Called from the raster thread. -- (flutter::DlCanvas*)compositeEmbeddedViewWithId:(int64_t)viewId; - -/// @brief Discards all platform views instances and auxiliary resources. -/// -/// Called from the raster thread. -- (void)reset; - -/// @brief Encode rendering for the Flutter overlay views and queue up perform platform view -/// mutations. -/// -/// Called from the raster thread. -- (BOOL)submitFrame:(std::unique_ptr)frame - withIosContext:(const std::shared_ptr&)iosContext - grContext:(GrDirectContext*)grContext; - -/// @brief Handler for platform view message channels. -- (void)onMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result; - -/// @brief Returns the platform view id if the platform view (or any of its descendant view) is -/// the first responder. -/// -/// Returns -1 if no such platform view is found. -- (long)firstResponderPlatformViewId; - -/// @brief Pushes backdrop filter mutation to the mutator stack of each visited platform view. -- (void)pushFilterToVisitedPlatformViews:(const std::shared_ptr&)filter - withRect:(const SkRect&)filterRect; - -/// @brief Pushes the view id of a visted platform view to the list of visied platform views. -- (void)pushVisitedPlatformViewId:(int64_t)viewId; - -@end - -@interface FlutterPlatformViewsController (Testing) - -- (size_t)embeddedViewCount; - -// Returns the `FlutterPlatformView`'s `view` object associated with the view_id. -// -// If the `PlatformViewsController` does not contain any `FlutterPlatformView` object or -// a `FlutterPlatformView` object associated with the view_id cannot be found, the method -// returns nil. -- (UIView*)platformViewForId:(int64_t)viewId; - -// Composite the PlatformView with `viewId`. -// -// Every frame, during the paint traversal of the layer tree, this method is called for all -// the PlatformViews in `_viewsToRecomposite`. -// -// Note that `_viewsToRecomposite` does not represent all the views in the view hierarchy, -// if a PlatformView does not change its composition parameter from last frame, it is not -// included in the `views_to_recomposite_`. -- (void)compositeView:(int64_t)viewId withParams:(const flutter::EmbeddedViewParams&)params; - -- (const flutter::EmbeddedViewParams&)compositionParamsForView:(int64_t)viewId; - -@end - -#endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERPLATFORMVIEWSCONTROLLER_H_ diff --git a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsController.mm b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsController.mm deleted file mode 100644 index 6c7cfe822e..0000000000 --- a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsController.mm +++ /dev/null @@ -1,1073 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsController.h" - -#include "flutter/display_list/effects/image_filters/dl_blur_image_filter.h" -#include "flutter/flow/surface_frame.h" -#include "flutter/flow/view_slicer.h" -#include "flutter/fml/make_copyable.h" -#include "flutter/fml/synchronization/count_down_latch.h" -#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.h" -#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterView.h" -#include "flutter/shell/platform/darwin/ios/framework/Source/overlay_layer_pool.h" -#import "flutter/shell/platform/darwin/ios/ios_surface.h" - -// The number of frames the rasterizer task runner will continue -// to run on the platform thread after no platform view is rendered. -// -// Note: this is an arbitrary number. -static constexpr int kDefaultMergedLeaseDuration = 10; - -static constexpr NSUInteger kFlutterClippingMaskViewPoolCapacity = 5; - -struct LayerData { - SkRect rect; - int64_t view_id; - int64_t overlay_id; - std::shared_ptr layer; -}; -using LayersMap = std::unordered_map; - -/// Each of the following structs stores part of the platform view hierarchy according to its -/// ID. -/// -/// This data must only be accessed on the platform thread. -struct PlatformViewData { - NSObject* view; - FlutterTouchInterceptingView* touch_interceptor; - UIView* root_view; -}; - -// Converts a SkMatrix to CATransform3D. -// -// Certain fields are ignored in CATransform3D since SkMatrix is 3x3 and CATransform3D is 4x4. -static CATransform3D GetCATransform3DFromSkMatrix(const SkMatrix& matrix) { - // Skia only supports 2D transform so we don't map z. - CATransform3D transform = CATransform3DIdentity; - transform.m11 = matrix.getScaleX(); - transform.m21 = matrix.getSkewX(); - transform.m41 = matrix.getTranslateX(); - transform.m14 = matrix.getPerspX(); - - transform.m12 = matrix.getSkewY(); - transform.m22 = matrix.getScaleY(); - transform.m42 = matrix.getTranslateY(); - transform.m24 = matrix.getPerspY(); - return transform; -} - -// Reset the anchor of `layer` to match the transform operation from flow. -// -// The position of the `layer` should be unchanged after resetting the anchor. -static void ResetAnchor(CALayer* layer) { - // Flow uses (0, 0) to apply transform matrix so we need to match that in Quartz. - layer.anchorPoint = CGPointZero; - layer.position = CGPointZero; -} - -static CGRect GetCGRectFromSkRect(const SkRect& clipSkRect) { - return CGRectMake(clipSkRect.fLeft, clipSkRect.fTop, clipSkRect.fRight - clipSkRect.fLeft, - clipSkRect.fBottom - clipSkRect.fTop); -} - -// Determines if the `clip_rect` from a clipRect mutator contains the -// `platformview_boundingrect`. -// -// `clip_rect` is in its own coordinate space. The rect needs to be transformed by -// `transform_matrix` to be in the coordinate space where the PlatformView is displayed. -// -// `platformview_boundingrect` is the final bounding rect of the PlatformView in the coordinate -// space where the PlatformView is displayed. -static bool ClipRectContainsPlatformViewBoundingRect(const SkRect& clip_rect, - const SkRect& platformview_boundingrect, - const SkMatrix& transform_matrix) { - SkRect transformed_rect = transform_matrix.mapRect(clip_rect); - return transformed_rect.contains(platformview_boundingrect); -} - -// Determines if the `clipRRect` from a clipRRect mutator contains the -// `platformview_boundingrect`. -// -// `clip_rrect` is in its own coordinate space. The rrect needs to be transformed by -// `transform_matrix` to be in the coordinate space where the PlatformView is displayed. -// -// `platformview_boundingrect` is the final bounding rect of the PlatformView in the coordinate -// space where the PlatformView is displayed. -static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect, - const SkRect& platformview_boundingrect, - const SkMatrix& transform_matrix) { - SkVector upper_left = clip_rrect.radii(SkRRect::Corner::kUpperLeft_Corner); - SkVector upper_right = clip_rrect.radii(SkRRect::Corner::kUpperRight_Corner); - SkVector lower_right = clip_rrect.radii(SkRRect::Corner::kLowerRight_Corner); - SkVector lower_left = clip_rrect.radii(SkRRect::Corner::kLowerLeft_Corner); - SkScalar transformed_upper_left_x = transform_matrix.mapRadius(upper_left.x()); - SkScalar transformed_upper_left_y = transform_matrix.mapRadius(upper_left.y()); - SkScalar transformed_upper_right_x = transform_matrix.mapRadius(upper_right.x()); - SkScalar transformed_upper_right_y = transform_matrix.mapRadius(upper_right.y()); - SkScalar transformed_lower_right_x = transform_matrix.mapRadius(lower_right.x()); - SkScalar transformed_lower_right_y = transform_matrix.mapRadius(lower_right.y()); - SkScalar transformed_lower_left_x = transform_matrix.mapRadius(lower_left.x()); - SkScalar transformed_lower_left_y = transform_matrix.mapRadius(lower_left.y()); - SkRect transformed_clip_rect = transform_matrix.mapRect(clip_rrect.rect()); - SkRRect transformed_rrect; - SkVector corners[] = {{transformed_upper_left_x, transformed_upper_left_y}, - {transformed_upper_right_x, transformed_upper_right_y}, - {transformed_lower_right_x, transformed_lower_right_y}, - {transformed_lower_left_x, transformed_lower_left_y}}; - transformed_rrect.setRectRadii(transformed_clip_rect, corners); - return transformed_rrect.contains(platformview_boundingrect); -} - -@interface FlutterPlatformViewsController () - -// The pool of reusable view layers. The pool allows to recycle layer in each frame. -@property(nonatomic, readonly) flutter::OverlayLayerPool* layerPool; - -// The platform view's |EmbedderViewSlice| keyed off the view id, which contains any subsequent -// operation until the next platform view or the end of the last leaf node in the layer tree. -// -// The Slices are deleted by the PlatformViewsController.reset(). -@property(nonatomic, readonly) - std::unordered_map>& slices; - -@property(nonatomic, readonly) FlutterClippingMaskViewPool* maskViewPool; - -@property(nonatomic, readonly) - std::unordered_map*>& factories; - -// The FlutterPlatformViewGestureRecognizersBlockingPolicy for each type of platform view. -@property(nonatomic, readonly) - std::unordered_map& - gestureRecognizersBlockingPolicies; - -/// The size of the current onscreen surface in physical pixels. -@property(nonatomic, assign) SkISize frameSize; - -/// The task runner for posting tasks to the platform thread. -@property(nonatomic, readonly) const fml::RefPtr& platformTaskRunner; - -/// This data must only be accessed on the platform thread. -@property(nonatomic, readonly) std::unordered_map& platformViews; - -/// The composition parameters for each platform view. -/// -/// This state is only modified on the raster thread. -@property(nonatomic, readonly) - std::unordered_map& currentCompositionParams; - -/// Method channel `OnDispose` calls adds the views to be disposed to this set to be disposed on -/// the next frame. -/// -/// This state is modified on both the platform and raster thread. -@property(nonatomic, readonly) std::unordered_set& viewsToDispose; - -/// view IDs in composition order. -/// -/// This state is only modified on the raster thread. -@property(nonatomic, readonly) std::vector& compositionOrder; - -/// platform view IDs visited during layer tree composition. -/// -/// This state is only modified on the raster thread. -@property(nonatomic, readonly) std::vector& visitedPlatformViews; - -/// Only composite platform views in this set. -/// -/// This state is only modified on the raster thread. -@property(nonatomic, readonly) std::unordered_set& viewsToRecomposite; - -/// @brief The composition order from the previous thread. -/// -/// Only accessed from the platform thread. -@property(nonatomic, readonly) std::vector& previousCompositionOrder; - -/// Whether the previous frame had any platform views in active composition order. -/// -/// This state is tracked so that the first frame after removing the last platform view -/// runs through the platform view rendering code path, giving us a chance to remove the -/// platform view from the UIView hierarchy. -/// -/// Only accessed from the raster thread. -@property(nonatomic, assign) BOOL hadPlatformViews; - -/// Whether blurred backdrop filters can be applied. -/// -/// Defaults to YES, but becomes NO if blurred backdrop filters cannot be applied. -@property(nonatomic, assign) BOOL canApplyBlurBackdrop; - -/// Populate any missing overlay layers. -/// -/// This requires posting a task to the platform thread and blocking on its completion. -- (void)createMissingOverlays:(size_t)requiredOverlayLayers - withIosContext:(const std::shared_ptr&)iosContext - grContext:(GrDirectContext*)grContext; - -/// Update the buffers and mutate the platform views in CATransaction on the platform thread. -- (void)performSubmit:(const LayersMap&)platformViewLayers - currentCompositionParams: - (std::unordered_map&)currentCompositionParams - viewsToRecomposite:(const std::unordered_set&)viewsToRecomposite - compositionOrder:(const std::vector&)compositionOrder - unusedLayers: - (const std::vector>&)unusedLayers - surfaceFrames: - (const std::vector>&)surfaceFrames; - -- (void)onCreate:(FlutterMethodCall*)call result:(FlutterResult)result; -- (void)onDispose:(FlutterMethodCall*)call result:(FlutterResult)result; -- (void)onAcceptGesture:(FlutterMethodCall*)call result:(FlutterResult)result; -- (void)onRejectGesture:(FlutterMethodCall*)call result:(FlutterResult)result; - -- (void)clipViewSetMaskView:(UIView*)clipView; - -// Applies the mutators in the mutatorsStack to the UIView chain that was constructed by -// `ReconstructClipViewsChain` -// -// Clips are applied to the `embeddedView`'s super view(|ChildClippingView|) using a -// |FlutterClippingMaskView|. Transforms are applied to `embeddedView` -// -// The `boundingRect` is the final bounding rect of the PlatformView -// (EmbeddedViewParams::finalBoundingRect). If a clip mutator's rect contains the final bounding -// rect of the PlatformView, the clip mutator is not applied for performance optimization. -// -// This method is only called when the `embeddedView` needs to be re-composited at the current -// frame. See: `compositeView:withParams:` for details. -- (void)applyMutators:(const flutter::MutatorsStack&)mutatorsStack - embeddedView:(UIView*)embeddedView - boundingRect:(const SkRect&)boundingRect; - -// Appends the overlay views and platform view and sets their z index based on the composition -// order. -- (void)bringLayersIntoView:(const LayersMap&)layerMap - withCompositionOrder:(const std::vector&)compositionOrder; - -- (std::shared_ptr)nextLayerInPool; - -/// Runs on the platform thread. -- (void)createLayerWithIosContext:(const std::shared_ptr&)iosContext - grContext:(GrDirectContext*)grContext - pixelFormat:(MTLPixelFormat)pixelFormat; - -/// Removes overlay views and platform views that aren't needed in the current frame. -/// Must run on the platform thread. -- (void)removeUnusedLayers:(const std::vector>&)unusedLayers - withCompositionOrder:(const std::vector&)compositionOrder; - -/// Computes and returns all views to be disposed on the platform thread, removes them from -/// self.platformViews, self.viewsToRecomposite, and self.currentCompositionParams. Any views that -/// still require compositing are not returned, but instead added to `viewsToDelayDispose` for -/// disposal on the next call. -- (std::vector)computeViewsToDispose; - -/// Resets the state of the frame. -- (void)resetFrameState; -@end - -@implementation FlutterPlatformViewsController { - // TODO(cbracken): Replace with Obj-C types and use @property declarations to automatically - // synthesize the ivars. - // - // These ivars are required because we're transitioning the previous C++ implementation to Obj-C. - // We require ivars to declare the concrete types and then wrap with @property declarations that - // return a reference to the ivar, allowing for use like `self.layerPool` and - // `self.slices[viewId] = x`. - std::unique_ptr _layerPool; - std::unordered_map> _slices; - std::unordered_map*> _factories; - std::unordered_map - _gestureRecognizersBlockingPolicies; - fml::RefPtr _platformTaskRunner; - std::unordered_map _platformViews; - std::unordered_map _currentCompositionParams; - std::unordered_set _viewsToDispose; - std::vector _compositionOrder; - std::vector _visitedPlatformViews; - std::unordered_set _viewsToRecomposite; - std::vector _previousCompositionOrder; -} - -- (id)init { - if (self = [super init]) { - _layerPool = std::make_unique(); - _maskViewPool = - [[FlutterClippingMaskViewPool alloc] initWithCapacity:kFlutterClippingMaskViewPoolCapacity]; - _hadPlatformViews = NO; - _canApplyBlurBackdrop = YES; - } - return self; -} - -- (const fml::RefPtr&)taskRunner { - return _platformTaskRunner; -} - -- (void)setTaskRunner:(const fml::RefPtr&)platformTaskRunner { - _platformTaskRunner = platformTaskRunner; -} - -- (void)onMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { - if ([[call method] isEqualToString:@"create"]) { - [self onCreate:call result:result]; - } else if ([[call method] isEqualToString:@"dispose"]) { - [self onDispose:call result:result]; - } else if ([[call method] isEqualToString:@"acceptGesture"]) { - [self onAcceptGesture:call result:result]; - } else if ([[call method] isEqualToString:@"rejectGesture"]) { - [self onRejectGesture:call result:result]; - } else { - result(FlutterMethodNotImplemented); - } -} - -- (void)onCreate:(FlutterMethodCall*)call result:(FlutterResult)result { - NSDictionary* args = [call arguments]; - - int64_t viewId = [args[@"id"] longLongValue]; - NSString* viewTypeString = args[@"viewType"]; - std::string viewType(viewTypeString.UTF8String); - - if (self.platformViews.count(viewId) != 0) { - result([FlutterError errorWithCode:@"recreating_view" - message:@"trying to create an already created view" - details:[NSString stringWithFormat:@"view id: '%lld'", viewId]]); - return; - } - - NSObject* factory = self.factories[viewType]; - if (factory == nil) { - result([FlutterError - errorWithCode:@"unregistered_view_type" - message:[NSString stringWithFormat:@"A UIKitView widget is trying to create a " - @"PlatformView with an unregistered type: < %@ >", - viewTypeString] - details:@"If you are the author of the PlatformView, make sure `registerViewFactory` " - @"is invoked.\n" - @"See: " - @"https://docs.flutter.dev/development/platform-integration/" - @"platform-views#on-the-platform-side-1 for more details.\n" - @"If you are not the author of the PlatformView, make sure to call " - @"`GeneratedPluginRegistrant.register`."]); - return; - } - - id params = nil; - if ([factory respondsToSelector:@selector(createArgsCodec)]) { - NSObject* codec = [factory createArgsCodec]; - if (codec != nil && args[@"params"] != nil) { - FlutterStandardTypedData* paramsData = args[@"params"]; - params = [codec decode:paramsData.data]; - } - } - - NSObject* embeddedView = [factory createWithFrame:CGRectZero - viewIdentifier:viewId - arguments:params]; - UIView* platformView = [embeddedView view]; - // Set a unique view identifier, so the platform view can be identified in unit tests. - platformView.accessibilityIdentifier = [NSString stringWithFormat:@"platform_view[%lld]", viewId]; - - FlutterTouchInterceptingView* touchInterceptor = [[FlutterTouchInterceptingView alloc] - initWithEmbeddedView:platformView - platformViewsController:self - gestureRecognizersBlockingPolicy:self.gestureRecognizersBlockingPolicies[viewType]]; - - ChildClippingView* clippingView = [[ChildClippingView alloc] initWithFrame:CGRectZero]; - [clippingView addSubview:touchInterceptor]; - - self.platformViews.emplace(viewId, PlatformViewData{ - .view = embeddedView, // - .touch_interceptor = touchInterceptor, // - .root_view = clippingView // - }); - - result(nil); -} - -- (void)onDispose:(FlutterMethodCall*)call result:(FlutterResult)result { - NSNumber* arg = [call arguments]; - int64_t viewId = [arg longLongValue]; - - if (self.platformViews.count(viewId) == 0) { - result([FlutterError errorWithCode:@"unknown_view" - message:@"trying to dispose an unknown" - details:[NSString stringWithFormat:@"view id: '%lld'", viewId]]); - return; - } - // We wait for next submitFrame to dispose views. - self.viewsToDispose.insert(viewId); - result(nil); -} - -- (void)onAcceptGesture:(FlutterMethodCall*)call result:(FlutterResult)result { - NSDictionary* args = [call arguments]; - int64_t viewId = [args[@"id"] longLongValue]; - - if (self.platformViews.count(viewId) == 0) { - result([FlutterError errorWithCode:@"unknown_view" - message:@"trying to set gesture state for an unknown view" - details:[NSString stringWithFormat:@"view id: '%lld'", viewId]]); - return; - } - - FlutterTouchInterceptingView* view = self.platformViews[viewId].touch_interceptor; - [view releaseGesture]; - - result(nil); -} - -- (void)onRejectGesture:(FlutterMethodCall*)call result:(FlutterResult)result { - NSDictionary* args = [call arguments]; - int64_t viewId = [args[@"id"] longLongValue]; - - if (self.platformViews.count(viewId) == 0) { - result([FlutterError errorWithCode:@"unknown_view" - message:@"trying to set gesture state for an unknown view" - details:[NSString stringWithFormat:@"view id: '%lld'", viewId]]); - return; - } - - FlutterTouchInterceptingView* view = self.platformViews[viewId].touch_interceptor; - [view blockGesture]; - - result(nil); -} - -- (void)registerViewFactory:(NSObject*)factory - withId:(NSString*)factoryId - gestureRecognizersBlockingPolicy: - (FlutterPlatformViewGestureRecognizersBlockingPolicy)gestureRecognizerBlockingPolicy { - std::string idString([factoryId UTF8String]); - FML_CHECK(self.factories.count(idString) == 0); - self.factories[idString] = factory; - self.gestureRecognizersBlockingPolicies[idString] = gestureRecognizerBlockingPolicy; -} - -- (void)beginFrameWithSize:(SkISize)frameSize { - [self resetFrameState]; - self.frameSize = frameSize; -} - -- (void)cancelFrame { - [self resetFrameState]; -} - -- (flutter::PostPrerollResult)postPrerollActionWithThreadMerger: - (const fml::RefPtr&)rasterThreadMerger - impellerEnabled:(BOOL)impellerEnabled { - // TODO(jonahwilliams): remove this once Software backend is removed for iOS Sim. -#ifdef FML_OS_IOS_SIMULATOR - const bool mergeThreads = true; -#else - const bool mergeThreads = !impellerEnabled; -#endif // FML_OS_IOS_SIMULATOR - - if (mergeThreads) { - if (self.compositionOrder.empty()) { - return flutter::PostPrerollResult::kSuccess; - } - if (!rasterThreadMerger->IsMerged()) { - // The raster thread merger may be disabled if the rasterizer is being - // created or teared down. - // - // In such cases, the current frame is dropped, and a new frame is attempted - // with the same layer tree. - // - // Eventually, the frame is submitted once this method returns `kSuccess`. - // At that point, the raster tasks are handled on the platform thread. - [self cancelFrame]; - return flutter::PostPrerollResult::kSkipAndRetryFrame; - } - // If the post preroll action is successful, we will display platform views in the current - // frame. In order to sync the rendering of the platform views (quartz) with skia's rendering, - // We need to begin an explicit CATransaction. This transaction needs to be submitted - // after the current frame is submitted. - rasterThreadMerger->ExtendLeaseTo(kDefaultMergedLeaseDuration); - } - return flutter::PostPrerollResult::kSuccess; -} - -- (void)endFrameWithResubmit:(BOOL)shouldResubmitFrame - threadMerger:(const fml::RefPtr&)rasterThreadMerger - impellerEnabled:(BOOL)impellerEnabled { -#if FML_OS_IOS_SIMULATOR - BOOL runCheck = YES; -#else - BOOL runCheck = !impellerEnabled; -#endif // FML_OS_IOS_SIMULATOR - if (runCheck && shouldResubmitFrame) { - rasterThreadMerger->MergeWithLease(kDefaultMergedLeaseDuration); - } -} - -- (void)pushFilterToVisitedPlatformViews:(const std::shared_ptr&)filter - withRect:(const SkRect&)filterRect { - for (int64_t id : self.visitedPlatformViews) { - flutter::EmbeddedViewParams params = self.currentCompositionParams[id]; - params.PushImageFilter(filter, filterRect); - self.currentCompositionParams[id] = params; - } -} - -- (void)prerollCompositeEmbeddedView:(int64_t)viewId - withParams:(std::unique_ptr)params { - SkRect viewBounds = SkRect::Make(self.frameSize); - std::unique_ptr view; - view = std::make_unique(viewBounds); - self.slices.insert_or_assign(viewId, std::move(view)); - - self.compositionOrder.push_back(viewId); - - if (self.currentCompositionParams.count(viewId) == 1 && - self.currentCompositionParams[viewId] == *params.get()) { - // Do nothing if the params didn't change. - return; - } - self.currentCompositionParams[viewId] = flutter::EmbeddedViewParams(*params.get()); - self.viewsToRecomposite.insert(viewId); -} - -- (size_t)embeddedViewCount { - return self.compositionOrder.size(); -} - -- (UIView*)platformViewForId:(int64_t)viewId { - return [self flutterTouchInterceptingViewForId:viewId].embeddedView; -} - -- (FlutterTouchInterceptingView*)flutterTouchInterceptingViewForId:(int64_t)viewId { - if (self.platformViews.empty()) { - return nil; - } - return self.platformViews[viewId].touch_interceptor; -} - -- (long)firstResponderPlatformViewId { - for (auto const& [id, platformViewData] : self.platformViews) { - UIView* rootView = platformViewData.root_view; - if (rootView.flt_hasFirstResponderInViewHierarchySubtree) { - return id; - } - } - return -1; -} - -- (void)clipViewSetMaskView:(UIView*)clipView { - FML_DCHECK([[NSThread currentThread] isMainThread]); - if (clipView.maskView) { - return; - } - CGRect frame = - CGRectMake(-clipView.frame.origin.x, -clipView.frame.origin.y, - CGRectGetWidth(self.flutterView.bounds), CGRectGetHeight(self.flutterView.bounds)); - clipView.maskView = [self.maskViewPool getMaskViewWithFrame:frame]; -} - -- (void)applyMutators:(const flutter::MutatorsStack&)mutatorsStack - embeddedView:(UIView*)embeddedView - boundingRect:(const SkRect&)boundingRect { - if (self.flutterView == nil) { - return; - } - - ResetAnchor(embeddedView.layer); - ChildClippingView* clipView = (ChildClippingView*)embeddedView.superview; - - SkMatrix transformMatrix; - NSMutableArray* blurFilters = [[NSMutableArray alloc] init]; - FML_DCHECK(!clipView.maskView || - [clipView.maskView isKindOfClass:[FlutterClippingMaskView class]]); - if (clipView.maskView) { - [self.maskViewPool insertViewToPoolIfNeeded:(FlutterClippingMaskView*)(clipView.maskView)]; - clipView.maskView = nil; - } - CGFloat screenScale = [UIScreen mainScreen].scale; - auto iter = mutatorsStack.Begin(); - while (iter != mutatorsStack.End()) { - switch ((*iter)->GetType()) { - case flutter::kTransform: { - transformMatrix.preConcat((*iter)->GetMatrix()); - break; - } - case flutter::kClipRect: { - if (ClipRectContainsPlatformViewBoundingRect((*iter)->GetRect(), boundingRect, - transformMatrix)) { - break; - } - [self clipViewSetMaskView:clipView]; - [(FlutterClippingMaskView*)clipView.maskView clipRect:(*iter)->GetRect() - matrix:transformMatrix]; - break; - } - case flutter::kClipRRect: { - if (ClipRRectContainsPlatformViewBoundingRect((*iter)->GetRRect(), boundingRect, - transformMatrix)) { - break; - } - [self clipViewSetMaskView:clipView]; - [(FlutterClippingMaskView*)clipView.maskView clipRRect:(*iter)->GetRRect() - matrix:transformMatrix]; - break; - } - case flutter::kClipPath: { - // TODO(cyanglaz): Find a way to pre-determine if path contains the PlatformView boudning - // rect. See `ClipRRectContainsPlatformViewBoundingRect`. - // https://github.com/flutter/flutter/issues/118650 - [self clipViewSetMaskView:clipView]; - [(FlutterClippingMaskView*)clipView.maskView clipPath:(*iter)->GetPath() - matrix:transformMatrix]; - break; - } - case flutter::kOpacity: - embeddedView.alpha = (*iter)->GetAlphaFloat() * embeddedView.alpha; - break; - case flutter::kBackdropFilter: { - // Only support DlBlurImageFilter for BackdropFilter. - if (!self.canApplyBlurBackdrop || !(*iter)->GetFilterMutation().GetFilter().asBlur()) { - break; - } - CGRect filterRect = GetCGRectFromSkRect((*iter)->GetFilterMutation().GetFilterRect()); - // `filterRect` is in global coordinates. We need to convert to local space. - filterRect = CGRectApplyAffineTransform( - filterRect, CGAffineTransformMakeScale(1 / screenScale, 1 / screenScale)); - // `filterRect` reprents the rect that should be filtered inside the `_flutterView`. - // The `PlatformViewFilter` needs the frame inside the `clipView` that needs to be - // filtered. - if (CGRectIsNull(CGRectIntersection(filterRect, clipView.frame))) { - break; - } - CGRect intersection = CGRectIntersection(filterRect, clipView.frame); - CGRect frameInClipView = [self.flutterView convertRect:intersection toView:clipView]; - // sigma_x is arbitrarily chosen as the radius value because Quartz sets - // sigma_x and sigma_y equal to each other. DlBlurImageFilter's Tile Mode - // is not supported in Quartz's gaussianBlur CAFilter, so it is not used - // to blur the PlatformView. - CGFloat blurRadius = (*iter)->GetFilterMutation().GetFilter().asBlur()->sigma_x(); - UIVisualEffectView* visualEffectView = [[UIVisualEffectView alloc] - initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]]; - PlatformViewFilter* filter = [[PlatformViewFilter alloc] initWithFrame:frameInClipView - blurRadius:blurRadius - visualEffectView:visualEffectView]; - if (!filter) { - self.canApplyBlurBackdrop = NO; - } else { - [blurFilters addObject:filter]; - } - break; - } - } - ++iter; - } - - if (self.canApplyBlurBackdrop) { - [clipView applyBlurBackdropFilters:blurFilters]; - } - - // The UIKit frame is set based on the logical resolution (points) instead of physical. - // (https://developer.apple.com/library/archive/documentation/DeviceInformation/Reference/iOSDeviceCompatibility/Displays/Displays.html). - // However, flow is based on the physical resolution. For example, 1000 pixels in flow equals - // 500 points in UIKit for devices that has screenScale of 2. We need to scale the transformMatrix - // down to the logical resoltion before applying it to the layer of PlatformView. - transformMatrix.postScale(1 / screenScale, 1 / screenScale); - - // Reverse the offset of the clipView. - // The clipView's frame includes the final translate of the final transform matrix. - // Thus, this translate needs to be reversed so the platform view can layout at the correct - // offset. - // - // Note that the transforms are not applied to the clipping paths because clipping paths happen on - // the mask view, whose origin is always (0,0) to the _flutterView. - transformMatrix.postTranslate(-clipView.frame.origin.x, -clipView.frame.origin.y); - - embeddedView.layer.transform = GetCATransform3DFromSkMatrix(transformMatrix); -} - -- (void)compositeView:(int64_t)viewId withParams:(const flutter::EmbeddedViewParams&)params { - // TODO(https://github.com/flutter/flutter/issues/109700) - CGRect frame = CGRectMake(0, 0, params.sizePoints().width(), params.sizePoints().height()); - FlutterTouchInterceptingView* touchInterceptor = self.platformViews[viewId].touch_interceptor; - touchInterceptor.layer.transform = CATransform3DIdentity; - touchInterceptor.frame = frame; - touchInterceptor.alpha = 1; - - const flutter::MutatorsStack& mutatorStack = params.mutatorsStack(); - UIView* clippingView = self.platformViews[viewId].root_view; - // The frame of the clipping view should be the final bounding rect. - // Because the translate matrix in the Mutator Stack also includes the offset, - // when we apply the transforms matrix in |applyMutators:embeddedView:boundingRect|, we need - // to remember to do a reverse translate. - const SkRect& rect = params.finalBoundingRect(); - CGFloat screenScale = [UIScreen mainScreen].scale; - clippingView.frame = CGRectMake(rect.x() / screenScale, rect.y() / screenScale, - rect.width() / screenScale, rect.height() / screenScale); - [self applyMutators:mutatorStack embeddedView:touchInterceptor boundingRect:rect]; -} - -- (flutter::DlCanvas*)compositeEmbeddedViewWithId:(int64_t)viewId { - return self.slices[viewId]->canvas(); -} - -- (void)reset { - // Reset will only be called from the raster thread or a merged raster/platform thread. - // _platformViews must only be modified on the platform thread, and any operations that - // read or modify platform views should occur there. - fml::TaskRunner::RunNowOrPostTask(self.platformTaskRunner, [self]() { - for (int64_t viewId : self.compositionOrder) { - [self.platformViews[viewId].root_view removeFromSuperview]; - } - self.platformViews.clear(); - }); - - self.compositionOrder.clear(); - self.slices.clear(); - self.currentCompositionParams.clear(); - self.viewsToRecomposite.clear(); - self.layerPool->RecycleLayers(); - self.visitedPlatformViews.clear(); -} - -- (BOOL)submitFrame:(std::unique_ptr)background_frame - withIosContext:(const std::shared_ptr&)iosContext - grContext:(GrDirectContext*)grContext { - TRACE_EVENT0("flutter", "PlatformViewsController::SubmitFrame"); - - // No platform views to render; we're done. - if (self.flutterView == nil || (self.compositionOrder.empty() && !self.hadPlatformViews)) { - self.hadPlatformViews = NO; - return background_frame->Submit(); - } - self.hadPlatformViews = !self.compositionOrder.empty(); - - bool didEncode = true; - LayersMap platformViewLayers; - std::vector> surfaceFrames; - surfaceFrames.reserve(self.compositionOrder.size()); - std::unordered_map viewRects; - - for (int64_t viewId : self.compositionOrder) { - viewRects[viewId] = self.currentCompositionParams[viewId].finalBoundingRect(); - } - - std::unordered_map overlayLayers = - SliceViews(background_frame->Canvas(), self.compositionOrder, self.slices, viewRects); - - size_t requiredOverlayLayers = 0; - for (int64_t viewId : self.compositionOrder) { - std::unordered_map::const_iterator overlay = overlayLayers.find(viewId); - if (overlay == overlayLayers.end()) { - continue; - } - requiredOverlayLayers++; - } - - // If there are not sufficient overlay layers, we must construct them on the platform - // thread, at least until we've refactored iOS surface creation to use IOSurfaces - // instead of CALayers. - [self createMissingOverlays:requiredOverlayLayers withIosContext:iosContext grContext:grContext]; - - int64_t overlayId = 0; - for (int64_t viewId : self.compositionOrder) { - std::unordered_map::const_iterator overlay = overlayLayers.find(viewId); - if (overlay == overlayLayers.end()) { - continue; - } - std::shared_ptr layer = self.nextLayerInPool; - if (!layer) { - continue; - } - - std::unique_ptr frame = layer->surface->AcquireFrame(self.frameSize); - // If frame is null, AcquireFrame already printed out an error message. - if (!frame) { - continue; - } - flutter::DlCanvas* overlayCanvas = frame->Canvas(); - int restoreCount = overlayCanvas->GetSaveCount(); - overlayCanvas->Save(); - overlayCanvas->ClipRect(overlay->second); - overlayCanvas->Clear(flutter::DlColor::kTransparent()); - self.slices[viewId]->render_into(overlayCanvas); - overlayCanvas->RestoreToCount(restoreCount); - - // This flutter view is never the last in a frame, since we always submit the - // underlay view last. - frame->set_submit_info({.frame_boundary = false, .present_with_transaction = true}); - layer->did_submit_last_frame = frame->Encode(); - - didEncode &= layer->did_submit_last_frame; - platformViewLayers[viewId] = LayerData{ - .rect = overlay->second, // - .view_id = viewId, // - .overlay_id = overlayId, // - .layer = layer // - }; - surfaceFrames.push_back(std::move(frame)); - overlayId++; - } - - auto previousSubmitInfo = background_frame->submit_info(); - background_frame->set_submit_info({ - .frame_damage = previousSubmitInfo.frame_damage, - .buffer_damage = previousSubmitInfo.buffer_damage, - .present_with_transaction = true, - }); - background_frame->Encode(); - surfaceFrames.push_back(std::move(background_frame)); - - // Mark all layers as available, so they can be used in the next frame. - std::vector> unusedLayers = - self.layerPool->RemoveUnusedLayers(); - self.layerPool->RecycleLayers(); - - auto task = [&, // - platformViewLayers = std::move(platformViewLayers), // - currentCompositionParams = self.currentCompositionParams, // - viewsToRecomposite = self.viewsToRecomposite, // - compositionOrder = self.compositionOrder, // - unusedLayers = std::move(unusedLayers), // - surfaceFrames = std::move(surfaceFrames) // - ]() mutable { - [self performSubmit:platformViewLayers - currentCompositionParams:currentCompositionParams - viewsToRecomposite:viewsToRecomposite - compositionOrder:compositionOrder - unusedLayers:unusedLayers - surfaceFrames:surfaceFrames]; - }; - - fml::TaskRunner::RunNowOrPostTask(self.platformTaskRunner, fml::MakeCopyable(std::move(task))); - - return didEncode; -} - -- (void)createMissingOverlays:(size_t)requiredOverlayLayers - withIosContext:(const std::shared_ptr&)iosContext - grContext:(GrDirectContext*)grContext { - TRACE_EVENT0("flutter", "PlatformViewsController::CreateMissingLayers"); - - if (requiredOverlayLayers <= self.layerPool->size()) { - return; - } - auto missingLayerCount = requiredOverlayLayers - self.layerPool->size(); - - // If the raster thread isn't merged, create layers on the platform thread and block until - // complete. - auto latch = std::make_shared(1u); - fml::TaskRunner::RunNowOrPostTask(self.platformTaskRunner, [&]() { - for (auto i = 0u; i < missingLayerCount; i++) { - [self createLayerWithIosContext:iosContext - grContext:grContext - pixelFormat:((FlutterView*)self.flutterView).pixelFormat]; - } - latch->CountDown(); - }); - if (![[NSThread currentThread] isMainThread]) { - latch->Wait(); - } -} - -- (void)performSubmit:(const LayersMap&)platformViewLayers - currentCompositionParams: - (std::unordered_map&)currentCompositionParams - viewsToRecomposite:(const std::unordered_set&)viewsToRecomposite - compositionOrder:(const std::vector&)compositionOrder - unusedLayers: - (const std::vector>&)unusedLayers - surfaceFrames: - (const std::vector>&)surfaceFrames { - TRACE_EVENT0("flutter", "PlatformViewsController::PerformSubmit"); - FML_DCHECK([[NSThread currentThread] isMainThread]); - - [CATransaction begin]; - - // Configure Flutter overlay views. - for (const auto& [viewId, layerData] : platformViewLayers) { - layerData.layer->UpdateViewState(self.flutterView, // - layerData.rect, // - layerData.view_id, // - layerData.overlay_id // - ); - } - - // Dispose unused Flutter Views. - for (auto& view : [self computeViewsToDispose]) { - [view removeFromSuperview]; - } - - // Composite Platform Views. - for (int64_t viewId : viewsToRecomposite) { - [self compositeView:viewId withParams:currentCompositionParams[viewId]]; - } - - // Present callbacks. - for (const auto& frame : surfaceFrames) { - frame->Submit(); - } - - // If a layer was allocated in the previous frame, but it's not used in the current frame, - // then it can be removed from the scene. - [self removeUnusedLayers:unusedLayers withCompositionOrder:compositionOrder]; - - // Organize the layers by their z indexes. - [self bringLayersIntoView:platformViewLayers withCompositionOrder:compositionOrder]; - - [CATransaction commit]; -} - -- (void)bringLayersIntoView:(const LayersMap&)layerMap - withCompositionOrder:(const std::vector&)compositionOrder { - FML_DCHECK(self.flutterView); - UIView* flutterView = self.flutterView; - - self.previousCompositionOrder.clear(); - NSMutableArray* desiredPlatformSubviews = [NSMutableArray array]; - for (int64_t platformViewId : compositionOrder) { - self.previousCompositionOrder.push_back(platformViewId); - UIView* platformViewRoot = self.platformViews[platformViewId].root_view; - if (platformViewRoot != nil) { - [desiredPlatformSubviews addObject:platformViewRoot]; - } - - auto maybeLayerData = layerMap.find(platformViewId); - if (maybeLayerData != layerMap.end()) { - auto view = maybeLayerData->second.layer->overlay_view_wrapper; - if (view != nil) { - [desiredPlatformSubviews addObject:view]; - } - } - } - - NSSet* desiredPlatformSubviewsSet = [NSSet setWithArray:desiredPlatformSubviews]; - NSArray* existingPlatformSubviews = [flutterView.subviews - filteredArrayUsingPredicate:[NSPredicate - predicateWithBlock:^BOOL(id object, NSDictionary* bindings) { - return [desiredPlatformSubviewsSet containsObject:object]; - }]]; - - // Manipulate view hierarchy only if needed, to address a performance issue where - // this method is called even when view hierarchy stays the same. - // See: https://github.com/flutter/flutter/issues/121833 - // TODO(hellohuanlin): investigate if it is possible to skip unnecessary bringLayersIntoView. - if (![desiredPlatformSubviews isEqualToArray:existingPlatformSubviews]) { - for (UIView* subview in desiredPlatformSubviews) { - // `addSubview` will automatically reorder subview if it is already added. - [flutterView addSubview:subview]; - } - } -} - -- (std::shared_ptr)nextLayerInPool { - return self.layerPool->GetNextLayer(); -} - -- (void)createLayerWithIosContext:(const std::shared_ptr&)iosContext - grContext:(GrDirectContext*)grContext - pixelFormat:(MTLPixelFormat)pixelFormat { - self.layerPool->CreateLayer(grContext, iosContext, pixelFormat); -} - -- (void)removeUnusedLayers:(const std::vector>&)unusedLayers - withCompositionOrder:(const std::vector&)compositionOrder { - for (const std::shared_ptr& layer : unusedLayers) { - [layer->overlay_view_wrapper removeFromSuperview]; - } - - std::unordered_set compositionOrderSet; - for (int64_t viewId : compositionOrder) { - compositionOrderSet.insert(viewId); - } - // Remove unused platform views. - for (int64_t viewId : self.previousCompositionOrder) { - if (compositionOrderSet.find(viewId) == compositionOrderSet.end()) { - UIView* platformViewRoot = self.platformViews[viewId].root_view; - [platformViewRoot removeFromSuperview]; - } - } -} - -- (std::vector)computeViewsToDispose { - std::vector views; - if (self.viewsToDispose.empty()) { - return views; - } - - std::unordered_set viewsToComposite(self.compositionOrder.begin(), - self.compositionOrder.end()); - std::unordered_set viewsToDelayDispose; - for (int64_t viewId : self.viewsToDispose) { - if (viewsToComposite.count(viewId)) { - viewsToDelayDispose.insert(viewId); - continue; - } - UIView* rootView = self.platformViews[viewId].root_view; - views.push_back(rootView); - self.currentCompositionParams.erase(viewId); - self.viewsToRecomposite.erase(viewId); - self.platformViews.erase(viewId); - } - self.viewsToDispose = std::move(viewsToDelayDispose); - return views; -} - -- (void)resetFrameState { - self.slices.clear(); - self.compositionOrder.clear(); - self.visitedPlatformViews.clear(); -} - -- (void)pushVisitedPlatformViewId:(int64_t)viewId { - self.visitedPlatformViews.push_back(viewId); -} - -- (const flutter::EmbeddedViewParams&)compositionParamsForView:(int64_t)viewId { - return self.currentCompositionParams.find(viewId)->second; -} - -#pragma mark - Properties - -- (flutter::OverlayLayerPool*)layerPool { - return _layerPool.get(); -} - -- (std::unordered_map>&)slices { - return _slices; -} - -- (std::unordered_map*>&)factories { - return _factories; -} -- (std::unordered_map&) - gestureRecognizersBlockingPolicies { - return _gestureRecognizersBlockingPolicies; -} - -- (std::unordered_map&)platformViews { - return _platformViews; -} - -- (std::unordered_map&)currentCompositionParams { - return _currentCompositionParams; -} - -- (std::unordered_set&)viewsToDispose { - return _viewsToDispose; -} - -- (std::vector&)compositionOrder { - return _compositionOrder; -} - -- (std::vector&)visitedPlatformViews { - return _visitedPlatformViews; -} - -- (std::unordered_set&)viewsToRecomposite { - return _viewsToRecomposite; -} - -- (std::vector&)previousCompositionOrder { - return _previousCompositionOrder; -} - -@end diff --git a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm index dd48e60364..8c0bb2b03e 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm +++ b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm @@ -2,22 +2,21 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterPlatformViews.h" - #import #import #import +#include "fml/synchronization/count_down_latch.h" +#include "shell/platform/darwin/ios/framework/Source/platform_views_controller.h" -#include "flutter/display_list/effects/dl_image_filters.h" -#include "flutter/fml/synchronization/count_down_latch.h" -#include "flutter/fml/thread.h" +#import "flutter/display_list/effects/dl_image_filters.h" +#import "flutter/fml/thread.h" #import "flutter/shell/platform/darwin/common/framework/Headers/FlutterMacros.h" +#import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterPlatformViews.h" #import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h" #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h" -#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsController.h" #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h" #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterTouchInterceptingView_Test.h" -#include "flutter/shell/platform/darwin/ios/platform_view_ios.h" +#import "flutter/shell/platform/darwin/ios/platform_view_ios.h" FLUTTER_ASSERT_ARC @@ -164,9 +163,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -179,21 +177,18 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @2, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], + result); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)]; - flutterPlatformViewsController.flutterView = flutterView; + flutterPlatformViewsController->SetFlutterView(flutterView); // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack @@ -209,12 +204,11 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams)]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); XCTAssertNotNil(gMockPlatformView); - [flutterPlatformViewsController reset]; + flutterPlatformViewsController->Reset(); } - (void)testCanCreatePlatformViewWithoutFlutterView { @@ -225,9 +219,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -240,19 +233,16 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @2, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], + result); XCTAssertNotNil(gMockPlatformView); } @@ -322,9 +312,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -337,24 +326,21 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @2, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], + result); XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; - flutterPlatformViewsController.flutterView = flutterView; + flutterPlatformViewsController->SetFlutterView(flutterView); // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack @@ -368,11 +354,9 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams)]; - [flutterPlatformViewsController - compositeView:2 - withParams:[flutterPlatformViewsController compositionParamsForView:2]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); + flutterPlatformViewsController->CompositeWithParams( + 2, flutterPlatformViewsController->GetCompositionParams(2)); XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:[ChildClippingView class]]); ChildClippingView* childClippingView = (ChildClippingView*)gMockPlatformView.superview.superview; @@ -405,9 +389,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -420,24 +403,21 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @2, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], + result); XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; - flutterPlatformViewsController.flutterView = flutterView; + flutterPlatformViewsController->SetFlutterView(flutterView); // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack @@ -451,11 +431,9 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(5, 10), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams)]; - [flutterPlatformViewsController - compositeView:2 - withParams:[flutterPlatformViewsController compositionParamsForView:2]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); + flutterPlatformViewsController->CompositeWithParams( + 2, flutterPlatformViewsController->GetCompositionParams(2)); XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:[ChildClippingView class]]); ChildClippingView* childClippingView = (ChildClippingView*)gMockPlatformView.superview.superview; @@ -488,9 +466,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -503,24 +480,21 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @2, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], + result); XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; - flutterPlatformViewsController.flutterView = flutterView; + flutterPlatformViewsController->SetFlutterView(flutterView); // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack @@ -536,11 +510,9 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(20, 20), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams)]; - [flutterPlatformViewsController - compositeView:2 - withParams:[flutterPlatformViewsController compositionParamsForView:2]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); + flutterPlatformViewsController->CompositeWithParams( + 2, flutterPlatformViewsController->GetCompositionParams(2)); XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:ChildClippingView.class]); ChildClippingView* childClippingView = (ChildClippingView*)gMockPlatformView.superview.superview; @@ -572,9 +544,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -587,24 +558,21 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @2, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], + result); XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; - flutterPlatformViewsController.flutterView = flutterView; + flutterPlatformViewsController->SetFlutterView(flutterView); // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack @@ -618,11 +586,9 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams)]; - [flutterPlatformViewsController - compositeView:2 - withParams:[flutterPlatformViewsController compositionParamsForView:2]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); + flutterPlatformViewsController->CompositeWithParams( + 2, flutterPlatformViewsController->GetCompositionParams(2)); XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:[ChildClippingView class]]); ChildClippingView* childClippingView = (ChildClippingView*)gMockPlatformView.superview.superview; @@ -659,11 +625,9 @@ fml::RefPtr GetDefaultTaskRunner() { embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack2); - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams)]; - [flutterPlatformViewsController - compositeView:2 - withParams:[flutterPlatformViewsController compositionParamsForView:2]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); + flutterPlatformViewsController->CompositeWithParams( + 2, flutterPlatformViewsController->GetCompositionParams(2)); [flutterView setNeedsLayout]; [flutterView layoutIfNeeded]; @@ -701,9 +665,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -716,24 +679,21 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @2, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], + result); XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; - flutterPlatformViewsController.flutterView = flutterView; + flutterPlatformViewsController->SetFlutterView(flutterView); // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack @@ -749,11 +709,9 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams)]; - [flutterPlatformViewsController - compositeView:2 - withParams:[flutterPlatformViewsController compositionParamsForView:2]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); + flutterPlatformViewsController->CompositeWithParams( + 2, flutterPlatformViewsController->GetCompositionParams(2)); XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:ChildClippingView.class]); ChildClippingView* childClippingView = (ChildClippingView*)gMockPlatformView.superview.superview; @@ -788,11 +746,9 @@ fml::RefPtr GetDefaultTaskRunner() { embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack2); - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams)]; - [flutterPlatformViewsController - compositeView:2 - withParams:[flutterPlatformViewsController compositionParamsForView:2]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); + flutterPlatformViewsController->CompositeWithParams( + 2, flutterPlatformViewsController->GetCompositionParams(2)); [flutterView setNeedsLayout]; [flutterView layoutIfNeeded]; @@ -831,11 +787,9 @@ fml::RefPtr GetDefaultTaskRunner() { embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack2); - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams)]; - [flutterPlatformViewsController - compositeView:2 - withParams:[flutterPlatformViewsController compositionParamsForView:2]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); + flutterPlatformViewsController->CompositeWithParams( + 2, flutterPlatformViewsController->GetCompositionParams(2)); [flutterView setNeedsLayout]; [flutterView layoutIfNeeded]; @@ -857,9 +811,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -872,24 +825,21 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @2, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], + result); XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; - flutterPlatformViewsController.flutterView = flutterView; + flutterPlatformViewsController->SetFlutterView(flutterView); // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack @@ -905,11 +855,9 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams)]; - [flutterPlatformViewsController - compositeView:2 - withParams:[flutterPlatformViewsController compositionParamsForView:2]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); + flutterPlatformViewsController->CompositeWithParams( + 2, flutterPlatformViewsController->GetCompositionParams(2)); XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:ChildClippingView.class]); ChildClippingView* childClippingView = (ChildClippingView*)gMockPlatformView.superview.superview; @@ -952,11 +900,9 @@ fml::RefPtr GetDefaultTaskRunner() { embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack2); - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams)]; - [flutterPlatformViewsController - compositeView:2 - withParams:[flutterPlatformViewsController compositionParamsForView:2]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); + flutterPlatformViewsController->CompositeWithParams( + 2, flutterPlatformViewsController->GetCompositionParams(2)); [flutterView setNeedsLayout]; [flutterView layoutIfNeeded]; @@ -1009,11 +955,9 @@ fml::RefPtr GetDefaultTaskRunner() { embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack2); - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams)]; - [flutterPlatformViewsController - compositeView:2 - withParams:[flutterPlatformViewsController compositionParamsForView:2]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); + flutterPlatformViewsController->CompositeWithParams( + 2, flutterPlatformViewsController->GetCompositionParams(2)); [flutterView setNeedsLayout]; [flutterView layoutIfNeeded]; @@ -1064,11 +1008,9 @@ fml::RefPtr GetDefaultTaskRunner() { embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack2); - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams)]; - [flutterPlatformViewsController - compositeView:2 - withParams:[flutterPlatformViewsController compositionParamsForView:2]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); + flutterPlatformViewsController->CompositeWithParams( + 2, flutterPlatformViewsController->GetCompositionParams(2)); [flutterView setNeedsLayout]; [flutterView layoutIfNeeded]; @@ -1116,11 +1058,9 @@ fml::RefPtr GetDefaultTaskRunner() { embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack2); - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams)]; - [flutterPlatformViewsController - compositeView:2 - withParams:[flutterPlatformViewsController compositionParamsForView:2]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); + flutterPlatformViewsController->CompositeWithParams( + 2, flutterPlatformViewsController->GetCompositionParams(2)); [flutterView setNeedsLayout]; [flutterView layoutIfNeeded]; @@ -1158,9 +1098,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -1173,24 +1112,21 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @2, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], + result); XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; - flutterPlatformViewsController.flutterView = flutterView; + flutterPlatformViewsController->SetFlutterView(flutterView); // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack @@ -1204,11 +1140,9 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams)]; - [flutterPlatformViewsController - compositeView:2 - withParams:[flutterPlatformViewsController compositionParamsForView:2]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); + flutterPlatformViewsController->CompositeWithParams( + 2, flutterPlatformViewsController->GetCompositionParams(2)); XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:[ChildClippingView class]]); ChildClippingView* childClippingView = (ChildClippingView*)gMockPlatformView.superview.superview; @@ -1248,11 +1182,9 @@ fml::RefPtr GetDefaultTaskRunner() { embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack2); - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams)]; - [flutterPlatformViewsController - compositeView:2 - withParams:[flutterPlatformViewsController compositionParamsForView:2]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); + flutterPlatformViewsController->CompositeWithParams( + 2, flutterPlatformViewsController->GetCompositionParams(2)); [flutterView setNeedsLayout]; [flutterView layoutIfNeeded]; @@ -1291,11 +1223,9 @@ fml::RefPtr GetDefaultTaskRunner() { embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack2); - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams)]; - [flutterPlatformViewsController - compositeView:2 - withParams:[flutterPlatformViewsController compositionParamsForView:2]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); + flutterPlatformViewsController->CompositeWithParams( + 2, flutterPlatformViewsController->GetCompositionParams(2)); [flutterView setNeedsLayout]; [flutterView layoutIfNeeded]; @@ -1334,11 +1264,9 @@ fml::RefPtr GetDefaultTaskRunner() { embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack2); - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams)]; - [flutterPlatformViewsController - compositeView:2 - withParams:[flutterPlatformViewsController compositionParamsForView:2]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); + flutterPlatformViewsController->CompositeWithParams( + 2, flutterPlatformViewsController->GetCompositionParams(2)); [flutterView setNeedsLayout]; [flutterView layoutIfNeeded]; @@ -1371,11 +1299,9 @@ fml::RefPtr GetDefaultTaskRunner() { embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack2); - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams)]; - [flutterPlatformViewsController - compositeView:2 - withParams:[flutterPlatformViewsController compositionParamsForView:2]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); + flutterPlatformViewsController->CompositeWithParams( + 2, flutterPlatformViewsController->GetCompositionParams(2)); [flutterView setNeedsLayout]; [flutterView layoutIfNeeded]; @@ -1491,9 +1417,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -1506,24 +1431,21 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @2, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], + result); XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)]; - flutterPlatformViewsController.flutterView = flutterView; + flutterPlatformViewsController->SetFlutterView(flutterView); // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack @@ -1539,11 +1461,9 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams)]; - [flutterPlatformViewsController - compositeView:2 - withParams:[flutterPlatformViewsController compositionParamsForView:2]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); + flutterPlatformViewsController->CompositeWithParams( + 2, flutterPlatformViewsController->GetCompositionParams(2)); CGRect platformViewRectInFlutterView = [gMockPlatformView convertRect:gMockPlatformView.bounds toView:flutterView]; @@ -1558,9 +1478,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -1573,24 +1492,21 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @2, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], + result); XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; - flutterPlatformViewsController.flutterView = flutterView; + flutterPlatformViewsController->SetFlutterView(flutterView); // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack @@ -1601,17 +1517,14 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack); - [flutterPlatformViewsController beginFrameWithSize:SkISize::Make(0, 0)]; - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams)]; - [flutterPlatformViewsController pushVisitedPlatformViewId:2]; + flutterPlatformViewsController->BeginFrame(SkISize::Make(0, 0)); + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); + flutterPlatformViewsController->PushVisitedPlatformView(2); auto filter = flutter::DlBlurImageFilter::Make(5, 2, flutter::DlTileMode::kClamp); - [flutterPlatformViewsController - pushFilterToVisitedPlatformViews:filter - withRect:SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)]; - [flutterPlatformViewsController - compositeView:2 - withParams:[flutterPlatformViewsController compositionParamsForView:2]]; + flutterPlatformViewsController->PushFilterToVisitedPlatformViews( + filter, SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); + flutterPlatformViewsController->CompositeWithParams( + 2, flutterPlatformViewsController->GetCompositionParams(2)); XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:[ChildClippingView class]]); ChildClippingView* childClippingView = (ChildClippingView*)gMockPlatformView.superview.superview; @@ -1638,12 +1551,10 @@ fml::RefPtr GetDefaultTaskRunner() { // New frame, with no filter pushed. auto embeddedViewParams2 = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack); - [flutterPlatformViewsController beginFrameWithSize:SkISize::Make(0, 0)]; - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams2)]; - [flutterPlatformViewsController - compositeView:2 - withParams:[flutterPlatformViewsController compositionParamsForView:2]]; + flutterPlatformViewsController->BeginFrame(SkISize::Make(0, 0)); + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams2)); + flutterPlatformViewsController->CompositeWithParams( + 2, flutterPlatformViewsController->GetCompositionParams(2)); XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:[ChildClippingView class]]); @@ -1668,9 +1579,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -1683,24 +1593,21 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @2, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], + result); XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)]; - flutterPlatformViewsController.flutterView = flutterView; + flutterPlatformViewsController->SetFlutterView(flutterView); // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack @@ -1717,11 +1624,9 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams)]; - [flutterPlatformViewsController - compositeView:2 - withParams:[flutterPlatformViewsController compositionParamsForView:2]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); + flutterPlatformViewsController->CompositeWithParams( + 2, flutterPlatformViewsController->GetCompositionParams(2)); CGRect platformViewRectInFlutterView = [gMockPlatformView convertRect:gMockPlatformView.bounds toView:flutterView]; @@ -1750,9 +1655,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -1765,24 +1669,21 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @2, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], + result); XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 30, 30)]; - flutterPlatformViewsController.flutterView = flutterView; + flutterPlatformViewsController->SetFlutterView(flutterView); // Create embedded view params. flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack. @@ -1804,11 +1705,9 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique( SkMatrix::Concat(screenScaleMatrix, translateMatrix), SkSize::Make(5, 5), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams)]; - [flutterPlatformViewsController - compositeView:2 - withParams:[flutterPlatformViewsController compositionParamsForView:2]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); + flutterPlatformViewsController->CompositeWithParams( + 2, flutterPlatformViewsController->GetCompositionParams(2)); gMockPlatformView.backgroundColor = UIColor.redColor; XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:ChildClippingView.class]); @@ -1828,9 +1727,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -1843,24 +1741,21 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @2, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], + result); XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 30, 30)]; - flutterPlatformViewsController.flutterView = flutterView; + flutterPlatformViewsController->SetFlutterView(flutterView); // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack. @@ -1880,11 +1775,9 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique( SkMatrix::Concat(screenScaleMatrix, translateMatrix), SkSize::Make(5, 5), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams)]; - [flutterPlatformViewsController - compositeView:2 - withParams:[flutterPlatformViewsController compositionParamsForView:2]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); + flutterPlatformViewsController->CompositeWithParams( + 2, flutterPlatformViewsController->GetCompositionParams(2)); gMockPlatformView.backgroundColor = UIColor.redColor; XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:ChildClippingView.class]); @@ -1905,9 +1798,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -1920,24 +1812,21 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @2, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], + result); XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; - flutterPlatformViewsController.flutterView = flutterView; + flutterPlatformViewsController->SetFlutterView(flutterView); // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack @@ -1951,11 +1840,9 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams)]; - [flutterPlatformViewsController - compositeView:2 - withParams:[flutterPlatformViewsController compositionParamsForView:2]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); + flutterPlatformViewsController->CompositeWithParams( + 2, flutterPlatformViewsController->GetCompositionParams(2)); gMockPlatformView.backgroundColor = UIColor.redColor; XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:ChildClippingView.class]); @@ -1987,9 +1874,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -2002,24 +1888,21 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @2, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], + result); XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; - flutterPlatformViewsController.flutterView = flutterView; + flutterPlatformViewsController->SetFlutterView(flutterView); // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack @@ -2036,11 +1919,9 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams)]; - [flutterPlatformViewsController - compositeView:2 - withParams:[flutterPlatformViewsController compositionParamsForView:2]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); + flutterPlatformViewsController->CompositeWithParams( + 2, flutterPlatformViewsController->GetCompositionParams(2)); gMockPlatformView.backgroundColor = UIColor.redColor; XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:ChildClippingView.class]); @@ -2089,9 +1970,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -2104,24 +1984,21 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @2, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], + result); XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; - flutterPlatformViewsController.flutterView = flutterView; + flutterPlatformViewsController->SetFlutterView(flutterView); // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack @@ -2135,11 +2012,9 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams)]; - [flutterPlatformViewsController - compositeView:2 - withParams:[flutterPlatformViewsController compositionParamsForView:2]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); + flutterPlatformViewsController->CompositeWithParams( + 2, flutterPlatformViewsController->GetCompositionParams(2)); gMockPlatformView.backgroundColor = UIColor.redColor; XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:ChildClippingView.class]); @@ -2198,9 +2073,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -2213,24 +2087,21 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @2, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], + result); XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; - flutterPlatformViewsController.flutterView = flutterView; + flutterPlatformViewsController->SetFlutterView(flutterView); // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack @@ -2247,11 +2118,9 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams)]; - [flutterPlatformViewsController - compositeView:2 - withParams:[flutterPlatformViewsController compositionParamsForView:2]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); + flutterPlatformViewsController->CompositeWithParams( + 2, flutterPlatformViewsController->GetCompositionParams(2)); gMockPlatformView.backgroundColor = UIColor.redColor; XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:ChildClippingView.class]); @@ -2324,9 +2193,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -2339,24 +2207,21 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @2, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], + result); XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; - flutterPlatformViewsController.flutterView = flutterView; + flutterPlatformViewsController->SetFlutterView(flutterView); // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack @@ -2371,11 +2236,9 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams)]; - [flutterPlatformViewsController - compositeView:2 - withParams:[flutterPlatformViewsController compositionParamsForView:2]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); + flutterPlatformViewsController->CompositeWithParams( + 2, flutterPlatformViewsController->GetCompositionParams(2)); gMockPlatformView.backgroundColor = UIColor.redColor; XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:ChildClippingView.class]); @@ -2434,9 +2297,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -2449,24 +2311,21 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @2, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], + result); XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; - flutterPlatformViewsController.flutterView = flutterView; + flutterPlatformViewsController->SetFlutterView(flutterView); // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack @@ -2484,11 +2343,9 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams)]; - [flutterPlatformViewsController - compositeView:2 - withParams:[flutterPlatformViewsController compositionParamsForView:2]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); + flutterPlatformViewsController->CompositeWithParams( + 2, flutterPlatformViewsController->GetCompositionParams(2)); gMockPlatformView.backgroundColor = UIColor.redColor; XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:ChildClippingView.class]); @@ -2561,9 +2418,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -2576,19 +2432,16 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @2, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], + result); XCTAssertNotNil(gMockPlatformView); @@ -2619,7 +2472,7 @@ fml::RefPtr GetDefaultTaskRunner() { // Set flutter view controller allows events to be dispatched. NSSet* touches2 = [[NSSet alloc] init]; id event2 = OCMClassMock([UIEvent class]); - flutterPlatformViewsController.flutterViewController = flutterViewController; + flutterPlatformViewsController->SetFlutterViewController(flutterViewController); [forwardGectureRecognizer touchesBegan:touches2 withEvent:event2]; OCMVerify([flutterViewController touchesBegan:touches2 withEvent:event2]); } @@ -2632,9 +2485,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -2647,19 +2499,16 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @2, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], + result); XCTAssertNotNil(gMockPlatformView); @@ -2682,14 +2531,14 @@ fml::RefPtr GetDefaultTaskRunner() { id flutterViewController = OCMClassMock([FlutterViewController class]); { // ***** Sequence 1, finishing touch event with touchEnded ***** // - flutterPlatformViewsController.flutterViewController = flutterViewController; + flutterPlatformViewsController->SetFlutterViewController(flutterViewController); NSSet* touches1 = [[NSSet alloc] init]; id event1 = OCMClassMock([UIEvent class]); [forwardGectureRecognizer touchesBegan:touches1 withEvent:event1]; OCMVerify([flutterViewController touchesBegan:touches1 withEvent:event1]); - flutterPlatformViewsController.flutterViewController = nil; + flutterPlatformViewsController->SetFlutterViewController(nil); // Allow the touch events to finish NSSet* touches2 = [[NSSet alloc] init]; @@ -2716,14 +2565,14 @@ fml::RefPtr GetDefaultTaskRunner() { { // ***** Sequence 2, finishing touch event with touchCancelled ***** // - flutterPlatformViewsController.flutterViewController = flutterViewController; + flutterPlatformViewsController->SetFlutterViewController(flutterViewController); NSSet* touches1 = [[NSSet alloc] init]; id event1 = OCMClassMock([UIEvent class]); [forwardGectureRecognizer touchesBegan:touches1 withEvent:event1]; OCMVerify([flutterViewController touchesBegan:touches1 withEvent:event1]); - flutterPlatformViewsController.flutterViewController = nil; + flutterPlatformViewsController->SetFlutterViewController(nil); // Allow the touch events to finish NSSet* touches2 = [[NSSet alloc] init]; @@ -2748,7 +2597,7 @@ fml::RefPtr GetDefaultTaskRunner() { OCMReject([flutterViewController touchesEnded:touches5 withEvent:event5]); } - [flutterPlatformViewsController reset]; + flutterPlatformViewsController->Reset(); } - (void) @@ -2760,9 +2609,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -2775,19 +2623,16 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @2, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], + result); XCTAssertNotNil(gMockPlatformView); @@ -2808,7 +2653,8 @@ fml::RefPtr GetDefaultTaskRunner() { } } id flutterViewController = OCMClassMock([FlutterViewController class]); - flutterPlatformViewsController.flutterViewController = flutterViewController; + + flutterPlatformViewsController->SetFlutterViewController(flutterViewController); // The touches in this sequence requires 1 touch object, we always create the NSSet with one item. NSSet* touches1 = [NSSet setWithObject:@1]; @@ -2817,7 +2663,7 @@ fml::RefPtr GetDefaultTaskRunner() { OCMVerify([flutterViewController touchesBegan:touches1 withEvent:event1]); FlutterViewController* flutterViewController2 = OCMClassMock([FlutterViewController class]); - flutterPlatformViewsController.flutterViewController = flutterViewController2; + flutterPlatformViewsController->SetFlutterViewController(flutterViewController2); // Touch events should still send to the old FlutterViewController if FlutterViewController // is updated in between. @@ -2866,7 +2712,7 @@ fml::RefPtr GetDefaultTaskRunner() { OCMVerify([flutterViewController2 touchesEnded:touches8 withEvent:event8]); OCMReject([flutterViewController touchesEnded:touches8 withEvent:event8]); - [flutterPlatformViewsController reset]; + flutterPlatformViewsController->Reset(); } - (void)testFlutterPlatformViewTouchesCancelledEventAreForcedToBeCancelled { @@ -2877,9 +2723,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -2892,19 +2737,16 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @2, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], + result); XCTAssertNotNil(gMockPlatformView); @@ -2925,7 +2767,8 @@ fml::RefPtr GetDefaultTaskRunner() { } } id flutterViewController = OCMClassMock([FlutterViewController class]); - flutterPlatformViewsController.flutterViewController = flutterViewController; + + flutterPlatformViewsController->SetFlutterViewController(flutterViewController); NSSet* touches1 = [NSSet setWithObject:@1]; id event1 = OCMClassMock([UIEvent class]); @@ -2934,7 +2777,7 @@ fml::RefPtr GetDefaultTaskRunner() { [forwardGectureRecognizer touchesCancelled:touches1 withEvent:event1]; OCMVerify([flutterViewController forceTouchesCancelled:touches1]); - [flutterPlatformViewsController reset]; + flutterPlatformViewsController->Reset(); } - (void)testFlutterPlatformViewTouchesEndedOrTouchesCancelledEventDoesNotFailTheGestureRecognizer { @@ -2945,9 +2788,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -2960,19 +2802,16 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @2, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], + result); XCTAssertNotNil(gMockPlatformView); @@ -2993,7 +2832,8 @@ fml::RefPtr GetDefaultTaskRunner() { } } id flutterViewController = OCMClassMock([FlutterViewController class]); - flutterPlatformViewsController.flutterViewController = flutterViewController; + + flutterPlatformViewsController->SetFlutterViewController(flutterViewController); NSSet* touches1 = [NSSet setWithObject:@1]; id event1 = OCMClassMock([UIEvent class]); @@ -3042,7 +2882,7 @@ fml::RefPtr GetDefaultTaskRunner() { }); [self waitForExpectationsWithTimeout:30 handler:nil]; - [flutterPlatformViewsController reset]; + flutterPlatformViewsController->Reset(); } - (void)testFlutterPlatformViewControllerSubmitFrameWithoutFlutterViewNotCrashing { @@ -3053,9 +2893,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -3068,19 +2907,16 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @2, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], + result); XCTAssertNotNil(gMockPlatformView); @@ -3091,11 +2927,9 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams_1 = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams_1)]; - [flutterPlatformViewsController - compositeView:2 - withParams:[flutterPlatformViewsController compositionParamsForView:2]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams_1)); + flutterPlatformViewsController->CompositeWithParams( + 2, flutterPlatformViewsController->GetCompositionParams(2)); flutter::SurfaceFrame::FramebufferInfo framebuffer_info; auto mock_surface = std::make_unique( @@ -3103,26 +2937,22 @@ fml::RefPtr GetDefaultTaskRunner() { [](const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) { return false; }, [](const flutter::SurfaceFrame& surface_frame) { return true; }, /*frame_size=*/SkISize::Make(800, 600)); - XCTAssertFalse([flutterPlatformViewsController submitFrame:std::move(mock_surface) - withIosContext:nil - grContext:nil]); + XCTAssertFalse( + flutterPlatformViewsController->SubmitFrame(nullptr, nullptr, std::move(mock_surface))); auto embeddedViewParams_2 = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams_2)]; - [flutterPlatformViewsController - compositeView:2 - withParams:[flutterPlatformViewsController compositionParamsForView:2]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams_2)); + flutterPlatformViewsController->CompositeWithParams( + 2, flutterPlatformViewsController->GetCompositionParams(2)); auto mock_surface_submit_true = std::make_unique( nullptr, framebuffer_info, [](const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) { return true; }, [](const flutter::SurfaceFrame& surface_frame) { return true; }, /*frame_size=*/SkISize::Make(800, 600)); - XCTAssertTrue([flutterPlatformViewsController submitFrame:std::move(mock_surface_submit_true) - withIosContext:nil - grContext:nil]); + XCTAssertTrue(flutterPlatformViewsController->SubmitFrame(nullptr, nullptr, + std::move(mock_surface_submit_true))); } - (void) @@ -3134,9 +2964,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -3148,38 +2977,34 @@ fml::RefPtr GetDefaultTaskRunner() { /*is_gpu_disabled_jsync_switch=*/std::make_shared()); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)]; - flutterPlatformViewsController.flutterView = flutterView; + flutterPlatformViewsController->SetFlutterView(flutterView); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; // autorelease pool to trigger an autorelease for all the root_views_ and touch_interceptors_. @autoreleasepool { - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @2, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], + result); flutter::MutatorsStack stack; SkMatrix finalMatrix; auto embeddedViewParams = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams)]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); - // Not calling |[flutterPlatformViewsController submitFrame:withIosContext:grContext:]| so that - // the platform views are not added to flutter_view_. + // Not calling |flutterPlatformViewsController::SubmitFrame| so that the platform views are not + // added to flutter_view_. XCTAssertNotNil(gMockPlatformView); - [flutterPlatformViewsController reset]; + flutterPlatformViewsController->Reset(); } XCTAssertNil(gMockPlatformView); } @@ -3192,9 +3017,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -3206,52 +3030,45 @@ fml::RefPtr GetDefaultTaskRunner() { /*is_gpu_disabled_jsync_switch=*/std::make_shared()); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)]; - flutterPlatformViewsController.flutterView = flutterView; + flutterPlatformViewsController->SetFlutterView(flutterView); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @0, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @0, @"viewType" : @"MockFlutterPlatformView"}], + result); - // First frame, |embeddedViewCount| is not empty after composite. - [flutterPlatformViewsController beginFrameWithSize:SkISize::Make(300, 300)]; + // First frame, |EmbeddedViewCount| is not empty after composite. + flutterPlatformViewsController->BeginFrame(SkISize::Make(300, 300)); flutter::MutatorsStack stack; SkMatrix finalMatrix; auto embeddedViewParams1 = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:0 - withParams:std::move(embeddedViewParams1)]; - [flutterPlatformViewsController - compositeView:0 - withParams:[flutterPlatformViewsController compositionParamsForView:0]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(0, std::move(embeddedViewParams1)); + flutterPlatformViewsController->CompositeWithParams( + 0, flutterPlatformViewsController->GetCompositionParams(0)); - XCTAssertEqual(flutterPlatformViewsController.embeddedViewCount, 1UL); + XCTAssertEqual(flutterPlatformViewsController->EmbeddedViewCount(), 1UL); - // Second frame, |embeddedViewCount| should be empty at the start - [flutterPlatformViewsController beginFrameWithSize:SkISize::Make(300, 300)]; - XCTAssertEqual(flutterPlatformViewsController.embeddedViewCount, 0UL); + // Second frame, |EmbeddedViewCount| should be empty at the start + flutterPlatformViewsController->BeginFrame(SkISize::Make(300, 300)); + XCTAssertEqual(flutterPlatformViewsController->EmbeddedViewCount(), 0UL); auto embeddedViewParams2 = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:0 - withParams:std::move(embeddedViewParams2)]; - [flutterPlatformViewsController - compositeView:0 - withParams:[flutterPlatformViewsController compositionParamsForView:0]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(0, std::move(embeddedViewParams2)); + flutterPlatformViewsController->CompositeWithParams( + 0, flutterPlatformViewsController->GetCompositionParams(0)); - XCTAssertEqual(flutterPlatformViewsController.embeddedViewCount, 1UL); + XCTAssertEqual(flutterPlatformViewsController->EmbeddedViewCount(), 1UL); } - (void) @@ -3263,9 +3080,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -3277,47 +3093,40 @@ fml::RefPtr GetDefaultTaskRunner() { /*is_gpu_disabled_jsync_switch=*/std::make_shared()); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)]; - flutterPlatformViewsController.flutterView = flutterView; + flutterPlatformViewsController->SetFlutterView(flutterView); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @0, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @0, @"viewType" : @"MockFlutterPlatformView"}], + result); UIView* view1 = gMockPlatformView; // This overwrites `gMockPlatformView` to another view. - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @1, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @1, @"viewType" : @"MockFlutterPlatformView"}], + result); UIView* view2 = gMockPlatformView; - [flutterPlatformViewsController beginFrameWithSize:SkISize::Make(300, 300)]; + flutterPlatformViewsController->BeginFrame(SkISize::Make(300, 300)); flutter::MutatorsStack stack; SkMatrix finalMatrix; auto embeddedViewParams1 = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:0 - withParams:std::move(embeddedViewParams1)]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(0, std::move(embeddedViewParams1)); auto embeddedViewParams2 = std::make_unique(finalMatrix, SkSize::Make(500, 500), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:1 - withParams:std::move(embeddedViewParams2)]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(1, std::move(embeddedViewParams2)); // SKSurface is required if the root FlutterView is present. const SkImageInfo image_info = SkImageInfo::MakeN32Premul(1000, 1000); @@ -3329,9 +3138,8 @@ fml::RefPtr GetDefaultTaskRunner() { [](const flutter::SurfaceFrame& surface_frame) { return true; }, /*frame_size=*/SkISize::Make(800, 600)); - XCTAssertTrue([flutterPlatformViewsController submitFrame:std::move(mock_surface) - withIosContext:nil - grContext:nil]); + XCTAssertTrue( + flutterPlatformViewsController->SubmitFrame(nullptr, nullptr, std::move(mock_surface))); // platform view is wrapped by touch interceptor, which itself is wrapped by clipping view. UIView* clippingView1 = view1.superview.superview; @@ -3341,17 +3149,15 @@ fml::RefPtr GetDefaultTaskRunner() { @"The first clipping view should be added before the second clipping view."); // Need to recreate these params since they are `std::move`ed. - [flutterPlatformViewsController beginFrameWithSize:SkISize::Make(300, 300)]; + flutterPlatformViewsController->BeginFrame(SkISize::Make(300, 300)); // Process the second frame in the opposite order. embeddedViewParams2 = std::make_unique(finalMatrix, SkSize::Make(500, 500), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:1 - withParams:std::move(embeddedViewParams2)]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(1, std::move(embeddedViewParams2)); embeddedViewParams1 = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:0 - withParams:std::move(embeddedViewParams1)]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(0, std::move(embeddedViewParams1)); mock_sk_surface = SkSurfaces::Raster(image_info); mock_surface = std::make_unique( @@ -3359,9 +3165,8 @@ fml::RefPtr GetDefaultTaskRunner() { [](const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) { return true; }, [](const flutter::SurfaceFrame& surface_frame) { return true; }, /*frame_size=*/SkISize::Make(800, 600)); - XCTAssertTrue([flutterPlatformViewsController submitFrame:std::move(mock_surface) - withIosContext:nil - grContext:nil]); + XCTAssertTrue( + flutterPlatformViewsController->SubmitFrame(nullptr, nullptr, std::move(mock_surface))); XCTAssertTrue([flutterView.subviews indexOfObject:clippingView1] > [flutterView.subviews indexOfObject:clippingView2], @@ -3377,9 +3182,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -3391,47 +3195,40 @@ fml::RefPtr GetDefaultTaskRunner() { /*is_gpu_disabled_jsync_switch=*/std::make_shared()); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)]; - flutterPlatformViewsController.flutterView = flutterView; + flutterPlatformViewsController->SetFlutterView(flutterView); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @0, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @0, @"viewType" : @"MockFlutterPlatformView"}], + result); UIView* view1 = gMockPlatformView; // This overwrites `gMockPlatformView` to another view. - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @1, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @1, @"viewType" : @"MockFlutterPlatformView"}], + result); UIView* view2 = gMockPlatformView; - [flutterPlatformViewsController beginFrameWithSize:SkISize::Make(300, 300)]; + flutterPlatformViewsController->BeginFrame(SkISize::Make(300, 300)); flutter::MutatorsStack stack; SkMatrix finalMatrix; auto embeddedViewParams1 = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:0 - withParams:std::move(embeddedViewParams1)]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(0, std::move(embeddedViewParams1)); auto embeddedViewParams2 = std::make_unique(finalMatrix, SkSize::Make(500, 500), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:1 - withParams:std::move(embeddedViewParams2)]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(1, std::move(embeddedViewParams2)); // SKSurface is required if the root FlutterView is present. const SkImageInfo image_info = SkImageInfo::MakeN32Premul(1000, 1000); @@ -3443,9 +3240,8 @@ fml::RefPtr GetDefaultTaskRunner() { [](const flutter::SurfaceFrame& surface_frame) { return true; }, /*frame_size=*/SkISize::Make(800, 600)); - XCTAssertTrue([flutterPlatformViewsController submitFrame:std::move(mock_surface) - withIosContext:nil - grContext:nil]); + XCTAssertTrue( + flutterPlatformViewsController->SubmitFrame(nullptr, nullptr, std::move(mock_surface))); // platform view is wrapped by touch interceptor, which itself is wrapped by clipping view. UIView* clippingView1 = view1.superview.superview; @@ -3455,17 +3251,15 @@ fml::RefPtr GetDefaultTaskRunner() { @"The first clipping view should be added before the second clipping view."); // Need to recreate these params since they are `std::move`ed. - [flutterPlatformViewsController beginFrameWithSize:SkISize::Make(300, 300)]; + flutterPlatformViewsController->BeginFrame(SkISize::Make(300, 300)); // Process the second frame in the same order. embeddedViewParams1 = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:0 - withParams:std::move(embeddedViewParams1)]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(0, std::move(embeddedViewParams1)); embeddedViewParams2 = std::make_unique(finalMatrix, SkSize::Make(500, 500), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:1 - withParams:std::move(embeddedViewParams2)]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(1, std::move(embeddedViewParams2)); mock_sk_surface = SkSurfaces::Raster(image_info); mock_surface = std::make_unique( @@ -3473,10 +3267,8 @@ fml::RefPtr GetDefaultTaskRunner() { [](const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) { return true; }, [](const flutter::SurfaceFrame& surface_frame) { return true; }, /*frame_size=*/SkISize::Make(800, 600)); - - XCTAssertTrue([flutterPlatformViewsController submitFrame:std::move(mock_surface) - withIosContext:nil - grContext:nil]); + XCTAssertTrue( + flutterPlatformViewsController->SubmitFrame(nullptr, nullptr, std::move(mock_surface))); XCTAssertTrue([flutterView.subviews indexOfObject:clippingView1] < [flutterView.subviews indexOfObject:clippingView2], @@ -3577,9 +3369,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -3592,23 +3383,20 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @1, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @1, @"viewType" : @"MockFlutterPlatformView"}], + result); XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; - flutterPlatformViewsController.flutterView = flutterView; + flutterPlatformViewsController->SetFlutterView(flutterView); // Create embedded view params flutter::MutatorsStack stack1; // Layer tree always pushes a screen scale factor to the stack @@ -3622,47 +3410,39 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams1 = std::make_unique( screenScaleMatrix, SkSize::Make(10, 10), stack1); - [flutterPlatformViewsController prerollCompositeEmbeddedView:1 - withParams:std::move(embeddedViewParams1)]; - [flutterPlatformViewsController - compositeView:1 - withParams:[flutterPlatformViewsController compositionParamsForView:1]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(1, std::move(embeddedViewParams1)); + flutterPlatformViewsController->CompositeWithParams( + 1, flutterPlatformViewsController->GetCompositionParams(1)); UIView* childClippingView1 = gMockPlatformView.superview.superview; UIView* maskView1 = childClippingView1.maskView; XCTAssertNotNil(maskView1); // Composite a new frame. - [flutterPlatformViewsController beginFrameWithSize:SkISize::Make(100, 100)]; + flutterPlatformViewsController->BeginFrame(SkISize::Make(100, 100)); flutter::MutatorsStack stack2; auto embeddedViewParams2 = std::make_unique( screenScaleMatrix, SkSize::Make(10, 10), stack2); auto embeddedViewParams3 = std::make_unique( screenScaleMatrix, SkSize::Make(10, 10), stack2); - [flutterPlatformViewsController prerollCompositeEmbeddedView:1 - withParams:std::move(embeddedViewParams3)]; - [flutterPlatformViewsController - compositeView:1 - withParams:[flutterPlatformViewsController compositionParamsForView:1]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(1, std::move(embeddedViewParams3)); + flutterPlatformViewsController->CompositeWithParams( + 1, flutterPlatformViewsController->GetCompositionParams(1)); childClippingView1 = gMockPlatformView.superview.superview; // This overrides gMockPlatformView to point to the newly created platform view. - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @2, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], + result); auto embeddedViewParams4 = std::make_unique( screenScaleMatrix, SkSize::Make(10, 10), stack1); - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams4)]; - [flutterPlatformViewsController - compositeView:2 - withParams:[flutterPlatformViewsController compositionParamsForView:2]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams4)); + flutterPlatformViewsController->CompositeWithParams( + 2, flutterPlatformViewsController->GetCompositionParams(2)); UIView* childClippingView2 = gMockPlatformView.superview.superview; @@ -3680,9 +3460,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -3695,35 +3474,30 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @1, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @1, @"viewType" : @"MockFlutterPlatformView"}], + result); UIView* view1 = gMockPlatformView; // This overwrites `gMockPlatformView` to another view. - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @2, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], + result); UIView* view2 = gMockPlatformView; XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; - flutterPlatformViewsController.flutterView = flutterView; + flutterPlatformViewsController->SetFlutterView(flutterView); // Create embedded view params flutter::MutatorsStack stack1; // Layer tree always pushes a screen scale factor to the stack @@ -3742,19 +3516,15 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams2 = std::make_unique( screenScaleMatrix, SkSize::Make(10, 10), stack2); - [flutterPlatformViewsController prerollCompositeEmbeddedView:1 - withParams:std::move(embeddedViewParams1)]; - [flutterPlatformViewsController - compositeView:1 - withParams:[flutterPlatformViewsController compositionParamsForView:1]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(1, std::move(embeddedViewParams1)); + flutterPlatformViewsController->CompositeWithParams( + 1, flutterPlatformViewsController->GetCompositionParams(1)); UIView* childClippingView1 = view1.superview.superview; - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams2)]; - [flutterPlatformViewsController - compositeView:2 - withParams:[flutterPlatformViewsController compositionParamsForView:2]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams2)); + flutterPlatformViewsController->CompositeWithParams( + 2, flutterPlatformViewsController->GetCompositionParams(2)); UIView* childClippingView2 = view2.superview.superview; UIView* maskView1 = childClippingView1.maskView; @@ -3770,9 +3540,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -3785,24 +3554,21 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @1, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @1, @"viewType" : @"MockFlutterPlatformView"}], + result); XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; - flutterPlatformViewsController.flutterView = flutterView; + flutterPlatformViewsController->SetFlutterView(flutterView); // Create embedded view params flutter::MutatorsStack stack1; // Layer tree always pushes a screen scale factor to the stack @@ -3821,11 +3587,9 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams2 = std::make_unique( screenScaleMatrix, SkSize::Make(10, 10), stack2); - [flutterPlatformViewsController prerollCompositeEmbeddedView:1 - withParams:std::move(embeddedViewParams1)]; - [flutterPlatformViewsController - compositeView:1 - withParams:[flutterPlatformViewsController compositionParamsForView:1]]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(1, std::move(embeddedViewParams1)); + flutterPlatformViewsController->CompositeWithParams( + 1, flutterPlatformViewsController->GetCompositionParams(1)); UIView* childClippingView = gMockPlatformView.superview.superview; @@ -3869,9 +3633,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -3883,58 +3646,50 @@ fml::RefPtr GetDefaultTaskRunner() { /*is_gpu_disabled_jsync_switch=*/std::make_shared()); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)]; - flutterPlatformViewsController.flutterView = flutterView; + flutterPlatformViewsController->SetFlutterView(flutterView); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @0, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @1, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @0, @"viewType" : @"MockFlutterPlatformView"}], + result); + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @1, @"viewType" : @"MockFlutterPlatformView"}], + result); { // **** First frame, view id 0, 1 in the composition_order_, disposing view 0 is called. **** // // No view should be disposed, or removed from the composition order. - [flutterPlatformViewsController beginFrameWithSize:SkISize::Make(300, 300)]; + flutterPlatformViewsController->BeginFrame(SkISize::Make(300, 300)); flutter::MutatorsStack stack; SkMatrix finalMatrix; auto embeddedViewParams0 = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:0 - withParams:std::move(embeddedViewParams0)]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(0, std::move(embeddedViewParams0)); auto embeddedViewParams1 = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:1 - withParams:std::move(embeddedViewParams1)]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(1, std::move(embeddedViewParams1)); - XCTAssertEqual(flutterPlatformViewsController.embeddedViewCount, 2UL); + XCTAssertEqual(flutterPlatformViewsController->EmbeddedViewCount(), 2UL); XCTestExpectation* expectation = [self expectationWithDescription:@"dispose call ended."]; FlutterResult disposeResult = ^(id result) { [expectation fulfill]; }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"dispose" arguments:@0] - result:disposeResult]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall methodCallWithMethodName:@"dispose" arguments:@0], disposeResult); [self waitForExpectationsWithTimeout:30 handler:nil]; const SkImageInfo image_info = SkImageInfo::MakeN32Premul(1000, 1000); @@ -3945,27 +3700,24 @@ fml::RefPtr GetDefaultTaskRunner() { [](const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) { return true; }, [](const flutter::SurfaceFrame& surface_frame) { return true; }, /*frame_size=*/SkISize::Make(800, 600)); - - XCTAssertTrue([flutterPlatformViewsController submitFrame:std::move(mock_surface) - withIosContext:nil - grContext:nil]); + XCTAssertTrue( + flutterPlatformViewsController->SubmitFrame(nullptr, nullptr, std::move(mock_surface))); // Disposing won't remove embedded views until the view is removed from the composition_order_ - XCTAssertEqual(flutterPlatformViewsController.embeddedViewCount, 2UL); - XCTAssertNotNil([flutterPlatformViewsController platformViewForId:0]); - XCTAssertNotNil([flutterPlatformViewsController platformViewForId:1]); + XCTAssertEqual(flutterPlatformViewsController->EmbeddedViewCount(), 2UL); + XCTAssertNotNil(flutterPlatformViewsController->GetPlatformViewByID(0)); + XCTAssertNotNil(flutterPlatformViewsController->GetPlatformViewByID(1)); } { // **** Second frame, view id 1 in the composition_order_, no disposing view is called, **** // // View 0 is removed from the composition order in this frame, hence also disposed. - [flutterPlatformViewsController beginFrameWithSize:SkISize::Make(300, 300)]; + flutterPlatformViewsController->BeginFrame(SkISize::Make(300, 300)); flutter::MutatorsStack stack; SkMatrix finalMatrix; auto embeddedViewParams1 = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:1 - withParams:std::move(embeddedViewParams1)]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(1, std::move(embeddedViewParams1)); const SkImageInfo image_info = SkImageInfo::MakeN32Premul(1000, 1000); sk_sp mock_sk_surface = SkSurfaces::Raster(image_info); @@ -3975,15 +3727,13 @@ fml::RefPtr GetDefaultTaskRunner() { [](const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) { return true; }, [](const flutter::SurfaceFrame& surface_frame) { return true; }, /*frame_size=*/SkISize::Make(800, 600)); - - XCTAssertTrue([flutterPlatformViewsController submitFrame:std::move(mock_surface) - withIosContext:nil - grContext:nil]); + XCTAssertTrue( + flutterPlatformViewsController->SubmitFrame(nullptr, nullptr, std::move(mock_surface))); // Disposing won't remove embedded views until the view is removed from the composition_order_ - XCTAssertEqual(flutterPlatformViewsController.embeddedViewCount, 1UL); - XCTAssertNil([flutterPlatformViewsController platformViewForId:0]); - XCTAssertNotNil([flutterPlatformViewsController platformViewForId:1]); + XCTAssertEqual(flutterPlatformViewsController->EmbeddedViewCount(), 1UL); + XCTAssertNil(flutterPlatformViewsController->GetPlatformViewByID(0)); + XCTAssertNotNil(flutterPlatformViewsController->GetPlatformViewByID(1)); } } - (void)testOnlyPlatformViewsAreRemovedWhenReset { @@ -3994,9 +3744,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -4009,21 +3758,18 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @2, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], + result); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)]; - flutterPlatformViewsController.flutterView = flutterView; + flutterPlatformViewsController->SetFlutterView(flutterView); // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack @@ -4039,8 +3785,7 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams)]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); // SKSurface is required if the root FlutterView is present. const SkImageInfo image_info = SkImageInfo::MakeN32Premul(1000, 1000); @@ -4052,14 +3797,12 @@ fml::RefPtr GetDefaultTaskRunner() { [](const flutter::SurfaceFrame& surface_frame) { return true; }, /*frame_size=*/SkISize::Make(800, 600)); - [flutterPlatformViewsController submitFrame:std::move(mock_surface) - withIosContext:nil - grContext:nil]; + flutterPlatformViewsController->SubmitFrame(nullptr, nullptr, std::move(mock_surface)); UIView* someView = [[UIView alloc] init]; [flutterView addSubview:someView]; - [flutterPlatformViewsController reset]; + flutterPlatformViewsController->Reset(); XCTAssertEqual(flutterView.subviews.count, 1u); XCTAssertEqual(flutterView.subviews.firstObject, someView); } @@ -4072,9 +3815,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -4087,21 +3829,18 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestNilFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestNilFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @2, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], + result); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)]; - flutterPlatformViewsController.flutterView = flutterView; + flutterPlatformViewsController->SetFlutterView(flutterView); // Create embedded view params flutter::MutatorsStack stack; @@ -4118,8 +3857,7 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:2 - withParams:std::move(embeddedViewParams)]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); // SKSurface is required if the root FlutterView is present. const SkImageInfo image_info = SkImageInfo::MakeN32Premul(1000, 1000); @@ -4131,9 +3869,7 @@ fml::RefPtr GetDefaultTaskRunner() { [](const flutter::SurfaceFrame& surface_frame) { return true; }, /*frame_size=*/SkISize::Make(800, 600)); - [flutterPlatformViewsController submitFrame:std::move(mock_surface) - withIosContext:nil - grContext:nil]; + flutterPlatformViewsController->SubmitFrame(nullptr, nullptr, std::move(mock_surface)); XCTAssertEqual(flutterView.subviews.count, 1u); } @@ -4179,9 +3915,8 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -4193,45 +3928,38 @@ fml::RefPtr GetDefaultTaskRunner() { /*is_gpu_disabled_jsync_switch=*/std::make_shared()); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)]; - flutterPlatformViewsController.flutterView = flutterView; + flutterPlatformViewsController->SetFlutterView(flutterView); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @0, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @0, @"viewType" : @"MockFlutterPlatformView"}], + result); // This overwrites `gMockPlatformView` to another view. - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @1, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @1, @"viewType" : @"MockFlutterPlatformView"}], + result); - [flutterPlatformViewsController beginFrameWithSize:SkISize::Make(300, 300)]; + flutterPlatformViewsController->BeginFrame(SkISize::Make(300, 300)); flutter::MutatorsStack stack; SkMatrix finalMatrix; auto embeddedViewParams1 = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:0 - withParams:std::move(embeddedViewParams1)]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(0, std::move(embeddedViewParams1)); auto embeddedViewParams2 = std::make_unique(finalMatrix, SkSize::Make(500, 500), stack); - [flutterPlatformViewsController prerollCompositeEmbeddedView:1 - withParams:std::move(embeddedViewParams2)]; + flutterPlatformViewsController->PrerollCompositeEmbeddedView(1, std::move(embeddedViewParams2)); // SKSurface is required if the root FlutterView is present. const SkImageInfo image_info = SkImageInfo::MakeN32Premul(1000, 1000); @@ -4251,9 +3979,8 @@ fml::RefPtr GetDefaultTaskRunner() { .buffer_damage = SkIRect::MakeWH(400, 600), }); - [flutterPlatformViewsController submitFrame:std::move(mock_surface) - withIosContext:nil - grContext:nil]; + XCTAssertTrue( + flutterPlatformViewsController->SubmitFrame(nullptr, nullptr, std::move(mock_surface))); XCTAssertTrue(submit_info.has_value()); XCTAssertEqual(*submit_info->frame_damage, SkIRect::MakeWH(800, 600)); diff --git a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h index b23d532cf4..8267b1ccfe 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h +++ b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h @@ -6,20 +6,20 @@ #define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERPLATFORMVIEWS_INTERNAL_H_ #import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterPlatformViews.h" +#include "fml/task_runner.h" +#include "impeller/base/thread_safety.h" +#include "third_party/skia/include/core/SkRect.h" #include #include "flutter/flow/surface.h" #include "flutter/fml/memory/weak_ptr.h" -#include "flutter/fml/task_runner.h" #include "flutter/fml/trace_event.h" -#include "flutter/impeller/base/thread_safety.h" #import "flutter/shell/platform/darwin/common/framework/Headers/FlutterChannels.h" #import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterPlugin.h" -#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsController.h" #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewResponder.h" -#include "flutter/shell/platform/darwin/ios/ios_context.h" -#include "third_party/skia/include/core/SkRect.h" +#import "flutter/shell/platform/darwin/ios/framework/Source/platform_views_controller.h" +#import "flutter/shell/platform/darwin/ios/ios_context.h" // A UIView that acts as a clipping mask for the |ChildClippingView|. // @@ -134,7 +134,8 @@ // 2. Dispatching all events that are hittested to the embedded view to the FlutterView. @interface FlutterTouchInterceptingView : UIView - (instancetype)initWithEmbeddedView:(UIView*)embeddedView - platformViewsController:(FlutterPlatformViewsController*)platformViewsController + platformViewsController: + (fml::WeakPtr)platformViewsController gestureRecognizersBlockingPolicy: (FlutterPlatformViewGestureRecognizersBlockingPolicy)blockingPolicy; @@ -191,7 +192,8 @@ // directly to the FlutterView. @interface ForwardingGestureRecognizer : UIGestureRecognizer - (instancetype)initWithTarget:(id)target - platformViewsController:(FlutterPlatformViewsController*)platformViewsController; + platformViewsController: + (fml::WeakPtr)platformViewsController; - (ForwardingGestureRecognizer*)recreateRecognizerWithTarget:(id)target; @end diff --git a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterView.h b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterView.h index 80619e44b7..53dd50e45d 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterView.h +++ b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterView.h @@ -14,11 +14,12 @@ @protocol FlutterViewEngineDelegate @property(nonatomic, readonly) BOOL isUsingImpeller; -@property(nonatomic, readonly) FlutterPlatformViewsController* platformViewsController; - (flutter::Rasterizer::Screenshot)takeScreenshot:(flutter::Rasterizer::ScreenshotType)type asBase64Encoded:(BOOL)base64Encode; +- (std::shared_ptr&)platformViewsController; + /** * A callback that is called when iOS queries accessibility information of the Flutter view. * diff --git a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index 2fd71c0874..319f423d84 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -745,14 +745,14 @@ static void SendFakeTouchEvent(UIScreen* screen, // thread. if (appeared) { [self installFirstFrameCallback]; - self.platformViewsController.flutterView = self.flutterView; - self.platformViewsController.flutterViewController = self; + [self.engine platformViewsController]->SetFlutterView(self.flutterView); + [self.engine platformViewsController]->SetFlutterViewController(self); [self.engine iosPlatformView]->NotifyCreated(); } else { self.displayingFlutterUI = NO; [self.engine iosPlatformView]->NotifyDestroyed(); - self.platformViewsController.flutterView = nil; - self.platformViewsController.flutterViewController = nil; + [self.engine platformViewsController]->SetFlutterView(nullptr); + [self.engine platformViewsController]->SetFlutterViewController(nullptr); } } @@ -2321,7 +2321,7 @@ static flutter::PointerData::DeviceKind DeviceKindFromTouchType(UITouch* touch) #pragma mark - Platform views -- (FlutterPlatformViewsController*)platformViewsController { +- (std::shared_ptr&)platformViewsController { return self.engine.platformViewsController; } diff --git a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h index 3645d2c376..62a7df4133 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h +++ b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h @@ -5,12 +5,11 @@ #ifndef FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERVIEWCONTROLLER_INTERNAL_H_ #define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERVIEWCONTROLLER_INTERNAL_H_ -#import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h" - #include "flutter/fml/time/time_point.h" + +#import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h" #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterKeySecondaryResponder.h" #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterKeyboardManager.h" -#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsController.h" #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h" #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterUIPressProxy.h" #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewResponder.h" @@ -57,8 +56,7 @@ typedef void (^FlutterKeyboardAnimationCallback)(fml::TimePoint); */ @property(nonatomic, assign, readwrite) BOOL prefersStatusBarHidden; -@property(nonatomic, readonly) FlutterPlatformViewsController* platformViewsController; - +- (std::shared_ptr&)platformViewsController; - (FlutterRestorationPlugin*)restorationPlugin; // Accepts keypress events, and then calls |nextAction| if the event was not diff --git a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterViewTest.mm b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterViewTest.mm index 357c65e4c8..08cf885da5 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterViewTest.mm +++ b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterViewTest.mm @@ -13,12 +13,13 @@ FLUTTER_ASSERT_ARC @property(nonatomic, assign) BOOL isUsingImpeller; @end -@implementation FakeDelegate - -@synthesize platformViewsController = _platformViewsController; +@implementation FakeDelegate { + std::shared_ptr _platformViewsController; +} - (instancetype)init { _callbackCalled = NO; + _platformViewsController = std::shared_ptr(nullptr); return self; } @@ -27,6 +28,10 @@ FLUTTER_ASSERT_ARC return {}; } +- (std::shared_ptr&)platformViewsController { + return _platformViewsController; +} + - (void)flutterViewAccessibilityDidCall { _callbackCalled = YES; } diff --git a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/SemanticsObjectTestMocks.h b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/SemanticsObjectTestMocks.h index 562c471e93..4ccd57b1bb 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/SemanticsObjectTestMocks.h +++ b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/SemanticsObjectTestMocks.h @@ -43,7 +43,9 @@ class MockAccessibilityBridge : public AccessibilityBridgeIos { } void AccessibilityObjectDidBecomeFocused(int32_t id) override {} void AccessibilityObjectDidLoseFocus(int32_t id) override {} - FlutterPlatformViewsController* GetPlatformViewsController() const override { return nil; } + std::shared_ptr GetPlatformViewsController() const override { + return nil; + } std::vector observations; bool isVoiceOverRunningValue; @@ -72,7 +74,9 @@ class MockAccessibilityBridgeNoWindow : public AccessibilityBridgeIos { } void AccessibilityObjectDidBecomeFocused(int32_t id) override {} void AccessibilityObjectDidLoseFocus(int32_t id) override {} - FlutterPlatformViewsController* GetPlatformViewsController() const override { return nil; } + std::shared_ptr GetPlatformViewsController() const override { + return nil; + } std::vector observations; bool isVoiceOverRunningValue; diff --git a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/accessibility_bridge.h b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/accessibility_bridge.h index e808b88d20..ffbd8e49dd 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/accessibility_bridge.h +++ b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/accessibility_bridge.h @@ -50,7 +50,7 @@ class AccessibilityBridge final : public AccessibilityBridgeIos { AccessibilityBridge(FlutterViewController* view_controller, PlatformViewIOS* platform_view, - __weak FlutterPlatformViewsController* platform_views_controller, + std::shared_ptr platform_views_controller, std::unique_ptr ios_delegate = nullptr); ~AccessibilityBridge(); @@ -72,7 +72,7 @@ class AccessibilityBridge final : public AccessibilityBridgeIos { fml::WeakPtr GetWeakPtr(); - FlutterPlatformViewsController* GetPlatformViewsController() const override { + std::shared_ptr GetPlatformViewsController() const override { return platform_views_controller_; }; @@ -91,7 +91,7 @@ class AccessibilityBridge final : public AccessibilityBridgeIos { FlutterViewController* view_controller_; PlatformViewIOS* platform_view_; - __weak FlutterPlatformViewsController* platform_views_controller_; + const std::shared_ptr platform_views_controller_; // If the this id is kSemanticObjectIdInvalid, it means either nothing has // been focused or the focus is currently outside of the flutter application // (i.e. the status bar or keyboard) diff --git a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/accessibility_bridge.mm b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/accessibility_bridge.mm index daf6389834..62467d3406 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/accessibility_bridge.mm +++ b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/accessibility_bridge.mm @@ -42,11 +42,11 @@ class DefaultIosDelegate : public AccessibilityBridge::IosDelegate { AccessibilityBridge::AccessibilityBridge( FlutterViewController* view_controller, PlatformViewIOS* platform_view, - __weak FlutterPlatformViewsController* platform_views_controller, + std::shared_ptr platform_views_controller, std::unique_ptr ios_delegate) : view_controller_(view_controller), platform_view_(platform_view), - platform_views_controller_(platform_views_controller), + platform_views_controller_(std::move(platform_views_controller)), last_focused_semantics_object_id_(kSemanticObjectIdInvalid), objects_([[NSMutableDictionary alloc] init]), previous_routes_({}), @@ -271,13 +271,11 @@ static SemanticsObject* CreateObject(const flutter::SemanticsNode& node, } else if (node.HasFlag(flutter::SemanticsFlags::kHasImplicitScrolling)) { return [[FlutterScrollableSemanticsObject alloc] initWithBridge:weak_ptr uid:node.id]; } else if (node.IsPlatformViewNode()) { - FlutterPlatformViewsController* platformViewsController = - weak_ptr->GetPlatformViewsController(); - FlutterTouchInterceptingView* touchInterceptingView = - [platformViewsController flutterTouchInterceptingViewForId:node.platformViewId]; - return [[FlutterPlatformViewSemanticsContainer alloc] initWithBridge:weak_ptr - uid:node.id - platformView:touchInterceptingView]; + return [[FlutterPlatformViewSemanticsContainer alloc] + initWithBridge:weak_ptr + uid:node.id + platformView:weak_ptr->GetPlatformViewsController()->GetFlutterTouchInterceptingViewByID( + node.platformViewId)]; } else { return [[FlutterSemanticsObject alloc] initWithBridge:weak_ptr uid:node.id]; } diff --git a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/accessibility_bridge_ios.h b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/accessibility_bridge_ios.h index 2168ca050d..0da3646a2e 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/accessibility_bridge_ios.h +++ b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/accessibility_bridge_ios.h @@ -12,9 +12,9 @@ #include "flutter/lib/ui/semantics/semantics_node.h" @class UIView; -@class FlutterPlatformViewsController; namespace flutter { +class PlatformViewsController; /// Interface that represents an accessibility bridge for iOS. class AccessibilityBridgeIos { @@ -39,7 +39,7 @@ class AccessibilityBridgeIos { * The input id is the uid of the newly focused SemanticObject. */ virtual void AccessibilityObjectDidLoseFocus(int32_t id) = 0; - virtual FlutterPlatformViewsController* GetPlatformViewsController() const = 0; + virtual std::shared_ptr GetPlatformViewsController() const = 0; }; } // namespace flutter diff --git a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm index 343ed99eae..63c2b14794 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm +++ b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm @@ -279,9 +279,8 @@ fml::RefPtr CreateNewThread(const std::string& name) { /*ui=*/thread_task_runner, /*io=*/thread_task_runner); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = thread_task_runner; + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(thread_task_runner); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -295,22 +294,19 @@ fml::RefPtr CreateNewThread(const std::string& name) { id mockFlutterViewController = OCMClassMock([FlutterViewController class]); OCMStub([mockFlutterViewController view]).andReturn(mockFlutterView); std::string label = "some label"; - flutterPlatformViewsController.flutterView = mockFlutterView; + flutterPlatformViewsController->SetFlutterView(mockFlutterView); MockFlutterPlatformFactory* factory = [[MockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @2, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], + result); auto bridge = std::make_unique( /*view_controller=*/mockFlutterViewController, @@ -326,7 +322,7 @@ fml::RefPtr CreateNewThread(const std::string& name) { flutter::CustomAccessibilityActionUpdates actions; bridge->UpdateSemantics(/*nodes=*/nodes, /*actions=*/actions); XCTAssertNotNil(gMockPlatformView); - [flutterPlatformViewsController reset]; + flutterPlatformViewsController->Reset(); } XCTAssertNil(gMockPlatformView); } @@ -344,9 +340,8 @@ fml::RefPtr CreateNewThread(const std::string& name) { /*ui=*/thread_task_runner, /*io=*/thread_task_runner); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = thread_task_runner; + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(thread_task_runner); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -358,19 +353,16 @@ fml::RefPtr CreateNewThread(const std::string& name) { /*is_gpu_disabled_sync_switch=*/std::make_shared()); MockFlutterPlatformFactory* factory = [[MockFlutterPlatformFactory alloc] init]; - [flutterPlatformViewsController - registerViewFactory:factory - withId:@"MockFlutterPlatformView" - gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); FlutterResult result = ^(id result) { }; - [flutterPlatformViewsController - onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" - arguments:@{ - @"id" : @2, - @"viewType" : @"MockFlutterPlatformView" - }] - result:result]; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], + result); auto bridge = std::make_unique( /*view_controller=*/flutterViewController, @@ -378,7 +370,7 @@ fml::RefPtr CreateNewThread(const std::string& name) { /*platform_views_controller=*/flutterPlatformViewsController); XCTAssertNotNil(gMockPlatformView); - [flutterPlatformViewsController reset]; + flutterPlatformViewsController->Reset(); platform_view->NotifyDestroyed(); } XCTAssertNil(gMockPlatformView); @@ -395,9 +387,8 @@ fml::RefPtr CreateNewThread(const std::string& name) { /*ui=*/thread_task_runner, /*io=*/thread_task_runner); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = thread_task_runner; + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(thread_task_runner); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -493,9 +484,8 @@ fml::RefPtr CreateNewThread(const std::string& name) { /*ui=*/thread_task_runner, /*io=*/thread_task_runner); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = thread_task_runner; + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(thread_task_runner); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -569,8 +559,8 @@ fml::RefPtr CreateNewThread(const std::string& name) { /*ui=*/thread_task_runner, /*io=*/thread_task_runner); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(thread_task_runner); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -2185,12 +2175,11 @@ fml::RefPtr CreateNewThread(const std::string& name) { /*is_gpu_disabled_sync_switch=*/std::make_shared()); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); - FlutterPlatformViewsController* flutterPlatformViewsController = - [[FlutterPlatformViewsController alloc] init]; - flutterPlatformViewsController.taskRunner = thread_task_runner; + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(thread_task_runner); OCMStub([mockFlutterViewController platformViewsController]) - .andReturn(flutterPlatformViewsController); + .andReturn(flutterPlatformViewsController.get()); platform_view->SetOwnerViewController(mockFlutterViewController); platform_view->SetSemanticsEnabled(true); diff --git a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/platform_views_controller.h b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/platform_views_controller.h new file mode 100644 index 0000000000..06fd638244 --- /dev/null +++ b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/platform_views_controller.h @@ -0,0 +1,318 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_PLATFORM_VIEWS_CONTROLLER_H_ +#define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_PLATFORM_VIEWS_CONTROLLER_H_ + +#include +#include +#include + +#include "flutter/flow/surface.h" +#include "flutter/fml/memory/weak_ptr.h" +#include "flutter/fml/task_runner.h" +#include "flutter/fml/trace_event.h" +#include "impeller/base/thread_safety.h" +#include "third_party/skia/include/core/SkRect.h" + +#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterChannels.h" +#import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterPlatformViews.h" +#import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterPlugin.h" +#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewResponder.h" +#import "flutter/shell/platform/darwin/ios/framework/Source/overlay_layer_pool.h" +#import "flutter/shell/platform/darwin/ios/ios_context.h" + +@class FlutterTouchInterceptingView; +@class FlutterClippingMaskViewPool; + +namespace flutter { + +/// @brief Composites Flutter UI and overlay layers alongside embedded UIViews. +class PlatformViewsController { + public: + PlatformViewsController(); + + ~PlatformViewsController() = default; + + /// @brief Retrieve a weak pointer to this controller. + fml::WeakPtr GetWeakPtr(); + + /// @brief Set the platform task runner used to post rendering tasks. + void SetTaskRunner(const fml::RefPtr& platform_task_runner); + + /// @brief Set the flutter view. + void SetFlutterView(UIView* flutter_view) __attribute__((cf_audited_transfer)); + + /// @brief Set the flutter view controller. + void SetFlutterViewController(UIViewController* flutter_view_controller) + __attribute__((cf_audited_transfer)); + + /// @brief Retrieve the view controller. + UIViewController* GetFlutterViewController() + __attribute__((cf_audited_transfer)); + + /// @brief set the factory used to construct embedded UI Views. + void RegisterViewFactory( + NSObject* factory, + NSString* factoryId, + FlutterPlatformViewGestureRecognizersBlockingPolicy gestureRecognizerBlockingPolicy) + __attribute__((cf_audited_transfer)); + + /// @brief Mark the beginning of a frame and record the size of the onscreen. + void BeginFrame(SkISize frame_size); + + /// @brief Cancel the current frame, indicating that no platform views are composited. + /// + /// Additionally, reverts the composition order to its original state at the beginning of the + /// frame. + void CancelFrame(); + + /// @brief Record a platform view in the layer tree to be rendered, along with the positioning and + /// mutator parameters. + /// + /// Called from the raster thread. + void PrerollCompositeEmbeddedView(int64_t view_id, + std::unique_ptr params); + + /// @brief Returns the`FlutterTouchInterceptingView` with the provided view_id. + /// + /// Returns nil if there is no platform view with the provided id. Called + /// from the platform thread. + FlutterTouchInterceptingView* GetFlutterTouchInterceptingViewByID(int64_t view_id); + + /// @brief Determine if thread merging is required after prerolling platform views. + /// + /// Called from the raster thread. + PostPrerollResult PostPrerollAction( + const fml::RefPtr& raster_thread_merger, + bool impeller_enabled); + + /// @brief Mark the end of a compositor frame. + /// + /// May determine changes are required to the thread merging state. + /// Called from the raster thread. + void EndFrame(bool should_resubmit_frame, + const fml::RefPtr& raster_thread_merger, + bool impeller_enabled); + + /// @brief Returns the Canvas for the overlay slice for the given platform view. + /// + /// Called from the raster thread. + DlCanvas* CompositeEmbeddedView(int64_t view_id); + + /// @brief Discards all platform views instances and auxiliary resources. + /// + /// Called from the raster thread. + void Reset(); + + /// @brief Encode rendering for the Flutter overlay views and queue up perform platform view + /// mutations. + /// + /// Called from the raster thread. + bool SubmitFrame(GrDirectContext* gr_context, + const std::shared_ptr& ios_context, + std::unique_ptr frame); + + /// @brief Handler for platform view message channels. + void OnMethodCall(FlutterMethodCall* call, FlutterResult result) + __attribute__((cf_audited_transfer)); + + /// @brief Returns the platform view id if the platform view (or any of its descendant view) is + /// the first responder. + /// + /// Returns -1 if no such platform view is found. + long FindFirstResponderPlatformViewId(); + + /// @brief Pushes backdrop filter mutation to the mutator stack of each visited platform view. + void PushFilterToVisitedPlatformViews(const std::shared_ptr& filter, + const SkRect& filter_rect); + + /// @brief Pushes the view id of a visted platform view to the list of visied platform views. + void PushVisitedPlatformView(int64_t view_id) { visited_platform_views_.push_back(view_id); } + + // visible for testing. + size_t EmbeddedViewCount() const; + + // visible for testing. + size_t LayerPoolSize() const; + + // visible for testing. + // Returns the `FlutterPlatformView`'s `view` object associated with the view_id. + // + // If the `PlatformViewsController` does not contain any `FlutterPlatformView` object or + // a `FlutterPlatformView` object associated with the view_id cannot be found, the method + // returns nil. + UIView* GetPlatformViewByID(int64_t view_id); + + // Visible for testing. + void CompositeWithParams(int64_t view_id, const EmbeddedViewParams& params); + + // Visible for testing. + const EmbeddedViewParams& GetCompositionParams(int64_t view_id) const { + return current_composition_params_.find(view_id)->second; + } + + private: + PlatformViewsController(const PlatformViewsController&) = delete; + PlatformViewsController& operator=(const PlatformViewsController&) = delete; + + struct LayerData { + SkRect rect; + int64_t view_id; + int64_t overlay_id; + std::shared_ptr layer; + }; + + using LayersMap = std::unordered_map; + + // Update the buffers and mutate the platform views in CATransaction. + // + // Runs on the platform thread. + void PerformSubmit(const LayersMap& platform_view_layers, + std::unordered_map& current_composition_params, + const std::unordered_set& views_to_recomposite, + const std::vector& composition_order, + const std::vector>& unused_layers, + const std::vector>& surface_frames); + + /// @brief Populate any missing overlay layers. + /// + /// This requires posting a task to the platform thread and blocking on its completion. + void CreateMissingOverlays(GrDirectContext* gr_context, + const std::shared_ptr& ios_context, + size_t required_overlay_layers); + + void OnCreate(FlutterMethodCall* call, FlutterResult result) __attribute__((cf_audited_transfer)); + + void OnDispose(FlutterMethodCall* call, FlutterResult result) + __attribute__((cf_audited_transfer)); + + void OnAcceptGesture(FlutterMethodCall* call, FlutterResult result) + __attribute__((cf_audited_transfer)); + + void OnRejectGesture(FlutterMethodCall* call, FlutterResult result) + __attribute__((cf_audited_transfer)); + + /// @brief Return all views to be disposed on the platform thread. + std::vector GetViewsToDispose(); + + void ClipViewSetMaskView(UIView* clipView) __attribute__((cf_audited_transfer)); + + // Applies the mutators in the mutators_stack to the UIView chain that was constructed by + // `ReconstructClipViewsChain` + // + // Clips are applied to the `embedded_view`'s super view(|ChildClippingView|) using a + // |FlutterClippingMaskView|. Transforms are applied to `embedded_view` + // + // The `bounding_rect` is the final bounding rect of the PlatformView + // (EmbeddedViewParams::finalBoundingRect). If a clip mutator's rect contains the final bounding + // rect of the PlatformView, the clip mutator is not applied for performance optimization. + void ApplyMutators(const MutatorsStack& mutators_stack, + UIView* embedded_view, + const SkRect& bounding_rect) __attribute__((cf_audited_transfer)); + + std::shared_ptr GetExistingLayer(); + + // Runs on the platform thread. + void CreateLayer(GrDirectContext* gr_context, + const std::shared_ptr& ios_context, + MTLPixelFormat pixel_format); + + // Removes overlay views and platform views that aren't needed in the current frame. + // Must run on the platform thread. + void RemoveUnusedLayers(const std::vector>& unused_layers, + const std::vector& composition_order); + + // Appends the overlay views and platform view and sets their z index based on the composition + // order. + void BringLayersIntoView(const LayersMap& layer_map, + const std::vector& composition_order); + + // Resets the state of the frame. + void ResetFrameState(); + + // The pool of reusable view layers. The pool allows to recycle layer in each frame. + std::unique_ptr layer_pool_; + + // The platform view's |EmbedderViewSlice| keyed off the view id, which contains any subsequent + // operation until the next platform view or the end of the last leaf node in the layer tree. + // + // The Slices are deleted by the PlatformViewsController.reset(). + std::unordered_map> slices_; + + UIView* flutter_view_; + UIViewController* flutter_view_controller_; + FlutterClippingMaskViewPool* mask_view_pool_; + std::unordered_map*> factories_; + + // The FlutterPlatformViewGestureRecognizersBlockingPolicy for each type of platform view. + std::unordered_map + gesture_recognizers_blocking_policies_; + + /// The size of the current onscreen surface in physical pixels. + SkISize frame_size_; + + /// The task runner for posting tasks to the platform thread. + fml::RefPtr platform_task_runner_; + + /// Each of the following structs stores part of the platform view hierarchy according to its + /// ID. + /// + /// This data must only be accessed on the platform thread. + struct PlatformViewData { + NSObject* view; + FlutterTouchInterceptingView* touch_interceptor; + UIView* root_view; + }; + + /// This data must only be accessed on the platform thread. + std::unordered_map platform_views_; + + /// The composition parameters for each platform view. + /// + /// This state is only modified on the raster thread. + std::unordered_map current_composition_params_; + + /// Method channel `OnDispose` calls adds the views to be disposed to this set to be disposed on + /// the next frame. + /// + /// This state is modified on both the platform and raster thread. + std::unordered_set views_to_dispose_; + + /// view IDs in composition order. + /// + /// This state is only modified on the raster thread. + std::vector composition_order_; + + /// platform view IDs visited during layer tree composition. + /// + /// This state is only modified on the raster thread. + std::vector visited_platform_views_; + + /// Only composite platform views in this set. + /// + /// This state is only modified on the raster thread. + std::unordered_set views_to_recomposite_; + + /// @brief The composition order from the previous thread. + /// + /// Only accessed from the platform thread. + std::vector previous_composition_order_; + + /// Whether the previous frame had any platform views in active composition order. + /// + /// This state is tracked so that the first frame after removing the last platform view + /// runs through the platform view rendering code path, giving us a chance to remove the + /// platform view from the UIView hierarchy. + /// + /// Only accessed from the raster thread. + bool had_platform_views_ = false; + + // WeakPtrFactory must be the last member. + std::unique_ptr> weak_factory_; +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_PLATFORM_VIEWS_CONTROLLER_H_ diff --git a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/platform_views_controller.mm b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/platform_views_controller.mm new file mode 100644 index 0000000000..6893c3d0f8 --- /dev/null +++ b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/platform_views_controller.mm @@ -0,0 +1,874 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "shell/platform/darwin/ios/framework/Source/platform_views_controller.h" + +#include "flutter/display_list/effects/image_filters/dl_blur_image_filter.h" +#include "flutter/flow/surface_frame.h" +#include "flutter/flow/view_slicer.h" +#include "flutter/fml/make_copyable.h" +#include "flutter/fml/synchronization/count_down_latch.h" + +#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.h" +#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterView.h" +#import "flutter/shell/platform/darwin/ios/ios_surface.h" + +namespace { + +// The number of frames the rasterizer task runner will continue +// to run on the platform thread after no platform view is rendered. +// +// Note: this is an arbitrary number. +static const int kDefaultMergedLeaseDuration = 10; + +static constexpr NSUInteger kFlutterClippingMaskViewPoolCapacity = 5; + +// Converts a SkMatrix to CATransform3D. +// +// Certain fields are ignored in CATransform3D since SkMatrix is 3x3 and CATransform3D is 4x4. +CATransform3D GetCATransform3DFromSkMatrix(const SkMatrix& matrix) { + // Skia only supports 2D transform so we don't map z. + CATransform3D transform = CATransform3DIdentity; + transform.m11 = matrix.getScaleX(); + transform.m21 = matrix.getSkewX(); + transform.m41 = matrix.getTranslateX(); + transform.m14 = matrix.getPerspX(); + + transform.m12 = matrix.getSkewY(); + transform.m22 = matrix.getScaleY(); + transform.m42 = matrix.getTranslateY(); + transform.m24 = matrix.getPerspY(); + return transform; +} + +// Reset the anchor of `layer` to match the transform operation from flow. +// +// The position of the `layer` should be unchanged after resetting the anchor. +void ResetAnchor(CALayer* layer) { + // Flow uses (0, 0) to apply transform matrix so we need to match that in Quartz. + layer.anchorPoint = CGPointZero; + layer.position = CGPointZero; +} + +CGRect GetCGRectFromSkRect(const SkRect& clipSkRect) { + return CGRectMake(clipSkRect.fLeft, clipSkRect.fTop, clipSkRect.fRight - clipSkRect.fLeft, + clipSkRect.fBottom - clipSkRect.fTop); +} + +// Determines if the `clip_rect` from a clipRect mutator contains the +// `platformview_boundingrect`. +// +// `clip_rect` is in its own coordinate space. The rect needs to be transformed by +// `transform_matrix` to be in the coordinate space where the PlatformView is displayed. +// +// `platformview_boundingrect` is the final bounding rect of the PlatformView in the coordinate +// space where the PlatformView is displayed. +bool ClipRectContainsPlatformViewBoundingRect(const SkRect& clip_rect, + const SkRect& platformview_boundingrect, + const SkMatrix& transform_matrix) { + SkRect transformed_rect = transform_matrix.mapRect(clip_rect); + return transformed_rect.contains(platformview_boundingrect); +} + +// Determines if the `clipRRect` from a clipRRect mutator contains the +// `platformview_boundingrect`. +// +// `clip_rrect` is in its own coordinate space. The rrect needs to be transformed by +// `transform_matrix` to be in the coordinate space where the PlatformView is displayed. +// +// `platformview_boundingrect` is the final bounding rect of the PlatformView in the coordinate +// space where the PlatformView is displayed. +bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect, + const SkRect& platformview_boundingrect, + const SkMatrix& transform_matrix) { + SkVector upper_left = clip_rrect.radii(SkRRect::Corner::kUpperLeft_Corner); + SkVector upper_right = clip_rrect.radii(SkRRect::Corner::kUpperRight_Corner); + SkVector lower_right = clip_rrect.radii(SkRRect::Corner::kLowerRight_Corner); + SkVector lower_left = clip_rrect.radii(SkRRect::Corner::kLowerLeft_Corner); + SkScalar transformed_upper_left_x = transform_matrix.mapRadius(upper_left.x()); + SkScalar transformed_upper_left_y = transform_matrix.mapRadius(upper_left.y()); + SkScalar transformed_upper_right_x = transform_matrix.mapRadius(upper_right.x()); + SkScalar transformed_upper_right_y = transform_matrix.mapRadius(upper_right.y()); + SkScalar transformed_lower_right_x = transform_matrix.mapRadius(lower_right.x()); + SkScalar transformed_lower_right_y = transform_matrix.mapRadius(lower_right.y()); + SkScalar transformed_lower_left_x = transform_matrix.mapRadius(lower_left.x()); + SkScalar transformed_lower_left_y = transform_matrix.mapRadius(lower_left.y()); + SkRect transformed_clip_rect = transform_matrix.mapRect(clip_rrect.rect()); + SkRRect transformed_rrect; + SkVector corners[] = {{transformed_upper_left_x, transformed_upper_left_y}, + {transformed_upper_right_x, transformed_upper_right_y}, + {transformed_lower_right_x, transformed_lower_right_y}, + {transformed_lower_left_x, transformed_lower_left_y}}; + transformed_rrect.setRectRadii(transformed_clip_rect, corners); + return transformed_rrect.contains(platformview_boundingrect); +} + +} // namespace + +namespace flutter { + +// Becomes NO if Apple's API changes and blurred backdrop filters cannot be applied. +BOOL canApplyBlurBackdrop = YES; + +PlatformViewsController::PlatformViewsController() + : layer_pool_(std::make_unique()), + weak_factory_(std::make_unique>(this)) { + mask_view_pool_ = + [[FlutterClippingMaskViewPool alloc] initWithCapacity:kFlutterClippingMaskViewPoolCapacity]; +}; + +void PlatformViewsController::SetTaskRunner( + const fml::RefPtr& platform_task_runner) { + platform_task_runner_ = platform_task_runner; +} + +fml::WeakPtr PlatformViewsController::GetWeakPtr() { + return weak_factory_->GetWeakPtr(); +} + +void PlatformViewsController::SetFlutterView(UIView* flutter_view) { + flutter_view_ = flutter_view; +} + +void PlatformViewsController::SetFlutterViewController( + UIViewController* flutter_view_controller) { + flutter_view_controller_ = flutter_view_controller; +} + +UIViewController* PlatformViewsController::GetFlutterViewController() { + return flutter_view_controller_; +} + +void PlatformViewsController::OnMethodCall(FlutterMethodCall* call, FlutterResult result) { + if ([[call method] isEqualToString:@"create"]) { + OnCreate(call, result); + } else if ([[call method] isEqualToString:@"dispose"]) { + OnDispose(call, result); + } else if ([[call method] isEqualToString:@"acceptGesture"]) { + OnAcceptGesture(call, result); + } else if ([[call method] isEqualToString:@"rejectGesture"]) { + OnRejectGesture(call, result); + } else { + result(FlutterMethodNotImplemented); + } +} + +void PlatformViewsController::OnCreate(FlutterMethodCall* call, FlutterResult result) { + NSDictionary* args = [call arguments]; + + int64_t viewId = [args[@"id"] longLongValue]; + NSString* viewTypeString = args[@"viewType"]; + std::string viewType(viewTypeString.UTF8String); + + if (platform_views_.count(viewId) != 0) { + result([FlutterError errorWithCode:@"recreating_view" + message:@"trying to create an already created view" + details:[NSString stringWithFormat:@"view id: '%lld'", viewId]]); + return; + } + + NSObject* factory = factories_[viewType]; + if (factory == nil) { + result([FlutterError + errorWithCode:@"unregistered_view_type" + message:[NSString stringWithFormat:@"A UIKitView widget is trying to create a " + @"PlatformView with an unregistered type: < %@ >", + viewTypeString] + details:@"If you are the author of the PlatformView, make sure `registerViewFactory` " + @"is invoked.\n" + @"See: " + @"https://docs.flutter.dev/development/platform-integration/" + @"platform-views#on-the-platform-side-1 for more details.\n" + @"If you are not the author of the PlatformView, make sure to call " + @"`GeneratedPluginRegistrant.register`."]); + return; + } + + id params = nil; + if ([factory respondsToSelector:@selector(createArgsCodec)]) { + NSObject* codec = [factory createArgsCodec]; + if (codec != nil && args[@"params"] != nil) { + FlutterStandardTypedData* paramsData = args[@"params"]; + params = [codec decode:paramsData.data]; + } + } + + NSObject* embedded_view = [factory createWithFrame:CGRectZero + viewIdentifier:viewId + arguments:params]; + UIView* platform_view = [embedded_view view]; + // Set a unique view identifier, so the platform view can be identified in unit tests. + platform_view.accessibilityIdentifier = + [NSString stringWithFormat:@"platform_view[%lld]", viewId]; + + FlutterTouchInterceptingView* touch_interceptor = [[FlutterTouchInterceptingView alloc] + initWithEmbeddedView:platform_view + platformViewsController:GetWeakPtr() + gestureRecognizersBlockingPolicy:gesture_recognizers_blocking_policies_[viewType]]; + + ChildClippingView* clipping_view = [[ChildClippingView alloc] initWithFrame:CGRectZero]; + [clipping_view addSubview:touch_interceptor]; + + platform_views_.emplace(viewId, PlatformViewData{ + .view = embedded_view, // + .touch_interceptor = touch_interceptor, // + .root_view = clipping_view // + }); + + result(nil); +} + +void PlatformViewsController::OnDispose(FlutterMethodCall* call, FlutterResult result) { + NSNumber* arg = [call arguments]; + int64_t viewId = [arg longLongValue]; + + if (platform_views_.count(viewId) == 0) { + result([FlutterError errorWithCode:@"unknown_view" + message:@"trying to dispose an unknown" + details:[NSString stringWithFormat:@"view id: '%lld'", viewId]]); + return; + } + // We wait for next submitFrame to dispose views. + views_to_dispose_.insert(viewId); + result(nil); +} + +void PlatformViewsController::OnAcceptGesture(FlutterMethodCall* call, FlutterResult result) { + NSDictionary* args = [call arguments]; + int64_t viewId = [args[@"id"] longLongValue]; + + if (platform_views_.count(viewId) == 0) { + result([FlutterError errorWithCode:@"unknown_view" + message:@"trying to set gesture state for an unknown view" + details:[NSString stringWithFormat:@"view id: '%lld'", viewId]]); + return; + } + + FlutterTouchInterceptingView* view = platform_views_[viewId].touch_interceptor; + [view releaseGesture]; + + result(nil); +} + +void PlatformViewsController::OnRejectGesture(FlutterMethodCall* call, FlutterResult result) { + NSDictionary* args = [call arguments]; + int64_t viewId = [args[@"id"] longLongValue]; + + if (platform_views_.count(viewId) == 0) { + result([FlutterError errorWithCode:@"unknown_view" + message:@"trying to set gesture state for an unknown view" + details:[NSString stringWithFormat:@"view id: '%lld'", viewId]]); + return; + } + + FlutterTouchInterceptingView* view = platform_views_[viewId].touch_interceptor; + [view blockGesture]; + + result(nil); +} + +void PlatformViewsController::RegisterViewFactory( + NSObject* factory, + NSString* factoryId, + FlutterPlatformViewGestureRecognizersBlockingPolicy gestureRecognizerBlockingPolicy) { + std::string idString([factoryId UTF8String]); + FML_CHECK(factories_.count(idString) == 0); + factories_[idString] = factory; + gesture_recognizers_blocking_policies_[idString] = gestureRecognizerBlockingPolicy; +} + +void PlatformViewsController::BeginFrame(SkISize frame_size) { + ResetFrameState(); + frame_size_ = frame_size; +} + +void PlatformViewsController::CancelFrame() { + ResetFrameState(); +} + +PostPrerollResult PlatformViewsController::PostPrerollAction( + const fml::RefPtr& raster_thread_merger, + bool impeller_enabled) { + // TODO(jonahwilliams): remove this once Software backend is removed for iOS Sim. +#ifdef FML_OS_IOS_SIMULATOR + const bool merge_threads = true; +#else + const bool merge_threads = !impeller_enabled; +#endif // FML_OS_IOS_SIMULATOR + + if (merge_threads) { + if (composition_order_.empty()) { + return PostPrerollResult::kSuccess; + } + if (!raster_thread_merger->IsMerged()) { + // The raster thread merger may be disabled if the rasterizer is being + // created or teared down. + // + // In such cases, the current frame is dropped, and a new frame is attempted + // with the same layer tree. + // + // Eventually, the frame is submitted once this method returns `kSuccess`. + // At that point, the raster tasks are handled on the platform thread. + CancelFrame(); + return PostPrerollResult::kSkipAndRetryFrame; + } + // If the post preroll action is successful, we will display platform views in the current + // frame. In order to sync the rendering of the platform views (quartz) with skia's rendering, + // We need to begin an explicit CATransaction. This transaction needs to be submitted + // after the current frame is submitted. + raster_thread_merger->ExtendLeaseTo(kDefaultMergedLeaseDuration); + } + return PostPrerollResult::kSuccess; +} + +void PlatformViewsController::EndFrame( + bool should_resubmit_frame, + const fml::RefPtr& raster_thread_merger, + bool impeller_enabled) { +#if FML_OS_IOS_SIMULATOR + bool run_check = true; +#else + bool run_check = !impeller_enabled; +#endif // FML_OS_IOS_SIMULATOR + if (run_check && should_resubmit_frame) { + raster_thread_merger->MergeWithLease(kDefaultMergedLeaseDuration); + } +} + +void PlatformViewsController::PushFilterToVisitedPlatformViews( + const std::shared_ptr& filter, + const SkRect& filter_rect) { + for (int64_t id : visited_platform_views_) { + EmbeddedViewParams params = current_composition_params_[id]; + params.PushImageFilter(filter, filter_rect); + current_composition_params_[id] = params; + } +} + +void PlatformViewsController::PrerollCompositeEmbeddedView( + int64_t view_id, + std::unique_ptr params) { + SkRect view_bounds = SkRect::Make(frame_size_); + std::unique_ptr view; + view = std::make_unique(view_bounds); + slices_.insert_or_assign(view_id, std::move(view)); + + composition_order_.push_back(view_id); + + if (current_composition_params_.count(view_id) == 1 && + current_composition_params_[view_id] == *params.get()) { + // Do nothing if the params didn't change. + return; + } + current_composition_params_[view_id] = EmbeddedViewParams(*params.get()); + views_to_recomposite_.insert(view_id); +} + +size_t PlatformViewsController::EmbeddedViewCount() const { + return composition_order_.size(); +} + +size_t PlatformViewsController::LayerPoolSize() const { + return layer_pool_->size(); +} + +UIView* PlatformViewsController::GetPlatformViewByID(int64_t view_id) { + return [GetFlutterTouchInterceptingViewByID(view_id) embeddedView]; +} + +FlutterTouchInterceptingView* PlatformViewsController::GetFlutterTouchInterceptingViewByID( + int64_t view_id) { + if (platform_views_.empty()) { + return nil; + } + return platform_views_[view_id].touch_interceptor; +} + +long PlatformViewsController::FindFirstResponderPlatformViewId() { + for (auto const& [id, platform_view_data] : platform_views_) { + UIView* root_view = platform_view_data.root_view; + if (root_view.flt_hasFirstResponderInViewHierarchySubtree) { + return id; + } + } + return -1; +} + +void PlatformViewsController::ClipViewSetMaskView(UIView* clipView) { + FML_DCHECK([[NSThread currentThread] isMainThread]); + if (clipView.maskView) { + return; + } + CGRect frame = + CGRectMake(-clipView.frame.origin.x, -clipView.frame.origin.y, + CGRectGetWidth(flutter_view_.bounds), CGRectGetHeight(flutter_view_.bounds)); + clipView.maskView = [mask_view_pool_ getMaskViewWithFrame:frame]; +} + +// This method is only called when the `embedded_view` needs to be re-composited at the current +// frame. See: `CompositeWithParams` for details. +void PlatformViewsController::ApplyMutators(const MutatorsStack& mutators_stack, + UIView* embedded_view, + const SkRect& bounding_rect) { + if (flutter_view_ == nullptr) { + return; + } + + ResetAnchor(embedded_view.layer); + ChildClippingView* clipView = (ChildClippingView*)embedded_view.superview; + + SkMatrix transformMatrix; + NSMutableArray* blurFilters = [[NSMutableArray alloc] init]; + FML_DCHECK(!clipView.maskView || + [clipView.maskView isKindOfClass:[FlutterClippingMaskView class]]); + if (clipView.maskView) { + [mask_view_pool_ insertViewToPoolIfNeeded:(FlutterClippingMaskView*)(clipView.maskView)]; + clipView.maskView = nil; + } + CGFloat screenScale = [UIScreen mainScreen].scale; + auto iter = mutators_stack.Begin(); + while (iter != mutators_stack.End()) { + switch ((*iter)->GetType()) { + case kTransform: { + transformMatrix.preConcat((*iter)->GetMatrix()); + break; + } + case kClipRect: { + if (ClipRectContainsPlatformViewBoundingRect((*iter)->GetRect(), bounding_rect, + transformMatrix)) { + break; + } + ClipViewSetMaskView(clipView); + [(FlutterClippingMaskView*)clipView.maskView clipRect:(*iter)->GetRect() + matrix:transformMatrix]; + break; + } + case kClipRRect: { + if (ClipRRectContainsPlatformViewBoundingRect((*iter)->GetRRect(), bounding_rect, + transformMatrix)) { + break; + } + ClipViewSetMaskView(clipView); + [(FlutterClippingMaskView*)clipView.maskView clipRRect:(*iter)->GetRRect() + matrix:transformMatrix]; + break; + } + case kClipPath: { + // TODO(cyanglaz): Find a way to pre-determine if path contains the PlatformView boudning + // rect. See `ClipRRectContainsPlatformViewBoundingRect`. + // https://github.com/flutter/flutter/issues/118650 + ClipViewSetMaskView(clipView); + [(FlutterClippingMaskView*)clipView.maskView clipPath:(*iter)->GetPath() + matrix:transformMatrix]; + break; + } + case kOpacity: + embedded_view.alpha = (*iter)->GetAlphaFloat() * embedded_view.alpha; + break; + case kBackdropFilter: { + // Only support DlBlurImageFilter for BackdropFilter. + if (!canApplyBlurBackdrop || !(*iter)->GetFilterMutation().GetFilter().asBlur()) { + break; + } + CGRect filterRect = GetCGRectFromSkRect((*iter)->GetFilterMutation().GetFilterRect()); + // `filterRect` is in global coordinates. We need to convert to local space. + filterRect = CGRectApplyAffineTransform( + filterRect, CGAffineTransformMakeScale(1 / screenScale, 1 / screenScale)); + // `filterRect` reprents the rect that should be filtered inside the `flutter_view_`. + // The `PlatformViewFilter` needs the frame inside the `clipView` that needs to be + // filtered. + if (CGRectIsNull(CGRectIntersection(filterRect, clipView.frame))) { + break; + } + CGRect intersection = CGRectIntersection(filterRect, clipView.frame); + CGRect frameInClipView = [flutter_view_ convertRect:intersection toView:clipView]; + // sigma_x is arbitrarily chosen as the radius value because Quartz sets + // sigma_x and sigma_y equal to each other. DlBlurImageFilter's Tile Mode + // is not supported in Quartz's gaussianBlur CAFilter, so it is not used + // to blur the PlatformView. + CGFloat blurRadius = (*iter)->GetFilterMutation().GetFilter().asBlur()->sigma_x(); + UIVisualEffectView* visualEffectView = [[UIVisualEffectView alloc] + initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]]; + PlatformViewFilter* filter = [[PlatformViewFilter alloc] initWithFrame:frameInClipView + blurRadius:blurRadius + visualEffectView:visualEffectView]; + if (!filter) { + canApplyBlurBackdrop = NO; + } else { + [blurFilters addObject:filter]; + } + break; + } + } + ++iter; + } + + if (canApplyBlurBackdrop) { + [clipView applyBlurBackdropFilters:blurFilters]; + } + + // The UIKit frame is set based on the logical resolution (points) instead of physical. + // (https://developer.apple.com/library/archive/documentation/DeviceInformation/Reference/iOSDeviceCompatibility/Displays/Displays.html). + // However, flow is based on the physical resolution. For example, 1000 pixels in flow equals + // 500 points in UIKit for devices that has screenScale of 2. We need to scale the transformMatrix + // down to the logical resoltion before applying it to the layer of PlatformView. + transformMatrix.postScale(1 / screenScale, 1 / screenScale); + + // Reverse the offset of the clipView. + // The clipView's frame includes the final translate of the final transform matrix. + // Thus, this translate needs to be reversed so the platform view can layout at the correct + // offset. + // + // Note that the transforms are not applied to the clipping paths because clipping paths happen on + // the mask view, whose origin is always (0,0) to the flutter_view. + transformMatrix.postTranslate(-clipView.frame.origin.x, -clipView.frame.origin.y); + + embedded_view.layer.transform = GetCATransform3DFromSkMatrix(transformMatrix); +} + +// Composite the PlatformView with `view_id`. +// +// Every frame, during the paint traversal of the layer tree, this method is called for all +// the PlatformViews in `views_to_recomposite_`. +// +// Note that `views_to_recomposite_` does not represent all the views in the view hierarchy, +// if a PlatformView does not change its composition parameter from last frame, it is not +// included in the `views_to_recomposite_`. +void PlatformViewsController::CompositeWithParams(int64_t view_id, + const EmbeddedViewParams& params) { + /// TODO(https://github.com/flutter/flutter/issues/109700) + CGRect frame = CGRectMake(0, 0, params.sizePoints().width(), params.sizePoints().height()); + FlutterTouchInterceptingView* touchInterceptor = platform_views_[view_id].touch_interceptor; + touchInterceptor.layer.transform = CATransform3DIdentity; + touchInterceptor.frame = frame; + touchInterceptor.alpha = 1; + + const MutatorsStack& mutatorStack = params.mutatorsStack(); + UIView* clippingView = platform_views_[view_id].root_view; + // The frame of the clipping view should be the final bounding rect. + // Because the translate matrix in the Mutator Stack also includes the offset, + // when we apply the transforms matrix in |ApplyMutators|, we need + // to remember to do a reverse translate. + const SkRect& rect = params.finalBoundingRect(); + CGFloat screenScale = [UIScreen mainScreen].scale; + clippingView.frame = CGRectMake(rect.x() / screenScale, rect.y() / screenScale, + rect.width() / screenScale, rect.height() / screenScale); + ApplyMutators(mutatorStack, touchInterceptor, rect); +} + +DlCanvas* PlatformViewsController::CompositeEmbeddedView(int64_t view_id) { + return slices_[view_id]->canvas(); +} + +void PlatformViewsController::Reset() { + // Reset will only be called from the raster thread or a merged raster/platform thread. + // platform_views_ must only be modified on the platform thread, and any operations that + // read or modify platform views should occur there. + fml::TaskRunner::RunNowOrPostTask(platform_task_runner_, + [&, composition_order = composition_order_]() { + for (int64_t view_id : composition_order_) { + [platform_views_[view_id].root_view removeFromSuperview]; + } + platform_views_.clear(); + }); + + composition_order_.clear(); + slices_.clear(); + current_composition_params_.clear(); + views_to_recomposite_.clear(); + layer_pool_->RecycleLayers(); + visited_platform_views_.clear(); +} + +bool PlatformViewsController::SubmitFrame(GrDirectContext* gr_context, + const std::shared_ptr& ios_context, + std::unique_ptr background_frame) { + TRACE_EVENT0("flutter", "PlatformViewsController::SubmitFrame"); + + // No platform views to render; we're done. + if (flutter_view_ == nullptr || (composition_order_.empty() && !had_platform_views_)) { + had_platform_views_ = false; + return background_frame->Submit(); + } + had_platform_views_ = !composition_order_.empty(); + + bool did_encode = true; + LayersMap platform_view_layers; + std::vector> surface_frames; + surface_frames.reserve(composition_order_.size()); + std::unordered_map view_rects; + + for (int64_t view_id : composition_order_) { + view_rects[view_id] = current_composition_params_[view_id].finalBoundingRect(); + } + + std::unordered_map overlay_layers = + SliceViews(background_frame->Canvas(), composition_order_, slices_, view_rects); + + size_t required_overlay_layers = 0; + for (int64_t view_id : composition_order_) { + std::unordered_map::const_iterator overlay = overlay_layers.find(view_id); + if (overlay == overlay_layers.end()) { + continue; + } + required_overlay_layers++; + } + + // If there are not sufficient overlay layers, we must construct them on the platform + // thread, at least until we've refactored iOS surface creation to use IOSurfaces + // instead of CALayers. + CreateMissingOverlays(gr_context, ios_context, required_overlay_layers); + + int64_t overlay_id = 0; + for (int64_t view_id : composition_order_) { + std::unordered_map::const_iterator overlay = overlay_layers.find(view_id); + if (overlay == overlay_layers.end()) { + continue; + } + std::shared_ptr layer = GetExistingLayer(); + if (!layer) { + continue; + } + + std::unique_ptr frame = layer->surface->AcquireFrame(frame_size_); + // If frame is null, AcquireFrame already printed out an error message. + if (!frame) { + continue; + } + DlCanvas* overlay_canvas = frame->Canvas(); + int restore_count = overlay_canvas->GetSaveCount(); + overlay_canvas->Save(); + overlay_canvas->ClipRect(overlay->second); + overlay_canvas->Clear(DlColor::kTransparent()); + slices_[view_id]->render_into(overlay_canvas); + overlay_canvas->RestoreToCount(restore_count); + + // This flutter view is never the last in a frame, since we always submit the + // underlay view last. + frame->set_submit_info({.frame_boundary = false, .present_with_transaction = true}); + layer->did_submit_last_frame = frame->Encode(); + + did_encode &= layer->did_submit_last_frame; + platform_view_layers[view_id] = LayerData{ + .rect = overlay->second, // + .view_id = view_id, // + .overlay_id = overlay_id, // + .layer = layer // + }; + surface_frames.push_back(std::move(frame)); + overlay_id++; + } + + auto previous_submit_info = background_frame->submit_info(); + background_frame->set_submit_info({ + .frame_damage = previous_submit_info.frame_damage, + .buffer_damage = previous_submit_info.buffer_damage, + .present_with_transaction = true, + }); + background_frame->Encode(); + surface_frames.push_back(std::move(background_frame)); + + // Mark all layers as available, so they can be used in the next frame. + std::vector> unused_layers = layer_pool_->RemoveUnusedLayers(); + layer_pool_->RecycleLayers(); + + auto task = [&, // + platform_view_layers = std::move(platform_view_layers), // + current_composition_params = current_composition_params_, // + views_to_recomposite = views_to_recomposite_, // + composition_order = composition_order_, // + unused_layers = std::move(unused_layers), // + surface_frames = std::move(surface_frames) // + ]() mutable { + PerformSubmit(platform_view_layers, // + current_composition_params, // + views_to_recomposite, // + composition_order, // + unused_layers, // + surface_frames // + ); + }; + + fml::TaskRunner::RunNowOrPostTask(platform_task_runner_, fml::MakeCopyable(std::move(task))); + + return did_encode; +} + +void PlatformViewsController::CreateMissingOverlays(GrDirectContext* gr_context, + const std::shared_ptr& ios_context, + size_t required_overlay_layers) { + TRACE_EVENT0("flutter", "PlatformViewsController::CreateMissingLayers"); + + if (required_overlay_layers <= layer_pool_->size()) { + return; + } + auto missing_layer_count = required_overlay_layers - layer_pool_->size(); + + // If the raster thread isn't merged, create layers on the platform thread and block until + // complete. + auto latch = std::make_shared(1u); + fml::TaskRunner::RunNowOrPostTask(platform_task_runner_, [&]() { + for (auto i = 0u; i < missing_layer_count; i++) { + CreateLayer(gr_context, // + ios_context, // + ((FlutterView*)flutter_view_).pixelFormat // + ); + } + latch->CountDown(); + }); + if (![[NSThread currentThread] isMainThread]) { + latch->Wait(); + } +} + +/// Update the buffers and mutate the platform views in CATransaction on the platform thread. +void PlatformViewsController::PerformSubmit( + const LayersMap& platform_view_layers, + std::unordered_map& current_composition_params, + const std::unordered_set& views_to_recomposite, + const std::vector& composition_order, + const std::vector>& unused_layers, + const std::vector>& surface_frames) { + TRACE_EVENT0("flutter", "PlatformViewsController::PerformSubmit"); + FML_DCHECK([[NSThread currentThread] isMainThread]); + + [CATransaction begin]; + + // Configure Flutter overlay views. + for (const auto& [view_id, layer_data] : platform_view_layers) { + layer_data.layer->UpdateViewState(flutter_view_, // + layer_data.rect, // + layer_data.view_id, // + layer_data.overlay_id // + ); + } + + // Dispose unused Flutter Views. + for (auto& view : GetViewsToDispose()) { + [view removeFromSuperview]; + } + + // Composite Platform Views. + for (int64_t view_id : views_to_recomposite) { + CompositeWithParams(view_id, current_composition_params[view_id]); + } + + // Present callbacks. + for (const auto& frame : surface_frames) { + frame->Submit(); + } + + // If a layer was allocated in the previous frame, but it's not used in the current frame, + // then it can be removed from the scene. + RemoveUnusedLayers(unused_layers, composition_order); + + // Organize the layers by their z indexes. + BringLayersIntoView(platform_view_layers, composition_order); + + [CATransaction commit]; +} + +void PlatformViewsController::BringLayersIntoView(const LayersMap& layer_map, + const std::vector& composition_order) { + FML_DCHECK(flutter_view_); + UIView* flutter_view = flutter_view_; + + previous_composition_order_.clear(); + NSMutableArray* desired_platform_subviews = [NSMutableArray array]; + for (int64_t platform_view_id : composition_order) { + previous_composition_order_.push_back(platform_view_id); + UIView* platform_view_root = platform_views_[platform_view_id].root_view; + if (platform_view_root != nil) { + [desired_platform_subviews addObject:platform_view_root]; + } + + auto maybe_layer_data = layer_map.find(platform_view_id); + if (maybe_layer_data != layer_map.end()) { + auto view = maybe_layer_data->second.layer->overlay_view_wrapper; + if (view != nil) { + [desired_platform_subviews addObject:view]; + } + } + } + + NSSet* desired_platform_subviews_set = [NSSet setWithArray:desired_platform_subviews]; + NSArray* existing_platform_subviews = [flutter_view.subviews + filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, + NSDictionary* bindings) { + return [desired_platform_subviews_set containsObject:object]; + }]]; + + // Manipulate view hierarchy only if needed, to address a performance issue where + // `BringLayersIntoView` is called even when view hierarchy stays the same. + // See: https://github.com/flutter/flutter/issues/121833 + // TODO(hellohuanlin): investigate if it is possible to skip unnecessary BringLayersIntoView. + if (![desired_platform_subviews isEqualToArray:existing_platform_subviews]) { + for (UIView* subview in desired_platform_subviews) { + // `addSubview` will automatically reorder subview if it is already added. + [flutter_view addSubview:subview]; + } + } +} + +std::shared_ptr PlatformViewsController::GetExistingLayer() { + return layer_pool_->GetNextLayer(); +} + +void PlatformViewsController::CreateLayer(GrDirectContext* gr_context, + const std::shared_ptr& ios_context, + MTLPixelFormat pixel_format) { + layer_pool_->CreateLayer(gr_context, ios_context, pixel_format); +} + +void PlatformViewsController::RemoveUnusedLayers( + const std::vector>& unused_layers, + const std::vector& composition_order) { + for (const std::shared_ptr& layer : unused_layers) { + [layer->overlay_view_wrapper removeFromSuperview]; + } + + std::unordered_set composition_order_set; + for (int64_t view_id : composition_order) { + composition_order_set.insert(view_id); + } + // Remove unused platform views. + for (int64_t view_id : previous_composition_order_) { + if (composition_order_set.find(view_id) == composition_order_set.end()) { + UIView* platform_view_root = platform_views_[view_id].root_view; + [platform_view_root removeFromSuperview]; + } + } +} + +std::vector PlatformViewsController::GetViewsToDispose() { + std::vector views; + if (views_to_dispose_.empty()) { + return views; + } + + std::unordered_set views_to_composite(composition_order_.begin(), + composition_order_.end()); + std::unordered_set views_to_delay_dispose; + for (int64_t viewId : views_to_dispose_) { + if (views_to_composite.count(viewId)) { + views_to_delay_dispose.insert(viewId); + continue; + } + UIView* root_view = platform_views_[viewId].root_view; + views.push_back(root_view); + current_composition_params_.erase(viewId); + views_to_recomposite_.erase(viewId); + platform_views_.erase(viewId); + } + views_to_dispose_ = std::move(views_to_delay_dispose); + return views; +} + +void PlatformViewsController::ResetFrameState() { + slices_.clear(); + composition_order_.clear(); + visited_platform_views_.clear(); +} + +} // namespace flutter diff --git a/engine/src/flutter/shell/platform/darwin/ios/ios_external_view_embedder.h b/engine/src/flutter/shell/platform/darwin/ios/ios_external_view_embedder.h index d22fc3fb47..6983ac83f0 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/ios_external_view_embedder.h +++ b/engine/src/flutter/shell/platform/darwin/ios/ios_external_view_embedder.h @@ -13,14 +13,14 @@ namespace flutter { class IOSExternalViewEmbedder : public ExternalViewEmbedder { public: IOSExternalViewEmbedder( - __weak FlutterPlatformViewsController* platform_views_controller, + const std::shared_ptr& platform_views_controller, const std::shared_ptr& context); // |ExternalViewEmbedder| virtual ~IOSExternalViewEmbedder() override; private: - __weak FlutterPlatformViewsController* platform_views_controller_; + const std::shared_ptr& platform_views_controller_; std::shared_ptr ios_context_; // |ExternalViewEmbedder| diff --git a/engine/src/flutter/shell/platform/darwin/ios/ios_external_view_embedder.mm b/engine/src/flutter/shell/platform/darwin/ios/ios_external_view_embedder.mm index ebde36386b..a2f5ff9c2b 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/ios_external_view_embedder.mm +++ b/engine/src/flutter/shell/platform/darwin/ios/ios_external_view_embedder.mm @@ -12,7 +12,7 @@ FLUTTER_ASSERT_ARC namespace flutter { IOSExternalViewEmbedder::IOSExternalViewEmbedder( - __weak FlutterPlatformViewsController* platform_views_controller, + const std::shared_ptr& platform_views_controller, const std::shared_ptr& context) : platform_views_controller_(platform_views_controller), ios_context_(context) { FML_CHECK(ios_context_); @@ -31,7 +31,7 @@ DlCanvas* IOSExternalViewEmbedder::GetRootCanvas() { void IOSExternalViewEmbedder::CancelFrame() { TRACE_EVENT0("flutter", "IOSExternalViewEmbedder::CancelFrame"); FML_CHECK(platform_views_controller_); - [platform_views_controller_ cancelFrame]; + platform_views_controller_->CancelFrame(); } // |ExternalViewEmbedder| @@ -42,7 +42,7 @@ void IOSExternalViewEmbedder::BeginFrame( // |ExternalViewEmbedder| void IOSExternalViewEmbedder::PrepareFlutterView(SkISize frame_size, double device_pixel_ratio) { FML_CHECK(platform_views_controller_); - [platform_views_controller_ beginFrameWithSize:frame_size]; + platform_views_controller_->BeginFrame(frame_size); } // |ExternalViewEmbedder| @@ -51,7 +51,7 @@ void IOSExternalViewEmbedder::PrerollCompositeEmbeddedView( std::unique_ptr params) { TRACE_EVENT0("flutter", "IOSExternalViewEmbedder::PrerollCompositeEmbeddedView"); FML_CHECK(platform_views_controller_); - [platform_views_controller_ prerollCompositeEmbeddedView:view_id withParams:std::move(params)]; + platform_views_controller_->PrerollCompositeEmbeddedView(view_id, std::move(params)); } // |ExternalViewEmbedder| @@ -59,10 +59,8 @@ PostPrerollResult IOSExternalViewEmbedder::PostPrerollAction( const fml::RefPtr& raster_thread_merger) { TRACE_EVENT0("flutter", "IOSExternalViewEmbedder::PostPrerollAction"); FML_CHECK(platform_views_controller_); - BOOL impeller_enabled = ios_context_->GetBackend() != IOSRenderingBackend::kSkia; - PostPrerollResult result = - [platform_views_controller_ postPrerollActionWithThreadMerger:raster_thread_merger - impellerEnabled:impeller_enabled]; + PostPrerollResult result = platform_views_controller_->PostPrerollAction( + raster_thread_merger, ios_context_->GetBackend() != IOSRenderingBackend::kSkia); return result; } @@ -70,7 +68,7 @@ PostPrerollResult IOSExternalViewEmbedder::PostPrerollAction( DlCanvas* IOSExternalViewEmbedder::CompositeEmbeddedView(int64_t view_id) { TRACE_EVENT0("flutter", "IOSExternalViewEmbedder::CompositeEmbeddedView"); FML_CHECK(platform_views_controller_); - return [platform_views_controller_ compositeEmbeddedViewWithId:view_id]; + return platform_views_controller_->CompositeEmbeddedView(view_id); } // |ExternalViewEmbedder| @@ -85,9 +83,7 @@ void IOSExternalViewEmbedder::SubmitFlutterView( // Properly support multi-view in the future. FML_DCHECK(flutter_view_id == kFlutterImplicitViewId); FML_CHECK(platform_views_controller_); - [platform_views_controller_ submitFrame:std::move(frame) - withIosContext:ios_context_ - grContext:context]; + platform_views_controller_->SubmitFrame(context, ios_context_, std::move(frame)); TRACE_EVENT0("flutter", "IOSExternalViewEmbedder::DidSubmitFrame"); } @@ -96,10 +92,8 @@ void IOSExternalViewEmbedder::EndFrame( bool should_resubmit_frame, const fml::RefPtr& raster_thread_merger) { TRACE_EVENT0("flutter", "IOSExternalViewEmbedder::EndFrame"); - BOOL impeller_enabled = ios_context_->GetBackend() != IOSRenderingBackend::kSkia; - [platform_views_controller_ endFrameWithResubmit:should_resubmit_frame - threadMerger:raster_thread_merger - impellerEnabled:impeller_enabled]; + platform_views_controller_->EndFrame(should_resubmit_frame, raster_thread_merger, + ios_context_->GetBackend() != IOSRenderingBackend::kSkia); } // |ExternalViewEmbedder| @@ -116,12 +110,12 @@ bool IOSExternalViewEmbedder::SupportsDynamicThreadMerging() { void IOSExternalViewEmbedder::PushFilterToVisitedPlatformViews( const std::shared_ptr& filter, const SkRect& filter_rect) { - [platform_views_controller_ pushFilterToVisitedPlatformViews:filter withRect:filter_rect]; + platform_views_controller_->PushFilterToVisitedPlatformViews(filter, filter_rect); } // |ExternalViewEmbedder| void IOSExternalViewEmbedder::PushVisitedPlatformView(int64_t view_id) { - [platform_views_controller_ pushVisitedPlatformViewId:view_id]; + platform_views_controller_->PushVisitedPlatformView(view_id); } } // namespace flutter diff --git a/engine/src/flutter/shell/platform/darwin/ios/platform_view_ios.h b/engine/src/flutter/shell/platform/darwin/ios/platform_view_ios.h index 4e1da467d2..0e65e6174f 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/platform_view_ios.h +++ b/engine/src/flutter/shell/platform/darwin/ios/platform_view_ios.h @@ -40,13 +40,13 @@ class PlatformViewIOS final : public PlatformView { public: PlatformViewIOS(PlatformView::Delegate& delegate, const std::shared_ptr& context, - __weak FlutterPlatformViewsController* platform_views_controller, + const std::shared_ptr& platform_views_controller, const flutter::TaskRunners& task_runners); explicit PlatformViewIOS( PlatformView::Delegate& delegate, IOSRenderingAPI rendering_api, - __weak FlutterPlatformViewsController* platform_views_controller, + const std::shared_ptr& platform_views_controller, const flutter::TaskRunners& task_runners, const std::shared_ptr& worker_task_runner, const std::shared_ptr& is_gpu_disabled_sync_switch); @@ -137,7 +137,7 @@ class PlatformViewIOS final : public PlatformView { std::mutex ios_surface_mutex_; std::unique_ptr ios_surface_; std::shared_ptr ios_context_; - __weak FlutterPlatformViewsController* platform_views_controller_; + const std::shared_ptr& platform_views_controller_; AccessibilityBridgeManager accessibility_bridge_; ScopedObserver dealloc_view_controller_observer_; std::vector platform_resolved_locale_; diff --git a/engine/src/flutter/shell/platform/darwin/ios/platform_view_ios.mm b/engine/src/flutter/shell/platform/darwin/ios/platform_view_ios.mm index b726fd8fc1..f651d00ec8 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/platform_view_ios.mm +++ b/engine/src/flutter/shell/platform/darwin/ios/platform_view_ios.mm @@ -41,10 +41,11 @@ void PlatformViewIOS::AccessibilityBridgeManager::Clear() { accessibility_bridge_.reset(); } -PlatformViewIOS::PlatformViewIOS(PlatformView::Delegate& delegate, - const std::shared_ptr& context, - __weak FlutterPlatformViewsController* platform_views_controller, - const flutter::TaskRunners& task_runners) +PlatformViewIOS::PlatformViewIOS( + PlatformView::Delegate& delegate, + const std::shared_ptr& context, + const std::shared_ptr& platform_views_controller, + const flutter::TaskRunners& task_runners) : PlatformView(delegate, task_runners), ios_context_(context), platform_views_controller_(platform_views_controller), @@ -55,7 +56,7 @@ PlatformViewIOS::PlatformViewIOS(PlatformView::Delegate& delegate, PlatformViewIOS::PlatformViewIOS( PlatformView::Delegate& delegate, IOSRenderingAPI rendering_api, - __weak FlutterPlatformViewsController* platform_views_controller, + const std::shared_ptr& platform_views_controller, const flutter::TaskRunners& task_runners, const std::shared_ptr& worker_task_runner, const std::shared_ptr& is_gpu_disabled_sync_switch) @@ -208,7 +209,7 @@ void PlatformViewIOS::OnPreEngineRestart() const { if (!owner_controller_) { return; } - [owner_controller_.platformViewsController reset]; + owner_controller_.platformViewsController->Reset(); [owner_controller_.restorationPlugin reset]; }