6 #include "display_list/geometry/dl_geometry_types.h"
7 #include "impeller/geometry/rounding_radii.h"
9 #include "flutter/display_list/effects/image_filters/dl_blur_image_filter.h"
10 #include "flutter/display_list/geometry/dl_geometry_conversions.h"
11 #include "flutter/display_list/utils/dl_matrix_clip_tracker.h"
12 #include "flutter/flow/surface_frame.h"
13 #include "flutter/flow/view_slicer.h"
14 #include "flutter/fml/logging.h"
15 #include "flutter/fml/make_copyable.h"
16 #include "flutter/fml/synchronization/count_down_latch.h"
17 #import "flutter/shell/platform/darwin/common/InternalFlutterSwiftCommon/InternalFlutterSwiftCommon.h"
23 using flutter::DlISize;
24 using flutter::DlMatrix;
25 using flutter::DlRect;
26 using flutter::DlRoundRect;
39 std::shared_ptr<flutter::OverlayLayer>
layer;
41 using LayersMap = std::unordered_map<int64_t, LayerData>;
48 NSObject<FlutterPlatformView>*
view;
55 CATransform3D transform = CATransform3DIdentity;
56 transform.m11 = matrix.m[0];
57 transform.m12 = matrix.m[1];
58 transform.m13 = matrix.m[2];
59 transform.m14 = matrix.m[3];
61 transform.m21 = matrix.m[4];
62 transform.m22 = matrix.m[5];
63 transform.m23 = matrix.m[6];
64 transform.m24 = matrix.m[7];
66 transform.m31 = matrix.m[8];
67 transform.m32 = matrix.m[9];
68 transform.m33 = matrix.m[10];
69 transform.m34 = matrix.m[11];
71 transform.m41 = matrix.m[12];
72 transform.m42 = matrix.m[13];
73 transform.m43 = matrix.m[14];
74 transform.m44 = matrix.m[15];
83 layer.anchorPoint = CGPointZero;
84 layer.position = CGPointZero;
88 return CGRectMake(clipDlRect.GetLeft(),
90 clipDlRect.GetWidth(),
91 clipDlRect.GetHeight());
95 auto iter = params.mutatorsStack().Begin();
96 while (iter != params.mutatorsStack().End()) {
97 switch ((*iter)->GetType()) {
98 case flutter::MutatorType::kClipRRect:
99 case flutter::MutatorType::kClipRSE:
100 case flutter::MutatorType::kClipPath:
114 const flutter::EmbeddedViewParams& params) {
115 flutter::DlMatrix transform;
116 auto iter = params.mutatorsStack().Begin();
117 while (iter != params.mutatorsStack().End()) {
118 switch ((*iter)->GetType()) {
119 case flutter::MutatorType::kTransform:
120 transform = transform * (*iter)->GetMatrix();
122 case flutter::MutatorType::kClipRRect: {
123 if (transform.IsIdentity()) {
124 overlay_canvas->ClipRoundRect((*iter)->GetRRect(), flutter::DlClipOp::kIntersect,
true);
126 auto path = flutter::DlPath::MakeRoundRect((*iter)->GetRRect());
127 auto transformed_path =
128 flutter::DlPath(path.GetSkPath().makeTransform(flutter::ToSkMatrix(transform)));
129 overlay_canvas->ClipPath(transformed_path, flutter::DlClipOp::kIntersect,
true);
133 case flutter::MutatorType::kClipRSE: {
134 if (transform.IsIdentity()) {
135 overlay_canvas->ClipRoundSuperellipse((*iter)->GetRSE(), flutter::DlClipOp::kIntersect,
138 auto path = flutter::DlPath::MakeRoundSuperellipse((*iter)->GetRSE());
139 auto transformed_path =
140 flutter::DlPath(path.GetSkPath().makeTransform(flutter::ToSkMatrix(transform)));
141 overlay_canvas->ClipPath(transformed_path, flutter::DlClipOp::kIntersect,
true);
145 case flutter::MutatorType::kClipPath: {
146 if (transform.IsIdentity()) {
147 overlay_canvas->ClipPath((*iter)->GetPath(), flutter::DlClipOp::kIntersect,
true);
149 auto transformed_path = flutter::DlPath(
150 (*iter)->GetPath().GetSkPath().makeTransform(flutter::ToSkMatrix(transform)));
151 overlay_canvas->ClipPath(transformed_path, flutter::DlClipOp::kIntersect,
true);
171 @property(nonatomic, readonly)
172 std::unordered_map<int64_t, std::unique_ptr<flutter::EmbedderViewSlice>>& slices;
176 @property(nonatomic, readonly)
177 std::unordered_map<std::string, NSObject<FlutterPlatformViewFactory>*>& factories;
180 @property(nonatomic, readonly)
181 std::unordered_map<std::string, FlutterPlatformViewGestureRecognizersBlockingPolicy>&
182 gestureRecognizersBlockingPoliciesByType;
185 @property(nonatomic, assign) DlISize frameSize;
191 @property(nonatomic, readonly) std::unordered_map<int64_t, PlatformViewData>& platformViews;
196 @property(nonatomic, readonly)
197 std::unordered_map<int64_t, flutter::EmbeddedViewParams>& currentCompositionParams;
203 @property(nonatomic, readonly) std::unordered_set<int64_t>& viewsToDispose;
208 @property(nonatomic, readonly) std::vector<int64_t>& compositionOrder;
213 @property(nonatomic, readonly) std::vector<int64_t>& visitedPlatformViews;
218 @property(nonatomic, readonly) std::unordered_set<int64_t>& viewsToRecomposite;
227 @property(nonatomic, assign) BOOL hadPlatformViews;
232 @property(nonatomic, assign) BOOL canApplyBlurBackdrop;
237 - (void)createMissingOverlays:(
size_t)requiredOverlayLayers
238 withIosContext:(const std::shared_ptr<
flutter::IOSContext>&)iosContext;
241 - (void)performSubmit:(const
LayersMap&)platformViewLayers
242 currentCompositionParams:
243 (std::unordered_map<int64_t,
flutter::EmbeddedViewParams>&)currentCompositionParams
244 viewsToRecomposite:(const std::unordered_set<int64_t>&)viewsToRecomposite
245 compositionOrder:(const std::vector<int64_t>&)compositionOrder
247 (const std::vector<std::shared_ptr<
flutter::OverlayLayer>>&)unusedLayers
249 (const std::vector<std::unique_ptr<
flutter::SurfaceFrame>>&)surfaceFrames;
256 - (void)clipViewSetMaskView:(UIView*)clipView;
270 - (void)applyMutators:(const
flutter::MutatorsStack&)mutatorsStack
271 embeddedView:(UIView*)embeddedView
272 boundingRect:(const DlRect&)boundingRect;
276 - (void)bringLayersIntoView:(const
LayersMap&)layerMap
277 withCompositionOrder:(const std::vector<int64_t>&)compositionOrder;
279 - (std::shared_ptr<flutter::OverlayLayer>)nextLayerInPool;
282 - (void)createLayerWithIosContext:(const std::shared_ptr<
flutter::IOSContext>&)iosContext
283 pixelFormat:(MTLPixelFormat)pixelFormat;
287 - (void)removeUnusedLayers:(const std::vector<std::shared_ptr<
flutter::OverlayLayer>>&)unusedLayers
288 withCompositionOrder:(const std::vector<int64_t>&)compositionOrder;
294 - (std::vector<UIView*>)computeViewsToDispose;
297 - (void)resetFrameState;
308 std::unique_ptr<flutter::OverlayLayerPool> _layerPool;
309 std::unordered_map<int64_t, std::unique_ptr<flutter::EmbedderViewSlice>>
_slices;
310 std::unordered_map<std::string, NSObject<FlutterPlatformViewFactory>*>
_factories;
311 std::unordered_map<std::string, FlutterPlatformViewGestureRecognizersBlockingPolicy>
324 if (
self = [super init]) {
325 _layerPool = std::make_unique<flutter::OverlayLayerPool>();
328 _hadPlatformViews = NO;
329 _canApplyBlurBackdrop = YES;
343 if ([[call method] isEqualToString:
@"create"]) {
344 [
self onCreate:call result:result];
345 }
else if ([[call method] isEqualToString:
@"dispose"]) {
346 [
self onDispose:call result:result];
347 }
else if ([[call method] isEqualToString:
@"acceptGesture"]) {
348 [
self onAcceptGesture:call result:result];
349 }
else if ([[call method] isEqualToString:
@"rejectGesture"]) {
350 [
self onRejectGesture:call result:result];
357 NSDictionary<NSString*, id>* args = [call
arguments];
359 int64_t viewId = [args[@"id"] longLongValue];
360 NSString* viewTypeString = args[@"viewType"];
361 std::string viewType(viewTypeString.UTF8String);
363 if (
self.platformViews.count(viewId) != 0) {
365 message:
@"trying to create an already created view"
366 details:[NSString stringWithFormat:
@"view id: '%lld'", viewId]]);
370 NSObject<FlutterPlatformViewFactory>* factory =
self.factories[viewType];
371 if (factory == nil) {
373 errorWithCode:
@"unregistered_view_type"
374 message:[NSString stringWithFormat:
@"A UIKitView widget is trying to create a "
375 @"PlatformView with an unregistered type: < %@ >",
377 details:
@"If you are the author of the PlatformView, make sure `registerViewFactory` "
380 @"https://docs.flutter.dev/development/platform-integration/"
381 @"platform-views#on-the-platform-side-1 for more details.\n"
382 @"If you are not the author of the PlatformView, make sure to call "
383 @"`GeneratedPluginRegistrant.register`."]);
388 if ([factory respondsToSelector:
@selector(createArgsCodec)]) {
389 NSObject<FlutterMessageCodec>* codec = [factory createArgsCodec];
390 if (codec != nil && args[
@"params"] != nil) {
392 params = [codec decode:paramsData.data];
396 NSObject<FlutterPlatformView>* embeddedView = [factory createWithFrame:CGRectZero
397 viewIdentifier:viewId
399 UIView* platformView = [embeddedView view];
401 platformView.accessibilityIdentifier = [NSString stringWithFormat:@"platform_view[%lld]", viewId];
403 NSString* gestureBlockingPolicyValue = args[@"gestureBlockingPolicy"];
409 }
else if ([gestureBlockingPolicyValue
411 gestureBlockingPolicy =
413 }
else if ([gestureBlockingPolicyValue
415 gestureBlockingPolicy =
self.gestureRecognizersBlockingPoliciesByType[viewType];
418 errorWithCode:
@"unknown_gesture_blocking_policy"
419 message:
@"Trying to create a platform view with an unknown gesture blocking policy"
420 details:[NSString stringWithFormat:
@"view id: '%lld'", viewId]]);
426 platformViewsController:self
427 gestureRecognizersBlockingPolicy:gestureBlockingPolicy];
430 [clippingView addSubview:touchInterceptor];
433 .
view = embeddedView,
434 .touch_interceptor = touchInterceptor,
435 .root_view = clippingView
443 int64_t viewId = [arg longLongValue];
445 if (
self.platformViews.count(viewId) == 0) {
447 message:
@"trying to dispose an unknown"
448 details:[NSString stringWithFormat:
@"view id: '%lld'", viewId]]);
452 self.viewsToDispose.insert(viewId);
457 NSDictionary<NSString*, id>* args = [call
arguments];
458 int64_t viewId = [args[@"id"] longLongValue];
460 if (
self.platformViews.count(viewId) == 0) {
462 message:
@"trying to set gesture state for an unknown view"
463 details:[NSString stringWithFormat:
@"view id: '%lld'", viewId]]);
474 NSDictionary<NSString*, id>* args = [call
arguments];
475 int64_t viewId = [args[@"id"] longLongValue];
477 if (
self.platformViews.count(viewId) == 0) {
479 message:
@"trying to set gesture state for an unknown view"
480 details:[NSString stringWithFormat:
@"view id: '%lld'", viewId]]);
491 withId:(NSString*)factoryId
492 gestureRecognizersBlockingPolicy:
494 std::string idString([factoryId UTF8String]);
495 FML_CHECK(
self.factories.count(idString) == 0);
496 self.factories[idString] = factory;
497 self.gestureRecognizersBlockingPoliciesByType[idString] = gestureRecognizerBlockingPolicy;
500 - (void)beginFrameWithSize:(DlISize)frameSize {
501 [
self resetFrameState];
502 self.frameSize = frameSize;
505 - (void)cancelFrame {
506 [
self resetFrameState];
509 - (
flutter::PostPrerollResult)postPrerollActionWithThreadMerger:
510 (const
fml::RefPtr<
fml::RasterThreadMerger>&)rasterThreadMerger {
511 return flutter::PostPrerollResult::kSuccess;
514 - (void)endFrameWithResubmit:(BOOL)shouldResubmitFrame
515 threadMerger:(const
fml::RefPtr<
fml::RasterThreadMerger>&)rasterThreadMerger {
518 - (void)pushFilterToVisitedPlatformViews:(const std::shared_ptr<
flutter::DlImageFilter>&)filter
519 withRect:(const
flutter::DlRect&)filterRect {
520 for (int64_t
id :
self.visitedPlatformViews) {
521 flutter::EmbeddedViewParams params =
self.currentCompositionParams[id];
522 params.PushImageFilter(filter, filterRect);
523 self.currentCompositionParams[id] = params;
527 - (void)prerollCompositeEmbeddedView:(int64_t)viewId
528 withParams:(std::unique_ptr<
flutter::EmbeddedViewParams>)params {
529 DlRect viewBounds = DlRect::MakeSize(
self.frameSize);
530 std::unique_ptr<flutter::EmbedderViewSlice> view;
531 view = std::make_unique<flutter::DisplayListEmbedderViewSlice>(viewBounds);
532 self.slices.insert_or_assign(viewId, std::move(view));
534 self.compositionOrder.push_back(viewId);
536 if (
self.currentCompositionParams.count(viewId) == 1 &&
537 self.currentCompositionParams[viewId] == *params.get()) {
541 self.currentCompositionParams[viewId] = flutter::EmbeddedViewParams(*params.get());
542 self.viewsToRecomposite.insert(viewId);
545 - (size_t)embeddedViewCount {
546 return self.compositionOrder.size();
549 - (UIView*)platformViewForId:(int64_t)viewId {
550 return [
self flutterTouchInterceptingViewForId:viewId].embeddedView;
554 if (
self.platformViews.empty()) {
557 return self.platformViews[viewId].touch_interceptor;
560 - (long)firstResponderPlatformViewId {
561 for (
auto const& [
id, platformViewData] :
self.platformViews) {
562 UIView* rootView = platformViewData.root_view;
563 if (rootView.flt_hasFirstResponderInViewHierarchySubtree) {
570 - (void)clipViewSetMaskView:(UIView*)clipView {
571 FML_DCHECK([[NSThread currentThread] isMainThread]);
572 if (clipView.maskView) {
576 CGRectMake(-clipView.frame.origin.x, -clipView.frame.origin.y,
577 CGRectGetWidth(
self.flutterView.bounds), CGRectGetHeight(
self.flutterView.bounds));
578 clipView.maskView = [
self.maskViewPool getMaskViewWithFrame:frame];
581 - (void)applyMutators:(const
flutter::MutatorsStack&)mutatorsStack
582 embeddedView:(UIView*)embeddedView
583 boundingRect:(const DlRect&)boundingRect {
584 if (
self.flutterView == nil) {
591 DlMatrix transformMatrix;
592 NSMutableArray* blurFilters = [[NSMutableArray alloc] init];
593 NSMutableArray<PendingRRectClip*>* pendingClipRRects = [[NSMutableArray alloc] init];
595 FML_DCHECK(!clipView.maskView ||
597 if (clipView.maskView) {
598 [
self.maskViewPool insertViewToPoolIfNeeded:(FlutterClippingMaskView*)(clipView.maskView)];
599 clipView.maskView = nil;
601 CGFloat screenScale = [UIScreen mainScreen].scale;
602 auto iter = mutatorsStack.Begin();
603 while (iter != mutatorsStack.End()) {
604 switch ((*iter)->GetType()) {
605 case flutter::MutatorType::kTransform: {
606 transformMatrix = transformMatrix * (*iter)->GetMatrix();
609 case flutter::MutatorType::kClipRect: {
610 if (flutter::DisplayListMatrixClipState::TransformedRectCoversBounds(
611 (*iter)->GetRect(), transformMatrix, boundingRect)) {
614 [
self clipViewSetMaskView:clipView];
616 matrix:transformMatrix];
619 case flutter::MutatorType::kClipRRect: {
620 if (flutter::DisplayListMatrixClipState::TransformedRRectCoversBounds(
621 (*iter)->GetRRect(), transformMatrix, boundingRect)) {
624 [
self clipViewSetMaskView:clipView];
626 matrix:transformMatrix];
629 case flutter::MutatorType::kClipRSE: {
630 if (flutter::DisplayListMatrixClipState::TransformedRoundSuperellipseCoversBounds(
631 (*iter)->GetRSE(), transformMatrix, boundingRect)) {
634 [
self clipViewSetMaskView:clipView];
636 matrix:transformMatrix];
639 case flutter::MutatorType::kClipPath: {
643 [
self clipViewSetMaskView:clipView];
645 matrix:transformMatrix];
648 case flutter::MutatorType::kOpacity:
649 embeddedView.alpha = (*iter)->GetAlphaFloat() * embeddedView.alpha;
651 case flutter::MutatorType::kBackdropFilter: {
653 if (!
self.canApplyBlurBackdrop || !(*iter)->GetFilterMutation().GetFilter().asBlur()) {
658 filterRect = CGRectApplyAffineTransform(
659 filterRect, CGAffineTransformMakeScale(1 / screenScale, 1 / screenScale));
663 if (CGRectIsNull(CGRectIntersection(filterRect, clipView.frame))) {
666 CGRect intersection = CGRectIntersection(filterRect, clipView.frame);
667 CGRect frameInClipView = [
self.flutterView convertRect:intersection toView:clipView];
672 CGFloat blurRadius = (*iter)->GetFilterMutation().GetFilter().asBlur()->sigma_x();
673 UIVisualEffectView* visualEffectView = [[UIVisualEffectView alloc]
674 initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]];
677 CGFloat cornerRadius = 0.0;
678 BOOL isRoundedSuperellipse = NO;
681 if ([pendingClipRRects count] > 0) {
682 cornerRadius = pendingClipRRects.lastObject.topLeftRadius;
683 isRoundedSuperellipse = pendingClipRRects.lastObject.isRoundedSuperellipse;
684 [pendingClipRRects removeAllObjects];
686 visualEffectView.layer.cornerRadius = cornerRadius;
687 visualEffectView.layer.cornerCurve =
688 isRoundedSuperellipse ? kCACornerCurveContinuous : kCACornerCurveCircular;
689 visualEffectView.clipsToBounds = YES;
692 blurRadius:blurRadius
693 cornerRadius:cornerRadius
694 isRoundedSuperellipse:isRoundedSuperellipse
695 visualEffectView:visualEffectView];
697 self.canApplyBlurBackdrop = NO;
699 [blurFilters addObject:filter];
703 case flutter::MutatorType::kBackdropClipRect: {
708 case flutter::MutatorType::kBackdropClipRRect: {
710 DlRoundRect rrect = (*iter)->GetBackdropClipRRect().rrect;
712 clip.
rect = boundingRect;
713 impeller::RoundingRadii radii = rrect.GetRadii();
718 [pendingClipRRects addObject:clip];
721 case flutter::MutatorType::kBackdropClipRSuperellipse: {
723 flutter::DlRoundSuperellipse rse = (*iter)->GetBackdropClipRSuperellipse().rse;
725 clip.
rect = boundingRect;
726 impeller::RoundingRadii radii = rse.GetRadii();
732 [pendingClipRRects addObject:clip];
735 case flutter::MutatorType::kBackdropClipPath: {
743 if (
self.canApplyBlurBackdrop) {
752 flutter::DlScalar pointScale = 1.0 / screenScale;
753 transformMatrix = DlMatrix::MakeScale({pointScale, pointScale, 1}) * transformMatrix;
762 impeller::Vector3 origin = impeller::Vector3(clipView.frame.origin.x, clipView.frame.origin.y);
763 transformMatrix = DlMatrix::MakeTranslation(-origin) * transformMatrix;
768 - (void)compositeView:(int64_t)viewId withParams:(const
flutter::EmbeddedViewParams&)params {
770 CGRect frame = CGRectMake(0, 0, params.sizePoints().width, params.sizePoints().height);
772 touchInterceptor.layer.transform = CATransform3DIdentity;
773 touchInterceptor.frame = frame;
774 touchInterceptor.alpha = 1;
776 const flutter::MutatorsStack& mutatorStack = params.mutatorsStack();
777 UIView* clippingView =
self.platformViews[viewId].root_view;
782 const DlRect& rect = params.finalBoundingRect();
783 CGFloat screenScale = [UIScreen mainScreen].scale;
784 clippingView.frame = CGRectMake(rect.GetX() / screenScale, rect.GetY() / screenScale,
785 rect.GetWidth() / screenScale, rect.GetHeight() / screenScale);
786 [
self applyMutators:mutatorStack embeddedView:touchInterceptor boundingRect:rect];
789 - (
flutter::DlCanvas*)compositeEmbeddedViewWithId:(int64_t)viewId {
790 FML_DCHECK(
self.slices.find(viewId) !=
self.slices.end());
791 return self.slices[viewId]->canvas();
798 std::vector<int64_t> compositionOrder =
self.compositionOrder;
799 [
self.taskRunner runNowOrPostTask:^{
800 for (int64_t viewId : compositionOrder) {
801 [
self.platformViews[viewId].root_view removeFromSuperview];
803 self.platformViews.clear();
804 _previousCompositionOrder.clear();
807 self.compositionOrder.clear();
809 self.currentCompositionParams.clear();
810 self.viewsToRecomposite.clear();
811 self.layerPool->RecycleLayers();
812 self.visitedPlatformViews.clear();
815 - (BOOL)submitFrame:(std::unique_ptr<
flutter::SurfaceFrame>)background_frame
816 withIosContext:(const std::shared_ptr<
flutter::IOSContext>&)iosContext {
817 TRACE_EVENT0(
"flutter",
"PlatformViewsController::SubmitFrame");
820 if (
self.flutterView == nil || (
self.compositionOrder.empty() && !
self.hadPlatformViews)) {
823 if (
self.flutterView != nil) {
826 const flutter::DlISize frameSize =
self.frameSize;
827 [
self.taskRunner runNowOrPostTask:^{
832 [strongSelf performResize:frameSize];
836 self.hadPlatformViews = NO;
837 return background_frame->Submit();
839 self.hadPlatformViews = !
self.compositionOrder.empty();
841 bool didEncode =
true;
843 std::vector<std::unique_ptr<flutter::SurfaceFrame>> surfaceFrames;
844 surfaceFrames.reserve(
self.compositionOrder.size());
845 std::unordered_map<int64_t, DlRect> viewRects;
846 std::unordered_set<int64_t> viewsWithUnderlayPreserved;
848 for (int64_t viewId :
self.compositionOrder) {
849 const flutter::EmbeddedViewParams& params =
self.currentCompositionParams[viewId];
850 viewRects[viewId] = params.finalBoundingRect();
852 viewsWithUnderlayPreserved.insert(viewId);
856 std::unordered_map<int64_t, DlRect> overlayLayers =
857 SliceViews(background_frame->Canvas(),
self.compositionOrder,
self.slices, viewRects,
858 viewsWithUnderlayPreserved);
860 size_t requiredOverlayLayers = 0;
861 for (int64_t viewId :
self.compositionOrder) {
862 std::unordered_map<int64_t, DlRect>::const_iterator overlay = overlayLayers.find(viewId);
863 if (overlay == overlayLayers.end()) {
866 requiredOverlayLayers++;
872 [
self createMissingOverlays:requiredOverlayLayers withIosContext:iosContext];
874 int64_t overlayId = 0;
875 for (int64_t viewId :
self.compositionOrder) {
876 std::unordered_map<int64_t, DlRect>::const_iterator overlay = overlayLayers.find(viewId);
877 if (overlay == overlayLayers.end()) {
880 std::shared_ptr<flutter::OverlayLayer> layer =
self.nextLayerInPool;
885 std::unique_ptr<flutter::SurfaceFrame> frame = layer->surface->AcquireFrame(
self.frameSize);
890 flutter::DlCanvas* overlayCanvas = frame->Canvas();
891 int restoreCount = overlayCanvas->GetSaveCount();
892 overlayCanvas->Save();
893 overlayCanvas->ClipRect(overlay->second);
894 if (viewsWithUnderlayPreserved.find(viewId) != viewsWithUnderlayPreserved.end()) {
897 overlayCanvas->Clear(flutter::DlColor::kTransparent());
898 self.slices[viewId]->render_into(overlayCanvas);
899 overlayCanvas->RestoreToCount(restoreCount);
903 frame->set_submit_info({.frame_boundary =
false, .present_with_transaction =
true});
904 layer->did_submit_last_frame = frame->Encode();
906 didEncode &= layer->did_submit_last_frame;
908 .
rect = overlay->second,
910 .overlay_id = overlayId,
913 surfaceFrames.push_back(std::move(frame));
917 auto previousSubmitInfo = background_frame->submit_info();
918 background_frame->set_submit_info({
919 .frame_damage = previousSubmitInfo.frame_damage,
920 .buffer_damage = previousSubmitInfo.buffer_damage,
921 .present_with_transaction =
true,
923 background_frame->Encode();
924 surfaceFrames.push_back(std::move(background_frame));
927 std::vector<std::shared_ptr<flutter::OverlayLayer>> unusedLayers =
928 self.layerPool->RemoveUnusedLayers();
929 self.layerPool->RecycleLayers();
930 auto task = fml::MakeCopyable([
self,
931 platformViewLayers = std::move(platformViewLayers),
932 currentCompositionParams =
self.currentCompositionParams,
933 viewsToRecomposite =
self.viewsToRecomposite,
934 compositionOrder =
self.compositionOrder,
935 unusedLayers = std::move(unusedLayers),
936 surfaceFrames = std::move(surfaceFrames)]()
mutable {
937 [
self performSubmit:platformViewLayers
938 currentCompositionParams:currentCompositionParams
939 viewsToRecomposite:viewsToRecomposite
940 compositionOrder:compositionOrder
941 unusedLayers:unusedLayers
942 surfaceFrames:surfaceFrames];
945 [
self.taskRunner runNowOrPostTask:^{
951 - (void)createMissingOverlays:(
size_t)requiredOverlayLayers
952 withIosContext:(const std::shared_ptr<
flutter::IOSContext>&)iosContext {
953 TRACE_EVENT0(
"flutter",
"PlatformViewsController::CreateMissingLayers");
955 if (requiredOverlayLayers <= self.layerPool->size()) {
958 auto missingLayerCount = requiredOverlayLayers -
self.layerPool->size();
963 auto latch = std::make_shared<fml::CountDownLatch>(1u);
964 [
self.taskRunner runNowOrPostTask:^{
965 for (auto i = 0u; i < missingLayerCount; i++) {
966 [
self createLayerWithIosContext:iosContext
967 pixelFormat:((FlutterView*)self.flutterView).pixelFormat];
971 if (![[NSThread currentThread] isMainThread]) {
976 - (void)performResize:(const
flutter::DlISize&)frameSize {
977 TRACE_EVENT0(
"flutter",
"PlatformViewsController::PerformResize");
978 FML_DCHECK([[NSThread currentThread] isMainThread]);
980 if (
self.flutterView != nil) {
982 setIntrinsicContentSize:CGSizeMake(frameSize.width, frameSize.height)];
986 - (void)performSubmit:(const
LayersMap&)platformViewLayers
987 currentCompositionParams:
988 (std::unordered_map<int64_t,
flutter::EmbeddedViewParams>&)currentCompositionParams
989 viewsToRecomposite:(const std::unordered_set<int64_t>&)viewsToRecomposite
990 compositionOrder:(const std::vector<int64_t>&)compositionOrder
992 (const std::vector<std::shared_ptr<
flutter::OverlayLayer>>&)unusedLayers
994 (const std::vector<std::unique_ptr<
flutter::SurfaceFrame>>&)surfaceFrames {
995 TRACE_EVENT0(
"flutter",
"PlatformViewsController::PerformSubmit");
996 FML_DCHECK([[NSThread currentThread] isMainThread]);
998 [CATransaction begin];
1001 for (
const auto& [viewId, layerData] : platformViewLayers) {
1002 layerData.layer->UpdateViewState(
self.flutterView,
1005 layerData.overlay_id
1010 for (
auto& view : [
self computeViewsToDispose]) {
1011 [view removeFromSuperview];
1015 for (int64_t viewId : viewsToRecomposite) {
1016 [
self compositeView:viewId withParams:currentCompositionParams[viewId]];
1020 for (
const auto& frame : surfaceFrames) {
1026 [
self removeUnusedLayers:unusedLayers withCompositionOrder:compositionOrder];
1029 [
self bringLayersIntoView:platformViewLayers withCompositionOrder:compositionOrder];
1031 [CATransaction commit];
1034 - (void)bringLayersIntoView:(const
LayersMap&)layerMap
1035 withCompositionOrder:(const std::vector<int64_t>&)compositionOrder {
1036 FML_DCHECK(
self.flutterView);
1037 UIView* flutterView =
self.flutterView;
1040 NSMutableArray* desiredPlatformSubviews = [NSMutableArray array];
1041 for (int64_t platformViewId : compositionOrder) {
1043 UIView* platformViewRoot =
self.platformViews[platformViewId].root_view;
1044 if (platformViewRoot != nil) {
1045 [desiredPlatformSubviews addObject:platformViewRoot];
1048 auto maybeLayerData = layerMap.find(platformViewId);
1049 if (maybeLayerData != layerMap.end()) {
1050 auto view = maybeLayerData->second.layer->overlay_view_wrapper;
1052 [desiredPlatformSubviews addObject:view];
1057 NSSet* desiredPlatformSubviewsSet = [NSSet setWithArray:desiredPlatformSubviews];
1058 NSArray* existingPlatformSubviews = [flutterView.subviews
1059 filteredArrayUsingPredicate:[NSPredicate
1060 predicateWithBlock:^BOOL(id object, NSDictionary* bindings) {
1061 return [desiredPlatformSubviewsSet containsObject:object];
1068 if (![desiredPlatformSubviews isEqualToArray:existingPlatformSubviews]) {
1069 for (UIView* subview in desiredPlatformSubviews) {
1071 [flutterView addSubview:subview];
1076 - (std::shared_ptr<flutter::OverlayLayer>)nextLayerInPool {
1077 return self.layerPool->GetNextLayer();
1080 - (void)createLayerWithIosContext:(const std::shared_ptr<
flutter::IOSContext>&)iosContext
1081 pixelFormat:(MTLPixelFormat)pixelFormat {
1082 self.layerPool->CreateLayer(iosContext, pixelFormat);
1085 - (void)removeUnusedLayers:(const std::vector<std::shared_ptr<
flutter::OverlayLayer>>&)unusedLayers
1086 withCompositionOrder:(const std::vector<int64_t>&)compositionOrder {
1087 for (
const std::shared_ptr<flutter::OverlayLayer>& layer : unusedLayers) {
1088 [layer->overlay_view_wrapper removeFromSuperview];
1091 std::unordered_set<int64_t> compositionOrderSet;
1092 for (int64_t viewId : compositionOrder) {
1093 compositionOrderSet.insert(viewId);
1097 if (compositionOrderSet.find(viewId) == compositionOrderSet.end()) {
1098 UIView* platformViewRoot =
self.platformViews[viewId].root_view;
1099 [platformViewRoot removeFromSuperview];
1104 - (std::vector<UIView*>)computeViewsToDispose {
1105 std::vector<UIView*> views;
1106 if (
self.viewsToDispose.empty()) {
1110 std::unordered_set<int64_t> viewsToComposite(
self.compositionOrder.begin(),
1111 self.compositionOrder.end());
1112 std::unordered_set<int64_t> viewsToDelayDispose;
1113 for (int64_t viewId :
self.viewsToDispose) {
1114 if (viewsToComposite.count(viewId)) {
1115 viewsToDelayDispose.insert(viewId);
1118 UIView* rootView =
self.platformViews[viewId].root_view;
1119 views.push_back(rootView);
1120 self.currentCompositionParams.erase(viewId);
1121 self.viewsToRecomposite.erase(viewId);
1122 self.platformViews.erase(viewId);
1124 self.viewsToDispose = std::move(viewsToDelayDispose);
1128 - (void)resetFrameState {
1129 self.slices.clear();
1130 self.compositionOrder.clear();
1131 self.visitedPlatformViews.clear();
1134 - (void)pushVisitedPlatformViewId:(int64_t)viewId {
1135 self.visitedPlatformViews.push_back(viewId);
1138 - (void)pushClipRectToVisitedPlatformViews:(const
flutter::DlRect&)clipRect {
1139 for (int64_t
id :
self.visitedPlatformViews) {
1140 flutter::EmbeddedViewParams params =
self.currentCompositionParams[id];
1141 params.PushPlatformViewClipRect(clipRect);
1142 self.currentCompositionParams[id] = params;
1146 - (void)pushClipRRectToVisitedPlatformViews:(const
flutter::DlRoundRect&)clipRRect {
1147 for (int64_t
id :
self.visitedPlatformViews) {
1148 flutter::EmbeddedViewParams params =
self.currentCompositionParams[id];
1149 params.PushPlatformViewClipRRect(clipRRect);
1150 self.currentCompositionParams[id] = params;
1154 - (void)pushClipRSuperellipseToVisitedPlatformViews:(const
flutter::DlRoundSuperellipse&)clipRse {
1155 for (int64_t
id :
self.visitedPlatformViews) {
1156 flutter::EmbeddedViewParams params =
self.currentCompositionParams[id];
1157 params.PushPlatformViewClipRSuperellipse(clipRse);
1158 self.currentCompositionParams[id] = params;
1162 - (void)pushClipPathToVisitedPlatformViews:(const
flutter::DlPath&)clipPath {
1163 for (int64_t
id :
self.visitedPlatformViews) {
1164 flutter::EmbeddedViewParams params =
self.currentCompositionParams[id];
1165 params.PushPlatformViewClipPath(clipPath);
1166 self.currentCompositionParams[id] = params;
1170 - (const
flutter::EmbeddedViewParams&)compositionParamsForView:(int64_t)viewId {
1171 return self.currentCompositionParams.find(viewId)->second;
1174 #pragma mark - Properties
1176 - (
flutter::OverlayLayerPool*)layerPool {
1177 return _layerPool.get();
1180 - (std::unordered_map<int64_t, std::unique_ptr<flutter::EmbedderViewSlice>>&)slices {
1184 - (std::unordered_map<std::string, NSObject<FlutterPlatformViewFactory>*>&)factories {
1188 - (std::unordered_map<std::string, FlutterPlatformViewGestureRecognizersBlockingPolicy>&)
1189 gestureRecognizersBlockingPoliciesByType {
1193 - (std::unordered_map<int64_t, PlatformViewData>&)platformViews {
1197 - (std::unordered_map<int64_t, flutter::EmbeddedViewParams>&)currentCompositionParams {
1201 - (std::unordered_set<int64_t>&)viewsToDispose {
1205 - (std::vector<int64_t>&)compositionOrder {
1209 - (std::vector<int64_t>&)visitedPlatformViews {
1213 - (std::unordered_set<int64_t>&)viewsToRecomposite {
1217 - (NSArray<NSNumber*>*)previousCompositionOrder {
1219 NSMutableArray* array = [NSMutableArray arrayWithCapacity:_previousCompositionOrder.size()];
1221 [array addObject:@(viewId)];
void(^ FlutterResult)(id _Nullable result)
FLUTTER_DARWIN_EXPORT NSObject const * FlutterMethodNotImplemented
FlutterPlatformViewGestureRecognizersBlockingPolicy
@ FlutterPlatformViewGestureRecognizersBlockingPolicyEager
@ FlutterPlatformViewGestureRecognizersBlockingPolicyWaitUntilTouchesEnded
@ FlutterPlatformViewGestureRecognizersBlockingPolicyDoNotBlockGesture
void applyBlurBackdropFilters:(NSArray< PlatformViewFilter * > *filters)
CGFloat bottomRightRadius
BOOL isRoundedSuperellipse
Storage for Overlay layers across frames.
std::shared_ptr< flutter::OverlayLayer > layer