7 #include "flutter/display_list/effects/image_filters/dl_blur_image_filter.h"
8 #include "flutter/display_list/utils/dl_matrix_clip_tracker.h"
9 #include "flutter/flow/surface_frame.h"
10 #include "flutter/flow/view_slicer.h"
11 #include "flutter/fml/make_copyable.h"
12 #include "flutter/fml/synchronization/count_down_latch.h"
19 using flutter::DlMatrix;
20 using flutter::DlRect;
21 using flutter::DlRoundRect;
29 std::shared_ptr<flutter::OverlayLayer>
layer;
31 using LayersMap = std::unordered_map<int64_t, LayerData>;
38 NSObject<FlutterPlatformView>*
view;
47 CATransform3D transform = CATransform3DIdentity;
48 transform.m11 = matrix.m[0];
49 transform.m12 = matrix.m[1];
50 transform.m13 = matrix.m[2];
51 transform.m14 = matrix.m[3];
53 transform.m21 = matrix.m[4];
54 transform.m22 = matrix.m[5];
55 transform.m23 = matrix.m[6];
56 transform.m24 = matrix.m[7];
58 transform.m31 = matrix.m[8];
59 transform.m32 = matrix.m[9];
60 transform.m33 = matrix.m[10];
61 transform.m34 = matrix.m[11];
63 transform.m41 = matrix.m[12];
64 transform.m42 = matrix.m[13];
65 transform.m43 = matrix.m[14];
66 transform.m44 = matrix.m[15];
75 layer.anchorPoint = CGPointZero;
76 layer.position = CGPointZero;
80 return CGRectMake(clipDlRect.GetLeft(),
82 clipDlRect.GetWidth(),
83 clipDlRect.GetHeight());
95 @property(nonatomic, readonly)
96 std::unordered_map<int64_t, std::unique_ptr<flutter::EmbedderViewSlice>>& slices;
100 @property(nonatomic, readonly)
101 std::unordered_map<std::string, NSObject<FlutterPlatformViewFactory>*>& factories;
104 @property(nonatomic, readonly)
105 std::unordered_map<std::string, FlutterPlatformViewGestureRecognizersBlockingPolicy>&
106 gestureRecognizersBlockingPolicies;
109 @property(nonatomic, assign) SkISize frameSize;
112 @property(nonatomic, readonly)
const fml::RefPtr<fml::TaskRunner>& platformTaskRunner;
115 @property(nonatomic, readonly) std::unordered_map<int64_t, PlatformViewData>& platformViews;
120 @property(nonatomic, readonly)
121 std::unordered_map<int64_t, flutter::EmbeddedViewParams>& currentCompositionParams;
127 @property(nonatomic, readonly) std::unordered_set<int64_t>& viewsToDispose;
132 @property(nonatomic, readonly) std::vector<int64_t>& compositionOrder;
137 @property(nonatomic, readonly) std::vector<int64_t>& visitedPlatformViews;
142 @property(nonatomic, readonly) std::unordered_set<int64_t>& viewsToRecomposite;
156 @property(nonatomic, assign) BOOL hadPlatformViews;
161 @property(nonatomic, assign) BOOL canApplyBlurBackdrop;
166 - (void)createMissingOverlays:(
size_t)requiredOverlayLayers
167 withIosContext:(const std::shared_ptr<
flutter::IOSContext>&)iosContext;
170 - (void)performSubmit:(const
LayersMap&)platformViewLayers
171 currentCompositionParams:
172 (std::unordered_map<int64_t,
flutter::EmbeddedViewParams>&)currentCompositionParams
173 viewsToRecomposite:(const std::unordered_set<int64_t>&)viewsToRecomposite
174 compositionOrder:(const std::vector<int64_t>&)compositionOrder
176 (const std::vector<std::shared_ptr<
flutter::OverlayLayer>>&)unusedLayers
178 (const std::vector<std::unique_ptr<
flutter::SurfaceFrame>>&)surfaceFrames;
185 - (void)clipViewSetMaskView:(UIView*)clipView;
199 - (void)applyMutators:(const
flutter::MutatorsStack&)mutatorsStack
200 embeddedView:(UIView*)embeddedView
201 boundingRect:(const SkRect&)boundingRect;
205 - (void)bringLayersIntoView:(const
LayersMap&)layerMap
206 withCompositionOrder:(const std::vector<int64_t>&)compositionOrder;
208 - (std::shared_ptr<flutter::OverlayLayer>)nextLayerInPool;
211 - (void)createLayerWithIosContext:(const std::shared_ptr<
flutter::IOSContext>&)iosContext
212 pixelFormat:(MTLPixelFormat)pixelFormat
213 screenScale:(CGFloat)screenScale;
217 - (void)removeUnusedLayers:(const std::vector<std::shared_ptr<
flutter::OverlayLayer>>&)unusedLayers
218 withCompositionOrder:(const std::vector<int64_t>&)compositionOrder;
224 - (std::vector<UIView*>)computeViewsToDispose;
227 - (void)resetFrameState;
238 std::unique_ptr<flutter::OverlayLayerPool> _layerPool;
239 std::unordered_map<int64_t, std::unique_ptr<flutter::EmbedderViewSlice>>
_slices;
240 std::unordered_map<std::string, NSObject<FlutterPlatformViewFactory>*>
_factories;
241 std::unordered_map<std::string, FlutterPlatformViewGestureRecognizersBlockingPolicy>
254 if (
self = [super init]) {
255 _layerPool = std::make_unique<flutter::OverlayLayerPool>();
258 _hadPlatformViews = NO;
259 _canApplyBlurBackdrop = YES;
264 - (const
fml::RefPtr<fml::TaskRunner>&)taskRunner {
268 - (void)setTaskRunner:(const
fml::RefPtr<
fml::TaskRunner>&)platformTaskRunner {
273 if ([[call method] isEqualToString:
@"create"]) {
274 [
self onCreate:call result:result];
275 }
else if ([[call method] isEqualToString:
@"dispose"]) {
276 [
self onDispose:call result:result];
277 }
else if ([[call method] isEqualToString:
@"acceptGesture"]) {
278 [
self onAcceptGesture:call result:result];
279 }
else if ([[call method] isEqualToString:
@"rejectGesture"]) {
280 [
self onRejectGesture:call result:result];
287 NSDictionary<NSString*, id>* args = [call
arguments];
289 int64_t viewId = [args[@"id"] longLongValue];
290 NSString* viewTypeString = args[@"viewType"];
291 std::string viewType(viewTypeString.UTF8String);
293 if (
self.platformViews.count(viewId) != 0) {
295 message:
@"trying to create an already created view"
296 details:[NSString stringWithFormat:
@"view id: '%lld'", viewId]]);
300 NSObject<FlutterPlatformViewFactory>* factory =
self.factories[viewType];
301 if (factory == nil) {
303 errorWithCode:
@"unregistered_view_type"
304 message:[NSString stringWithFormat:
@"A UIKitView widget is trying to create a "
305 @"PlatformView with an unregistered type: < %@ >",
307 details:
@"If you are the author of the PlatformView, make sure `registerViewFactory` "
310 @"https://docs.flutter.dev/development/platform-integration/"
311 @"platform-views#on-the-platform-side-1 for more details.\n"
312 @"If you are not the author of the PlatformView, make sure to call "
313 @"`GeneratedPluginRegistrant.register`."]);
318 if ([factory respondsToSelector:
@selector(createArgsCodec)]) {
319 NSObject<FlutterMessageCodec>* codec = [factory createArgsCodec];
320 if (codec != nil && args[
@"params"] != nil) {
322 params = [codec decode:paramsData.data];
326 NSObject<FlutterPlatformView>* embeddedView = [factory createWithFrame:CGRectZero
327 viewIdentifier:viewId
329 UIView* platformView = [embeddedView view];
331 platformView.accessibilityIdentifier = [NSString stringWithFormat:@"platform_view[%lld]", viewId];
334 initWithEmbeddedView:platformView
335 platformViewsController:self
336 gestureRecognizersBlockingPolicy:self.gestureRecognizersBlockingPolicies[viewType]];
339 [clippingView addSubview:touchInterceptor];
342 .
view = embeddedView,
343 .touch_interceptor = touchInterceptor,
344 .root_view = clippingView
352 int64_t viewId = [arg longLongValue];
354 if (
self.platformViews.count(viewId) == 0) {
356 message:
@"trying to dispose an unknown"
357 details:[NSString stringWithFormat:
@"view id: '%lld'", viewId]]);
361 self.viewsToDispose.insert(viewId);
366 NSDictionary<NSString*, id>* args = [call
arguments];
367 int64_t viewId = [args[@"id"] longLongValue];
369 if (
self.platformViews.count(viewId) == 0) {
371 message:
@"trying to set gesture state for an unknown view"
372 details:[NSString stringWithFormat:
@"view id: '%lld'", viewId]]);
383 NSDictionary<NSString*, id>* args = [call
arguments];
384 int64_t viewId = [args[@"id"] longLongValue];
386 if (
self.platformViews.count(viewId) == 0) {
388 message:
@"trying to set gesture state for an unknown view"
389 details:[NSString stringWithFormat:
@"view id: '%lld'", viewId]]);
400 withId:(NSString*)factoryId
401 gestureRecognizersBlockingPolicy:
403 std::string idString([factoryId UTF8String]);
404 FML_CHECK(
self.factories.count(idString) == 0);
405 self.factories[idString] = factory;
406 self.gestureRecognizersBlockingPolicies[idString] = gestureRecognizerBlockingPolicy;
409 - (void)beginFrameWithSize:(SkISize)frameSize {
410 [
self resetFrameState];
411 self.frameSize = frameSize;
414 - (void)cancelFrame {
415 [
self resetFrameState];
418 - (
flutter::PostPrerollResult)postPrerollActionWithThreadMerger:
419 (const
fml::RefPtr<
fml::RasterThreadMerger>&)rasterThreadMerger {
420 return flutter::PostPrerollResult::kSuccess;
423 - (void)endFrameWithResubmit:(BOOL)shouldResubmitFrame
424 threadMerger:(const
fml::RefPtr<
fml::RasterThreadMerger>&)rasterThreadMerger {
427 - (void)pushFilterToVisitedPlatformViews:(const std::shared_ptr<
flutter::DlImageFilter>&)filter
428 withRect:(const SkRect&)filterRect {
429 for (int64_t
id :
self.visitedPlatformViews) {
430 flutter::EmbeddedViewParams params =
self.currentCompositionParams[id];
431 params.PushImageFilter(filter, filterRect);
432 self.currentCompositionParams[id] = params;
436 - (void)prerollCompositeEmbeddedView:(int64_t)viewId
437 withParams:(std::unique_ptr<
flutter::EmbeddedViewParams>)params {
438 SkRect viewBounds = SkRect::Make(
self.frameSize);
439 std::unique_ptr<flutter::EmbedderViewSlice> view;
440 view = std::make_unique<flutter::DisplayListEmbedderViewSlice>(viewBounds);
441 self.slices.insert_or_assign(viewId, std::move(view));
443 self.compositionOrder.push_back(viewId);
445 if (
self.currentCompositionParams.count(viewId) == 1 &&
446 self.currentCompositionParams[viewId] == *params.get()) {
450 self.currentCompositionParams[viewId] = flutter::EmbeddedViewParams(*params.get());
451 self.viewsToRecomposite.insert(viewId);
454 - (size_t)embeddedViewCount {
455 return self.compositionOrder.size();
458 - (UIView*)platformViewForId:(int64_t)viewId {
459 return [
self flutterTouchInterceptingViewForId:viewId].embeddedView;
463 if (
self.platformViews.empty()) {
466 return self.platformViews[viewId].touch_interceptor;
469 - (long)firstResponderPlatformViewId {
470 for (
auto const& [
id, platformViewData] :
self.platformViews) {
471 UIView* rootView = platformViewData.root_view;
472 if (rootView.flt_hasFirstResponderInViewHierarchySubtree) {
479 - (void)clipViewSetMaskView:(UIView*)clipView {
480 FML_DCHECK([[NSThread currentThread] isMainThread]);
481 if (clipView.maskView) {
485 CGRectMake(-clipView.frame.origin.x, -clipView.frame.origin.y,
486 CGRectGetWidth(
self.flutterView.bounds), CGRectGetHeight(
self.flutterView.bounds));
487 clipView.maskView = [
self.maskViewPool
488 getMaskViewWithFrame:frame
489 screenScale:[
self.flutterViewController flutterScreenIfViewLoaded].scale];
492 - (void)applyMutators:(const
flutter::MutatorsStack&)mutatorsStack
493 embeddedView:(UIView*)embeddedView
494 boundingRect:(const SkRect&)boundingRect {
495 if (
self.flutterView == nil) {
502 DlMatrix transformMatrix;
503 const DlRect& dlBoundingRect = flutter::ToDlRect(boundingRect);
504 NSMutableArray* blurFilters = [[NSMutableArray alloc] init];
505 FML_DCHECK(!clipView.maskView ||
507 if (clipView.maskView) {
508 [
self.maskViewPool insertViewToPoolIfNeeded:(FlutterClippingMaskView*)(clipView.maskView)];
509 clipView.maskView = nil;
511 CGFloat screenScale = [
self.flutterViewController flutterScreenIfViewLoaded].scale;
512 auto iter = mutatorsStack.Begin();
513 while (iter != mutatorsStack.End()) {
514 switch ((*iter)->GetType()) {
515 case flutter::MutatorType::kTransform: {
516 transformMatrix = transformMatrix * (*iter)->GetMatrix();
519 case flutter::MutatorType::kClipRect: {
520 if (flutter::DisplayListMatrixClipState::TransformedRectCoversBounds(
521 (*iter)->GetRect(), transformMatrix, dlBoundingRect)) {
524 [
self clipViewSetMaskView:clipView];
526 matrix:transformMatrix];
529 case flutter::MutatorType::kClipRRect: {
530 if (flutter::DisplayListMatrixClipState::TransformedRRectCoversBounds(
531 (*iter)->GetRRect(), transformMatrix, dlBoundingRect)) {
534 [
self clipViewSetMaskView:clipView];
536 matrix:transformMatrix];
539 case flutter::MutatorType::kClipRSE: {
540 if (flutter::DisplayListMatrixClipState::TransformedRoundSuperellipseCoversBounds(
541 (*iter)->GetRSE(), transformMatrix, dlBoundingRect)) {
544 [
self clipViewSetMaskView:clipView];
546 matrix:transformMatrix];
549 case flutter::MutatorType::kClipPath: {
553 [
self clipViewSetMaskView:clipView];
555 matrix:transformMatrix];
558 case flutter::MutatorType::kOpacity:
559 embeddedView.alpha = (*iter)->GetAlphaFloat() * embeddedView.alpha;
561 case flutter::MutatorType::kBackdropFilter: {
563 if (!
self.canApplyBlurBackdrop || !(*iter)->GetFilterMutation().GetFilter().asBlur()) {
568 filterRect = CGRectApplyAffineTransform(
569 filterRect, CGAffineTransformMakeScale(1 / screenScale, 1 / screenScale));
573 if (CGRectIsNull(CGRectIntersection(filterRect, clipView.frame))) {
576 CGRect intersection = CGRectIntersection(filterRect, clipView.frame);
577 CGRect frameInClipView = [
self.flutterView convertRect:intersection toView:clipView];
582 CGFloat blurRadius = (*iter)->GetFilterMutation().GetFilter().asBlur()->sigma_x();
583 UIVisualEffectView* visualEffectView = [[UIVisualEffectView alloc]
584 initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]];
586 blurRadius:blurRadius
587 visualEffectView:visualEffectView];
589 self.canApplyBlurBackdrop = NO;
591 [blurFilters addObject:filter];
599 if (
self.canApplyBlurBackdrop) {
608 flutter::DlScalar pointScale = 1.0 / screenScale;
609 transformMatrix = DlMatrix::MakeScale({pointScale, pointScale, 1}) * transformMatrix;
618 impeller::Vector3 origin = impeller::Vector3(clipView.frame.origin.x, clipView.frame.origin.y);
619 transformMatrix = DlMatrix::MakeTranslation(-origin) * transformMatrix;
624 - (void)compositeView:(int64_t)viewId withParams:(const
flutter::EmbeddedViewParams&)params {
626 CGRect frame = CGRectMake(0, 0, params.sizePoints().width(), params.sizePoints().height());
628 touchInterceptor.layer.transform = CATransform3DIdentity;
629 touchInterceptor.frame = frame;
630 touchInterceptor.alpha = 1;
632 const flutter::MutatorsStack& mutatorStack = params.mutatorsStack();
633 UIView* clippingView =
self.platformViews[viewId].root_view;
638 const SkRect& rect = params.finalBoundingRect();
639 CGFloat screenScale = [
self.flutterViewController flutterScreenIfViewLoaded].scale;
640 clippingView.frame = CGRectMake(rect.x() / screenScale, rect.y() / screenScale,
641 rect.width() / screenScale, rect.height() / screenScale);
642 [
self applyMutators:mutatorStack embeddedView:touchInterceptor boundingRect:rect];
645 - (
flutter::DlCanvas*)compositeEmbeddedViewWithId:(int64_t)viewId {
646 FML_DCHECK(
self.slices.find(viewId) !=
self.slices.end());
647 return self.slices[viewId]->canvas();
654 fml::TaskRunner::RunNowOrPostTask(
self.platformTaskRunner, [
self]() {
655 for (int64_t viewId :
self.compositionOrder) {
656 [
self.platformViews[viewId].root_view removeFromSuperview];
658 self.platformViews.clear();
659 self.previousCompositionOrder.clear();
662 self.compositionOrder.clear();
664 self.currentCompositionParams.clear();
665 self.viewsToRecomposite.clear();
666 self.layerPool->RecycleLayers();
667 self.visitedPlatformViews.clear();
670 - (BOOL)submitFrame:(std::unique_ptr<
flutter::SurfaceFrame>)background_frame
671 withIosContext:(const std::shared_ptr<
flutter::IOSContext>&)iosContext {
672 TRACE_EVENT0(
"flutter",
"PlatformViewsController::SubmitFrame");
675 if (
self.flutterView == nil || (
self.compositionOrder.empty() && !
self.hadPlatformViews)) {
676 self.hadPlatformViews = NO;
677 return background_frame->Submit();
679 self.hadPlatformViews = !
self.compositionOrder.empty();
681 bool didEncode =
true;
683 std::vector<std::unique_ptr<flutter::SurfaceFrame>> surfaceFrames;
684 surfaceFrames.reserve(
self.compositionOrder.size());
685 std::unordered_map<int64_t, SkRect> viewRects;
687 for (int64_t viewId :
self.compositionOrder) {
688 viewRects[viewId] =
self.currentCompositionParams[viewId].finalBoundingRect();
691 std::unordered_map<int64_t, SkRect> overlayLayers =
692 SliceViews(background_frame->Canvas(),
self.compositionOrder,
self.slices, viewRects);
694 size_t requiredOverlayLayers = 0;
695 for (int64_t viewId :
self.compositionOrder) {
696 std::unordered_map<int64_t, SkRect>::const_iterator overlay = overlayLayers.find(viewId);
697 if (overlay == overlayLayers.end()) {
700 requiredOverlayLayers++;
706 [
self createMissingOverlays:requiredOverlayLayers withIosContext:iosContext];
708 int64_t overlayId = 0;
709 for (int64_t viewId :
self.compositionOrder) {
710 std::unordered_map<int64_t, SkRect>::const_iterator overlay = overlayLayers.find(viewId);
711 if (overlay == overlayLayers.end()) {
714 std::shared_ptr<flutter::OverlayLayer> layer =
self.nextLayerInPool;
719 std::unique_ptr<flutter::SurfaceFrame> frame = layer->surface->AcquireFrame(
self.frameSize);
724 flutter::DlCanvas* overlayCanvas = frame->Canvas();
725 int restoreCount = overlayCanvas->GetSaveCount();
726 overlayCanvas->Save();
727 overlayCanvas->ClipRect(flutter::ToDlRect(overlay->second));
728 overlayCanvas->Clear(flutter::DlColor::kTransparent());
729 self.slices[viewId]->render_into(overlayCanvas);
730 overlayCanvas->RestoreToCount(restoreCount);
734 frame->set_submit_info({.frame_boundary =
false, .present_with_transaction =
true});
735 layer->did_submit_last_frame = frame->Encode();
737 didEncode &= layer->did_submit_last_frame;
739 .
rect = overlay->second,
741 .overlay_id = overlayId,
744 surfaceFrames.push_back(std::move(frame));
748 auto previousSubmitInfo = background_frame->submit_info();
749 background_frame->set_submit_info({
750 .frame_damage = previousSubmitInfo.frame_damage,
751 .buffer_damage = previousSubmitInfo.buffer_damage,
752 .present_with_transaction =
true,
754 background_frame->Encode();
755 surfaceFrames.push_back(std::move(background_frame));
758 std::vector<std::shared_ptr<flutter::OverlayLayer>> unusedLayers =
759 self.layerPool->RemoveUnusedLayers();
760 self.layerPool->RecycleLayers();
763 platformViewLayers = std::move(platformViewLayers),
764 currentCompositionParams = self.currentCompositionParams,
765 viewsToRecomposite = self.viewsToRecomposite,
766 compositionOrder = self.compositionOrder,
767 unusedLayers = std::move(unusedLayers),
768 surfaceFrames = std::move(surfaceFrames)
770 [
self performSubmit:platformViewLayers
771 currentCompositionParams:currentCompositionParams
772 viewsToRecomposite:viewsToRecomposite
773 compositionOrder:compositionOrder
774 unusedLayers:unusedLayers
775 surfaceFrames:surfaceFrames];
778 fml::TaskRunner::RunNowOrPostTask(
self.platformTaskRunner, fml::MakeCopyable(std::move(task)));
783 - (void)createMissingOverlays:(
size_t)requiredOverlayLayers
784 withIosContext:(const std::shared_ptr<
flutter::IOSContext>&)iosContext {
785 TRACE_EVENT0(
"flutter",
"PlatformViewsController::CreateMissingLayers");
787 if (requiredOverlayLayers <= self.layerPool->size()) {
790 auto missingLayerCount = requiredOverlayLayers -
self.layerPool->size();
794 auto latch = std::make_shared<fml::CountDownLatch>(1u);
795 fml::TaskRunner::RunNowOrPostTask(
796 self.platformTaskRunner, [
self, missingLayerCount, iosContext, latch]() {
797 for (
auto i = 0u; i < missingLayerCount; i++) {
798 [
self createLayerWithIosContext:iosContext
799 pixelFormat:((FlutterView*)self.flutterView).pixelFormat
800 screenScale:((FlutterView*)self.flutterView).screen.scale];
804 if (![[NSThread currentThread] isMainThread]) {
809 - (void)performSubmit:(const
LayersMap&)platformViewLayers
810 currentCompositionParams:
811 (std::unordered_map<int64_t,
flutter::EmbeddedViewParams>&)currentCompositionParams
812 viewsToRecomposite:(const std::unordered_set<int64_t>&)viewsToRecomposite
813 compositionOrder:(const std::vector<int64_t>&)compositionOrder
815 (const std::vector<std::shared_ptr<
flutter::OverlayLayer>>&)unusedLayers
817 (const std::vector<std::unique_ptr<
flutter::SurfaceFrame>>&)surfaceFrames {
818 TRACE_EVENT0(
"flutter",
"PlatformViewsController::PerformSubmit");
819 FML_DCHECK([[NSThread currentThread] isMainThread]);
821 [CATransaction begin];
824 for (
const auto& [viewId, layerData] : platformViewLayers) {
825 layerData.layer->UpdateViewState(
self.flutterView,
833 for (
auto& view : [
self computeViewsToDispose]) {
834 [view removeFromSuperview];
838 for (int64_t viewId : viewsToRecomposite) {
839 [
self compositeView:viewId withParams:currentCompositionParams[viewId]];
843 for (
const auto& frame : surfaceFrames) {
849 [
self removeUnusedLayers:unusedLayers withCompositionOrder:compositionOrder];
852 [
self bringLayersIntoView:platformViewLayers withCompositionOrder:compositionOrder];
854 [CATransaction commit];
857 - (void)bringLayersIntoView:(const
LayersMap&)layerMap
858 withCompositionOrder:(const std::vector<int64_t>&)compositionOrder {
859 FML_DCHECK(
self.flutterView);
860 UIView* flutterView =
self.flutterView;
862 self.previousCompositionOrder.clear();
863 NSMutableArray* desiredPlatformSubviews = [NSMutableArray array];
864 for (int64_t platformViewId : compositionOrder) {
865 self.previousCompositionOrder.push_back(platformViewId);
866 UIView* platformViewRoot =
self.platformViews[platformViewId].root_view;
867 if (platformViewRoot != nil) {
868 [desiredPlatformSubviews addObject:platformViewRoot];
871 auto maybeLayerData = layerMap.find(platformViewId);
872 if (maybeLayerData != layerMap.end()) {
873 auto view = maybeLayerData->second.layer->overlay_view_wrapper;
875 [desiredPlatformSubviews addObject:view];
880 NSSet* desiredPlatformSubviewsSet = [NSSet setWithArray:desiredPlatformSubviews];
881 NSArray* existingPlatformSubviews = [flutterView.subviews
882 filteredArrayUsingPredicate:[NSPredicate
883 predicateWithBlock:^BOOL(id object, NSDictionary* bindings) {
884 return [desiredPlatformSubviewsSet containsObject:object];
891 if (![desiredPlatformSubviews isEqualToArray:existingPlatformSubviews]) {
892 for (UIView* subview in desiredPlatformSubviews) {
894 [flutterView addSubview:subview];
899 - (std::shared_ptr<flutter::OverlayLayer>)nextLayerInPool {
900 return self.layerPool->GetNextLayer();
903 - (void)createLayerWithIosContext:(const std::shared_ptr<
flutter::IOSContext>&)iosContext
904 pixelFormat:(MTLPixelFormat)pixelFormat
905 screenScale:(CGFloat)screenScale {
906 self.layerPool->CreateLayer(iosContext, pixelFormat, screenScale);
909 - (void)removeUnusedLayers:(const std::vector<std::shared_ptr<
flutter::OverlayLayer>>&)unusedLayers
910 withCompositionOrder:(const std::vector<int64_t>&)compositionOrder {
911 for (
const std::shared_ptr<flutter::OverlayLayer>& layer : unusedLayers) {
912 [layer->overlay_view_wrapper removeFromSuperview];
915 std::unordered_set<int64_t> compositionOrderSet;
916 for (int64_t viewId : compositionOrder) {
917 compositionOrderSet.insert(viewId);
920 for (int64_t viewId :
self.previousCompositionOrder) {
921 if (compositionOrderSet.find(viewId) == compositionOrderSet.end()) {
922 UIView* platformViewRoot =
self.platformViews[viewId].root_view;
923 [platformViewRoot removeFromSuperview];
928 - (std::vector<UIView*>)computeViewsToDispose {
929 std::vector<UIView*> views;
930 if (
self.viewsToDispose.empty()) {
934 std::unordered_set<int64_t> viewsToComposite(
self.compositionOrder.begin(),
935 self.compositionOrder.end());
936 std::unordered_set<int64_t> viewsToDelayDispose;
937 for (int64_t viewId :
self.viewsToDispose) {
938 if (viewsToComposite.count(viewId)) {
939 viewsToDelayDispose.insert(viewId);
942 UIView* rootView =
self.platformViews[viewId].root_view;
943 views.push_back(rootView);
944 self.currentCompositionParams.erase(viewId);
945 self.viewsToRecomposite.erase(viewId);
946 self.platformViews.erase(viewId);
948 self.viewsToDispose = std::move(viewsToDelayDispose);
952 - (void)resetFrameState {
954 self.compositionOrder.clear();
955 self.visitedPlatformViews.clear();
958 - (void)pushVisitedPlatformViewId:(int64_t)viewId {
959 self.visitedPlatformViews.push_back(viewId);
962 - (const
flutter::EmbeddedViewParams&)compositionParamsForView:(int64_t)viewId {
963 return self.currentCompositionParams.find(viewId)->second;
966 #pragma mark - Properties
968 - (
flutter::OverlayLayerPool*)layerPool {
969 return _layerPool.get();
972 - (std::unordered_map<int64_t, std::unique_ptr<flutter::EmbedderViewSlice>>&)slices {
976 - (std::unordered_map<std::string, NSObject<FlutterPlatformViewFactory>*>&)factories {
979 - (std::unordered_map<std::string, FlutterPlatformViewGestureRecognizersBlockingPolicy>&)
980 gestureRecognizersBlockingPolicies {
984 - (std::unordered_map<int64_t, PlatformViewData>&)platformViews {
988 - (std::unordered_map<int64_t, flutter::EmbeddedViewParams>&)currentCompositionParams {
992 - (std::unordered_set<int64_t>&)viewsToDispose {
996 - (std::vector<int64_t>&)compositionOrder {
1000 - (std::vector<int64_t>&)visitedPlatformViews {
1004 - (std::unordered_set<int64_t>&)viewsToRecomposite {
1008 - (std::vector<int64_t>&)previousCompositionOrder {