From afd05afc406deb79fbe9c16684aeeeb19322b288 Mon Sep 17 00:00:00 2001 From: Chris Bracken Date: Mon, 25 Nov 2024 17:23:21 -0800 Subject: [PATCH] iOS: Migrate PlatformViewsController to Objective-C (flutter/engine#56790) This migrates PlatformViewController from C++ to Objective-C. Generally, we try to keep the embedder interfaces and components written in Objective-C except for the few places where C++ interfaces are requried to interface with engine APIs such as Shell and PlatformView (e.g. the PlatformViewIOS subclass). Now that the implementation is Objective-C, the class and file are renamed to match Objective-C naming conventions. This allows us to take advantage of ARC and weak references, which eliminates the need for std::shared_ptr, fml::WeakPtr etc. Further, this eliminates some particularly unintuitive behaviour wherein this class was owned via a std::shared_ptr held by FlutterEngine, and injected into many other classes (e.g. AccessibilityBridge) via a std::shared_ptr& reference -- such that only one instance of the std::shared_ptr actually ever existed, presumably to avoid std::shared_ptr refcounting overhead. Given that this overhead was only incurred a single time at engine initialisation, this seems like overkill. One might ask why it wasn't therefore held in a `std::unique_ptr` and a `std::unique_ptr&` reference passed around. Likely, this was because we wanted to take a `fml::WeakPtr` reference on it. Regardless, none of this is necessary any longer now that we can inject `__weak FlutterPlatformViewsController*` instances to classes that use it. To be clear, this patch makes no attempt whatsoever to simplify or clean up the interface or implementation of this class. This class ties together far too many concepts and is injected into far too many places, and we should break it up and simplify it. However, the goal of this patch was simply to port to an Objective-C interface that plays nicely with the rest of the iOS embedder. This does include a couple minor cleanups in `#include`/`#import` order and usage to match our style guide. [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style --- .../ci/licenses_golden/licenses_flutter | 8 +- .../shell/platform/darwin/ios/BUILD.gn | 4 +- .../ios/framework/Source/FlutterEngine.mm | 39 +- .../framework/Source/FlutterEngine_Internal.h | 2 +- .../Source/FlutterPlatformViewsController.h | 152 ++ .../Source/FlutterPlatformViewsController.mm | 1083 ++++++++++++ .../Source/FlutterPlatformViewsTest.mm | 1559 ++++++++++------- .../Source/FlutterPlatformViews_Internal.h | 16 +- .../Source/FlutterPlatformViews_Internal.mm | 16 +- .../darwin/ios/framework/Source/FlutterView.h | 3 +- .../framework/Source/FlutterViewController.mm | 10 +- .../Source/FlutterViewController_Internal.h | 8 +- .../ios/framework/Source/FlutterViewTest.mm | 11 +- .../Source/SemanticsObjectTestMocks.h | 8 +- .../framework/Source/accessibility_bridge.h | 6 +- .../framework/Source/accessibility_bridge.mm | 16 +- .../Source/accessibility_bridge_ios.h | 4 +- .../Source/accessibility_bridge_test.mm | 75 +- .../Source/platform_views_controller.h | 318 ---- .../Source/platform_views_controller.mm | 874 --------- .../darwin/ios/ios_external_view_embedder.h | 4 +- .../darwin/ios/ios_external_view_embedder.mm | 30 +- .../platform/darwin/ios/platform_view_ios.h | 6 +- .../platform/darwin/ios/platform_view_ios.mm | 13 +- 24 files changed, 2292 insertions(+), 1973 deletions(-) create mode 100644 engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsController.h create mode 100644 engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsController.mm delete mode 100644 engine/src/flutter/shell/platform/darwin/ios/framework/Source/platform_views_controller.h delete mode 100644 engine/src/flutter/shell/platform/darwin/ios/framework/Source/platform_views_controller.mm diff --git a/engine/src/flutter/ci/licenses_golden/licenses_flutter b/engine/src/flutter/ci/licenses_golden/licenses_flutter index 3d02635b70..e8a869695e 100644 --- a/engine/src/flutter/ci/licenses_golden/licenses_flutter +++ b/engine/src/flutter/ci/licenses_golden/licenses_flutter @@ -44563,6 +44563,8 @@ ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterOverl ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h + ../../../flutter/LICENSE 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/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/FlutterPlatformViews_Internal.mm + ../../../flutter/LICENSE @@ -44625,8 +44627,6 @@ 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 @@ -47499,6 +47499,8 @@ FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterOverlay FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h 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/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/FlutterPlatformViews_Internal.mm @@ -47561,8 +47563,6 @@ 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 85616de70f..86b27e070f 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/BUILD.gn +++ b/engine/src/flutter/shell/platform/darwin/ios/BUILD.gn @@ -79,6 +79,8 @@ source_set("flutter_framework_source") { "framework/Source/FlutterOverlayView.mm", "framework/Source/FlutterPlatformPlugin.h", "framework/Source/FlutterPlatformPlugin.mm", + "framework/Source/FlutterPlatformViewsController.h", + "framework/Source/FlutterPlatformViewsController.mm", "framework/Source/FlutterPlatformViews_Internal.h", "framework/Source/FlutterPlatformViews_Internal.mm", "framework/Source/FlutterPluginAppLifeCycleDelegate.mm", @@ -120,8 +122,6 @@ 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 85f1ba5519..eff08e6cc5 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,6 +105,8 @@ 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; @@ -150,7 +152,6 @@ static constexpr int kNumProfilerSamplesPerSec = 5; std::shared_ptr _threadHost; std::unique_ptr _shell; - std::shared_ptr _platformViewsController; flutter::IOSRenderingAPI _renderingApi; std::shared_ptr _profiler; @@ -211,7 +212,7 @@ static constexpr int kNumProfilerSamplesPerSec = 5; _pluginPublications = [[NSMutableDictionary alloc] init]; _registrars = [[NSMutableDictionary alloc] init]; - [self recreatePlatformViewController]; + [self recreatePlatformViewsController]; _binaryMessenger = [[FlutterBinaryMessengerRelay alloc] initWithParent:self]; _textureRegistry = [[FlutterTextureRegistryRelay alloc] initWithParent:self]; _connections.reset(new flutter::ConnectionCollection()); @@ -262,9 +263,9 @@ static constexpr int kNumProfilerSamplesPerSec = 5; object:nil]; } -- (void)recreatePlatformViewController { +- (void)recreatePlatformViewsController { _renderingApi = flutter::GetRenderingAPIForProcess(FlutterView.forceSoftwareRendering); - _platformViewsController.reset(new flutter::PlatformViewsController()); + _platformViewsController = [[FlutterPlatformViewsController alloc] init]; } - (flutter::IOSRenderingAPI)platformViewsRenderingAPI { @@ -452,11 +453,7 @@ static constexpr int kNumProfilerSamplesPerSec = 5; _shell.reset(); _profiler.reset(); _threadHost.reset(); - _platformViewsController.reset(); -} - -- (std::shared_ptr&)platformViewsController { - return _platformViewsController; + _platformViewsController = nil; } - (NSURL*)observatoryUrl { @@ -635,7 +632,7 @@ static constexpr int kNumProfilerSamplesPerSec = 5; [self.platformViewsChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) { if (weakSelf) { - weakSelf.platformViewsController->OnMethodCall(call, result); + [weakSelf.platformViewsController onMethodCall:call result:result]; } }]; @@ -777,11 +774,11 @@ static void SetEntryPoint(flutter::Settings* settings, NSString* entrypoint, NSS if (!strongSelf) { return std::unique_ptr(); } - [strongSelf recreatePlatformViewController]; - strongSelf->_platformViewsController->SetTaskRunner( - shell.GetTaskRunners().GetPlatformTaskRunner()); + [strongSelf recreatePlatformViewsController]; + strongSelf.platformViewsController.taskRunner = + shell.GetTaskRunners().GetPlatformTaskRunner(); return std::make_unique( - shell, strongSelf->_renderingApi, strongSelf->_platformViewsController, + shell, strongSelf->_renderingApi, strongSelf.platformViewsController, shell.GetTaskRunners(), shell.GetConcurrentWorkerTaskRunner(), shell.GetIsGpuDisabledSyncSwitch()); }; @@ -1103,7 +1100,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->FindFirstResponderPlatformViewId(); + long platform_view_id = [self.platformViewsController firstResponderPlatformViewId]; if (platform_view_id == -1) { return; } @@ -1400,11 +1397,10 @@ 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 recreatePlatformViewController]; - result->_platformViewsController->SetTaskRunner( - shell.GetTaskRunners().GetPlatformTaskRunner()); + [result recreatePlatformViewsController]; + result.platformViewsController.taskRunner = 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 = @@ -1499,8 +1495,9 @@ static void SetEntryPoint(flutter::Settings* settings, NSString* entrypoint, NSS withId:(NSString*)factoryId gestureRecognizersBlockingPolicy: (FlutterPlatformViewGestureRecognizersBlockingPolicy)gestureRecognizersBlockingPolicy { - [_flutterEngine platformViewsController]->RegisterViewFactory(factory, factoryId, - gestureRecognizersBlockingPolicy); + [_flutterEngine.platformViewsController registerViewFactory:factory + withId:factoryId + gestureRecognizersBlockingPolicy: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 6f954adbcb..bb3beca9db 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,7 +46,6 @@ NS_ASSUME_NONNULL_BEGIN base64Encode:(bool)base64Encode; - (FlutterPlatformPlugin*)platformPlugin; -- (std::shared_ptr&)platformViewsController; - (FlutterTextInputPlugin*)textInputPlugin; - (FlutterRestorationPlugin*)restorationPlugin; - (void)launchEngine:(nullable NSString*)entrypoint @@ -81,6 +80,7 @@ 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/FlutterPlatformViewsController.h b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsController.h new file mode 100644 index 0000000000..2c2dea71e3 --- /dev/null +++ b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsController.h @@ -0,0 +1,152 @@ +// 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; + +// TODO(cbracken): Delete. This is unused. +- (size_t)layerPoolSize; + +// 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 new file mode 100644 index 0000000000..f6c2f0a2ad --- /dev/null +++ b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsController.mm @@ -0,0 +1,1083 @@ +// 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" +#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); +} + +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; +}; + +} // namespace + +@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; + +/// 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 + +namespace flutter { + +// TODO(cbracken): Eliminate the use of globals. +// Becomes NO if Apple's API changes and blurred backdrop filters cannot be applied. +BOOL canApplyBlurBackdrop = YES; + +} // namespace flutter + +@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; + } + 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(); +} + +- (size_t)layerPoolSize { + return self.layerPool->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 (!flutter::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) { + flutter::canApplyBlurBackdrop = NO; + } else { + [blurFilters addObject:filter]; + } + break; + } + } + ++iter; + } + + if (flutter::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 8c0bb2b03e..dd48e60364 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,21 +2,22 @@ // 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" -#import "flutter/display_list/effects/dl_image_filters.h" -#import "flutter/fml/thread.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/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" -#import "flutter/shell/platform/darwin/ios/platform_view_ios.h" +#include "flutter/shell/platform/darwin/ios/platform_view_ios.h" FLUTTER_ASSERT_ARC @@ -163,8 +164,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -177,18 +179,21 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @2, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)]; - flutterPlatformViewsController->SetFlutterView(flutterView); + flutterPlatformViewsController.flutterView = flutterView; // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack @@ -204,11 +209,12 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams)]; XCTAssertNotNil(gMockPlatformView); - flutterPlatformViewsController->Reset(); + [flutterPlatformViewsController reset]; } - (void)testCanCreatePlatformViewWithoutFlutterView { @@ -219,8 +225,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -233,16 +240,19 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @2, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; XCTAssertNotNil(gMockPlatformView); } @@ -312,8 +322,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -326,21 +337,24 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @2, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; - flutterPlatformViewsController->SetFlutterView(flutterView); + flutterPlatformViewsController.flutterView = flutterView; // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack @@ -354,9 +368,11 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); - flutterPlatformViewsController->CompositeWithParams( - 2, flutterPlatformViewsController->GetCompositionParams(2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams)]; + [flutterPlatformViewsController + compositeView:2 + withParams:[flutterPlatformViewsController compositionParamsForView:2]]; XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:[ChildClippingView class]]); ChildClippingView* childClippingView = (ChildClippingView*)gMockPlatformView.superview.superview; @@ -389,8 +405,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -403,21 +420,24 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @2, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; - flutterPlatformViewsController->SetFlutterView(flutterView); + flutterPlatformViewsController.flutterView = flutterView; // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack @@ -431,9 +451,11 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(5, 10), stack); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); - flutterPlatformViewsController->CompositeWithParams( - 2, flutterPlatformViewsController->GetCompositionParams(2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams)]; + [flutterPlatformViewsController + compositeView:2 + withParams:[flutterPlatformViewsController compositionParamsForView:2]]; XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:[ChildClippingView class]]); ChildClippingView* childClippingView = (ChildClippingView*)gMockPlatformView.superview.superview; @@ -466,8 +488,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -480,21 +503,24 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @2, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; - flutterPlatformViewsController->SetFlutterView(flutterView); + flutterPlatformViewsController.flutterView = flutterView; // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack @@ -510,9 +536,11 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(20, 20), stack); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); - flutterPlatformViewsController->CompositeWithParams( - 2, flutterPlatformViewsController->GetCompositionParams(2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams)]; + [flutterPlatformViewsController + compositeView:2 + withParams:[flutterPlatformViewsController compositionParamsForView:2]]; XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:ChildClippingView.class]); ChildClippingView* childClippingView = (ChildClippingView*)gMockPlatformView.superview.superview; @@ -544,8 +572,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -558,21 +587,24 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @2, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; - flutterPlatformViewsController->SetFlutterView(flutterView); + flutterPlatformViewsController.flutterView = flutterView; // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack @@ -586,9 +618,11 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); - flutterPlatformViewsController->CompositeWithParams( - 2, flutterPlatformViewsController->GetCompositionParams(2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams)]; + [flutterPlatformViewsController + compositeView:2 + withParams:[flutterPlatformViewsController compositionParamsForView:2]]; XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:[ChildClippingView class]]); ChildClippingView* childClippingView = (ChildClippingView*)gMockPlatformView.superview.superview; @@ -625,9 +659,11 @@ fml::RefPtr GetDefaultTaskRunner() { embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack2); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); - flutterPlatformViewsController->CompositeWithParams( - 2, flutterPlatformViewsController->GetCompositionParams(2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams)]; + [flutterPlatformViewsController + compositeView:2 + withParams:[flutterPlatformViewsController compositionParamsForView:2]]; [flutterView setNeedsLayout]; [flutterView layoutIfNeeded]; @@ -665,8 +701,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -679,21 +716,24 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @2, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; - flutterPlatformViewsController->SetFlutterView(flutterView); + flutterPlatformViewsController.flutterView = flutterView; // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack @@ -709,9 +749,11 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); - flutterPlatformViewsController->CompositeWithParams( - 2, flutterPlatformViewsController->GetCompositionParams(2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams)]; + [flutterPlatformViewsController + compositeView:2 + withParams:[flutterPlatformViewsController compositionParamsForView:2]]; XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:ChildClippingView.class]); ChildClippingView* childClippingView = (ChildClippingView*)gMockPlatformView.superview.superview; @@ -746,9 +788,11 @@ fml::RefPtr GetDefaultTaskRunner() { embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack2); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); - flutterPlatformViewsController->CompositeWithParams( - 2, flutterPlatformViewsController->GetCompositionParams(2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams)]; + [flutterPlatformViewsController + compositeView:2 + withParams:[flutterPlatformViewsController compositionParamsForView:2]]; [flutterView setNeedsLayout]; [flutterView layoutIfNeeded]; @@ -787,9 +831,11 @@ fml::RefPtr GetDefaultTaskRunner() { embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack2); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); - flutterPlatformViewsController->CompositeWithParams( - 2, flutterPlatformViewsController->GetCompositionParams(2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams)]; + [flutterPlatformViewsController + compositeView:2 + withParams:[flutterPlatformViewsController compositionParamsForView:2]]; [flutterView setNeedsLayout]; [flutterView layoutIfNeeded]; @@ -811,8 +857,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -825,21 +872,24 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @2, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; - flutterPlatformViewsController->SetFlutterView(flutterView); + flutterPlatformViewsController.flutterView = flutterView; // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack @@ -855,9 +905,11 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); - flutterPlatformViewsController->CompositeWithParams( - 2, flutterPlatformViewsController->GetCompositionParams(2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams)]; + [flutterPlatformViewsController + compositeView:2 + withParams:[flutterPlatformViewsController compositionParamsForView:2]]; XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:ChildClippingView.class]); ChildClippingView* childClippingView = (ChildClippingView*)gMockPlatformView.superview.superview; @@ -900,9 +952,11 @@ fml::RefPtr GetDefaultTaskRunner() { embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack2); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); - flutterPlatformViewsController->CompositeWithParams( - 2, flutterPlatformViewsController->GetCompositionParams(2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams)]; + [flutterPlatformViewsController + compositeView:2 + withParams:[flutterPlatformViewsController compositionParamsForView:2]]; [flutterView setNeedsLayout]; [flutterView layoutIfNeeded]; @@ -955,9 +1009,11 @@ fml::RefPtr GetDefaultTaskRunner() { embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack2); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); - flutterPlatformViewsController->CompositeWithParams( - 2, flutterPlatformViewsController->GetCompositionParams(2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams)]; + [flutterPlatformViewsController + compositeView:2 + withParams:[flutterPlatformViewsController compositionParamsForView:2]]; [flutterView setNeedsLayout]; [flutterView layoutIfNeeded]; @@ -1008,9 +1064,11 @@ fml::RefPtr GetDefaultTaskRunner() { embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack2); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); - flutterPlatformViewsController->CompositeWithParams( - 2, flutterPlatformViewsController->GetCompositionParams(2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams)]; + [flutterPlatformViewsController + compositeView:2 + withParams:[flutterPlatformViewsController compositionParamsForView:2]]; [flutterView setNeedsLayout]; [flutterView layoutIfNeeded]; @@ -1058,9 +1116,11 @@ fml::RefPtr GetDefaultTaskRunner() { embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack2); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); - flutterPlatformViewsController->CompositeWithParams( - 2, flutterPlatformViewsController->GetCompositionParams(2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams)]; + [flutterPlatformViewsController + compositeView:2 + withParams:[flutterPlatformViewsController compositionParamsForView:2]]; [flutterView setNeedsLayout]; [flutterView layoutIfNeeded]; @@ -1098,8 +1158,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -1112,21 +1173,24 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @2, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; - flutterPlatformViewsController->SetFlutterView(flutterView); + flutterPlatformViewsController.flutterView = flutterView; // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack @@ -1140,9 +1204,11 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); - flutterPlatformViewsController->CompositeWithParams( - 2, flutterPlatformViewsController->GetCompositionParams(2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams)]; + [flutterPlatformViewsController + compositeView:2 + withParams:[flutterPlatformViewsController compositionParamsForView:2]]; XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:[ChildClippingView class]]); ChildClippingView* childClippingView = (ChildClippingView*)gMockPlatformView.superview.superview; @@ -1182,9 +1248,11 @@ fml::RefPtr GetDefaultTaskRunner() { embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack2); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); - flutterPlatformViewsController->CompositeWithParams( - 2, flutterPlatformViewsController->GetCompositionParams(2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams)]; + [flutterPlatformViewsController + compositeView:2 + withParams:[flutterPlatformViewsController compositionParamsForView:2]]; [flutterView setNeedsLayout]; [flutterView layoutIfNeeded]; @@ -1223,9 +1291,11 @@ fml::RefPtr GetDefaultTaskRunner() { embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack2); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); - flutterPlatformViewsController->CompositeWithParams( - 2, flutterPlatformViewsController->GetCompositionParams(2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams)]; + [flutterPlatformViewsController + compositeView:2 + withParams:[flutterPlatformViewsController compositionParamsForView:2]]; [flutterView setNeedsLayout]; [flutterView layoutIfNeeded]; @@ -1264,9 +1334,11 @@ fml::RefPtr GetDefaultTaskRunner() { embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack2); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); - flutterPlatformViewsController->CompositeWithParams( - 2, flutterPlatformViewsController->GetCompositionParams(2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams)]; + [flutterPlatformViewsController + compositeView:2 + withParams:[flutterPlatformViewsController compositionParamsForView:2]]; [flutterView setNeedsLayout]; [flutterView layoutIfNeeded]; @@ -1299,9 +1371,11 @@ fml::RefPtr GetDefaultTaskRunner() { embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack2); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); - flutterPlatformViewsController->CompositeWithParams( - 2, flutterPlatformViewsController->GetCompositionParams(2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams)]; + [flutterPlatformViewsController + compositeView:2 + withParams:[flutterPlatformViewsController compositionParamsForView:2]]; [flutterView setNeedsLayout]; [flutterView layoutIfNeeded]; @@ -1417,8 +1491,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -1431,21 +1506,24 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @2, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)]; - flutterPlatformViewsController->SetFlutterView(flutterView); + flutterPlatformViewsController.flutterView = flutterView; // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack @@ -1461,9 +1539,11 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); - flutterPlatformViewsController->CompositeWithParams( - 2, flutterPlatformViewsController->GetCompositionParams(2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams)]; + [flutterPlatformViewsController + compositeView:2 + withParams:[flutterPlatformViewsController compositionParamsForView:2]]; CGRect platformViewRectInFlutterView = [gMockPlatformView convertRect:gMockPlatformView.bounds toView:flutterView]; @@ -1478,8 +1558,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -1492,21 +1573,24 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @2, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; - flutterPlatformViewsController->SetFlutterView(flutterView); + flutterPlatformViewsController.flutterView = flutterView; // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack @@ -1517,14 +1601,17 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack); - flutterPlatformViewsController->BeginFrame(SkISize::Make(0, 0)); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); - flutterPlatformViewsController->PushVisitedPlatformView(2); + [flutterPlatformViewsController beginFrameWithSize:SkISize::Make(0, 0)]; + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams)]; + [flutterPlatformViewsController pushVisitedPlatformViewId:2]; auto filter = flutter::DlBlurImageFilter::Make(5, 2, flutter::DlTileMode::kClamp); - flutterPlatformViewsController->PushFilterToVisitedPlatformViews( - filter, SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); - flutterPlatformViewsController->CompositeWithParams( - 2, flutterPlatformViewsController->GetCompositionParams(2)); + [flutterPlatformViewsController + pushFilterToVisitedPlatformViews:filter + withRect:SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)]; + [flutterPlatformViewsController + compositeView:2 + withParams:[flutterPlatformViewsController compositionParamsForView:2]]; XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:[ChildClippingView class]]); ChildClippingView* childClippingView = (ChildClippingView*)gMockPlatformView.superview.superview; @@ -1551,10 +1638,12 @@ fml::RefPtr GetDefaultTaskRunner() { // New frame, with no filter pushed. auto embeddedViewParams2 = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack); - flutterPlatformViewsController->BeginFrame(SkISize::Make(0, 0)); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams2)); - flutterPlatformViewsController->CompositeWithParams( - 2, flutterPlatformViewsController->GetCompositionParams(2)); + [flutterPlatformViewsController beginFrameWithSize:SkISize::Make(0, 0)]; + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams2)]; + [flutterPlatformViewsController + compositeView:2 + withParams:[flutterPlatformViewsController compositionParamsForView:2]]; XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:[ChildClippingView class]]); @@ -1579,8 +1668,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -1593,21 +1683,24 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @2, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)]; - flutterPlatformViewsController->SetFlutterView(flutterView); + flutterPlatformViewsController.flutterView = flutterView; // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack @@ -1624,9 +1717,11 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); - flutterPlatformViewsController->CompositeWithParams( - 2, flutterPlatformViewsController->GetCompositionParams(2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams)]; + [flutterPlatformViewsController + compositeView:2 + withParams:[flutterPlatformViewsController compositionParamsForView:2]]; CGRect platformViewRectInFlutterView = [gMockPlatformView convertRect:gMockPlatformView.bounds toView:flutterView]; @@ -1655,8 +1750,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -1669,21 +1765,24 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @2, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 30, 30)]; - flutterPlatformViewsController->SetFlutterView(flutterView); + flutterPlatformViewsController.flutterView = flutterView; // Create embedded view params. flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack. @@ -1705,9 +1804,11 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique( SkMatrix::Concat(screenScaleMatrix, translateMatrix), SkSize::Make(5, 5), stack); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); - flutterPlatformViewsController->CompositeWithParams( - 2, flutterPlatformViewsController->GetCompositionParams(2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams)]; + [flutterPlatformViewsController + compositeView:2 + withParams:[flutterPlatformViewsController compositionParamsForView:2]]; gMockPlatformView.backgroundColor = UIColor.redColor; XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:ChildClippingView.class]); @@ -1727,8 +1828,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -1741,21 +1843,24 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @2, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 30, 30)]; - flutterPlatformViewsController->SetFlutterView(flutterView); + flutterPlatformViewsController.flutterView = flutterView; // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack. @@ -1775,9 +1880,11 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique( SkMatrix::Concat(screenScaleMatrix, translateMatrix), SkSize::Make(5, 5), stack); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); - flutterPlatformViewsController->CompositeWithParams( - 2, flutterPlatformViewsController->GetCompositionParams(2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams)]; + [flutterPlatformViewsController + compositeView:2 + withParams:[flutterPlatformViewsController compositionParamsForView:2]]; gMockPlatformView.backgroundColor = UIColor.redColor; XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:ChildClippingView.class]); @@ -1798,8 +1905,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -1812,21 +1920,24 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @2, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; - flutterPlatformViewsController->SetFlutterView(flutterView); + flutterPlatformViewsController.flutterView = flutterView; // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack @@ -1840,9 +1951,11 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); - flutterPlatformViewsController->CompositeWithParams( - 2, flutterPlatformViewsController->GetCompositionParams(2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams)]; + [flutterPlatformViewsController + compositeView:2 + withParams:[flutterPlatformViewsController compositionParamsForView:2]]; gMockPlatformView.backgroundColor = UIColor.redColor; XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:ChildClippingView.class]); @@ -1874,8 +1987,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -1888,21 +2002,24 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @2, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; - flutterPlatformViewsController->SetFlutterView(flutterView); + flutterPlatformViewsController.flutterView = flutterView; // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack @@ -1919,9 +2036,11 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); - flutterPlatformViewsController->CompositeWithParams( - 2, flutterPlatformViewsController->GetCompositionParams(2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams)]; + [flutterPlatformViewsController + compositeView:2 + withParams:[flutterPlatformViewsController compositionParamsForView:2]]; gMockPlatformView.backgroundColor = UIColor.redColor; XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:ChildClippingView.class]); @@ -1970,8 +2089,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -1984,21 +2104,24 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @2, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; - flutterPlatformViewsController->SetFlutterView(flutterView); + flutterPlatformViewsController.flutterView = flutterView; // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack @@ -2012,9 +2135,11 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); - flutterPlatformViewsController->CompositeWithParams( - 2, flutterPlatformViewsController->GetCompositionParams(2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams)]; + [flutterPlatformViewsController + compositeView:2 + withParams:[flutterPlatformViewsController compositionParamsForView:2]]; gMockPlatformView.backgroundColor = UIColor.redColor; XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:ChildClippingView.class]); @@ -2073,8 +2198,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -2087,21 +2213,24 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @2, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; - flutterPlatformViewsController->SetFlutterView(flutterView); + flutterPlatformViewsController.flutterView = flutterView; // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack @@ -2118,9 +2247,11 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); - flutterPlatformViewsController->CompositeWithParams( - 2, flutterPlatformViewsController->GetCompositionParams(2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams)]; + [flutterPlatformViewsController + compositeView:2 + withParams:[flutterPlatformViewsController compositionParamsForView:2]]; gMockPlatformView.backgroundColor = UIColor.redColor; XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:ChildClippingView.class]); @@ -2193,8 +2324,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -2207,21 +2339,24 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @2, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; - flutterPlatformViewsController->SetFlutterView(flutterView); + flutterPlatformViewsController.flutterView = flutterView; // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack @@ -2236,9 +2371,11 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); - flutterPlatformViewsController->CompositeWithParams( - 2, flutterPlatformViewsController->GetCompositionParams(2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams)]; + [flutterPlatformViewsController + compositeView:2 + withParams:[flutterPlatformViewsController compositionParamsForView:2]]; gMockPlatformView.backgroundColor = UIColor.redColor; XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:ChildClippingView.class]); @@ -2297,8 +2434,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -2311,21 +2449,24 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @2, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; - flutterPlatformViewsController->SetFlutterView(flutterView); + flutterPlatformViewsController.flutterView = flutterView; // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack @@ -2343,9 +2484,11 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(screenScaleMatrix, SkSize::Make(10, 10), stack); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); - flutterPlatformViewsController->CompositeWithParams( - 2, flutterPlatformViewsController->GetCompositionParams(2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams)]; + [flutterPlatformViewsController + compositeView:2 + withParams:[flutterPlatformViewsController compositionParamsForView:2]]; gMockPlatformView.backgroundColor = UIColor.redColor; XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:ChildClippingView.class]); @@ -2418,8 +2561,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -2432,16 +2576,19 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @2, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; XCTAssertNotNil(gMockPlatformView); @@ -2472,7 +2619,7 @@ fml::RefPtr GetDefaultTaskRunner() { // Set flutter view controller allows events to be dispatched. NSSet* touches2 = [[NSSet alloc] init]; id event2 = OCMClassMock([UIEvent class]); - flutterPlatformViewsController->SetFlutterViewController(flutterViewController); + flutterPlatformViewsController.flutterViewController = flutterViewController; [forwardGectureRecognizer touchesBegan:touches2 withEvent:event2]; OCMVerify([flutterViewController touchesBegan:touches2 withEvent:event2]); } @@ -2485,8 +2632,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -2499,16 +2647,19 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @2, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; XCTAssertNotNil(gMockPlatformView); @@ -2531,14 +2682,14 @@ fml::RefPtr GetDefaultTaskRunner() { id flutterViewController = OCMClassMock([FlutterViewController class]); { // ***** Sequence 1, finishing touch event with touchEnded ***** // - flutterPlatformViewsController->SetFlutterViewController(flutterViewController); + flutterPlatformViewsController.flutterViewController = flutterViewController; NSSet* touches1 = [[NSSet alloc] init]; id event1 = OCMClassMock([UIEvent class]); [forwardGectureRecognizer touchesBegan:touches1 withEvent:event1]; OCMVerify([flutterViewController touchesBegan:touches1 withEvent:event1]); - flutterPlatformViewsController->SetFlutterViewController(nil); + flutterPlatformViewsController.flutterViewController = nil; // Allow the touch events to finish NSSet* touches2 = [[NSSet alloc] init]; @@ -2565,14 +2716,14 @@ fml::RefPtr GetDefaultTaskRunner() { { // ***** Sequence 2, finishing touch event with touchCancelled ***** // - flutterPlatformViewsController->SetFlutterViewController(flutterViewController); + flutterPlatformViewsController.flutterViewController = flutterViewController; NSSet* touches1 = [[NSSet alloc] init]; id event1 = OCMClassMock([UIEvent class]); [forwardGectureRecognizer touchesBegan:touches1 withEvent:event1]; OCMVerify([flutterViewController touchesBegan:touches1 withEvent:event1]); - flutterPlatformViewsController->SetFlutterViewController(nil); + flutterPlatformViewsController.flutterViewController = nil; // Allow the touch events to finish NSSet* touches2 = [[NSSet alloc] init]; @@ -2597,7 +2748,7 @@ fml::RefPtr GetDefaultTaskRunner() { OCMReject([flutterViewController touchesEnded:touches5 withEvent:event5]); } - flutterPlatformViewsController->Reset(); + [flutterPlatformViewsController reset]; } - (void) @@ -2609,8 +2760,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -2623,16 +2775,19 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @2, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; XCTAssertNotNil(gMockPlatformView); @@ -2653,8 +2808,7 @@ fml::RefPtr GetDefaultTaskRunner() { } } id flutterViewController = OCMClassMock([FlutterViewController class]); - - flutterPlatformViewsController->SetFlutterViewController(flutterViewController); + flutterPlatformViewsController.flutterViewController = flutterViewController; // The touches in this sequence requires 1 touch object, we always create the NSSet with one item. NSSet* touches1 = [NSSet setWithObject:@1]; @@ -2663,7 +2817,7 @@ fml::RefPtr GetDefaultTaskRunner() { OCMVerify([flutterViewController touchesBegan:touches1 withEvent:event1]); FlutterViewController* flutterViewController2 = OCMClassMock([FlutterViewController class]); - flutterPlatformViewsController->SetFlutterViewController(flutterViewController2); + flutterPlatformViewsController.flutterViewController = flutterViewController2; // Touch events should still send to the old FlutterViewController if FlutterViewController // is updated in between. @@ -2712,7 +2866,7 @@ fml::RefPtr GetDefaultTaskRunner() { OCMVerify([flutterViewController2 touchesEnded:touches8 withEvent:event8]); OCMReject([flutterViewController touchesEnded:touches8 withEvent:event8]); - flutterPlatformViewsController->Reset(); + [flutterPlatformViewsController reset]; } - (void)testFlutterPlatformViewTouchesCancelledEventAreForcedToBeCancelled { @@ -2723,8 +2877,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -2737,16 +2892,19 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @2, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; XCTAssertNotNil(gMockPlatformView); @@ -2767,8 +2925,7 @@ fml::RefPtr GetDefaultTaskRunner() { } } id flutterViewController = OCMClassMock([FlutterViewController class]); - - flutterPlatformViewsController->SetFlutterViewController(flutterViewController); + flutterPlatformViewsController.flutterViewController = flutterViewController; NSSet* touches1 = [NSSet setWithObject:@1]; id event1 = OCMClassMock([UIEvent class]); @@ -2777,7 +2934,7 @@ fml::RefPtr GetDefaultTaskRunner() { [forwardGectureRecognizer touchesCancelled:touches1 withEvent:event1]; OCMVerify([flutterViewController forceTouchesCancelled:touches1]); - flutterPlatformViewsController->Reset(); + [flutterPlatformViewsController reset]; } - (void)testFlutterPlatformViewTouchesEndedOrTouchesCancelledEventDoesNotFailTheGestureRecognizer { @@ -2788,8 +2945,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -2802,16 +2960,19 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @2, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; XCTAssertNotNil(gMockPlatformView); @@ -2832,8 +2993,7 @@ fml::RefPtr GetDefaultTaskRunner() { } } id flutterViewController = OCMClassMock([FlutterViewController class]); - - flutterPlatformViewsController->SetFlutterViewController(flutterViewController); + flutterPlatformViewsController.flutterViewController = flutterViewController; NSSet* touches1 = [NSSet setWithObject:@1]; id event1 = OCMClassMock([UIEvent class]); @@ -2882,7 +3042,7 @@ fml::RefPtr GetDefaultTaskRunner() { }); [self waitForExpectationsWithTimeout:30 handler:nil]; - flutterPlatformViewsController->Reset(); + [flutterPlatformViewsController reset]; } - (void)testFlutterPlatformViewControllerSubmitFrameWithoutFlutterViewNotCrashing { @@ -2893,8 +3053,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -2907,16 +3068,19 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @2, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; XCTAssertNotNil(gMockPlatformView); @@ -2927,9 +3091,11 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams_1 = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams_1)); - flutterPlatformViewsController->CompositeWithParams( - 2, flutterPlatformViewsController->GetCompositionParams(2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams_1)]; + [flutterPlatformViewsController + compositeView:2 + withParams:[flutterPlatformViewsController compositionParamsForView:2]]; flutter::SurfaceFrame::FramebufferInfo framebuffer_info; auto mock_surface = std::make_unique( @@ -2937,22 +3103,26 @@ 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(nullptr, nullptr, std::move(mock_surface))); + XCTAssertFalse([flutterPlatformViewsController submitFrame:std::move(mock_surface) + withIosContext:nil + grContext:nil]); auto embeddedViewParams_2 = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams_2)); - flutterPlatformViewsController->CompositeWithParams( - 2, flutterPlatformViewsController->GetCompositionParams(2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams_2)]; + [flutterPlatformViewsController + compositeView:2 + withParams:[flutterPlatformViewsController compositionParamsForView: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(nullptr, nullptr, - std::move(mock_surface_submit_true))); + XCTAssertTrue([flutterPlatformViewsController submitFrame:std::move(mock_surface_submit_true) + withIosContext:nil + grContext:nil]); } - (void) @@ -2964,8 +3134,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -2977,34 +3148,38 @@ fml::RefPtr GetDefaultTaskRunner() { /*is_gpu_disabled_jsync_switch=*/std::make_shared()); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)]; - flutterPlatformViewsController->SetFlutterView(flutterView); + flutterPlatformViewsController.flutterView = flutterView; FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy: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); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @2, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; flutter::MutatorsStack stack; SkMatrix finalMatrix; auto embeddedViewParams = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams)]; - // Not calling |flutterPlatformViewsController::SubmitFrame| so that the platform views are not - // added to flutter_view_. + // Not calling |[flutterPlatformViewsController submitFrame:withIosContext:grContext:]| so that + // the platform views are not added to flutter_view_. XCTAssertNotNil(gMockPlatformView); - flutterPlatformViewsController->Reset(); + [flutterPlatformViewsController reset]; } XCTAssertNil(gMockPlatformView); } @@ -3017,8 +3192,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -3030,45 +3206,52 @@ fml::RefPtr GetDefaultTaskRunner() { /*is_gpu_disabled_jsync_switch=*/std::make_shared()); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)]; - flutterPlatformViewsController->SetFlutterView(flutterView); + flutterPlatformViewsController.flutterView = flutterView; FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @0, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @0, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; - // First frame, |EmbeddedViewCount| is not empty after composite. - flutterPlatformViewsController->BeginFrame(SkISize::Make(300, 300)); + // First frame, |embeddedViewCount| is not empty after composite. + [flutterPlatformViewsController beginFrameWithSize:SkISize::Make(300, 300)]; flutter::MutatorsStack stack; SkMatrix finalMatrix; auto embeddedViewParams1 = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(0, std::move(embeddedViewParams1)); - flutterPlatformViewsController->CompositeWithParams( - 0, flutterPlatformViewsController->GetCompositionParams(0)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:0 + withParams:std::move(embeddedViewParams1)]; + [flutterPlatformViewsController + compositeView:0 + withParams:[flutterPlatformViewsController compositionParamsForView:0]]; - XCTAssertEqual(flutterPlatformViewsController->EmbeddedViewCount(), 1UL); + XCTAssertEqual(flutterPlatformViewsController.embeddedViewCount, 1UL); - // Second frame, |EmbeddedViewCount| should be empty at the start - flutterPlatformViewsController->BeginFrame(SkISize::Make(300, 300)); - XCTAssertEqual(flutterPlatformViewsController->EmbeddedViewCount(), 0UL); + // Second frame, |embeddedViewCount| should be empty at the start + [flutterPlatformViewsController beginFrameWithSize:SkISize::Make(300, 300)]; + XCTAssertEqual(flutterPlatformViewsController.embeddedViewCount, 0UL); auto embeddedViewParams2 = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(0, std::move(embeddedViewParams2)); - flutterPlatformViewsController->CompositeWithParams( - 0, flutterPlatformViewsController->GetCompositionParams(0)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:0 + withParams:std::move(embeddedViewParams2)]; + [flutterPlatformViewsController + compositeView:0 + withParams:[flutterPlatformViewsController compositionParamsForView:0]]; - XCTAssertEqual(flutterPlatformViewsController->EmbeddedViewCount(), 1UL); + XCTAssertEqual(flutterPlatformViewsController.embeddedViewCount, 1UL); } - (void) @@ -3080,8 +3263,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -3093,40 +3277,47 @@ fml::RefPtr GetDefaultTaskRunner() { /*is_gpu_disabled_jsync_switch=*/std::make_shared()); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)]; - flutterPlatformViewsController->SetFlutterView(flutterView); + flutterPlatformViewsController.flutterView = flutterView; FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @0, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @0, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; UIView* view1 = gMockPlatformView; // This overwrites `gMockPlatformView` to another view. - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @1, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @1, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; UIView* view2 = gMockPlatformView; - flutterPlatformViewsController->BeginFrame(SkISize::Make(300, 300)); + [flutterPlatformViewsController beginFrameWithSize:SkISize::Make(300, 300)]; flutter::MutatorsStack stack; SkMatrix finalMatrix; auto embeddedViewParams1 = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(0, std::move(embeddedViewParams1)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:0 + withParams:std::move(embeddedViewParams1)]; auto embeddedViewParams2 = std::make_unique(finalMatrix, SkSize::Make(500, 500), stack); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(1, std::move(embeddedViewParams2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:1 + withParams:std::move(embeddedViewParams2)]; // SKSurface is required if the root FlutterView is present. const SkImageInfo image_info = SkImageInfo::MakeN32Premul(1000, 1000); @@ -3138,8 +3329,9 @@ fml::RefPtr GetDefaultTaskRunner() { [](const flutter::SurfaceFrame& surface_frame) { return true; }, /*frame_size=*/SkISize::Make(800, 600)); - XCTAssertTrue( - flutterPlatformViewsController->SubmitFrame(nullptr, nullptr, std::move(mock_surface))); + XCTAssertTrue([flutterPlatformViewsController submitFrame:std::move(mock_surface) + withIosContext:nil + grContext:nil]); // platform view is wrapped by touch interceptor, which itself is wrapped by clipping view. UIView* clippingView1 = view1.superview.superview; @@ -3149,15 +3341,17 @@ 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->BeginFrame(SkISize::Make(300, 300)); + [flutterPlatformViewsController beginFrameWithSize: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, std::move(embeddedViewParams2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:1 + withParams:std::move(embeddedViewParams2)]; embeddedViewParams1 = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(0, std::move(embeddedViewParams1)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:0 + withParams:std::move(embeddedViewParams1)]; mock_sk_surface = SkSurfaces::Raster(image_info); mock_surface = std::make_unique( @@ -3165,8 +3359,9 @@ 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(nullptr, nullptr, std::move(mock_surface))); + XCTAssertTrue([flutterPlatformViewsController submitFrame:std::move(mock_surface) + withIosContext:nil + grContext:nil]); XCTAssertTrue([flutterView.subviews indexOfObject:clippingView1] > [flutterView.subviews indexOfObject:clippingView2], @@ -3182,8 +3377,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -3195,40 +3391,47 @@ fml::RefPtr GetDefaultTaskRunner() { /*is_gpu_disabled_jsync_switch=*/std::make_shared()); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)]; - flutterPlatformViewsController->SetFlutterView(flutterView); + flutterPlatformViewsController.flutterView = flutterView; FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @0, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @0, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; UIView* view1 = gMockPlatformView; // This overwrites `gMockPlatformView` to another view. - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @1, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @1, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; UIView* view2 = gMockPlatformView; - flutterPlatformViewsController->BeginFrame(SkISize::Make(300, 300)); + [flutterPlatformViewsController beginFrameWithSize:SkISize::Make(300, 300)]; flutter::MutatorsStack stack; SkMatrix finalMatrix; auto embeddedViewParams1 = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(0, std::move(embeddedViewParams1)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:0 + withParams:std::move(embeddedViewParams1)]; auto embeddedViewParams2 = std::make_unique(finalMatrix, SkSize::Make(500, 500), stack); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(1, std::move(embeddedViewParams2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:1 + withParams:std::move(embeddedViewParams2)]; // SKSurface is required if the root FlutterView is present. const SkImageInfo image_info = SkImageInfo::MakeN32Premul(1000, 1000); @@ -3240,8 +3443,9 @@ fml::RefPtr GetDefaultTaskRunner() { [](const flutter::SurfaceFrame& surface_frame) { return true; }, /*frame_size=*/SkISize::Make(800, 600)); - XCTAssertTrue( - flutterPlatformViewsController->SubmitFrame(nullptr, nullptr, std::move(mock_surface))); + XCTAssertTrue([flutterPlatformViewsController submitFrame:std::move(mock_surface) + withIosContext:nil + grContext:nil]); // platform view is wrapped by touch interceptor, which itself is wrapped by clipping view. UIView* clippingView1 = view1.superview.superview; @@ -3251,15 +3455,17 @@ 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->BeginFrame(SkISize::Make(300, 300)); + [flutterPlatformViewsController beginFrameWithSize: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, std::move(embeddedViewParams1)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:0 + withParams:std::move(embeddedViewParams1)]; embeddedViewParams2 = std::make_unique(finalMatrix, SkSize::Make(500, 500), stack); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(1, std::move(embeddedViewParams2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:1 + withParams:std::move(embeddedViewParams2)]; mock_sk_surface = SkSurfaces::Raster(image_info); mock_surface = std::make_unique( @@ -3267,8 +3473,10 @@ 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(nullptr, nullptr, std::move(mock_surface))); + + XCTAssertTrue([flutterPlatformViewsController submitFrame:std::move(mock_surface) + withIosContext:nil + grContext:nil]); XCTAssertTrue([flutterView.subviews indexOfObject:clippingView1] < [flutterView.subviews indexOfObject:clippingView2], @@ -3369,8 +3577,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -3383,20 +3592,23 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @1, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @1, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; - flutterPlatformViewsController->SetFlutterView(flutterView); + flutterPlatformViewsController.flutterView = flutterView; // Create embedded view params flutter::MutatorsStack stack1; // Layer tree always pushes a screen scale factor to the stack @@ -3410,39 +3622,47 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams1 = std::make_unique( screenScaleMatrix, SkSize::Make(10, 10), stack1); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(1, std::move(embeddedViewParams1)); - flutterPlatformViewsController->CompositeWithParams( - 1, flutterPlatformViewsController->GetCompositionParams(1)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:1 + withParams:std::move(embeddedViewParams1)]; + [flutterPlatformViewsController + compositeView:1 + withParams:[flutterPlatformViewsController compositionParamsForView:1]]; UIView* childClippingView1 = gMockPlatformView.superview.superview; UIView* maskView1 = childClippingView1.maskView; XCTAssertNotNil(maskView1); // Composite a new frame. - flutterPlatformViewsController->BeginFrame(SkISize::Make(100, 100)); + [flutterPlatformViewsController beginFrameWithSize: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, std::move(embeddedViewParams3)); - flutterPlatformViewsController->CompositeWithParams( - 1, flutterPlatformViewsController->GetCompositionParams(1)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:1 + withParams:std::move(embeddedViewParams3)]; + [flutterPlatformViewsController + compositeView:1 + withParams:[flutterPlatformViewsController compositionParamsForView: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); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @2, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; auto embeddedViewParams4 = std::make_unique( screenScaleMatrix, SkSize::Make(10, 10), stack1); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams4)); - flutterPlatformViewsController->CompositeWithParams( - 2, flutterPlatformViewsController->GetCompositionParams(2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams4)]; + [flutterPlatformViewsController + compositeView:2 + withParams:[flutterPlatformViewsController compositionParamsForView:2]]; UIView* childClippingView2 = gMockPlatformView.superview.superview; @@ -3460,8 +3680,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -3474,30 +3695,35 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @1, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @1, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; UIView* view1 = gMockPlatformView; // This overwrites `gMockPlatformView` to another view. - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @2, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; UIView* view2 = gMockPlatformView; XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; - flutterPlatformViewsController->SetFlutterView(flutterView); + flutterPlatformViewsController.flutterView = flutterView; // Create embedded view params flutter::MutatorsStack stack1; // Layer tree always pushes a screen scale factor to the stack @@ -3516,15 +3742,19 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams2 = std::make_unique( screenScaleMatrix, SkSize::Make(10, 10), stack2); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(1, std::move(embeddedViewParams1)); - flutterPlatformViewsController->CompositeWithParams( - 1, flutterPlatformViewsController->GetCompositionParams(1)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:1 + withParams:std::move(embeddedViewParams1)]; + [flutterPlatformViewsController + compositeView:1 + withParams:[flutterPlatformViewsController compositionParamsForView:1]]; UIView* childClippingView1 = view1.superview.superview; - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams2)); - flutterPlatformViewsController->CompositeWithParams( - 2, flutterPlatformViewsController->GetCompositionParams(2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams2)]; + [flutterPlatformViewsController + compositeView:2 + withParams:[flutterPlatformViewsController compositionParamsForView:2]]; UIView* childClippingView2 = view2.superview.superview; UIView* maskView1 = childClippingView1.maskView; @@ -3540,8 +3770,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -3554,21 +3785,24 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @1, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @1, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; XCTAssertNotNil(gMockPlatformView); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; - flutterPlatformViewsController->SetFlutterView(flutterView); + flutterPlatformViewsController.flutterView = flutterView; // Create embedded view params flutter::MutatorsStack stack1; // Layer tree always pushes a screen scale factor to the stack @@ -3587,9 +3821,11 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams2 = std::make_unique( screenScaleMatrix, SkSize::Make(10, 10), stack2); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(1, std::move(embeddedViewParams1)); - flutterPlatformViewsController->CompositeWithParams( - 1, flutterPlatformViewsController->GetCompositionParams(1)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:1 + withParams:std::move(embeddedViewParams1)]; + [flutterPlatformViewsController + compositeView:1 + withParams:[flutterPlatformViewsController compositionParamsForView:1]]; UIView* childClippingView = gMockPlatformView.superview.superview; @@ -3633,8 +3869,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -3646,50 +3883,58 @@ fml::RefPtr GetDefaultTaskRunner() { /*is_gpu_disabled_jsync_switch=*/std::make_shared()); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)]; - flutterPlatformViewsController->SetFlutterView(flutterView); + flutterPlatformViewsController.flutterView = flutterView; FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @0, @"viewType" : @"MockFlutterPlatformView"}], - result); - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @1, @"viewType" : @"MockFlutterPlatformView"}], - 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]; { // **** 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->BeginFrame(SkISize::Make(300, 300)); + [flutterPlatformViewsController beginFrameWithSize:SkISize::Make(300, 300)]; flutter::MutatorsStack stack; SkMatrix finalMatrix; auto embeddedViewParams0 = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(0, std::move(embeddedViewParams0)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:0 + withParams:std::move(embeddedViewParams0)]; auto embeddedViewParams1 = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(1, std::move(embeddedViewParams1)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:1 + withParams: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], disposeResult); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"dispose" arguments:@0] + result:disposeResult]; [self waitForExpectationsWithTimeout:30 handler:nil]; const SkImageInfo image_info = SkImageInfo::MakeN32Premul(1000, 1000); @@ -3700,24 +3945,27 @@ 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(nullptr, nullptr, std::move(mock_surface))); + + XCTAssertTrue([flutterPlatformViewsController submitFrame:std::move(mock_surface) + withIosContext:nil + grContext:nil]); // Disposing won't remove embedded views until the view is removed from the composition_order_ - XCTAssertEqual(flutterPlatformViewsController->EmbeddedViewCount(), 2UL); - XCTAssertNotNil(flutterPlatformViewsController->GetPlatformViewByID(0)); - XCTAssertNotNil(flutterPlatformViewsController->GetPlatformViewByID(1)); + XCTAssertEqual(flutterPlatformViewsController.embeddedViewCount, 2UL); + XCTAssertNotNil([flutterPlatformViewsController platformViewForId:0]); + XCTAssertNotNil([flutterPlatformViewsController platformViewForId: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->BeginFrame(SkISize::Make(300, 300)); + [flutterPlatformViewsController beginFrameWithSize:SkISize::Make(300, 300)]; flutter::MutatorsStack stack; SkMatrix finalMatrix; auto embeddedViewParams1 = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(1, std::move(embeddedViewParams1)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:1 + withParams:std::move(embeddedViewParams1)]; const SkImageInfo image_info = SkImageInfo::MakeN32Premul(1000, 1000); sk_sp mock_sk_surface = SkSurfaces::Raster(image_info); @@ -3727,13 +3975,15 @@ 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(nullptr, nullptr, std::move(mock_surface))); + + XCTAssertTrue([flutterPlatformViewsController submitFrame:std::move(mock_surface) + withIosContext:nil + grContext:nil]); // Disposing won't remove embedded views until the view is removed from the composition_order_ - XCTAssertEqual(flutterPlatformViewsController->EmbeddedViewCount(), 1UL); - XCTAssertNil(flutterPlatformViewsController->GetPlatformViewByID(0)); - XCTAssertNotNil(flutterPlatformViewsController->GetPlatformViewByID(1)); + XCTAssertEqual(flutterPlatformViewsController.embeddedViewCount, 1UL); + XCTAssertNil([flutterPlatformViewsController platformViewForId:0]); + XCTAssertNotNil([flutterPlatformViewsController platformViewForId:1]); } } - (void)testOnlyPlatformViewsAreRemovedWhenReset { @@ -3744,8 +3994,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -3758,18 +4009,21 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @2, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)]; - flutterPlatformViewsController->SetFlutterView(flutterView); + flutterPlatformViewsController.flutterView = flutterView; // Create embedded view params flutter::MutatorsStack stack; // Layer tree always pushes a screen scale factor to the stack @@ -3785,7 +4039,8 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams)]; // SKSurface is required if the root FlutterView is present. const SkImageInfo image_info = SkImageInfo::MakeN32Premul(1000, 1000); @@ -3797,12 +4052,14 @@ fml::RefPtr GetDefaultTaskRunner() { [](const flutter::SurfaceFrame& surface_frame) { return true; }, /*frame_size=*/SkISize::Make(800, 600)); - flutterPlatformViewsController->SubmitFrame(nullptr, nullptr, std::move(mock_surface)); + [flutterPlatformViewsController submitFrame:std::move(mock_surface) + withIosContext:nil + grContext:nil]; UIView* someView = [[UIView alloc] init]; [flutterView addSubview:someView]; - flutterPlatformViewsController->Reset(); + [flutterPlatformViewsController reset]; XCTAssertEqual(flutterView.subviews.count, 1u); XCTAssertEqual(flutterView.subviews.firstObject, someView); } @@ -3815,8 +4072,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -3829,18 +4087,21 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterPlatformViewsTestNilFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestNilFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @2, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)]; - flutterPlatformViewsController->SetFlutterView(flutterView); + flutterPlatformViewsController.flutterView = flutterView; // Create embedded view params flutter::MutatorsStack stack; @@ -3857,7 +4118,8 @@ fml::RefPtr GetDefaultTaskRunner() { auto embeddedViewParams = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:2 + withParams:std::move(embeddedViewParams)]; // SKSurface is required if the root FlutterView is present. const SkImageInfo image_info = SkImageInfo::MakeN32Premul(1000, 1000); @@ -3869,7 +4131,9 @@ fml::RefPtr GetDefaultTaskRunner() { [](const flutter::SurfaceFrame& surface_frame) { return true; }, /*frame_size=*/SkISize::Make(800, 600)); - flutterPlatformViewsController->SubmitFrame(nullptr, nullptr, std::move(mock_surface)); + [flutterPlatformViewsController submitFrame:std::move(mock_surface) + withIosContext:nil + grContext:nil]; XCTAssertEqual(flutterView.subviews.count, 1u); } @@ -3915,8 +4179,9 @@ fml::RefPtr GetDefaultTaskRunner() { /*raster=*/GetDefaultTaskRunner(), /*ui=*/GetDefaultTaskRunner(), /*io=*/GetDefaultTaskRunner()); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = GetDefaultTaskRunner(); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -3928,38 +4193,45 @@ fml::RefPtr GetDefaultTaskRunner() { /*is_gpu_disabled_jsync_switch=*/std::make_shared()); UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)]; - flutterPlatformViewsController->SetFlutterView(flutterView); + flutterPlatformViewsController.flutterView = flutterView; FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @0, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @0, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; // This overwrites `gMockPlatformView` to another view. - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @1, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @1, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; - flutterPlatformViewsController->BeginFrame(SkISize::Make(300, 300)); + [flutterPlatformViewsController beginFrameWithSize:SkISize::Make(300, 300)]; flutter::MutatorsStack stack; SkMatrix finalMatrix; auto embeddedViewParams1 = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(0, std::move(embeddedViewParams1)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:0 + withParams:std::move(embeddedViewParams1)]; auto embeddedViewParams2 = std::make_unique(finalMatrix, SkSize::Make(500, 500), stack); - flutterPlatformViewsController->PrerollCompositeEmbeddedView(1, std::move(embeddedViewParams2)); + [flutterPlatformViewsController prerollCompositeEmbeddedView:1 + withParams:std::move(embeddedViewParams2)]; // SKSurface is required if the root FlutterView is present. const SkImageInfo image_info = SkImageInfo::MakeN32Premul(1000, 1000); @@ -3979,8 +4251,9 @@ fml::RefPtr GetDefaultTaskRunner() { .buffer_damage = SkIRect::MakeWH(400, 600), }); - XCTAssertTrue( - flutterPlatformViewsController->SubmitFrame(nullptr, nullptr, std::move(mock_surface))); + [flutterPlatformViewsController submitFrame:std::move(mock_surface) + withIosContext:nil + grContext:nil]; 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 8267b1ccfe..b23d532cf4 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" -#import "flutter/shell/platform/darwin/ios/framework/Source/platform_views_controller.h" -#import "flutter/shell/platform/darwin/ios/ios_context.h" +#include "flutter/shell/platform/darwin/ios/ios_context.h" +#include "third_party/skia/include/core/SkRect.h" // A UIView that acts as a clipping mask for the |ChildClippingView|. // @@ -134,8 +134,7 @@ // 2. Dispatching all events that are hittested to the embedded view to the FlutterView. @interface FlutterTouchInterceptingView : UIView - (instancetype)initWithEmbeddedView:(UIView*)embeddedView - platformViewsController: - (fml::WeakPtr)platformViewsController + platformViewsController:(FlutterPlatformViewsController*)platformViewsController gestureRecognizersBlockingPolicy: (FlutterPlatformViewGestureRecognizersBlockingPolicy)blockingPolicy; @@ -192,8 +191,7 @@ // directly to the FlutterView. @interface ForwardingGestureRecognizer : UIGestureRecognizer - (instancetype)initWithTarget:(id)target - platformViewsController: - (fml::WeakPtr)platformViewsController; + platformViewsController:(FlutterPlatformViewsController*)platformViewsController; - (ForwardingGestureRecognizer*)recreateRecognizerWithTarget:(id)target; @end diff --git a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm index ce38124365..a0e140e6e4 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm +++ b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm @@ -518,8 +518,7 @@ static BOOL _preparedOnce = NO; @implementation FlutterTouchInterceptingView - (instancetype)initWithEmbeddedView:(UIView*)embeddedView - platformViewsController: - (fml::WeakPtr)platformViewsController + platformViewsController:(FlutterPlatformViewsController*)platformViewsController gestureRecognizersBlockingPolicy: (FlutterPlatformViewGestureRecognizersBlockingPolicy)blockingPolicy { self = [super initWithFrame:embeddedView.frame]; @@ -667,7 +666,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. - fml::WeakPtr _platformViewsController; + __weak FlutterPlatformViewsController* _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. @@ -678,13 +677,12 @@ static BOOL _preparedOnce = NO; } - (instancetype)initWithTarget:(id)target - platformViewsController: - (fml::WeakPtr)platformViewsController { + platformViewsController:(FlutterPlatformViewsController*)platformViewsController { self = [super initWithTarget:target action:nil]; if (self) { self.delegate = self; - FML_DCHECK(platformViewsController.get() != nullptr); - _platformViewsController = std::move(platformViewsController); + FML_DCHECK(platformViewsController); + _platformViewsController = platformViewsController; _currentTouchPointersCount = 0; } return self; @@ -692,7 +690,7 @@ static BOOL _preparedOnce = NO; - (ForwardingGestureRecognizer*)recreateRecognizerWithTarget:(id)target { return [[ForwardingGestureRecognizer alloc] initWithTarget:target - platformViewsController:std::move(_platformViewsController)]; + platformViewsController:_platformViewsController]; } - (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { @@ -701,7 +699,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->GetFlutterViewController(); + _flutterViewController = _platformViewsController.flutterViewController; } [_flutterViewController touchesBegan:touches withEvent:event]; _currentTouchPointersCount += touches.count; 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 53dd50e45d..80619e44b7 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,12 +14,11 @@ @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 319f423d84..2fd71c0874 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.engine platformViewsController]->SetFlutterView(self.flutterView); - [self.engine platformViewsController]->SetFlutterViewController(self); + self.platformViewsController.flutterView = self.flutterView; + self.platformViewsController.flutterViewController = self; [self.engine iosPlatformView]->NotifyCreated(); } else { self.displayingFlutterUI = NO; [self.engine iosPlatformView]->NotifyDestroyed(); - [self.engine platformViewsController]->SetFlutterView(nullptr); - [self.engine platformViewsController]->SetFlutterViewController(nullptr); + self.platformViewsController.flutterView = nil; + self.platformViewsController.flutterViewController = nil; } } @@ -2321,7 +2321,7 @@ static flutter::PointerData::DeviceKind DeviceKindFromTouchType(UITouch* touch) #pragma mark - Platform views -- (std::shared_ptr&)platformViewsController { +- (FlutterPlatformViewsController*)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 62a7df4133..3645d2c376 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,11 +5,12 @@ #ifndef FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERVIEWCONTROLLER_INTERNAL_H_ #define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERVIEWCONTROLLER_INTERNAL_H_ -#include "flutter/fml/time/time_point.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/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" @@ -56,7 +57,8 @@ typedef void (^FlutterKeyboardAnimationCallback)(fml::TimePoint); */ @property(nonatomic, assign, readwrite) BOOL prefersStatusBarHidden; -- (std::shared_ptr&)platformViewsController; +@property(nonatomic, readonly) FlutterPlatformViewsController* 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 08cf885da5..357c65e4c8 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,13 +13,12 @@ FLUTTER_ASSERT_ARC @property(nonatomic, assign) BOOL isUsingImpeller; @end -@implementation FakeDelegate { - std::shared_ptr _platformViewsController; -} +@implementation FakeDelegate + +@synthesize platformViewsController = _platformViewsController; - (instancetype)init { _callbackCalled = NO; - _platformViewsController = std::shared_ptr(nullptr); return self; } @@ -28,10 +27,6 @@ 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 4ccd57b1bb..562c471e93 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,9 +43,7 @@ class MockAccessibilityBridge : public AccessibilityBridgeIos { } void AccessibilityObjectDidBecomeFocused(int32_t id) override {} void AccessibilityObjectDidLoseFocus(int32_t id) override {} - std::shared_ptr GetPlatformViewsController() const override { - return nil; - } + FlutterPlatformViewsController* GetPlatformViewsController() const override { return nil; } std::vector observations; bool isVoiceOverRunningValue; @@ -74,9 +72,7 @@ class MockAccessibilityBridgeNoWindow : public AccessibilityBridgeIos { } void AccessibilityObjectDidBecomeFocused(int32_t id) override {} void AccessibilityObjectDidLoseFocus(int32_t id) override {} - std::shared_ptr GetPlatformViewsController() const override { - return nil; - } + FlutterPlatformViewsController* 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 ffbd8e49dd..e808b88d20 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, - std::shared_ptr platform_views_controller, + __weak FlutterPlatformViewsController* platform_views_controller, std::unique_ptr ios_delegate = nullptr); ~AccessibilityBridge(); @@ -72,7 +72,7 @@ class AccessibilityBridge final : public AccessibilityBridgeIos { fml::WeakPtr GetWeakPtr(); - std::shared_ptr GetPlatformViewsController() const override { + FlutterPlatformViewsController* GetPlatformViewsController() const override { return platform_views_controller_; }; @@ -91,7 +91,7 @@ class AccessibilityBridge final : public AccessibilityBridgeIos { FlutterViewController* view_controller_; PlatformViewIOS* platform_view_; - const std::shared_ptr platform_views_controller_; + __weak FlutterPlatformViewsController* 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 62467d3406..daf6389834 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, - std::shared_ptr platform_views_controller, + __weak FlutterPlatformViewsController* platform_views_controller, std::unique_ptr ios_delegate) : view_controller_(view_controller), platform_view_(platform_view), - platform_views_controller_(std::move(platform_views_controller)), + platform_views_controller_(platform_views_controller), last_focused_semantics_object_id_(kSemanticObjectIdInvalid), objects_([[NSMutableDictionary alloc] init]), previous_routes_({}), @@ -271,11 +271,13 @@ 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()) { - return [[FlutterPlatformViewSemanticsContainer alloc] - initWithBridge:weak_ptr - uid:node.id - platformView:weak_ptr->GetPlatformViewsController()->GetFlutterTouchInterceptingViewByID( - node.platformViewId)]; + FlutterPlatformViewsController* platformViewsController = + weak_ptr->GetPlatformViewsController(); + FlutterTouchInterceptingView* touchInterceptingView = + [platformViewsController flutterTouchInterceptingViewForId:node.platformViewId]; + return [[FlutterPlatformViewSemanticsContainer alloc] initWithBridge:weak_ptr + uid:node.id + platformView:touchInterceptingView]; } 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 0da3646a2e..2168ca050d 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 std::shared_ptr GetPlatformViewsController() const = 0; + virtual FlutterPlatformViewsController* 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 63c2b14794..343ed99eae 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,8 +279,9 @@ fml::RefPtr CreateNewThread(const std::string& name) { /*ui=*/thread_task_runner, /*io=*/thread_task_runner); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(thread_task_runner); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = thread_task_runner; auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -294,19 +295,22 @@ fml::RefPtr CreateNewThread(const std::string& name) { id mockFlutterViewController = OCMClassMock([FlutterViewController class]); OCMStub([mockFlutterViewController view]).andReturn(mockFlutterView); std::string label = "some label"; - flutterPlatformViewsController->SetFlutterView(mockFlutterView); + flutterPlatformViewsController.flutterView = mockFlutterView; MockFlutterPlatformFactory* factory = [[MockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @2, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; auto bridge = std::make_unique( /*view_controller=*/mockFlutterViewController, @@ -322,7 +326,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); } @@ -340,8 +344,9 @@ fml::RefPtr CreateNewThread(const std::string& name) { /*ui=*/thread_task_runner, /*io=*/thread_task_runner); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(thread_task_runner); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = thread_task_runner; auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -353,16 +358,19 @@ fml::RefPtr CreateNewThread(const std::string& name) { /*is_gpu_disabled_sync_switch=*/std::make_shared()); MockFlutterPlatformFactory* factory = [[MockFlutterPlatformFactory alloc] init]; - flutterPlatformViewsController->RegisterViewFactory( - factory, @"MockFlutterPlatformView", - FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + [flutterPlatformViewsController + registerViewFactory:factory + withId:@"MockFlutterPlatformView" + gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager]; FlutterResult result = ^(id result) { }; - flutterPlatformViewsController->OnMethodCall( - [FlutterMethodCall - methodCallWithMethodName:@"create" - arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], - result); + [flutterPlatformViewsController + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"create" + arguments:@{ + @"id" : @2, + @"viewType" : @"MockFlutterPlatformView" + }] + result:result]; auto bridge = std::make_unique( /*view_controller=*/flutterViewController, @@ -370,7 +378,7 @@ fml::RefPtr CreateNewThread(const std::string& name) { /*platform_views_controller=*/flutterPlatformViewsController); XCTAssertNotNil(gMockPlatformView); - flutterPlatformViewsController->Reset(); + [flutterPlatformViewsController reset]; platform_view->NotifyDestroyed(); } XCTAssertNil(gMockPlatformView); @@ -387,8 +395,9 @@ fml::RefPtr CreateNewThread(const std::string& name) { /*ui=*/thread_task_runner, /*io=*/thread_task_runner); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(thread_task_runner); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = thread_task_runner; auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -484,8 +493,9 @@ fml::RefPtr CreateNewThread(const std::string& name) { /*ui=*/thread_task_runner, /*io=*/thread_task_runner); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(thread_task_runner); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = thread_task_runner; auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -559,8 +569,8 @@ fml::RefPtr CreateNewThread(const std::string& name) { /*ui=*/thread_task_runner, /*io=*/thread_task_runner); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(thread_task_runner); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/mock_delegate.settings_.enable_impeller @@ -2175,11 +2185,12 @@ fml::RefPtr CreateNewThread(const std::string& name) { /*is_gpu_disabled_sync_switch=*/std::make_shared()); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); - auto flutterPlatformViewsController = std::make_shared(); - flutterPlatformViewsController->SetTaskRunner(thread_task_runner); + FlutterPlatformViewsController* flutterPlatformViewsController = + [[FlutterPlatformViewsController alloc] init]; + flutterPlatformViewsController.taskRunner = thread_task_runner; OCMStub([mockFlutterViewController platformViewsController]) - .andReturn(flutterPlatformViewsController.get()); + .andReturn(flutterPlatformViewsController); 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 deleted file mode 100644 index 06fd638244..0000000000 --- a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/platform_views_controller.h +++ /dev/null @@ -1,318 +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_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 deleted file mode 100644 index 6893c3d0f8..0000000000 --- a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/platform_views_controller.mm +++ /dev/null @@ -1,874 +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/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 6983ac83f0..d22fc3fb47 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( - const std::shared_ptr& platform_views_controller, + __weak FlutterPlatformViewsController* platform_views_controller, const std::shared_ptr& context); // |ExternalViewEmbedder| virtual ~IOSExternalViewEmbedder() override; private: - const std::shared_ptr& platform_views_controller_; + __weak FlutterPlatformViewsController* 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 a2f5ff9c2b..ebde36386b 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( - const std::shared_ptr& platform_views_controller, + __weak FlutterPlatformViewsController* 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_->BeginFrame(frame_size); + [platform_views_controller_ beginFrameWithSize: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, std::move(params)); + [platform_views_controller_ prerollCompositeEmbeddedView:view_id withParams:std::move(params)]; } // |ExternalViewEmbedder| @@ -59,8 +59,10 @@ PostPrerollResult IOSExternalViewEmbedder::PostPrerollAction( const fml::RefPtr& raster_thread_merger) { TRACE_EVENT0("flutter", "IOSExternalViewEmbedder::PostPrerollAction"); FML_CHECK(platform_views_controller_); - PostPrerollResult result = platform_views_controller_->PostPrerollAction( - raster_thread_merger, ios_context_->GetBackend() != IOSRenderingBackend::kSkia); + BOOL impeller_enabled = ios_context_->GetBackend() != IOSRenderingBackend::kSkia; + PostPrerollResult result = + [platform_views_controller_ postPrerollActionWithThreadMerger:raster_thread_merger + impellerEnabled:impeller_enabled]; return result; } @@ -68,7 +70,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_->CompositeEmbeddedView(view_id); + return [platform_views_controller_ compositeEmbeddedViewWithId:view_id]; } // |ExternalViewEmbedder| @@ -83,7 +85,9 @@ 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(context, ios_context_, std::move(frame)); + [platform_views_controller_ submitFrame:std::move(frame) + withIosContext:ios_context_ + grContext:context]; TRACE_EVENT0("flutter", "IOSExternalViewEmbedder::DidSubmitFrame"); } @@ -92,8 +96,10 @@ void IOSExternalViewEmbedder::EndFrame( bool should_resubmit_frame, const fml::RefPtr& raster_thread_merger) { TRACE_EVENT0("flutter", "IOSExternalViewEmbedder::EndFrame"); - platform_views_controller_->EndFrame(should_resubmit_frame, raster_thread_merger, - ios_context_->GetBackend() != IOSRenderingBackend::kSkia); + BOOL impeller_enabled = ios_context_->GetBackend() != IOSRenderingBackend::kSkia; + [platform_views_controller_ endFrameWithResubmit:should_resubmit_frame + threadMerger:raster_thread_merger + impellerEnabled:impeller_enabled]; } // |ExternalViewEmbedder| @@ -110,12 +116,12 @@ bool IOSExternalViewEmbedder::SupportsDynamicThreadMerging() { void IOSExternalViewEmbedder::PushFilterToVisitedPlatformViews( const std::shared_ptr& filter, const SkRect& filter_rect) { - platform_views_controller_->PushFilterToVisitedPlatformViews(filter, filter_rect); + [platform_views_controller_ pushFilterToVisitedPlatformViews:filter withRect:filter_rect]; } // |ExternalViewEmbedder| void IOSExternalViewEmbedder::PushVisitedPlatformView(int64_t view_id) { - platform_views_controller_->PushVisitedPlatformView(view_id); + [platform_views_controller_ pushVisitedPlatformViewId: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 0e65e6174f..4e1da467d2 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, - const std::shared_ptr& platform_views_controller, + __weak FlutterPlatformViewsController* platform_views_controller, const flutter::TaskRunners& task_runners); explicit PlatformViewIOS( PlatformView::Delegate& delegate, IOSRenderingAPI rendering_api, - const std::shared_ptr& platform_views_controller, + __weak FlutterPlatformViewsController* 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_; - const std::shared_ptr& platform_views_controller_; + __weak FlutterPlatformViewsController* 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 f651d00ec8..b726fd8fc1 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,11 +41,10 @@ void PlatformViewIOS::AccessibilityBridgeManager::Clear() { accessibility_bridge_.reset(); } -PlatformViewIOS::PlatformViewIOS( - PlatformView::Delegate& delegate, - const std::shared_ptr& context, - const std::shared_ptr& platform_views_controller, - const flutter::TaskRunners& task_runners) +PlatformViewIOS::PlatformViewIOS(PlatformView::Delegate& delegate, + const std::shared_ptr& context, + __weak FlutterPlatformViewsController* platform_views_controller, + const flutter::TaskRunners& task_runners) : PlatformView(delegate, task_runners), ios_context_(context), platform_views_controller_(platform_views_controller), @@ -56,7 +55,7 @@ PlatformViewIOS::PlatformViewIOS( PlatformViewIOS::PlatformViewIOS( PlatformView::Delegate& delegate, IOSRenderingAPI rendering_api, - const std::shared_ptr& platform_views_controller, + __weak FlutterPlatformViewsController* platform_views_controller, const flutter::TaskRunners& task_runners, const std::shared_ptr& worker_task_runner, const std::shared_ptr& is_gpu_disabled_sync_switch) @@ -209,7 +208,7 @@ void PlatformViewIOS::OnPreEngineRestart() const { if (!owner_controller_) { return; } - owner_controller_.platformViewsController->Reset(); + [owner_controller_.platformViewsController reset]; [owner_controller_.restorationPlugin reset]; }