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"
18 using flutter::DlMatrix;
19 using flutter::DlRect;
20 using flutter::DlRoundRect;
28 std::shared_ptr<flutter::OverlayLayer>
layer;
30 using LayersMap = std::unordered_map<int64_t, LayerData>;
37 NSObject<FlutterPlatformView>*
view;
46 CATransform3D transform = CATransform3DIdentity;
47 transform.m11 = matrix.m[0];
48 transform.m12 = matrix.m[1];
49 transform.m13 = matrix.m[2];
50 transform.m14 = matrix.m[3];
52 transform.m21 = matrix.m[4];
53 transform.m22 = matrix.m[5];
54 transform.m23 = matrix.m[6];
55 transform.m24 = matrix.m[7];
57 transform.m31 = matrix.m[8];
58 transform.m32 = matrix.m[9];
59 transform.m33 = matrix.m[10];
60 transform.m34 = matrix.m[11];
62 transform.m41 = matrix.m[12];
63 transform.m42 = matrix.m[13];
64 transform.m43 = matrix.m[14];
65 transform.m44 = matrix.m[15];
74 layer.anchorPoint = CGPointZero;
75 layer.position = CGPointZero;
79 return CGRectMake(clipDlRect.GetLeft(),
81 clipDlRect.GetWidth(),
82 clipDlRect.GetHeight());
94 @property(nonatomic, readonly)
95 std::unordered_map<int64_t, std::unique_ptr<flutter::EmbedderViewSlice>>& slices;
99 @property(nonatomic, readonly)
100 std::unordered_map<std::string, NSObject<FlutterPlatformViewFactory>*>& factories;
103 @property(nonatomic, readonly)
104 std::unordered_map<std::string, FlutterPlatformViewGestureRecognizersBlockingPolicy>&
105 gestureRecognizersBlockingPolicies;
108 @property(nonatomic, assign) SkISize frameSize;
111 @property(nonatomic, readonly)
const fml::RefPtr<fml::TaskRunner>& platformTaskRunner;
114 @property(nonatomic, readonly) std::unordered_map<int64_t, PlatformViewData>& platformViews;
119 @property(nonatomic, readonly)
120 std::unordered_map<int64_t, flutter::EmbeddedViewParams>& currentCompositionParams;
126 @property(nonatomic, readonly) std::unordered_set<int64_t>& viewsToDispose;
131 @property(nonatomic, readonly) std::vector<int64_t>& compositionOrder;
136 @property(nonatomic, readonly) std::vector<int64_t>& visitedPlatformViews;
141 @property(nonatomic, readonly) std::unordered_set<int64_t>& viewsToRecomposite;
155 @property(nonatomic, assign) BOOL hadPlatformViews;
160 @property(nonatomic, assign) BOOL canApplyBlurBackdrop;
165 - (void)createMissingOverlays:(
size_t)requiredOverlayLayers
166 withIosContext:(const std::shared_ptr<
flutter::IOSContext>&)iosContext;
169 - (void)performSubmit:(const
LayersMap&)platformViewLayers
170 currentCompositionParams:
171 (std::unordered_map<int64_t,
flutter::EmbeddedViewParams>&)currentCompositionParams
172 viewsToRecomposite:(const std::unordered_set<int64_t>&)viewsToRecomposite
173 compositionOrder:(const std::vector<int64_t>&)compositionOrder
175 (const std::vector<std::shared_ptr<
flutter::OverlayLayer>>&)unusedLayers
177 (const std::vector<std::unique_ptr<
flutter::SurfaceFrame>>&)surfaceFrames;
184 - (void)clipViewSetMaskView:(UIView*)clipView;
198 - (void)applyMutators:(const
flutter::MutatorsStack&)mutatorsStack
199 embeddedView:(UIView*)embeddedView
200 boundingRect:(const SkRect&)boundingRect;
204 - (void)bringLayersIntoView:(const
LayersMap&)layerMap
205 withCompositionOrder:(const std::vector<int64_t>&)compositionOrder;
207 - (std::shared_ptr<flutter::OverlayLayer>)nextLayerInPool;
210 - (void)createLayerWithIosContext:(const std::shared_ptr<
flutter::IOSContext>&)iosContext
211 pixelFormat:(MTLPixelFormat)pixelFormat;
215 - (void)removeUnusedLayers:(const std::vector<std::shared_ptr<
flutter::OverlayLayer>>&)unusedLayers
216 withCompositionOrder:(const std::vector<int64_t>&)compositionOrder;
222 - (std::vector<UIView*>)computeViewsToDispose;
225 - (void)resetFrameState;
236 std::unique_ptr<flutter::OverlayLayerPool> _layerPool;
237 std::unordered_map<int64_t, std::unique_ptr<flutter::EmbedderViewSlice>>
_slices;
238 std::unordered_map<std::string, NSObject<FlutterPlatformViewFactory>*>
_factories;
239 std::unordered_map<std::string, FlutterPlatformViewGestureRecognizersBlockingPolicy>
252 if (
self = [super init]) {
253 _layerPool = std::make_unique<flutter::OverlayLayerPool>();
256 _hadPlatformViews = NO;
257 _canApplyBlurBackdrop = YES;
262 - (const
fml::RefPtr<fml::TaskRunner>&)taskRunner {
266 - (void)setTaskRunner:(const
fml::RefPtr<
fml::TaskRunner>&)platformTaskRunner {
271 if ([[call method] isEqualToString:
@"create"]) {
272 [
self onCreate:call result:result];
273 }
else if ([[call method] isEqualToString:
@"dispose"]) {
274 [
self onDispose:call result:result];
275 }
else if ([[call method] isEqualToString:
@"acceptGesture"]) {
276 [
self onAcceptGesture:call result:result];
277 }
else if ([[call method] isEqualToString:
@"rejectGesture"]) {
278 [
self onRejectGesture:call result:result];
285 NSDictionary<NSString*, id>* args = [call
arguments];
287 int64_t viewId = [args[@"id"] longLongValue];
288 NSString* viewTypeString = args[@"viewType"];
289 std::string viewType(viewTypeString.UTF8String);
291 if (
self.platformViews.count(viewId) != 0) {
293 message:
@"trying to create an already created view"
294 details:[NSString stringWithFormat:
@"view id: '%lld'", viewId]]);
298 NSObject<FlutterPlatformViewFactory>* factory =
self.factories[viewType];
299 if (factory == nil) {
301 errorWithCode:
@"unregistered_view_type"
302 message:[NSString stringWithFormat:
@"A UIKitView widget is trying to create a "
303 @"PlatformView with an unregistered type: < %@ >",
305 details:
@"If you are the author of the PlatformView, make sure `registerViewFactory` "
308 @"https://docs.flutter.cn/development/platform-integration/"
309 @"platform-views#on-the-platform-side-1 for more details.\n"
310 @"If you are not the author of the PlatformView, make sure to call "
311 @"`GeneratedPluginRegistrant.register`."]);
316 if ([factory respondsToSelector:
@selector(createArgsCodec)]) {
317 NSObject<FlutterMessageCodec>* codec = [factory createArgsCodec];
318 if (codec != nil && args[
@"params"] != nil) {
320 params = [codec decode:paramsData.data];
324 NSObject<FlutterPlatformView>* embeddedView = [factory createWithFrame:CGRectZero
325 viewIdentifier:viewId
327 UIView* platformView = [embeddedView view];
329 platformView.accessibilityIdentifier = [NSString stringWithFormat:@"platform_view[%lld]", viewId];
332 initWithEmbeddedView:platformView
333 platformViewsController:self
334 gestureRecognizersBlockingPolicy:self.gestureRecognizersBlockingPolicies[viewType]];
337 [clippingView addSubview:touchInterceptor];
340 .
view = embeddedView,
341 .touch_interceptor = touchInterceptor,
342 .root_view = clippingView
350 int64_t viewId = [arg longLongValue];
352 if (
self.platformViews.count(viewId) == 0) {
354 message:
@"trying to dispose an unknown"
355 details:[NSString stringWithFormat:
@"view id: '%lld'", viewId]]);
359 self.viewsToDispose.insert(viewId);
364 NSDictionary<NSString*, id>* args = [call
arguments];
365 int64_t viewId = [args[@"id"] longLongValue];
367 if (
self.platformViews.count(viewId) == 0) {
369 message:
@"trying to set gesture state for an unknown view"
370 details:[NSString stringWithFormat:
@"view id: '%lld'", viewId]]);
381 NSDictionary<NSString*, id>* args = [call
arguments];
382 int64_t viewId = [args[@"id"] longLongValue];
384 if (
self.platformViews.count(viewId) == 0) {
386 message:
@"trying to set gesture state for an unknown view"
387 details:[NSString stringWithFormat:
@"view id: '%lld'", viewId]]);
398 withId:(NSString*)factoryId
399 gestureRecognizersBlockingPolicy:
401 std::string idString([factoryId UTF8String]);
402 FML_CHECK(
self.factories.count(idString) == 0);
403 self.factories[idString] = factory;
404 self.gestureRecognizersBlockingPolicies[idString] = gestureRecognizerBlockingPolicy;
407 - (void)beginFrameWithSize:(SkISize)frameSize {
408 [
self resetFrameState];
409 self.frameSize = frameSize;
412 - (void)cancelFrame {
413 [
self resetFrameState];
416 - (
flutter::PostPrerollResult)postPrerollActionWithThreadMerger:
417 (const
fml::RefPtr<
fml::RasterThreadMerger>&)rasterThreadMerger {
418 return flutter::PostPrerollResult::kSuccess;
421 - (void)endFrameWithResubmit:(BOOL)shouldResubmitFrame
422 threadMerger:(const
fml::RefPtr<
fml::RasterThreadMerger>&)rasterThreadMerger {
425 - (void)pushFilterToVisitedPlatformViews:(const std::shared_ptr<
flutter::DlImageFilter>&)filter
426 withRect:(const SkRect&)filterRect {
427 for (int64_t
id :
self.visitedPlatformViews) {
428 flutter::EmbeddedViewParams params =
self.currentCompositionParams[id];
429 params.PushImageFilter(filter, filterRect);
430 self.currentCompositionParams[id] = params;
434 - (void)prerollCompositeEmbeddedView:(int64_t)viewId
435 withParams:(std::unique_ptr<
flutter::EmbeddedViewParams>)params {
436 SkRect viewBounds = SkRect::Make(
self.frameSize);
437 std::unique_ptr<flutter::EmbedderViewSlice> view;
438 view = std::make_unique<flutter::DisplayListEmbedderViewSlice>(viewBounds);
439 self.slices.insert_or_assign(viewId, std::move(view));
441 self.compositionOrder.push_back(viewId);
443 if (
self.currentCompositionParams.count(viewId) == 1 &&
444 self.currentCompositionParams[viewId] == *params.get()) {
448 self.currentCompositionParams[viewId] = flutter::EmbeddedViewParams(*params.get());
449 self.viewsToRecomposite.insert(viewId);
452 - (size_t)embeddedViewCount {
453 return self.compositionOrder.size();
456 - (UIView*)platformViewForId:(int64_t)viewId {
457 return [
self flutterTouchInterceptingViewForId:viewId].embeddedView;
461 if (
self.platformViews.empty()) {
464 return self.platformViews[viewId].touch_interceptor;
467 - (long)firstResponderPlatformViewId {
468 for (
auto const& [
id, platformViewData] :
self.platformViews) {
469 UIView* rootView = platformViewData.root_view;
470 if (rootView.flt_hasFirstResponderInViewHierarchySubtree) {
477 - (void)clipViewSetMaskView:(UIView*)clipView {
478 FML_DCHECK([[NSThread currentThread] isMainThread]);
479 if (clipView.maskView) {
483 CGRectMake(-clipView.frame.origin.x, -clipView.frame.origin.y,
484 CGRectGetWidth(
self.flutterView.bounds), CGRectGetHeight(
self.flutterView.bounds));
485 clipView.maskView = [
self.maskViewPool getMaskViewWithFrame:frame];
488 - (void)applyMutators:(const
flutter::MutatorsStack&)mutatorsStack
489 embeddedView:(UIView*)embeddedView
490 boundingRect:(const SkRect&)boundingRect {
491 if (
self.flutterView == nil) {
498 DlMatrix transformMatrix;
499 const DlRect& dlBoundingRect = flutter::ToDlRect(boundingRect);
500 NSMutableArray* blurFilters = [[NSMutableArray alloc] init];
501 FML_DCHECK(!clipView.maskView ||
503 if (clipView.maskView) {
504 [
self.maskViewPool insertViewToPoolIfNeeded:(FlutterClippingMaskView*)(clipView.maskView)];
505 clipView.maskView = nil;
507 CGFloat screenScale = [UIScreen mainScreen].scale;
508 auto iter = mutatorsStack.Begin();
509 while (iter != mutatorsStack.End()) {
510 switch ((*iter)->GetType()) {
511 case flutter::MutatorType::kTransform: {
512 transformMatrix = transformMatrix * (*iter)->GetMatrix();
515 case flutter::MutatorType::kClipRect: {
516 if (flutter::DisplayListMatrixClipState::TransformedRectCoversBounds(
517 (*iter)->GetRect(), transformMatrix, dlBoundingRect)) {
520 [
self clipViewSetMaskView:clipView];
522 matrix:transformMatrix];
525 case flutter::MutatorType::kClipRRect: {
526 if (flutter::DisplayListMatrixClipState::TransformedRRectCoversBounds(
527 (*iter)->GetRRect(), transformMatrix, dlBoundingRect)) {
530 [
self clipViewSetMaskView:clipView];
532 matrix:transformMatrix];
535 case flutter::MutatorType::kClipRSE: {
536 if (flutter::DisplayListMatrixClipState::TransformedRoundSuperellipseCoversBounds(
537 (*iter)->GetRSE(), transformMatrix, dlBoundingRect)) {
540 [
self clipViewSetMaskView:clipView];
542 matrix:transformMatrix];
545 case flutter::MutatorType::kClipPath: {
549 [
self clipViewSetMaskView:clipView];
551 matrix:transformMatrix];
554 case flutter::MutatorType::kOpacity:
555 embeddedView.alpha = (*iter)->GetAlphaFloat() * embeddedView.alpha;
557 case flutter::MutatorType::kBackdropFilter: {
559 if (!
self.canApplyBlurBackdrop || !(*iter)->GetFilterMutation().GetFilter().asBlur()) {
564 filterRect = CGRectApplyAffineTransform(
565 filterRect, CGAffineTransformMakeScale(1 / screenScale, 1 / screenScale));
569 if (CGRectIsNull(CGRectIntersection(filterRect, clipView.frame))) {
572 CGRect intersection = CGRectIntersection(filterRect, clipView.frame);
573 CGRect frameInClipView = [
self.flutterView convertRect:intersection toView:clipView];
578 CGFloat blurRadius = (*iter)->GetFilterMutation().GetFilter().asBlur()->sigma_x();
579 UIVisualEffectView* visualEffectView = [[UIVisualEffectView alloc]
580 initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]];
582 blurRadius:blurRadius
583 visualEffectView:visualEffectView];
585 self.canApplyBlurBackdrop = NO;
587 [blurFilters addObject:filter];
595 if (
self.canApplyBlurBackdrop) {
604 flutter::DlScalar pointScale = 1.0 / screenScale;
605 transformMatrix = DlMatrix::MakeScale({pointScale, pointScale, 1}) * transformMatrix;
614 impeller::Vector3 origin = impeller::Vector3(clipView.frame.origin.x, clipView.frame.origin.y);
615 transformMatrix = DlMatrix::MakeTranslation(-origin) * transformMatrix;
620 - (void)compositeView:(int64_t)viewId withParams:(const
flutter::EmbeddedViewParams&)params {
622 CGRect frame = CGRectMake(0, 0, params.sizePoints().width(), params.sizePoints().height());
624 touchInterceptor.layer.transform = CATransform3DIdentity;
625 touchInterceptor.frame = frame;
626 touchInterceptor.alpha = 1;
628 const flutter::MutatorsStack& mutatorStack = params.mutatorsStack();
629 UIView* clippingView =
self.platformViews[viewId].root_view;
634 const SkRect& rect = params.finalBoundingRect();
635 CGFloat screenScale = [UIScreen mainScreen].scale;
636 clippingView.frame = CGRectMake(rect.x() / screenScale, rect.y() / screenScale,
637 rect.width() / screenScale, rect.height() / screenScale);
638 [
self applyMutators:mutatorStack embeddedView:touchInterceptor boundingRect:rect];
641 - (
flutter::DlCanvas*)compositeEmbeddedViewWithId:(int64_t)viewId {
642 FML_DCHECK(
self.slices.find(viewId) !=
self.slices.end());
643 return self.slices[viewId]->canvas();
650 fml::TaskRunner::RunNowOrPostTask(
self.platformTaskRunner, [
self]() {
651 for (int64_t viewId :
self.compositionOrder) {
652 [
self.platformViews[viewId].root_view removeFromSuperview];
654 self.platformViews.clear();
655 self.previousCompositionOrder.clear();
658 self.compositionOrder.clear();
660 self.currentCompositionParams.clear();
661 self.viewsToRecomposite.clear();
662 self.layerPool->RecycleLayers();
663 self.visitedPlatformViews.clear();
666 - (BOOL)submitFrame:(std::unique_ptr<
flutter::SurfaceFrame>)background_frame
667 withIosContext:(const std::shared_ptr<
flutter::IOSContext>&)iosContext {
668 TRACE_EVENT0(
"flutter",
"PlatformViewsController::SubmitFrame");
671 if (
self.flutterView == nil || (
self.compositionOrder.empty() && !
self.hadPlatformViews)) {
672 self.hadPlatformViews = NO;
673 return background_frame->Submit();
675 self.hadPlatformViews = !
self.compositionOrder.empty();
677 bool didEncode =
true;
679 std::vector<std::unique_ptr<flutter::SurfaceFrame>> surfaceFrames;
680 surfaceFrames.reserve(
self.compositionOrder.size());
681 std::unordered_map<int64_t, SkRect> viewRects;
683 for (int64_t viewId :
self.compositionOrder) {
684 viewRects[viewId] =
self.currentCompositionParams[viewId].finalBoundingRect();
687 std::unordered_map<int64_t, SkRect> overlayLayers =
688 SliceViews(background_frame->Canvas(),
self.compositionOrder,
self.slices, viewRects);
690 size_t requiredOverlayLayers = 0;
691 for (int64_t viewId :
self.compositionOrder) {
692 std::unordered_map<int64_t, SkRect>::const_iterator overlay = overlayLayers.find(viewId);
693 if (overlay == overlayLayers.end()) {
696 requiredOverlayLayers++;
702 [
self createMissingOverlays:requiredOverlayLayers withIosContext:iosContext];
704 int64_t overlayId = 0;
705 for (int64_t viewId :
self.compositionOrder) {
706 std::unordered_map<int64_t, SkRect>::const_iterator overlay = overlayLayers.find(viewId);
707 if (overlay == overlayLayers.end()) {
710 std::shared_ptr<flutter::OverlayLayer> layer =
self.nextLayerInPool;
715 std::unique_ptr<flutter::SurfaceFrame> frame = layer->surface->AcquireFrame(
self.frameSize);
720 flutter::DlCanvas* overlayCanvas = frame->Canvas();
721 int restoreCount = overlayCanvas->GetSaveCount();
722 overlayCanvas->Save();
723 overlayCanvas->ClipRect(flutter::ToDlRect(overlay->second));
724 overlayCanvas->Clear(flutter::DlColor::kTransparent());
725 self.slices[viewId]->render_into(overlayCanvas);
726 overlayCanvas->RestoreToCount(restoreCount);
730 frame->set_submit_info({.frame_boundary =
false, .present_with_transaction =
true});
731 layer->did_submit_last_frame = frame->Encode();
733 didEncode &= layer->did_submit_last_frame;
735 .
rect = overlay->second,
737 .overlay_id = overlayId,
740 surfaceFrames.push_back(std::move(frame));
744 auto previousSubmitInfo = background_frame->submit_info();
745 background_frame->set_submit_info({
746 .frame_damage = previousSubmitInfo.frame_damage,
747 .buffer_damage = previousSubmitInfo.buffer_damage,
748 .present_with_transaction =
true,
750 background_frame->Encode();
751 surfaceFrames.push_back(std::move(background_frame));
754 std::vector<std::shared_ptr<flutter::OverlayLayer>> unusedLayers =
755 self.layerPool->RemoveUnusedLayers();
756 self.layerPool->RecycleLayers();
759 platformViewLayers = std::move(platformViewLayers),
760 currentCompositionParams = self.currentCompositionParams,
761 viewsToRecomposite = self.viewsToRecomposite,
762 compositionOrder = self.compositionOrder,
763 unusedLayers = std::move(unusedLayers),
764 surfaceFrames = std::move(surfaceFrames)
766 [
self performSubmit:platformViewLayers
767 currentCompositionParams:currentCompositionParams
768 viewsToRecomposite:viewsToRecomposite
769 compositionOrder:compositionOrder
770 unusedLayers:unusedLayers
771 surfaceFrames:surfaceFrames];
774 fml::TaskRunner::RunNowOrPostTask(
self.platformTaskRunner, fml::MakeCopyable(std::move(task)));
779 - (void)createMissingOverlays:(
size_t)requiredOverlayLayers
780 withIosContext:(const std::shared_ptr<
flutter::IOSContext>&)iosContext {
781 TRACE_EVENT0(
"flutter",
"PlatformViewsController::CreateMissingLayers");
783 if (requiredOverlayLayers <= self.layerPool->size()) {
786 auto missingLayerCount = requiredOverlayLayers -
self.layerPool->size();
790 auto latch = std::make_shared<fml::CountDownLatch>(1u);
791 fml::TaskRunner::RunNowOrPostTask(
792 self.platformTaskRunner, [
self, missingLayerCount, iosContext, latch]() {
793 for (
auto i = 0u; i < missingLayerCount; i++) {
794 [
self createLayerWithIosContext:iosContext
795 pixelFormat:((FlutterView*)self.flutterView).pixelFormat];
799 if (![[NSThread currentThread] isMainThread]) {
804 - (void)performSubmit:(const
LayersMap&)platformViewLayers
805 currentCompositionParams:
806 (std::unordered_map<int64_t,
flutter::EmbeddedViewParams>&)currentCompositionParams
807 viewsToRecomposite:(const std::unordered_set<int64_t>&)viewsToRecomposite
808 compositionOrder:(const std::vector<int64_t>&)compositionOrder
810 (const std::vector<std::shared_ptr<
flutter::OverlayLayer>>&)unusedLayers
812 (const std::vector<std::unique_ptr<
flutter::SurfaceFrame>>&)surfaceFrames {
813 TRACE_EVENT0(
"flutter",
"PlatformViewsController::PerformSubmit");
814 FML_DCHECK([[NSThread currentThread] isMainThread]);
816 [CATransaction begin];
819 for (
const auto& [viewId, layerData] : platformViewLayers) {
820 layerData.layer->UpdateViewState(
self.flutterView,
828 for (
auto& view : [
self computeViewsToDispose]) {
829 [view removeFromSuperview];
833 for (int64_t viewId : viewsToRecomposite) {
834 [
self compositeView:viewId withParams:currentCompositionParams[viewId]];
838 for (
const auto& frame : surfaceFrames) {
844 [
self removeUnusedLayers:unusedLayers withCompositionOrder:compositionOrder];
847 [
self bringLayersIntoView:platformViewLayers withCompositionOrder:compositionOrder];
849 [CATransaction commit];
852 - (void)bringLayersIntoView:(const
LayersMap&)layerMap
853 withCompositionOrder:(const std::vector<int64_t>&)compositionOrder {
854 FML_DCHECK(
self.flutterView);
855 UIView* flutterView =
self.flutterView;
857 self.previousCompositionOrder.clear();
858 NSMutableArray* desiredPlatformSubviews = [NSMutableArray array];
859 for (int64_t platformViewId : compositionOrder) {
860 self.previousCompositionOrder.push_back(platformViewId);
861 UIView* platformViewRoot =
self.platformViews[platformViewId].root_view;
862 if (platformViewRoot != nil) {
863 [desiredPlatformSubviews addObject:platformViewRoot];
866 auto maybeLayerData = layerMap.find(platformViewId);
867 if (maybeLayerData != layerMap.end()) {
868 auto view = maybeLayerData->second.layer->overlay_view_wrapper;
870 [desiredPlatformSubviews addObject:view];
875 NSSet* desiredPlatformSubviewsSet = [NSSet setWithArray:desiredPlatformSubviews];
876 NSArray* existingPlatformSubviews = [flutterView.subviews
877 filteredArrayUsingPredicate:[NSPredicate
878 predicateWithBlock:^BOOL(id object, NSDictionary* bindings) {
879 return [desiredPlatformSubviewsSet containsObject:object];
886 if (![desiredPlatformSubviews isEqualToArray:existingPlatformSubviews]) {
887 for (UIView* subview in desiredPlatformSubviews) {
889 [flutterView addSubview:subview];
894 - (std::shared_ptr<flutter::OverlayLayer>)nextLayerInPool {
895 return self.layerPool->GetNextLayer();
898 - (void)createLayerWithIosContext:(const std::shared_ptr<
flutter::IOSContext>&)iosContext
899 pixelFormat:(MTLPixelFormat)pixelFormat {
900 self.layerPool->CreateLayer(iosContext, pixelFormat);
903 - (void)removeUnusedLayers:(const std::vector<std::shared_ptr<
flutter::OverlayLayer>>&)unusedLayers
904 withCompositionOrder:(const std::vector<int64_t>&)compositionOrder {
905 for (
const std::shared_ptr<flutter::OverlayLayer>& layer : unusedLayers) {
906 [layer->overlay_view_wrapper removeFromSuperview];
909 std::unordered_set<int64_t> compositionOrderSet;
910 for (int64_t viewId : compositionOrder) {
911 compositionOrderSet.insert(viewId);
914 for (int64_t viewId :
self.previousCompositionOrder) {
915 if (compositionOrderSet.find(viewId) == compositionOrderSet.end()) {
916 UIView* platformViewRoot =
self.platformViews[viewId].root_view;
917 [platformViewRoot removeFromSuperview];
922 - (std::vector<UIView*>)computeViewsToDispose {
923 std::vector<UIView*> views;
924 if (
self.viewsToDispose.empty()) {
928 std::unordered_set<int64_t> viewsToComposite(
self.compositionOrder.begin(),
929 self.compositionOrder.end());
930 std::unordered_set<int64_t> viewsToDelayDispose;
931 for (int64_t viewId :
self.viewsToDispose) {
932 if (viewsToComposite.count(viewId)) {
933 viewsToDelayDispose.insert(viewId);
936 UIView* rootView =
self.platformViews[viewId].root_view;
937 views.push_back(rootView);
938 self.currentCompositionParams.erase(viewId);
939 self.viewsToRecomposite.erase(viewId);
940 self.platformViews.erase(viewId);
942 self.viewsToDispose = std::move(viewsToDelayDispose);
946 - (void)resetFrameState {
948 self.compositionOrder.clear();
949 self.visitedPlatformViews.clear();
952 - (void)pushVisitedPlatformViewId:(int64_t)viewId {
953 self.visitedPlatformViews.push_back(viewId);
956 - (const
flutter::EmbeddedViewParams&)compositionParamsForView:(int64_t)viewId {
957 return self.currentCompositionParams.find(viewId)->second;
960 #pragma mark - Properties
962 - (
flutter::OverlayLayerPool*)layerPool {
963 return _layerPool.get();
966 - (std::unordered_map<int64_t, std::unique_ptr<flutter::EmbedderViewSlice>>&)slices {
970 - (std::unordered_map<std::string, NSObject<FlutterPlatformViewFactory>*>&)factories {
973 - (std::unordered_map<std::string, FlutterPlatformViewGestureRecognizersBlockingPolicy>&)
974 gestureRecognizersBlockingPolicies {
978 - (std::unordered_map<int64_t, PlatformViewData>&)platformViews {
982 - (std::unordered_map<int64_t, flutter::EmbeddedViewParams>&)currentCompositionParams {
986 - (std::unordered_set<int64_t>&)viewsToDispose {
990 - (std::vector<int64_t>&)compositionOrder {
994 - (std::vector<int64_t>&)visitedPlatformViews {
998 - (std::unordered_set<int64_t>&)viewsToRecomposite {
1002 - (std::vector<int64_t>&)previousCompositionOrder {
void(^ FlutterResult)(id _Nullable result)
FLUTTER_DARWIN_EXPORT NSObject const * FlutterMethodNotImplemented
FlutterPlatformViewGestureRecognizersBlockingPolicy
void applyBlurBackdropFilters:(NSArray< PlatformViewFilter * > *filters)
Storage for Overlay layers across frames.
std::shared_ptr< flutter::OverlayLayer > layer