5 #include "display_list/geometry/dl_geometry_types.h"
8 #import <OCMock/OCMock.h>
9 #import <UIKit/UIKit.h>
10 #import <WebKit/WebKit.h>
11 #import <XCTest/XCTest.h>
15 #include "flutter/display_list/effects/dl_image_filters.h"
16 #include "flutter/fml/synchronization/count_down_latch.h"
17 #include "flutter/fml/thread.h"
42 - (instancetype)init {
62 @property(nonatomic, strong) NSMutableArray<NSNumber*>* toggleHistory;
66 - (instancetype)init {
69 _toggleHistory = [NSMutableArray array];
73 - (void)setEnabled:(BOOL)enabled {
74 [
super setEnabled:enabled];
75 [
self.toggleHistory addObject:@(enabled)];
87 @property(nonatomic, strong) UIView* view;
88 @property(nonatomic, assign) BOOL viewCreated;
93 - (instancetype)init {
94 if (
self = [super init]) {
102 [
self checkViewCreatedOnce];
106 - (void)checkViewCreatedOnce {
110 self.viewCreated = YES;
119 : NSObject <FlutterPlatformViewFactory>
124 viewIdentifier:(int64_t)viewId
125 arguments:(
id _Nullable)args {
132 @property(nonatomic, strong) UIView* view;
133 @property(nonatomic, assign) BOOL viewCreated;
137 - (instancetype)init {
138 if (
self = [super init]) {
139 _view = [[WKWebView alloc] init];
147 [
self checkViewCreatedOnce];
151 - (void)checkViewCreatedOnce {
155 self.viewCreated = YES;
167 - (NSObject<FlutterPlatformView>*)createWithFrame:(CGRect)frame
168 viewIdentifier:(int64_t)viewId
169 arguments:(
id _Nullable)args {
178 - (NSObject<FlutterPlatformView>*)createWithFrame:(CGRect)frame
179 viewIdentifier:(int64_t)viewId
180 arguments:(
id _Nullable)args {
187 @property(nonatomic, strong) UIView* view;
188 @property(nonatomic, assign) BOOL viewCreated;
192 - (instancetype)init {
193 if (
self = [super init]) {
194 _view = [[UIView alloc] init];
195 [_view addSubview:[[WKWebView alloc] init]];
203 [
self checkViewCreatedOnce];
207 - (void)checkViewCreatedOnce {
211 self.viewCreated = YES;
223 - (NSObject<FlutterPlatformView>*)createWithFrame:(CGRect)frame
224 viewIdentifier:(int64_t)viewId
225 arguments:(
id _Nullable)args {
231 @property(nonatomic, strong) UIView* view;
232 @property(nonatomic, assign) BOOL viewCreated;
236 - (instancetype)init {
237 if (
self = [super init]) {
238 _view = [[UIView alloc] init];
239 UIView* childView = [[UIView alloc] init];
240 [_view addSubview:childView];
241 [childView addSubview:[[WKWebView alloc] init]];
249 [
self checkViewCreatedOnce];
253 - (void)checkViewCreatedOnce {
257 self.viewCreated = YES;
262 : NSObject <FlutterPlatformViewFactory>
267 viewIdentifier:(int64_t)viewId
268 arguments:(
id _Nullable)args {
275 class FlutterPlatformViewsTestMockPlatformViewDelegate :
public PlatformView::Delegate {
277 void OnPlatformViewCreated(std::unique_ptr<Surface> surface)
override {}
278 void OnPlatformViewDestroyed()
override {}
279 void OnPlatformViewScheduleFrame()
override {}
280 void OnPlatformViewAddView(int64_t view_id,
281 const ViewportMetrics& viewport_metrics,
282 AddViewCallback callback)
override {}
283 void OnPlatformViewRemoveView(int64_t view_id, RemoveViewCallback callback)
override {}
284 void OnPlatformViewSendViewFocusEvent(
const ViewFocusEvent& event)
override {};
285 void OnPlatformViewSetNextFrameCallback(
const fml::closure& closure)
override {}
286 void OnPlatformViewSetViewportMetrics(int64_t view_id,
const ViewportMetrics& metrics)
override {}
287 const flutter::Settings& OnPlatformViewGetSettings()
const override {
return settings_; }
288 void OnPlatformViewDispatchPlatformMessage(std::unique_ptr<PlatformMessage> message)
override {}
289 void OnPlatformViewDispatchPointerDataPacket(std::unique_ptr<PointerDataPacket> packet)
override {
291 HitTestResponse OnPlatformViewHitTest(int64_t view_id,
const flutter::PointData offset)
override {
292 return {.has_platform_view =
false};
294 void OnPlatformViewDispatchSemanticsAction(int64_t view_id,
296 SemanticsAction action,
297 fml::MallocMapping args)
override {}
298 void OnPlatformViewSetSemanticsEnabled(
bool enabled)
override {}
299 void OnPlatformViewSetAccessibilityFeatures(int32_t flags)
override {}
300 void OnPlatformViewRegisterTexture(std::shared_ptr<Texture> texture)
override {}
301 void OnPlatformViewUnregisterTexture(int64_t
texture_id)
override {}
302 void OnPlatformViewMarkTextureFrameAvailable(int64_t
texture_id)
override {}
304 void LoadDartDeferredLibrary(intptr_t loading_unit_id,
305 std::unique_ptr<const fml::Mapping> snapshot_data,
306 std::unique_ptr<const fml::Mapping> snapshot_instructions)
override {
308 void LoadDartDeferredLibraryError(intptr_t loading_unit_id,
309 const std::string error_message,
310 bool transient)
override {}
311 void UpdateAssetResolverByType(std::unique_ptr<flutter::AssetResolver> updated_asset_resolver,
312 flutter::AssetResolver::AssetResolverType type)
override {}
317 BOOL BlurRadiusEqualToBlurRadius(CGFloat radius1, CGFloat radius2) {
318 const CGFloat epsilon = 0.01;
319 return std::abs(radius1 - radius2) < epsilon;
338 view = view.superview;
345 static UIGestureRecognizer* FindForwardingGestureRecognizer(UIView* view) {
346 for (UIGestureRecognizer* gestureRecognizer in view.gestureRecognizers) {
348 return gestureRecognizer;
354 - (void)testFlutterViewOnlyCreateOnceInOneFrame {
355 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
360 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
363 flutterPlatformViewsController,
366 std::make_shared<fml::SyncSwitch>());
370 [flutterPlatformViewsController
372 withId:@"MockFlutterPlatformView"
376 [flutterPlatformViewsController
380 @"viewType" : @"MockFlutterPlatformView",
381 @"gestureBlockingPolicy" : @"eager"
384 UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)];
385 flutterPlatformViewsController.
flutterView = flutterView;
387 flutter::MutatorsStack stack;
389 flutter::DlScalar screenScale = [UIScreen mainScreen].scale;
390 flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
391 stack.PushTransform(screenScaleMatrix);
393 flutter::DlMatrix translateMatrix = flutter::DlMatrix::MakeTranslation({100, 100});
394 stack.PushTransform(translateMatrix);
395 flutter::DlMatrix finalMatrix = screenScaleMatrix * translateMatrix;
397 auto embeddedViewParams =
398 std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, flutter::DlSize(300, 300), stack);
400 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
401 withParams:std::move(embeddedViewParams)];
405 [flutterPlatformViewsController
reset];
408 - (void)testCanCreatePlatformViewWithoutFlutterView {
409 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
414 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
417 flutterPlatformViewsController,
420 std::make_shared<fml::SyncSwitch>());
424 [flutterPlatformViewsController
426 withId:@"MockFlutterPlatformView"
430 [flutterPlatformViewsController
434 @"viewType" : @"MockFlutterPlatformView",
435 @"gestureBlockingPolicy" : @"eager"
442 - (void)testChildClippingViewHitTests {
445 UIView* childView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
446 [childClippingView addSubview:childView];
448 XCTAssertFalse([childClippingView pointInside:CGPointMake(50, 50) withEvent:nil]);
449 XCTAssertFalse([childClippingView pointInside:CGPointMake(99, 100) withEvent:nil]);
450 XCTAssertFalse([childClippingView pointInside:CGPointMake(100, 99) withEvent:nil]);
451 XCTAssertFalse([childClippingView pointInside:CGPointMake(201, 200) withEvent:nil]);
452 XCTAssertFalse([childClippingView pointInside:CGPointMake(200, 201) withEvent:nil]);
453 XCTAssertFalse([childClippingView pointInside:CGPointMake(99, 200) withEvent:nil]);
454 XCTAssertFalse([childClippingView pointInside:CGPointMake(200, 299) withEvent:nil]);
456 XCTAssertTrue([childClippingView pointInside:CGPointMake(150, 150) withEvent:nil]);
457 XCTAssertTrue([childClippingView pointInside:CGPointMake(100, 100) withEvent:nil]);
458 XCTAssertTrue([childClippingView pointInside:CGPointMake(199, 100) withEvent:nil]);
459 XCTAssertTrue([childClippingView pointInside:CGPointMake(100, 199) withEvent:nil]);
460 XCTAssertTrue([childClippingView pointInside:CGPointMake(199, 199) withEvent:nil]);
463 - (void)testReleasesBackdropFilterSubviewsOnChildClippingViewDealloc {
464 __weak NSMutableArray<UIVisualEffectView*>* weakBackdropFilterSubviews = nil;
465 __weak UIVisualEffectView* weakVisualEffectView1 = nil;
466 __weak UIVisualEffectView* weakVisualEffectView2 = nil;
470 UIVisualEffectView* visualEffectView1 = [[UIVisualEffectView alloc]
471 initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]];
472 weakVisualEffectView1 = visualEffectView1;
477 isRoundedSuperellipse:NO
478 visualEffectView:visualEffectView1];
483 UIVisualEffectView* visualEffectView2 = [[UIVisualEffectView alloc]
484 initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleDark]];
485 weakVisualEffectView2 = visualEffectView2;
490 isRoundedSuperellipse:NO
491 visualEffectView:visualEffectView2];
495 XCTAssertNotNil(weakBackdropFilterSubviews);
498 XCTAssertNil(weakBackdropFilterSubviews);
499 XCTAssertNil(weakVisualEffectView1);
500 XCTAssertNil(weakVisualEffectView2);
503 - (void)testApplyBackdropFilter {
504 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
509 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
512 flutterPlatformViewsController,
515 std::make_shared<fml::SyncSwitch>());
519 [flutterPlatformViewsController
521 withId:@"MockFlutterPlatformView"
525 [flutterPlatformViewsController
529 @"viewType" : @"MockFlutterPlatformView",
530 @"gestureBlockingPolicy" : @"eager"
536 UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
537 flutterPlatformViewsController.
flutterView = flutterView;
539 flutter::MutatorsStack stack;
541 flutter::DlScalar screenScale = [UIScreen mainScreen].scale;
542 flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
543 stack.PushTransform(screenScaleMatrix);
545 auto filter = flutter::DlBlurImageFilter::Make(5, 2, flutter::DlTileMode::kClamp);
546 stack.PushBackdropFilter(filter,
547 flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
549 auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
550 screenScaleMatrix, flutter::DlSize(10, 10), stack);
552 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
553 withParams:std::move(embeddedViewParams)];
554 [flutterPlatformViewsController
560 [flutterView addSubview:childClippingView];
562 [flutterView setNeedsLayout];
563 [flutterView layoutIfNeeded];
566 NSUInteger numberOfExpectedVisualEffectView = 0;
567 for (UIView* subview in childClippingView.subviews) {
568 if (![subview isKindOfClass:[UIVisualEffectView
class]]) {
571 XCTAssertLessThan(numberOfExpectedVisualEffectView, 1u);
572 if ([
self validateOneVisualEffectView:subview
573 expectedFrame:CGRectMake(0, 0, 10, 10)
575 numberOfExpectedVisualEffectView++;
578 XCTAssertEqual(numberOfExpectedVisualEffectView, 1u);
581 - (void)testApplyBackdropFilterWithCorrectFrame {
582 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
587 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
590 flutterPlatformViewsController,
593 std::make_shared<fml::SyncSwitch>());
597 [flutterPlatformViewsController
599 withId:@"MockFlutterPlatformView"
603 [flutterPlatformViewsController
607 @"viewType" : @"MockFlutterPlatformView",
608 @"gestureBlockingPolicy" : @"eager"
614 UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
615 flutterPlatformViewsController.
flutterView = flutterView;
617 flutter::MutatorsStack stack;
619 flutter::DlScalar screenScale = [UIScreen mainScreen].scale;
620 flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
621 stack.PushTransform(screenScaleMatrix);
623 auto filter = flutter::DlBlurImageFilter::Make(5, 2, flutter::DlTileMode::kClamp);
624 stack.PushBackdropFilter(filter,
625 flutter::DlRect::MakeXYWH(0, 0, screenScale * 8, screenScale * 8));
627 auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
628 screenScaleMatrix, flutter::DlSize(5, 10), stack);
630 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
631 withParams:std::move(embeddedViewParams)];
632 [flutterPlatformViewsController
638 [flutterView addSubview:childClippingView];
640 [flutterView setNeedsLayout];
641 [flutterView layoutIfNeeded];
644 NSUInteger numberOfExpectedVisualEffectView = 0;
645 for (UIView* subview in childClippingView.subviews) {
646 if (![subview isKindOfClass:[UIVisualEffectView
class]]) {
649 XCTAssertLessThan(numberOfExpectedVisualEffectView, 1u);
650 if ([
self validateOneVisualEffectView:subview
651 expectedFrame:CGRectMake(0, 0, 5, 8)
653 numberOfExpectedVisualEffectView++;
656 XCTAssertEqual(numberOfExpectedVisualEffectView, 1u);
659 - (void)testApplyMultipleBackdropFilters {
660 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
665 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
668 flutterPlatformViewsController,
671 std::make_shared<fml::SyncSwitch>());
675 [flutterPlatformViewsController
677 withId:@"MockFlutterPlatformView"
681 [flutterPlatformViewsController
685 @"viewType" : @"MockFlutterPlatformView",
686 @"gestureBlockingPolicy" : @"eager"
692 UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
693 flutterPlatformViewsController.
flutterView = flutterView;
695 flutter::MutatorsStack stack;
697 flutter::DlScalar screenScale = [UIScreen mainScreen].scale;
698 flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
699 stack.PushTransform(screenScaleMatrix);
701 for (
int i = 0; i < 50; i++) {
702 auto filter = flutter::DlBlurImageFilter::Make(i, 2, flutter::DlTileMode::kClamp);
703 stack.PushBackdropFilter(filter,
704 flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
707 auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
708 screenScaleMatrix, flutter::DlSize(20, 20), stack);
710 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
711 withParams:std::move(embeddedViewParams)];
712 [flutterPlatformViewsController
718 [flutterView addSubview:childClippingView];
720 [flutterView setNeedsLayout];
721 [flutterView layoutIfNeeded];
723 NSUInteger numberOfExpectedVisualEffectView = 0;
724 for (UIView* subview in childClippingView.subviews) {
725 if (![subview isKindOfClass:[UIVisualEffectView
class]]) {
728 XCTAssertLessThan(numberOfExpectedVisualEffectView, 50u);
729 if ([
self validateOneVisualEffectView:subview
730 expectedFrame:CGRectMake(0, 0, 10, 10)
731 inputRadius:(CGFloat)numberOfExpectedVisualEffectView]) {
732 numberOfExpectedVisualEffectView++;
735 XCTAssertEqual(numberOfExpectedVisualEffectView, (NSUInteger)numberOfExpectedVisualEffectView);
738 - (void)testAddBackdropFilters {
739 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
745 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
748 flutterPlatformViewsController,
751 std::make_shared<fml::SyncSwitch>());
755 [flutterPlatformViewsController
757 withId:@"MockFlutterPlatformView"
761 [flutterPlatformViewsController
765 @"viewType" : @"MockFlutterPlatformView",
766 @"gestureBlockingPolicy" : @"eager"
772 UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
773 flutterPlatformViewsController.
flutterView = flutterView;
775 flutter::MutatorsStack stack;
777 flutter::DlScalar screenScale = [UIScreen mainScreen].scale;
778 flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
779 stack.PushTransform(screenScaleMatrix);
781 auto filter = flutter::DlBlurImageFilter::Make(5, 2, flutter::DlTileMode::kClamp);
782 stack.PushBackdropFilter(filter,
783 flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
785 auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
786 screenScaleMatrix, flutter::DlSize(10, 10), stack);
788 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
789 withParams:std::move(embeddedViewParams)];
790 [flutterPlatformViewsController
796 [flutterView addSubview:childClippingView];
798 [flutterView setNeedsLayout];
799 [flutterView layoutIfNeeded];
801 NSMutableArray* originalVisualEffectViews = [[NSMutableArray alloc] init];
802 for (UIView* subview in childClippingView.subviews) {
803 if (![subview isKindOfClass:[UIVisualEffectView
class]]) {
806 XCTAssertLessThan(originalVisualEffectViews.count, 1u);
807 if ([
self validateOneVisualEffectView:subview
808 expectedFrame:CGRectMake(0, 0, 10, 10)
809 inputRadius:(CGFloat)5]) {
810 [originalVisualEffectViews addObject:subview];
813 XCTAssertEqual(originalVisualEffectViews.count, 1u);
818 flutter::MutatorsStack stack2;
820 stack2.PushTransform(screenScaleMatrix);
822 for (
int i = 0; i < 2; i++) {
823 stack2.PushBackdropFilter(filter,
824 flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
827 embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
828 screenScaleMatrix, flutter::DlSize(10, 10), stack2);
830 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
831 withParams:std::move(embeddedViewParams)];
832 [flutterPlatformViewsController
836 [flutterView setNeedsLayout];
837 [flutterView layoutIfNeeded];
839 NSMutableArray* newVisualEffectViews = [[NSMutableArray alloc] init];
840 for (UIView* subview in childClippingView.subviews) {
841 if (![subview isKindOfClass:[UIVisualEffectView
class]]) {
844 XCTAssertLessThan(newVisualEffectViews.count, 2u);
846 if ([
self validateOneVisualEffectView:subview
847 expectedFrame:CGRectMake(0, 0, 10, 10)
848 inputRadius:(CGFloat)5]) {
849 [newVisualEffectViews addObject:subview];
852 XCTAssertEqual(newVisualEffectViews.count, 2u);
853 for (NSUInteger i = 0; i < originalVisualEffectViews.count; i++) {
854 UIView* originalView = originalVisualEffectViews[i];
855 UIView* newView = newVisualEffectViews[i];
857 XCTAssertEqual(originalView, newView);
858 id mockOrignalView = OCMPartialMock(originalView);
859 OCMReject([mockOrignalView removeFromSuperview]);
860 [mockOrignalView stopMocking];
864 - (void)testRemoveBackdropFilters {
865 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
871 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
874 flutterPlatformViewsController,
877 std::make_shared<fml::SyncSwitch>());
881 [flutterPlatformViewsController
883 withId:@"MockFlutterPlatformView"
887 [flutterPlatformViewsController
891 @"viewType" : @"MockFlutterPlatformView",
892 @"gestureBlockingPolicy" : @"eager"
898 UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
899 flutterPlatformViewsController.
flutterView = flutterView;
901 flutter::MutatorsStack stack;
903 flutter::DlScalar screenScale = [UIScreen mainScreen].scale;
904 flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
905 stack.PushTransform(screenScaleMatrix);
907 auto filter = flutter::DlBlurImageFilter::Make(5, 2, flutter::DlTileMode::kClamp);
908 for (
int i = 0; i < 5; i++) {
909 stack.PushBackdropFilter(filter,
910 flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
913 auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
914 screenScaleMatrix, flutter::DlSize(10, 10), stack);
916 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
917 withParams:std::move(embeddedViewParams)];
918 [flutterPlatformViewsController
924 [flutterView addSubview:childClippingView];
926 [flutterView setNeedsLayout];
927 [flutterView layoutIfNeeded];
929 NSMutableArray* originalVisualEffectViews = [[NSMutableArray alloc] init];
930 for (UIView* subview in childClippingView.subviews) {
931 if (![subview isKindOfClass:[UIVisualEffectView
class]]) {
934 XCTAssertLessThan(originalVisualEffectViews.count, 5u);
935 if ([
self validateOneVisualEffectView:subview
936 expectedFrame:CGRectMake(0, 0, 10, 10)
937 inputRadius:(CGFloat)5]) {
938 [originalVisualEffectViews addObject:subview];
944 flutter::MutatorsStack stack2;
946 stack2.PushTransform(screenScaleMatrix);
948 for (
int i = 0; i < 4; i++) {
949 stack2.PushBackdropFilter(filter,
950 flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
953 embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
954 screenScaleMatrix, flutter::DlSize(10, 10), stack2);
956 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
957 withParams:std::move(embeddedViewParams)];
958 [flutterPlatformViewsController
962 [flutterView setNeedsLayout];
963 [flutterView layoutIfNeeded];
965 NSMutableArray* newVisualEffectViews = [[NSMutableArray alloc] init];
966 for (UIView* subview in childClippingView.subviews) {
967 if (![subview isKindOfClass:[UIVisualEffectView
class]]) {
970 XCTAssertLessThan(newVisualEffectViews.count, 4u);
971 if ([
self validateOneVisualEffectView:subview
972 expectedFrame:CGRectMake(0, 0, 10, 10)
973 inputRadius:(CGFloat)5]) {
974 [newVisualEffectViews addObject:subview];
977 XCTAssertEqual(newVisualEffectViews.count, 4u);
979 for (NSUInteger i = 0; i < newVisualEffectViews.count; i++) {
980 UIView* newView = newVisualEffectViews[i];
981 id mockNewView = OCMPartialMock(newView);
982 UIView* originalView = originalVisualEffectViews[i];
984 XCTAssertEqual(originalView, newView);
985 OCMReject([mockNewView removeFromSuperview]);
986 [mockNewView stopMocking];
991 for (
int i = 0; i < 5; i++) {
996 embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
997 screenScaleMatrix, flutter::DlSize(10, 10), stack2);
999 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
1000 withParams:std::move(embeddedViewParams)];
1001 [flutterPlatformViewsController
1005 [flutterView setNeedsLayout];
1006 [flutterView layoutIfNeeded];
1008 NSUInteger numberOfExpectedVisualEffectView = 0u;
1009 for (UIView* subview in childClippingView.subviews) {
1010 if ([subview isKindOfClass:[UIVisualEffectView
class]]) {
1011 numberOfExpectedVisualEffectView++;
1014 XCTAssertEqual(numberOfExpectedVisualEffectView, 0u);
1017 - (void)testEditBackdropFilters {
1018 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
1024 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
1027 flutterPlatformViewsController,
1030 std::make_shared<fml::SyncSwitch>());
1034 [flutterPlatformViewsController
1036 withId:@"MockFlutterPlatformView"
1040 [flutterPlatformViewsController
1044 @"viewType" : @"MockFlutterPlatformView",
1045 @"gestureBlockingPolicy" : @"eager"
1051 UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
1052 flutterPlatformViewsController.
flutterView = flutterView;
1054 flutter::MutatorsStack stack;
1056 flutter::DlScalar screenScale = [UIScreen mainScreen].scale;
1057 flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
1058 stack.PushTransform(screenScaleMatrix);
1060 auto filter = flutter::DlBlurImageFilter::Make(5, 2, flutter::DlTileMode::kClamp);
1061 for (
int i = 0; i < 5; i++) {
1062 stack.PushBackdropFilter(filter,
1063 flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
1066 auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
1067 screenScaleMatrix, flutter::DlSize(10, 10), stack);
1069 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
1070 withParams:std::move(embeddedViewParams)];
1071 [flutterPlatformViewsController
1077 [flutterView addSubview:childClippingView];
1079 [flutterView setNeedsLayout];
1080 [flutterView layoutIfNeeded];
1082 NSMutableArray* originalVisualEffectViews = [[NSMutableArray alloc] init];
1083 for (UIView* subview in childClippingView.subviews) {
1084 if (![subview isKindOfClass:[UIVisualEffectView
class]]) {
1087 XCTAssertLessThan(originalVisualEffectViews.count, 5u);
1088 if ([
self validateOneVisualEffectView:subview
1089 expectedFrame:CGRectMake(0, 0, 10, 10)
1090 inputRadius:(CGFloat)5]) {
1091 [originalVisualEffectViews addObject:subview];
1097 flutter::MutatorsStack stack2;
1099 stack2.PushTransform(screenScaleMatrix);
1101 for (
int i = 0; i < 5; i++) {
1103 auto filter2 = flutter::DlBlurImageFilter::Make(2, 5, flutter::DlTileMode::kClamp);
1105 stack2.PushBackdropFilter(
1106 filter2, flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
1110 stack2.PushBackdropFilter(filter,
1111 flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
1114 embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
1115 screenScaleMatrix, flutter::DlSize(10, 10), stack2);
1117 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
1118 withParams:std::move(embeddedViewParams)];
1119 [flutterPlatformViewsController
1123 [flutterView setNeedsLayout];
1124 [flutterView layoutIfNeeded];
1126 NSMutableArray* newVisualEffectViews = [[NSMutableArray alloc] init];
1127 for (UIView* subview in childClippingView.subviews) {
1128 if (![subview isKindOfClass:[UIVisualEffectView
class]]) {
1131 XCTAssertLessThan(newVisualEffectViews.count, 5u);
1132 CGFloat expectInputRadius = 5;
1133 if (newVisualEffectViews.count == 3) {
1134 expectInputRadius = 2;
1136 if ([
self validateOneVisualEffectView:subview
1137 expectedFrame:CGRectMake(0, 0, 10, 10)
1138 inputRadius:expectInputRadius]) {
1139 [newVisualEffectViews addObject:subview];
1142 XCTAssertEqual(newVisualEffectViews.count, 5u);
1143 for (NSUInteger i = 0; i < newVisualEffectViews.count; i++) {
1144 UIView* newView = newVisualEffectViews[i];
1145 id mockNewView = OCMPartialMock(newView);
1146 UIView* originalView = originalVisualEffectViews[i];
1148 XCTAssertEqual(originalView, newView);
1149 OCMReject([mockNewView removeFromSuperview]);
1150 [mockNewView stopMocking];
1152 [newVisualEffectViews removeAllObjects];
1156 for (
int i = 0; i < 5; i++) {
1160 for (
int i = 0; i < 5; i++) {
1162 auto filter2 = flutter::DlBlurImageFilter::Make(2, 5, flutter::DlTileMode::kClamp);
1163 stack2.PushBackdropFilter(
1164 filter2, flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
1168 stack2.PushBackdropFilter(filter,
1169 flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
1172 embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
1173 screenScaleMatrix, flutter::DlSize(10, 10), stack2);
1175 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
1176 withParams:std::move(embeddedViewParams)];
1177 [flutterPlatformViewsController
1181 [flutterView setNeedsLayout];
1182 [flutterView layoutIfNeeded];
1184 for (UIView* subview in childClippingView.subviews) {
1185 if (![subview isKindOfClass:[UIVisualEffectView
class]]) {
1188 XCTAssertLessThan(newVisualEffectViews.count, 5u);
1189 CGFloat expectInputRadius = 5;
1190 if (newVisualEffectViews.count == 0) {
1191 expectInputRadius = 2;
1193 if ([
self validateOneVisualEffectView:subview
1194 expectedFrame:CGRectMake(0, 0, 10, 10)
1195 inputRadius:expectInputRadius]) {
1196 [newVisualEffectViews addObject:subview];
1199 for (NSUInteger i = 0; i < newVisualEffectViews.count; i++) {
1200 UIView* newView = newVisualEffectViews[i];
1201 id mockNewView = OCMPartialMock(newView);
1202 UIView* originalView = originalVisualEffectViews[i];
1204 XCTAssertEqual(originalView, newView);
1205 OCMReject([mockNewView removeFromSuperview]);
1206 [mockNewView stopMocking];
1208 [newVisualEffectViews removeAllObjects];
1212 for (
int i = 0; i < 5; i++) {
1216 for (
int i = 0; i < 5; i++) {
1218 auto filter2 = flutter::DlBlurImageFilter::Make(2, 5, flutter::DlTileMode::kClamp);
1219 stack2.PushBackdropFilter(
1220 filter2, flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
1224 stack2.PushBackdropFilter(filter,
1225 flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
1228 embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
1229 screenScaleMatrix, flutter::DlSize(10, 10), stack2);
1231 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
1232 withParams:std::move(embeddedViewParams)];
1233 [flutterPlatformViewsController
1237 [flutterView setNeedsLayout];
1238 [flutterView layoutIfNeeded];
1240 for (UIView* subview in childClippingView.subviews) {
1241 if (![subview isKindOfClass:[UIVisualEffectView
class]]) {
1244 XCTAssertLessThan(newVisualEffectViews.count, 5u);
1245 CGFloat expectInputRadius = 5;
1246 if (newVisualEffectViews.count == 4) {
1247 expectInputRadius = 2;
1249 if ([
self validateOneVisualEffectView:subview
1250 expectedFrame:CGRectMake(0, 0, 10, 10)
1251 inputRadius:expectInputRadius]) {
1252 [newVisualEffectViews addObject:subview];
1255 XCTAssertEqual(newVisualEffectViews.count, 5u);
1257 for (NSUInteger i = 0; i < newVisualEffectViews.count; i++) {
1258 UIView* newView = newVisualEffectViews[i];
1259 id mockNewView = OCMPartialMock(newView);
1260 UIView* originalView = originalVisualEffectViews[i];
1262 XCTAssertEqual(originalView, newView);
1263 OCMReject([mockNewView removeFromSuperview]);
1264 [mockNewView stopMocking];
1266 [newVisualEffectViews removeAllObjects];
1270 for (
int i = 0; i < 5; i++) {
1274 for (
int i = 0; i < 5; i++) {
1275 auto filter2 = flutter::DlBlurImageFilter::Make(i, 2, flutter::DlTileMode::kClamp);
1277 stack2.PushBackdropFilter(filter2,
1278 flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
1281 embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
1282 screenScaleMatrix, flutter::DlSize(10, 10), stack2);
1284 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
1285 withParams:std::move(embeddedViewParams)];
1286 [flutterPlatformViewsController
1290 [flutterView setNeedsLayout];
1291 [flutterView layoutIfNeeded];
1293 for (UIView* subview in childClippingView.subviews) {
1294 if (![subview isKindOfClass:[UIVisualEffectView
class]]) {
1297 XCTAssertLessThan(newVisualEffectViews.count, 5u);
1298 if ([
self validateOneVisualEffectView:subview
1299 expectedFrame:CGRectMake(0, 0, 10, 10)
1300 inputRadius:(CGFloat)newVisualEffectViews.count]) {
1301 [newVisualEffectViews addObject:subview];
1304 XCTAssertEqual(newVisualEffectViews.count, 5u);
1306 for (NSUInteger i = 0; i < newVisualEffectViews.count; i++) {
1307 UIView* newView = newVisualEffectViews[i];
1308 id mockNewView = OCMPartialMock(newView);
1309 UIView* originalView = originalVisualEffectViews[i];
1311 XCTAssertEqual(originalView, newView);
1312 OCMReject([mockNewView removeFromSuperview]);
1313 [mockNewView stopMocking];
1315 [newVisualEffectViews removeAllObjects];
1318 - (void)testApplyBackdropFilterNotDlBlurImageFilter {
1319 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
1325 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
1328 flutterPlatformViewsController,
1331 std::make_shared<fml::SyncSwitch>());
1335 [flutterPlatformViewsController
1337 withId:@"MockFlutterPlatformView"
1341 [flutterPlatformViewsController
1345 @"viewType" : @"MockFlutterPlatformView",
1346 @"gestureBlockingPolicy" : @"eager"
1352 UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
1353 flutterPlatformViewsController.
flutterView = flutterView;
1355 flutter::MutatorsStack stack;
1357 flutter::DlScalar screenScale = [UIScreen mainScreen].scale;
1358 flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
1359 stack.PushTransform(screenScaleMatrix);
1361 auto dilateFilter = flutter::DlDilateImageFilter::Make(5, 2);
1362 stack.PushBackdropFilter(dilateFilter, flutter::DlRect());
1364 auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
1365 screenScaleMatrix, flutter::DlSize(10, 10), stack);
1367 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
1368 withParams:std::move(embeddedViewParams)];
1369 [flutterPlatformViewsController
1376 [flutterView addSubview:childClippingView];
1378 [flutterView setNeedsLayout];
1379 [flutterView layoutIfNeeded];
1381 NSUInteger numberOfExpectedVisualEffectView = 0;
1382 for (UIView* subview in childClippingView.subviews) {
1383 if ([subview isKindOfClass:[UIVisualEffectView
class]]) {
1384 numberOfExpectedVisualEffectView++;
1387 XCTAssertEqual(numberOfExpectedVisualEffectView, 0u);
1391 flutter::MutatorsStack stack2;
1393 stack2.PushTransform(screenScaleMatrix);
1395 auto blurFilter = flutter::DlBlurImageFilter::Make(5, 2, flutter::DlTileMode::kClamp);
1397 for (
int i = 0; i < 5; i++) {
1399 stack2.PushBackdropFilter(
1400 dilateFilter, flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
1404 stack2.PushBackdropFilter(blurFilter,
1405 flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
1408 embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
1409 screenScaleMatrix, flutter::DlSize(10, 10), stack2);
1411 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
1412 withParams:std::move(embeddedViewParams)];
1413 [flutterPlatformViewsController
1417 [flutterView setNeedsLayout];
1418 [flutterView layoutIfNeeded];
1420 numberOfExpectedVisualEffectView = 0;
1421 for (UIView* subview in childClippingView.subviews) {
1422 if (![subview isKindOfClass:[UIVisualEffectView
class]]) {
1425 XCTAssertLessThan(numberOfExpectedVisualEffectView, 4u);
1426 if ([
self validateOneVisualEffectView:subview
1427 expectedFrame:CGRectMake(0, 0, 10, 10)
1428 inputRadius:(CGFloat)5]) {
1429 numberOfExpectedVisualEffectView++;
1432 XCTAssertEqual(numberOfExpectedVisualEffectView, 4u);
1436 for (
int i = 0; i < 5; i++) {
1440 for (
int i = 0; i < 5; i++) {
1442 stack2.PushBackdropFilter(
1443 dilateFilter, flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
1447 stack2.PushBackdropFilter(blurFilter,
1448 flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
1451 embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
1452 screenScaleMatrix, flutter::DlSize(10, 10), stack2);
1454 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
1455 withParams:std::move(embeddedViewParams)];
1456 [flutterPlatformViewsController
1460 [flutterView setNeedsLayout];
1461 [flutterView layoutIfNeeded];
1463 numberOfExpectedVisualEffectView = 0;
1464 for (UIView* subview in childClippingView.subviews) {
1465 if (![subview isKindOfClass:[UIVisualEffectView
class]]) {
1468 XCTAssertLessThan(numberOfExpectedVisualEffectView, 4u);
1469 if ([
self validateOneVisualEffectView:subview
1470 expectedFrame:CGRectMake(0, 0, 10, 10)
1471 inputRadius:(CGFloat)5]) {
1472 numberOfExpectedVisualEffectView++;
1475 XCTAssertEqual(numberOfExpectedVisualEffectView, 4u);
1479 for (
int i = 0; i < 5; i++) {
1483 for (
int i = 0; i < 5; i++) {
1485 stack2.PushBackdropFilter(
1486 dilateFilter, flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
1490 stack2.PushBackdropFilter(blurFilter,
1491 flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
1494 embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
1495 screenScaleMatrix, flutter::DlSize(10, 10), stack2);
1497 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
1498 withParams:std::move(embeddedViewParams)];
1499 [flutterPlatformViewsController
1503 [flutterView setNeedsLayout];
1504 [flutterView layoutIfNeeded];
1506 numberOfExpectedVisualEffectView = 0;
1507 for (UIView* subview in childClippingView.subviews) {
1508 if (![subview isKindOfClass:[UIVisualEffectView
class]]) {
1511 XCTAssertLessThan(numberOfExpectedVisualEffectView, 4u);
1512 if ([
self validateOneVisualEffectView:subview
1513 expectedFrame:CGRectMake(0, 0, 10, 10)
1514 inputRadius:(CGFloat)5]) {
1515 numberOfExpectedVisualEffectView++;
1518 XCTAssertEqual(numberOfExpectedVisualEffectView, 4u);
1522 for (
int i = 0; i < 5; i++) {
1526 for (
int i = 0; i < 5; i++) {
1527 stack2.PushBackdropFilter(dilateFilter,
1528 flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
1531 embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
1532 screenScaleMatrix, flutter::DlSize(10, 10), stack2);
1534 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
1535 withParams:std::move(embeddedViewParams)];
1536 [flutterPlatformViewsController
1540 [flutterView setNeedsLayout];
1541 [flutterView layoutIfNeeded];
1543 numberOfExpectedVisualEffectView = 0;
1544 for (UIView* subview in childClippingView.subviews) {
1545 if ([subview isKindOfClass:[UIVisualEffectView
class]]) {
1546 numberOfExpectedVisualEffectView++;
1549 XCTAssertEqual(numberOfExpectedVisualEffectView, 0u);
1552 - (void)testApplyBackdropFilterCorrectAPI {
1557 UIVisualEffectView* visualEffectView = [[UIVisualEffectView alloc]
1558 initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]];
1563 isRoundedSuperellipse:NO
1564 visualEffectView:visualEffectView];
1565 XCTAssertNotNil(platformViewFilter);
1568 - (void)testApplyBackdropFilterAPIChangedInvalidUIVisualEffectView {
1570 UIVisualEffectView* visualEffectView = [[UIVisualEffectView alloc] init];
1575 isRoundedSuperellipse:NO
1576 visualEffectView:visualEffectView];
1577 XCTAssertNil(platformViewFilter);
1580 - (void)testApplyBackdropFilterAPIChangedNoGaussianBlurFilter {
1582 UIVisualEffectView* editedUIVisualEffectView = [[UIVisualEffectView alloc]
1583 initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]];
1584 NSArray* subviews = editedUIVisualEffectView.subviews;
1585 for (UIView* view in subviews) {
1586 if ([NSStringFromClass([view
class]) hasSuffix:
@"BackdropView"]) {
1587 for (CIFilter* filter in view.layer.filters) {
1588 if ([[filter valueForKey:
@"name"] isEqual:
@"gaussianBlur"]) {
1589 [filter setValue:@"notGaussianBlur" forKey:@"name"];
1600 isRoundedSuperellipse:NO
1601 visualEffectView:editedUIVisualEffectView];
1602 XCTAssertNil(platformViewFilter);
1605 - (void)testApplyBackdropFilterAPIChangedInvalidInputRadius {
1607 UIVisualEffectView* editedUIVisualEffectView = [[UIVisualEffectView alloc]
1608 initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]];
1609 NSArray* subviews = editedUIVisualEffectView.subviews;
1610 for (UIView* view in subviews) {
1611 if ([NSStringFromClass([view
class]) hasSuffix:
@"BackdropView"]) {
1612 for (CIFilter* filter in view.layer.filters) {
1613 if ([[filter valueForKey:
@"name"] isEqual:
@"gaussianBlur"]) {
1614 [filter setValue:@"invalidInputRadius" forKey:@"inputRadius"];
1626 isRoundedSuperellipse:NO
1627 visualEffectView:editedUIVisualEffectView];
1628 XCTAssertNil(platformViewFilter);
1631 - (void)testApplyBackdropFilterRespectsClipRRect {
1632 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
1638 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
1641 flutterPlatformViewsController,
1644 std::make_shared<fml::SyncSwitch>());
1648 [flutterPlatformViewsController
1650 withId:@"MockFlutterPlatformView"
1654 [flutterPlatformViewsController
1659 @"viewType" : @"MockFlutterPlatformView",
1660 @"gestureBlockingPolicy" : @"fallbackToPluginDefault"
1666 UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
1667 flutterPlatformViewsController.
flutterView = flutterView;
1669 flutter::MutatorsStack stack;
1671 flutter::DlScalar screenScale = [UIScreen mainScreen].scale;
1672 flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
1673 stack.PushTransform(screenScaleMatrix);
1676 auto clipRect = flutter::DlRect::MakeXYWH(2, 2, 6, 6);
1677 auto clipRRect = flutter::DlRoundRect::MakeRectXY(clipRect, 3, 3);
1678 stack.PushPlatformViewClipRRect(clipRRect);
1681 auto filter = flutter::DlBlurImageFilter::Make(5, 2, flutter::DlTileMode::kClamp);
1682 stack.PushBackdropFilter(filter,
1683 flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
1685 auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
1686 screenScaleMatrix, flutter::DlSize(10, 10), stack);
1688 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
1689 withParams:std::move(embeddedViewParams)];
1690 [flutterPlatformViewsController
1696 [flutterView addSubview:childClippingView];
1698 [flutterView setNeedsLayout];
1699 [flutterView layoutIfNeeded];
1702 XCTAssertEqual(filters.count, 1u);
1704 UIVisualEffectView* visualEffectView = filters[0];
1705 auto radii = clipRRect.GetRadii();
1707 XCTAssertEqual(visualEffectView.layer.cornerRadius, radii.top_left.width);
1708 XCTAssertEqual(visualEffectView.layer.cornerCurve, kCACornerCurveCircular);
1711 - (void)testApplyBackdropFilterRespectsClipRSuperellipse {
1712 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
1718 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
1721 flutterPlatformViewsController,
1724 std::make_shared<fml::SyncSwitch>());
1728 [flutterPlatformViewsController
1730 withId:@"MockFlutterPlatformView"
1734 [flutterPlatformViewsController
1739 @"viewType" : @"MockFlutterPlatformView",
1740 @"gestureBlockingPolicy" : @"fallbackToPluginDefault"
1746 UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
1747 flutterPlatformViewsController.
flutterView = flutterView;
1749 flutter::MutatorsStack stack;
1751 flutter::DlScalar screenScale = [UIScreen mainScreen].scale;
1752 flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
1753 stack.PushTransform(screenScaleMatrix);
1756 auto clipRect = flutter::DlRect::MakeXYWH(2, 2, 6, 6);
1757 auto clipRSE = flutter::DlRoundSuperellipse::MakeRectXY(clipRect, 3, 3);
1758 stack.PushPlatformViewClipRSuperellipse(clipRSE);
1761 auto filter = flutter::DlBlurImageFilter::Make(5, 2, flutter::DlTileMode::kClamp);
1762 stack.PushBackdropFilter(filter,
1763 flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
1765 auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
1766 screenScaleMatrix, flutter::DlSize(10, 10), stack);
1768 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
1769 withParams:std::move(embeddedViewParams)];
1770 [flutterPlatformViewsController
1776 [flutterView addSubview:childClippingView];
1778 [flutterView setNeedsLayout];
1779 [flutterView layoutIfNeeded];
1782 XCTAssertEqual(filters.count, 1u);
1784 UIVisualEffectView* visualEffectView = filters[0];
1785 auto radii = clipRSE.GetRadii();
1787 XCTAssertEqual(visualEffectView.layer.cornerRadius, radii.top_left.width);
1788 XCTAssertEqual(visualEffectView.layer.cornerCurve, kCACornerCurveContinuous);
1791 - (void)testBackdropFilterVisualEffectSubviewBackgroundColor {
1792 __weak UIVisualEffectView* weakVisualEffectView;
1795 UIVisualEffectView* visualEffectView = [[UIVisualEffectView alloc]
1796 initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]];
1797 weakVisualEffectView = visualEffectView;
1802 isRoundedSuperellipse:NO
1803 visualEffectView:visualEffectView];
1804 CGColorRef visualEffectSubviewBackgroundColor = nil;
1805 for (UIView* view in [platformViewFilter backdropFilterView].subviews) {
1806 if ([NSStringFromClass([view
class]) hasSuffix:
@"VisualEffectSubview"]) {
1807 visualEffectSubviewBackgroundColor = view.layer.backgroundColor;
1811 CGColorEqualToColor(visualEffectSubviewBackgroundColor, UIColor.clearColor.CGColor));
1813 XCTAssertNil(weakVisualEffectView);
1816 - (void)testCompositePlatformView {
1817 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
1823 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
1826 flutterPlatformViewsController,
1829 std::make_shared<fml::SyncSwitch>());
1833 [flutterPlatformViewsController
1835 withId:@"MockFlutterPlatformView"
1839 [flutterPlatformViewsController
1843 @"viewType" : @"MockFlutterPlatformView",
1844 @"gestureBlockingPolicy" : @"eager"
1850 UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)];
1851 flutterPlatformViewsController.
flutterView = flutterView;
1853 flutter::MutatorsStack stack;
1855 flutter::DlScalar screenScale = [UIScreen mainScreen].scale;
1856 flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
1857 stack.PushTransform(screenScaleMatrix);
1859 flutter::DlMatrix translateMatrix = flutter::DlMatrix::MakeTranslation({100, 100});
1860 stack.PushTransform(translateMatrix);
1861 flutter::DlMatrix finalMatrix = screenScaleMatrix * translateMatrix;
1863 auto embeddedViewParams =
1864 std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, flutter::DlSize(300, 300), stack);
1866 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
1867 withParams:std::move(embeddedViewParams)];
1868 [flutterPlatformViewsController
1872 CGRect platformViewRectInFlutterView = [gMockPlatformView convertRect:gMockPlatformView.bounds
1873 toView:flutterView];
1874 XCTAssertTrue(CGRectEqualToRect(platformViewRectInFlutterView, CGRectMake(100, 100, 300, 300)));
1877 - (void)testBackdropFilterCorrectlyPushedAndReset {
1878 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
1884 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
1887 flutterPlatformViewsController,
1890 std::make_shared<fml::SyncSwitch>());
1894 [flutterPlatformViewsController
1896 withId:@"MockFlutterPlatformView"
1900 [flutterPlatformViewsController
1904 @"viewType" : @"MockFlutterPlatformView",
1905 @"gestureBlockingPolicy" : @"eager"
1911 UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
1912 flutterPlatformViewsController.
flutterView = flutterView;
1914 flutter::MutatorsStack stack;
1916 flutter::DlScalar screenScale = [UIScreen mainScreen].scale;
1917 flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
1918 stack.PushTransform(screenScaleMatrix);
1920 auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
1921 screenScaleMatrix, flutter::DlSize(10, 10), stack);
1923 [flutterPlatformViewsController beginFrameWithSize:flutter::DlISize(0, 0)];
1924 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
1925 withParams:std::move(embeddedViewParams)];
1927 auto filter = flutter::DlBlurImageFilter::Make(5, 2, flutter::DlTileMode::kClamp, std::nullopt);
1928 [flutterPlatformViewsController
1929 pushFilterToVisitedPlatformViews:filter
1930 withRect:flutter::DlRect::MakeXYWH(0, 0, screenScale * 10,
1932 [flutterPlatformViewsController
1938 [flutterView addSubview:childClippingView];
1940 [flutterView setNeedsLayout];
1941 [flutterView layoutIfNeeded];
1944 NSUInteger numberOfExpectedVisualEffectView = 0;
1945 for (UIView* subview in childClippingView.subviews) {
1946 if (![subview isKindOfClass:[UIVisualEffectView
class]]) {
1949 XCTAssertLessThan(numberOfExpectedVisualEffectView, 1u);
1950 if ([
self validateOneVisualEffectView:subview
1951 expectedFrame:CGRectMake(0, 0, 10, 10)
1953 numberOfExpectedVisualEffectView++;
1956 XCTAssertEqual(numberOfExpectedVisualEffectView, 1u);
1959 auto embeddedViewParams2 = std::make_unique<flutter::EmbeddedViewParams>(
1960 screenScaleMatrix, flutter::DlSize(10, 10), stack);
1961 [flutterPlatformViewsController beginFrameWithSize:flutter::DlISize(0, 0)];
1962 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
1963 withParams:std::move(embeddedViewParams2)];
1964 [flutterPlatformViewsController
1970 [flutterView setNeedsLayout];
1971 [flutterView layoutIfNeeded];
1973 numberOfExpectedVisualEffectView = 0;
1974 for (UIView* subview in childClippingView.subviews) {
1975 if (![subview isKindOfClass:[UIVisualEffectView
class]]) {
1978 numberOfExpectedVisualEffectView++;
1980 XCTAssertEqual(numberOfExpectedVisualEffectView, 0u);
1983 - (void)testChildClippingViewShouldBeTheBoundingRectOfPlatformView {
1984 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
1990 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
1993 flutterPlatformViewsController,
1996 std::make_shared<fml::SyncSwitch>());
2000 [flutterPlatformViewsController
2002 withId:@"MockFlutterPlatformView"
2006 [flutterPlatformViewsController
2010 @"viewType" : @"MockFlutterPlatformView",
2011 @"gestureBlockingPolicy" : @"eager"
2017 UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)];
2018 flutterPlatformViewsController.
flutterView = flutterView;
2020 flutter::MutatorsStack stack;
2022 flutter::DlScalar screenScale = [UIScreen mainScreen].scale;
2023 flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
2024 stack.PushTransform(screenScaleMatrix);
2026 flutter::DlMatrix rotateMatrix = flutter::DlMatrix::MakeRotationZ(flutter::DlDegrees(10));
2027 stack.PushTransform(rotateMatrix);
2028 flutter::DlMatrix finalMatrix = screenScaleMatrix * rotateMatrix;
2030 auto embeddedViewParams =
2031 std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, flutter::DlSize(300, 300), stack);
2033 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
2034 withParams:std::move(embeddedViewParams)];
2035 [flutterPlatformViewsController
2039 CGRect platformViewRectInFlutterView = [gMockPlatformView convertRect:gMockPlatformView.bounds
2040 toView:flutterView];
2046 XCTAssertLessThan(fabs(platformViewRectInFlutterView.origin.x - childClippingView.frame.origin.x),
2048 XCTAssertLessThan(fabs(platformViewRectInFlutterView.origin.y - childClippingView.frame.origin.y),
2051 fabs(platformViewRectInFlutterView.size.width - childClippingView.frame.size.width),
2054 fabs(platformViewRectInFlutterView.size.height - childClippingView.frame.size.height),
2058 - (void)testClipsDoNotInterceptWithPlatformViewShouldNotAddMaskView {
2059 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
2065 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
2068 flutterPlatformViewsController,
2071 std::make_shared<fml::SyncSwitch>());
2075 [flutterPlatformViewsController
2077 withId:@"MockFlutterPlatformView"
2081 [flutterPlatformViewsController
2085 @"viewType" : @"MockFlutterPlatformView",
2086 @"gestureBlockingPolicy" : @"eager"
2092 UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 30, 30)];
2093 flutterPlatformViewsController.
flutterView = flutterView;
2095 flutter::MutatorsStack stack;
2097 flutter::DlScalar screenScale = [UIScreen mainScreen].scale;
2098 flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
2099 stack.PushTransform(screenScaleMatrix);
2100 flutter::DlMatrix translateMatrix = flutter::DlMatrix::MakeTranslation({5, 5});
2102 stack.PushTransform(translateMatrix);
2104 flutter::DlRect rect = flutter::DlRect::MakeXYWH(0, 0, 25, 25);
2105 stack.PushClipRect(rect);
2108 flutter::DlRect rect_for_rrect = flutter::DlRect::MakeXYWH(-1, -1, 25, 25);
2109 flutter::DlRoundRect rrect = flutter::DlRoundRect::MakeRectXY(rect_for_rrect, 1, 1);
2110 stack.PushClipRRect(rrect);
2112 auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
2113 screenScaleMatrix * translateMatrix, flutter::DlSize(5, 5), stack);
2115 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
2116 withParams:std::move(embeddedViewParams)];
2117 [flutterPlatformViewsController
2124 [flutterView addSubview:childClippingView];
2126 [flutterView setNeedsLayout];
2127 [flutterView layoutIfNeeded];
2128 XCTAssertNil(childClippingView.maskView);
2131 - (void)testClipRRectOnlyHasCornersInterceptWithPlatformViewShouldAddMaskView {
2132 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
2138 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
2141 flutterPlatformViewsController,
2144 std::make_shared<fml::SyncSwitch>());
2148 [flutterPlatformViewsController
2150 withId:@"MockFlutterPlatformView"
2154 [flutterPlatformViewsController
2158 @"viewType" : @"MockFlutterPlatformView",
2159 @"gestureBlockingPolicy" : @"eager"
2165 UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 30, 30)];
2166 flutterPlatformViewsController.
flutterView = flutterView;
2168 flutter::MutatorsStack stack;
2170 flutter::DlScalar screenScale = [UIScreen mainScreen].scale;
2171 flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
2172 stack.PushTransform(screenScaleMatrix);
2173 flutter::DlMatrix translateMatrix = flutter::DlMatrix::MakeTranslation({5, 5});
2175 stack.PushTransform(translateMatrix);
2179 flutter::DlRect rect_for_rrect = flutter::DlRect::MakeXYWH(0, 0, 10, 10);
2180 flutter::DlRoundRect rrect = flutter::DlRoundRect::MakeRectXY(rect_for_rrect, 1, 1);
2181 stack.PushClipRRect(rrect);
2183 auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
2184 screenScaleMatrix * translateMatrix, flutter::DlSize(5, 5), stack);
2186 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
2187 withParams:std::move(embeddedViewParams)];
2188 [flutterPlatformViewsController
2195 [flutterView addSubview:childClippingView];
2197 [flutterView setNeedsLayout];
2198 [flutterView layoutIfNeeded];
2200 XCTAssertNotNil(childClippingView.maskView);
2203 - (void)testClipRect {
2204 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
2210 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
2213 flutterPlatformViewsController,
2216 std::make_shared<fml::SyncSwitch>());
2220 [flutterPlatformViewsController
2222 withId:@"MockFlutterPlatformView"
2226 [flutterPlatformViewsController
2230 @"viewType" : @"MockFlutterPlatformView",
2231 @"gestureBlockingPolicy" : @"eager"
2237 UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
2238 flutterPlatformViewsController.
flutterView = flutterView;
2240 flutter::MutatorsStack stack;
2242 flutter::DlScalar screenScale = [UIScreen mainScreen].scale;
2243 flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
2244 stack.PushTransform(screenScaleMatrix);
2246 flutter::DlRect rect = flutter::DlRect::MakeXYWH(2, 2, 3, 3);
2247 stack.PushClipRect(rect);
2249 auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
2250 screenScaleMatrix, flutter::DlSize(10, 10), stack);
2252 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
2253 withParams:std::move(embeddedViewParams)];
2254 [flutterPlatformViewsController
2261 [flutterView addSubview:childClippingView];
2263 [flutterView setNeedsLayout];
2264 [flutterView layoutIfNeeded];
2266 CGRect insideClipping = CGRectMake(2, 2, 3, 3);
2267 for (
int i = 0; i < 10; i++) {
2268 for (
int j = 0; j < 10; j++) {
2269 CGPoint point = CGPointMake(i, j);
2270 int alpha = [
self alphaOfPoint:CGPointMake(i, j) onView:flutterView];
2271 if (CGRectContainsPoint(insideClipping, point)) {
2272 XCTAssertEqual(alpha, 255);
2274 XCTAssertEqual(alpha, 0);
2280 - (void)testClipRect_multipleClips {
2281 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
2287 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
2290 flutterPlatformViewsController,
2293 std::make_shared<fml::SyncSwitch>());
2297 [flutterPlatformViewsController
2299 withId:@"MockFlutterPlatformView"
2303 [flutterPlatformViewsController
2307 @"viewType" : @"MockFlutterPlatformView",
2308 @"gestureBlockingPolicy" : @"eager"
2314 UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
2315 flutterPlatformViewsController.
flutterView = flutterView;
2317 flutter::MutatorsStack stack;
2319 flutter::DlScalar screenScale = [UIScreen mainScreen].scale;
2320 flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
2321 stack.PushTransform(screenScaleMatrix);
2323 flutter::DlRect rect1 = flutter::DlRect::MakeXYWH(2, 2, 3, 3);
2324 stack.PushClipRect(rect1);
2326 flutter::DlRect rect2 = flutter::DlRect::MakeXYWH(3, 3, 3, 3);
2327 stack.PushClipRect(rect2);
2329 auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
2330 screenScaleMatrix, flutter::DlSize(10, 10), stack);
2332 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
2333 withParams:std::move(embeddedViewParams)];
2334 [flutterPlatformViewsController
2341 [flutterView addSubview:childClippingView];
2343 [flutterView setNeedsLayout];
2344 [flutterView layoutIfNeeded];
2363 CGRect insideClipping = CGRectMake(3, 3, 2, 2);
2364 for (
int i = 0; i < 10; i++) {
2365 for (
int j = 0; j < 10; j++) {
2366 CGPoint point = CGPointMake(i, j);
2367 int alpha = [
self alphaOfPoint:CGPointMake(i, j) onView:flutterView];
2368 if (CGRectContainsPoint(insideClipping, point)) {
2369 XCTAssertEqual(alpha, 255);
2371 XCTAssertEqual(alpha, 0);
2377 - (void)testClipRRect {
2378 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
2384 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
2387 flutterPlatformViewsController,
2390 std::make_shared<fml::SyncSwitch>());
2394 [flutterPlatformViewsController
2396 withId:@"MockFlutterPlatformView"
2400 [flutterPlatformViewsController
2404 @"viewType" : @"MockFlutterPlatformView",
2405 @"gestureBlockingPolicy" : @"eager"
2411 UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
2412 flutterPlatformViewsController.
flutterView = flutterView;
2414 flutter::MutatorsStack stack;
2416 flutter::DlScalar screenScale = [UIScreen mainScreen].scale;
2417 flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
2418 stack.PushTransform(screenScaleMatrix);
2420 flutter::DlRoundRect rrect =
2421 flutter::DlRoundRect::MakeRectXY(flutter::DlRect::MakeXYWH(2, 2, 6, 6), 1, 1);
2422 stack.PushClipRRect(rrect);
2424 auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
2425 screenScaleMatrix, flutter::DlSize(10, 10), stack);
2427 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
2428 withParams:std::move(embeddedViewParams)];
2429 [flutterPlatformViewsController
2436 [flutterView addSubview:childClippingView];
2438 [flutterView setNeedsLayout];
2439 [flutterView layoutIfNeeded];
2460 CGRect innerClipping1 = CGRectMake(3, 2, 4, 6);
2461 CGRect innerClipping2 = CGRectMake(2, 3, 6, 4);
2462 CGRect outterClipping = CGRectMake(2, 2, 6, 6);
2463 for (
int i = 0; i < 10; i++) {
2464 for (
int j = 0; j < 10; j++) {
2465 CGPoint point = CGPointMake(i, j);
2466 int alpha = [
self alphaOfPoint:CGPointMake(i, j) onView:flutterView];
2467 if (CGRectContainsPoint(innerClipping1, point) ||
2468 CGRectContainsPoint(innerClipping2, point)) {
2470 XCTAssertEqual(alpha, 255);
2471 }
else if (CGRectContainsPoint(outterClipping, point)) {
2473 XCTAssert(0 < alpha && alpha < 255);
2476 XCTAssertEqual(alpha, 0);
2482 - (void)testClipRRect_multipleClips {
2483 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
2489 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
2492 flutterPlatformViewsController,
2495 std::make_shared<fml::SyncSwitch>());
2499 [flutterPlatformViewsController
2501 withId:@"MockFlutterPlatformView"
2505 [flutterPlatformViewsController
2509 @"viewType" : @"MockFlutterPlatformView",
2510 @"gestureBlockingPolicy" : @"eager"
2516 UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
2517 flutterPlatformViewsController.
flutterView = flutterView;
2519 flutter::MutatorsStack stack;
2521 flutter::DlScalar screenScale = [UIScreen mainScreen].scale;
2522 flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
2523 stack.PushTransform(screenScaleMatrix);
2525 flutter::DlRoundRect rrect =
2526 flutter::DlRoundRect::MakeRectXY(flutter::DlRect::MakeXYWH(2, 2, 6, 6), 1, 1);
2527 stack.PushClipRRect(rrect);
2529 flutter::DlRect rect = flutter::DlRect::MakeXYWH(4, 2, 6, 6);
2530 stack.PushClipRect(rect);
2532 auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
2533 screenScaleMatrix, flutter::DlSize(10, 10), stack);
2535 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
2536 withParams:std::move(embeddedViewParams)];
2537 [flutterPlatformViewsController
2544 [flutterView addSubview:childClippingView];
2546 [flutterView setNeedsLayout];
2547 [flutterView layoutIfNeeded];
2568 CGRect clipping = CGRectMake(4, 2, 4, 6);
2569 for (
int i = 0; i < 10; i++) {
2570 for (
int j = 0; j < 10; j++) {
2571 CGPoint point = CGPointMake(i, j);
2572 int alpha = [
self alphaOfPoint:CGPointMake(i, j) onView:flutterView];
2573 if (i == 7 && (j == 2 || j == 7)) {
2575 XCTAssert(0 < alpha && alpha < 255);
2578 (i == 4 && j >= 2 && j <= 7) ||
2580 (i == 7 && j >= 2 && j <= 7) ||
2582 (j == 2 && i >= 4 && i <= 7) ||
2584 (j == 7 && i >= 4 && i <= 7)) {
2587 XCTAssert(alpha > 127);
2588 }
else if ((i == 3 && j >= 1 && j <= 8) || (i == 8 && j >= 1 && j <= 8) ||
2589 (j == 1 && i >= 3 && i <= 8) || (j == 8 && i >= 3 && i <= 8)) {
2592 XCTAssert(alpha < 127);
2593 }
else if (CGRectContainsPoint(clipping, point)) {
2595 XCTAssertEqual(alpha, 255);
2598 XCTAssertEqual(alpha, 0);
2604 - (void)testClipPath {
2605 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
2611 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
2614 flutterPlatformViewsController,
2617 std::make_shared<fml::SyncSwitch>());
2621 [flutterPlatformViewsController
2623 withId:@"MockFlutterPlatformView"
2627 [flutterPlatformViewsController
2631 @"viewType" : @"MockFlutterPlatformView",
2632 @"gestureBlockingPolicy" : @"eager"
2638 UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
2639 flutterPlatformViewsController.
flutterView = flutterView;
2641 flutter::MutatorsStack stack;
2643 flutter::DlScalar screenScale = [UIScreen mainScreen].scale;
2644 flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
2645 stack.PushTransform(screenScaleMatrix);
2647 flutter::DlPath path =
2648 flutter::DlPath::MakeRoundRectXY(flutter::DlRect::MakeXYWH(2, 2, 6, 6), 1, 1);
2649 stack.PushClipPath(path);
2651 auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
2652 screenScaleMatrix, flutter::DlSize(10, 10), stack);
2654 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
2655 withParams:std::move(embeddedViewParams)];
2656 [flutterPlatformViewsController
2663 [flutterView addSubview:childClippingView];
2665 [flutterView setNeedsLayout];
2666 [flutterView layoutIfNeeded];
2687 CGRect innerClipping1 = CGRectMake(3, 2, 4, 6);
2688 CGRect innerClipping2 = CGRectMake(2, 3, 6, 4);
2689 CGRect outterClipping = CGRectMake(2, 2, 6, 6);
2690 for (
int i = 0; i < 10; i++) {
2691 for (
int j = 0; j < 10; j++) {
2692 CGPoint point = CGPointMake(i, j);
2693 int alpha = [
self alphaOfPoint:CGPointMake(i, j) onView:flutterView];
2694 if (CGRectContainsPoint(innerClipping1, point) ||
2695 CGRectContainsPoint(innerClipping2, point)) {
2697 XCTAssertEqual(alpha, 255);
2698 }
else if (CGRectContainsPoint(outterClipping, point)) {
2700 XCTAssert(0 < alpha && alpha < 255);
2703 XCTAssertEqual(alpha, 0);
2709 - (void)testClipPath_multipleClips {
2710 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
2716 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
2719 flutterPlatformViewsController,
2722 std::make_shared<fml::SyncSwitch>());
2726 [flutterPlatformViewsController
2728 withId:@"MockFlutterPlatformView"
2732 [flutterPlatformViewsController
2736 @"viewType" : @"MockFlutterPlatformView",
2737 @"gestureBlockingPolicy" : @"eager"
2743 UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
2744 flutterPlatformViewsController.
flutterView = flutterView;
2746 flutter::MutatorsStack stack;
2748 flutter::DlScalar screenScale = [UIScreen mainScreen].scale;
2749 flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
2750 stack.PushTransform(screenScaleMatrix);
2752 flutter::DlPath path =
2753 flutter::DlPath::MakeRoundRectXY(flutter::DlRect::MakeXYWH(2, 2, 6, 6), 1, 1);
2754 stack.PushClipPath(path);
2756 flutter::DlRect rect = flutter::DlRect::MakeXYWH(4, 2, 6, 6);
2757 stack.PushClipRect(rect);
2759 auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
2760 screenScaleMatrix, flutter::DlSize(10, 10), stack);
2762 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
2763 withParams:std::move(embeddedViewParams)];
2764 [flutterPlatformViewsController
2771 [flutterView addSubview:childClippingView];
2773 [flutterView setNeedsLayout];
2774 [flutterView layoutIfNeeded];
2795 CGRect clipping = CGRectMake(4, 2, 4, 6);
2796 for (
int i = 0; i < 10; i++) {
2797 for (
int j = 0; j < 10; j++) {
2798 CGPoint point = CGPointMake(i, j);
2799 int alpha = [
self alphaOfPoint:CGPointMake(i, j) onView:flutterView];
2800 if (i == 7 && (j == 2 || j == 7)) {
2802 XCTAssert(0 < alpha && alpha < 255);
2805 (i == 4 && j >= 2 && j <= 7) ||
2807 (i == 7 && j >= 2 && j <= 7) ||
2809 (j == 2 && i >= 4 && i <= 7) ||
2811 (j == 7 && i >= 4 && i <= 7)) {
2814 XCTAssert(alpha > 127);
2815 }
else if ((i == 3 && j >= 1 && j <= 8) || (i == 8 && j >= 1 && j <= 8) ||
2816 (j == 1 && i >= 3 && i <= 8) || (j == 8 && i >= 3 && i <= 8)) {
2819 XCTAssert(alpha < 127);
2820 }
else if (CGRectContainsPoint(clipping, point)) {
2822 XCTAssertEqual(alpha, 255);
2825 XCTAssertEqual(alpha, 0);
2831 - (void)testSetFlutterViewControllerAfterCreateCanStillDispatchTouchEvents {
2832 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
2838 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
2841 flutterPlatformViewsController,
2844 std::make_shared<fml::SyncSwitch>());
2848 [flutterPlatformViewsController
2850 withId:@"MockFlutterPlatformView"
2854 [flutterPlatformViewsController
2858 @"viewType" : @"MockFlutterPlatformView",
2859 @"gestureBlockingPolicy" : @"eager"
2866 XCTAssertNotNil(touchInterceptorView);
2868 UIGestureRecognizer* forwardGectureRecognizer =
2869 FindForwardingGestureRecognizer(touchInterceptorView);
2872 NSSet* touches1 = [[NSSet alloc] init];
2873 id event1 = OCMClassMock([UIEvent
class]);
2875 [forwardGectureRecognizer touchesBegan:touches1 withEvent:event1];
2876 OCMReject([flutterViewController touchesBegan:touches1 withEvent:event1]);
2879 NSSet* touches2 = [[NSSet alloc] init];
2880 id event2 = OCMClassMock([UIEvent
class]);
2882 [forwardGectureRecognizer touchesBegan:touches2 withEvent:event2];
2883 OCMVerify([flutterViewController touchesBegan:touches2 withEvent:event2]);
2886 - (void)testSetFlutterViewControllerInTheMiddleOfTouchEventShouldStillAllowGesturesToBeHandled {
2887 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
2893 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
2896 flutterPlatformViewsController,
2899 std::make_shared<fml::SyncSwitch>());
2903 [flutterPlatformViewsController
2905 withId:@"MockFlutterPlatformView"
2909 [flutterPlatformViewsController
2913 @"viewType" : @"MockFlutterPlatformView",
2914 @"gestureBlockingPolicy" : @"eager"
2921 XCTAssertNotNil(touchInterceptorView);
2923 UIGestureRecognizer* forwardGectureRecognizer =
2924 FindForwardingGestureRecognizer(touchInterceptorView);
2930 NSSet* touches1 = [[NSSet alloc] init];
2931 id event1 = OCMClassMock([UIEvent
class]);
2932 [forwardGectureRecognizer touchesBegan:touches1 withEvent:event1];
2933 OCMVerify([flutterViewController touchesBegan:touches1 withEvent:event1]);
2938 NSSet* touches2 = [[NSSet alloc] init];
2939 id event2 = OCMClassMock([UIEvent
class]);
2940 [forwardGectureRecognizer touchesMoved:touches2 withEvent:event2];
2941 OCMVerify([flutterViewController touchesMoved:touches2 withEvent:event2]);
2943 NSSet* touches3 = [[NSSet alloc] init];
2944 id event3 = OCMClassMock([UIEvent
class]);
2945 [forwardGectureRecognizer touchesEnded:touches3 withEvent:event3];
2946 OCMVerify([flutterViewController touchesEnded:touches3 withEvent:event3]);
2949 NSSet* touches4 = [[NSSet alloc] init];
2950 id event4 = OCMClassMock([UIEvent
class]);
2951 [forwardGectureRecognizer touchesBegan:touches4 withEvent:event4];
2952 OCMReject([flutterViewController touchesBegan:touches4 withEvent:event4]);
2954 NSSet* touches5 = [[NSSet alloc] init];
2955 id event5 = OCMClassMock([UIEvent
class]);
2956 [forwardGectureRecognizer touchesEnded:touches5 withEvent:event5];
2957 OCMReject([flutterViewController touchesEnded:touches5 withEvent:event5]);
2964 NSSet* touches1 = [[NSSet alloc] init];
2965 id event1 = OCMClassMock([UIEvent
class]);
2966 [forwardGectureRecognizer touchesBegan:touches1 withEvent:event1];
2967 OCMVerify([flutterViewController touchesBegan:touches1 withEvent:event1]);
2972 NSSet* touches2 = [[NSSet alloc] init];
2973 id event2 = OCMClassMock([UIEvent
class]);
2974 [forwardGectureRecognizer touchesMoved:touches2 withEvent:event2];
2975 OCMVerify([flutterViewController touchesMoved:touches2 withEvent:event2]);
2977 NSSet* touches3 = [[NSSet alloc] init];
2978 id event3 = OCMClassMock([UIEvent
class]);
2979 [forwardGectureRecognizer touchesCancelled:touches3 withEvent:event3];
2980 OCMVerify([flutterViewController forceTouchesCancelled:touches3]);
2983 NSSet* touches4 = [[NSSet alloc] init];
2984 id event4 = OCMClassMock([UIEvent
class]);
2985 [forwardGectureRecognizer touchesBegan:touches4 withEvent:event4];
2986 OCMReject([flutterViewController touchesBegan:touches4 withEvent:event4]);
2988 NSSet* touches5 = [[NSSet alloc] init];
2989 id event5 = OCMClassMock([UIEvent
class]);
2990 [forwardGectureRecognizer touchesEnded:touches5 withEvent:event5];
2991 OCMReject([flutterViewController touchesEnded:touches5 withEvent:event5]);
2994 [flutterPlatformViewsController
reset];
2998 testSetFlutterViewControllerInTheMiddleOfTouchEventAllowsTheNewControllerToHandleSecondTouchSequence {
2999 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
3005 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
3008 flutterPlatformViewsController,
3011 std::make_shared<fml::SyncSwitch>());
3015 [flutterPlatformViewsController
3017 withId:@"MockFlutterPlatformView"
3021 [flutterPlatformViewsController
3025 @"viewType" : @"MockFlutterPlatformView",
3026 @"gestureBlockingPolicy" : @"eager"
3033 XCTAssertNotNil(touchInterceptorView);
3035 UIGestureRecognizer* forwardGectureRecognizer =
3036 FindForwardingGestureRecognizer(touchInterceptorView);
3041 NSSet* touches1 = [NSSet setWithObject:@1];
3042 id event1 = OCMClassMock([UIEvent
class]);
3043 [forwardGectureRecognizer touchesBegan:touches1 withEvent:event1];
3044 OCMVerify([flutterViewController touchesBegan:touches1 withEvent:event1]);
3051 NSSet* touches2 = [NSSet setWithObject:@1];
3052 id event2 = OCMClassMock([UIEvent
class]);
3053 [forwardGectureRecognizer touchesBegan:touches2 withEvent:event2];
3054 OCMVerify([flutterViewController touchesBegan:touches2 withEvent:event2]);
3055 OCMReject([flutterViewController2 touchesBegan:touches2 withEvent:event2]);
3057 NSSet* touches3 = [NSSet setWithObject:@1];
3058 id event3 = OCMClassMock([UIEvent
class]);
3059 [forwardGectureRecognizer touchesMoved:touches3 withEvent:event3];
3060 OCMVerify([flutterViewController touchesMoved:touches3 withEvent:event3]);
3061 OCMReject([flutterViewController2 touchesMoved:touches3 withEvent:event3]);
3063 NSSet* touches4 = [NSSet setWithObject:@1];
3064 id event4 = OCMClassMock([UIEvent
class]);
3065 [forwardGectureRecognizer touchesEnded:touches4 withEvent:event4];
3066 OCMVerify([flutterViewController touchesEnded:touches4 withEvent:event4]);
3067 OCMReject([flutterViewController2 touchesEnded:touches4 withEvent:event4]);
3069 NSSet* touches5 = [NSSet setWithObject:@1];
3070 id event5 = OCMClassMock([UIEvent
class]);
3071 [forwardGectureRecognizer touchesEnded:touches5 withEvent:event5];
3072 OCMVerify([flutterViewController touchesEnded:touches5 withEvent:event5]);
3073 OCMReject([flutterViewController2 touchesEnded:touches5 withEvent:event5]);
3077 NSSet* touches6 = [NSSet setWithObject:@1];
3078 id event6 = OCMClassMock([UIEvent
class]);
3079 [forwardGectureRecognizer touchesBegan:touches6 withEvent:event6];
3080 OCMVerify([flutterViewController2 touchesBegan:touches6 withEvent:event6]);
3081 OCMReject([flutterViewController touchesBegan:touches6 withEvent:event6]);
3084 NSSet* touches7 = [NSSet setWithObject:@1];
3085 id event7 = OCMClassMock([UIEvent
class]);
3086 [forwardGectureRecognizer touchesMoved:touches7 withEvent:event7];
3087 OCMVerify([flutterViewController2 touchesMoved:touches7 withEvent:event7]);
3088 OCMReject([flutterViewController touchesMoved:touches7 withEvent:event7]);
3090 NSSet* touches8 = [NSSet setWithObject:@1];
3091 id event8 = OCMClassMock([UIEvent
class]);
3092 [forwardGectureRecognizer touchesEnded:touches8 withEvent:event8];
3093 OCMVerify([flutterViewController2 touchesEnded:touches8 withEvent:event8]);
3094 OCMReject([flutterViewController touchesEnded:touches8 withEvent:event8]);
3096 [flutterPlatformViewsController
reset];
3099 - (void)testFlutterPlatformViewTouchesCancelledEventAreForcedToBeCancelled {
3100 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
3106 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
3109 flutterPlatformViewsController,
3112 std::make_shared<fml::SyncSwitch>());
3116 [flutterPlatformViewsController
3118 withId:@"MockFlutterPlatformView"
3122 [flutterPlatformViewsController
3126 @"viewType" : @"MockFlutterPlatformView",
3127 @"gestureBlockingPolicy" : @"eager"
3134 XCTAssertNotNil(touchInterceptorView);
3136 UIGestureRecognizer* forwardGectureRecognizer =
3137 FindForwardingGestureRecognizer(touchInterceptorView);
3141 NSSet* touches1 = [NSSet setWithObject:@1];
3142 id event1 = OCMClassMock([UIEvent
class]);
3143 [forwardGectureRecognizer touchesBegan:touches1 withEvent:event1];
3145 [forwardGectureRecognizer touchesCancelled:touches1 withEvent:event1];
3146 OCMVerify([flutterViewController forceTouchesCancelled:touches1]);
3148 [flutterPlatformViewsController
reset];
3151 - (void)testFlutterPlatformViewTouchesEndedOrTouchesCancelledEventDoesNotFailTheGestureRecognizer {
3156 if (@available(iOS 26.0, *)) {
3160 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
3166 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
3169 flutterPlatformViewsController,
3172 std::make_shared<fml::SyncSwitch>());
3176 [flutterPlatformViewsController
3178 withId:@"MockFlutterPlatformView"
3182 [flutterPlatformViewsController
3186 @"viewType" : @"MockFlutterPlatformView",
3187 @"gestureBlockingPolicy" : @"eager"
3194 XCTAssertNotNil(touchInterceptorView);
3196 __block UIGestureRecognizer* forwardGestureRecognizer =
3197 FindForwardingGestureRecognizer(touchInterceptorView);
3201 NSSet* touches1 = [NSSet setWithObject:@1];
3202 id event1 = OCMClassMock([UIEvent
class]);
3203 XCTAssert(forwardGestureRecognizer.state == UIGestureRecognizerStatePossible,
3204 @"Forwarding gesture recognizer must start with possible state.");
3205 [forwardGestureRecognizer touchesBegan:touches1 withEvent:event1];
3206 [forwardGestureRecognizer touchesEnded:touches1 withEvent:event1];
3207 XCTAssert(forwardGestureRecognizer.state == UIGestureRecognizerStateFailed,
3208 @"Forwarding gesture recognizer must end with failed state.");
3210 XCTestExpectation* touchEndedExpectation =
3211 [
self expectationWithDescription:@"Wait for gesture recognizer's state change."];
3212 dispatch_async(dispatch_get_main_queue(), ^{
3214 forwardGestureRecognizer = FindForwardingGestureRecognizer(touchInterceptorView);
3215 XCTAssert(forwardGestureRecognizer.state == UIGestureRecognizerStatePossible,
3216 @"Forwarding gesture recognizer must be reset to possible state.");
3217 [touchEndedExpectation fulfill];
3219 [
self waitForExpectationsWithTimeout:30 handler:nil];
3221 XCTAssert(forwardGestureRecognizer.state == UIGestureRecognizerStatePossible,
3222 @"Forwarding gesture recognizer must start with possible state.");
3223 [forwardGestureRecognizer touchesBegan:touches1 withEvent:event1];
3224 [forwardGestureRecognizer touchesCancelled:touches1 withEvent:event1];
3225 XCTAssert(forwardGestureRecognizer.state == UIGestureRecognizerStateFailed,
3226 @"Forwarding gesture recognizer must end with failed state.");
3227 XCTestExpectation* touchCancelledExpectation =
3228 [
self expectationWithDescription:@"Wait for gesture recognizer's state change."];
3229 dispatch_async(dispatch_get_main_queue(), ^{
3231 forwardGestureRecognizer = FindForwardingGestureRecognizer(touchInterceptorView);
3232 XCTAssert(forwardGestureRecognizer.state == UIGestureRecognizerStatePossible,
3233 @"Forwarding gesture recognizer must be reset to possible state.");
3234 [touchCancelledExpectation fulfill];
3236 [
self waitForExpectationsWithTimeout:30 handler:nil];
3238 [flutterPlatformViewsController
reset];
3242 testFlutterPlatformViewBlockGestureUnderEagerPolicyShouldRemoveAndAddBackDelayingRecognizerForWebView {
3243 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
3249 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
3252 flutterPlatformViewsController,
3255 std::make_shared<fml::SyncSwitch>());
3259 [flutterPlatformViewsController
3265 [flutterPlatformViewsController
3269 @"viewType" : @"MockWebView",
3270 @"gestureBlockingPolicy" : @"eager"
3277 XCTAssertNotNil(touchInterceptorView);
3279 XCTAssert(touchInterceptorView.gestureRecognizers.count == 2);
3280 UIGestureRecognizer* delayingRecognizer = touchInterceptorView.gestureRecognizers[0];
3281 UIGestureRecognizer* forwardingRecognizer = touchInterceptorView.gestureRecognizers[1];
3288 BOOL shouldReAddDelayingRecognizer = NO;
3289 if (@available(iOS 26.0, *)) {
3293 }
else if (@available(iOS 18.2, *)) {
3294 shouldReAddDelayingRecognizer = YES;
3296 if (shouldReAddDelayingRecognizer) {
3298 XCTAssertEqual(touchInterceptorView.gestureRecognizers[0], forwardingRecognizer);
3299 XCTAssertEqual(touchInterceptorView.gestureRecognizers[1], delayingRecognizer);
3301 XCTAssertEqual(touchInterceptorView.gestureRecognizers[0], delayingRecognizer);
3302 XCTAssertEqual(touchInterceptorView.gestureRecognizers[1], forwardingRecognizer);
3307 testFlutterPlatformViewBlockGestureUnderEagerPolicyShouldRemoveAndAddBackDelayingRecognizerForWrapperWebView {
3308 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
3314 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
3317 flutterPlatformViewsController,
3320 std::make_shared<fml::SyncSwitch>());
3324 [flutterPlatformViewsController
3326 withId:@"MockWrapperWebView"
3330 [flutterPlatformViewsController
3335 @"viewType" : @"MockWrapperWebView",
3336 @"gestureBlockingPolicy" : @"fallbackToPluginDefault"
3343 XCTAssertNotNil(touchInterceptorView);
3345 XCTAssert(touchInterceptorView.gestureRecognizers.count == 2);
3346 UIGestureRecognizer* delayingRecognizer = touchInterceptorView.gestureRecognizers[0];
3347 UIGestureRecognizer* forwardingRecognizer = touchInterceptorView.gestureRecognizers[1];
3354 BOOL shouldReAddDelayingRecognizer = NO;
3355 if (@available(iOS 26.0, *)) {
3359 }
else if (@available(iOS 18.2, *)) {
3360 shouldReAddDelayingRecognizer = YES;
3362 if (shouldReAddDelayingRecognizer) {
3364 XCTAssertEqual(touchInterceptorView.gestureRecognizers[0], forwardingRecognizer);
3365 XCTAssertEqual(touchInterceptorView.gestureRecognizers[1], delayingRecognizer);
3367 XCTAssertEqual(touchInterceptorView.gestureRecognizers[0], delayingRecognizer);
3368 XCTAssertEqual(touchInterceptorView.gestureRecognizers[1], forwardingRecognizer);
3373 testFlutterPlatformViewBlockGestureUnderEagerPolicyShouldRemoveAndAddBackDelayingRecognizerForNestedWrapperWebView {
3374 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
3380 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
3383 flutterPlatformViewsController,
3386 std::make_shared<fml::SyncSwitch>());
3390 [flutterPlatformViewsController
3392 withId:@"MockNestedWrapperWebView"
3396 [flutterPlatformViewsController
3400 @"viewType" : @"MockNestedWrapperWebView",
3401 @"gestureBlockingPolicy" : @"eager"
3408 XCTAssertNotNil(touchInterceptorView);
3410 XCTAssert(touchInterceptorView.gestureRecognizers.count == 2);
3411 UIGestureRecognizer* delayingRecognizer = touchInterceptorView.gestureRecognizers[0];
3412 UIGestureRecognizer* forwardingRecognizer = touchInterceptorView.gestureRecognizers[1];
3419 BOOL shouldReAddDelayingRecognizer = NO;
3420 if (@available(iOS 26.0, *)) {
3424 }
else if (@available(iOS 18.2, *)) {
3425 shouldReAddDelayingRecognizer = YES;
3427 if (shouldReAddDelayingRecognizer) {
3429 XCTAssertEqual(touchInterceptorView.gestureRecognizers[0], forwardingRecognizer);
3430 XCTAssertEqual(touchInterceptorView.gestureRecognizers[1], delayingRecognizer);
3432 XCTAssertEqual(touchInterceptorView.gestureRecognizers[0], delayingRecognizer);
3433 XCTAssertEqual(touchInterceptorView.gestureRecognizers[1], forwardingRecognizer);
3438 testFlutterPlatformViewBlockGestureUnderEagerPolicyShouldNotRemoveAndAddBackDelayingRecognizerForNonWebView {
3439 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
3445 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
3448 flutterPlatformViewsController,
3451 std::make_shared<fml::SyncSwitch>());
3455 [flutterPlatformViewsController
3457 withId:@"MockFlutterPlatformView"
3461 [flutterPlatformViewsController
3465 @"viewType" : @"MockFlutterPlatformView",
3466 @"gestureBlockingPolicy" : @"eager"
3473 XCTAssertNotNil(touchInterceptorView);
3475 XCTAssert(touchInterceptorView.gestureRecognizers.count == 2);
3476 UIGestureRecognizer* delayingRecognizer = touchInterceptorView.gestureRecognizers[0];
3477 UIGestureRecognizer* forwardingRecognizer = touchInterceptorView.gestureRecognizers[1];
3484 XCTAssertEqual(touchInterceptorView.gestureRecognizers[0], delayingRecognizer);
3485 XCTAssertEqual(touchInterceptorView.gestureRecognizers[1], forwardingRecognizer);
3489 testFlutterPlatformViewBlockGestureUnderEagerPolicyShouldDisableAndReEnableTouchEventsGestureRecognizerForSimpleWebView {
3490 if (@available(iOS 26.4, *)) {
3492 }
else if (@available(iOS 26.0, *)) {
3493 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
3499 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
3502 flutterPlatformViewsController,
3505 std::make_shared<fml::SyncSwitch>());
3509 [flutterPlatformViewsController
3515 [flutterPlatformViewsController
3520 @"viewType" : @"MockWebView",
3521 @"gestureBlockingPolicy" : @"fallbackToPluginDefault"
3529 XCTAssertNotNil(touchInterceptorView);
3543 root.gestureRecognizers = nil;
3544 for (UIView* subview in root.subviews) {
3545 [subview removeFromSuperview];
3549 [root addGestureRecognizer:normalRecognizer0];
3551 UIView* child1 = [[UIView alloc] init];
3552 [root addSubview:child1];
3554 [child1 addGestureRecognizer:normalRecognizer1];
3556 UIView* child2 = [[UIView alloc] init];
3557 [root addSubview:child2];
3559 [child2 addGestureRecognizer:normalRecognizer2];
3561 UIView* child2_1 = [[UIView alloc] init];
3562 [child2 addSubview:child2_1];
3564 [child2_1 addGestureRecognizer:normalRecognizer2_1];
3566 UIView* child2_2 = [[UIView alloc] init];
3567 [child2 addSubview:child2_2];
3569 [child2_2 addGestureRecognizer:normalRecognizer2_2];
3574 [root addGestureRecognizer:targetRecognizer0];
3578 [child2_2 addGestureRecognizer:targetRecognizer2_2];
3582 NSArray* normalRecognizers = @[
3583 normalRecognizer0, normalRecognizer1, normalRecognizer2, normalRecognizer2_1,
3587 NSArray* targetRecognizers = @[ targetRecognizer0, targetRecognizer2_2 ];
3589 NSArray* expectedEmptyHistory = @[];
3590 NSArray* expectedToggledHistory = @[ @NO, @YES ];
3593 XCTAssertEqualObjects(recognizer.toggleHistory, expectedEmptyHistory);
3596 XCTAssertEqualObjects(recognizer.toggleHistory, expectedToggledHistory);
3602 testFlutterPlatformViewBlockGestureUnderEagerPolicyShouldDisableAndReEnableTouchEventsGestureRecognizerForMultipleWebViewInDifferentBranches {
3603 if (@available(iOS 26.4, *)) {
3605 }
else if (@available(iOS 26.0, *)) {
3606 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
3612 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
3615 flutterPlatformViewsController,
3618 std::make_shared<fml::SyncSwitch>());
3622 [flutterPlatformViewsController
3624 withId:@"MockWrapperWebView"
3628 [flutterPlatformViewsController
3633 @"viewType" : @"MockWrapperWebView",
3634 @"gestureBlockingPolicy" : @"fallbackToPluginDefault"
3642 XCTAssertNotNil(touchInterceptorView);
3660 for (UIView* subview in root.subviews) {
3661 [subview removeFromSuperview];
3665 [root addGestureRecognizer:normalRecognizer0];
3667 UIView* child1 = [[UIView alloc] init];
3668 [root addSubview:child1];
3670 [child1 addGestureRecognizer:normalRecognizer1];
3672 UIView* child2 = [[WKWebView alloc] init];
3673 child2.gestureRecognizers = nil;
3674 for (UIView* subview in child2.subviews) {
3675 [subview removeFromSuperview];
3677 [root addSubview:child2];
3679 [child2 addGestureRecognizer:normalRecognizer2];
3681 UIView* child2_1 = [[UIView alloc] init];
3682 [child2 addSubview:child2_1];
3684 [child2_1 addGestureRecognizer:normalRecognizer2_1];
3686 UIView* child2_2 = [[UIView alloc] init];
3687 [child2 addSubview:child2_2];
3689 [child2_2 addGestureRecognizer:normalRecognizer2_2];
3691 UIView* child3 = [[UIView alloc] init];
3692 [root addSubview:child3];
3694 [child3 addGestureRecognizer:normalRecognizer3];
3696 UIView* child3_1 = [[WKWebView alloc] init];
3697 child3_1.gestureRecognizers = nil;
3698 for (UIView* subview in child3_1.subviews) {
3699 [subview removeFromSuperview];
3701 [child3 addSubview:child3_1];
3703 [child3_1 addGestureRecognizer:normalRecognizer3_1];
3705 UIView* child3_1_1 = [[UIView alloc] init];
3706 [child3_1 addSubview:child3_1_1];
3708 [child3_1_1 addGestureRecognizer:normalRecognizer3_1_1];
3710 UIView* child3_1_2 = [[UIView alloc] init];
3711 [child3_1 addSubview:child3_1_2];
3713 [child3_1_2 addGestureRecognizer:normalRecognizer3_1_2];
3719 [child2_2 addGestureRecognizer:targetRecognizer2_2];
3723 [child3_1_2 addGestureRecognizer:targetRecognizer3_1_2];
3727 NSArray* normalRecognizers = @[
3728 normalRecognizer0, normalRecognizer1, normalRecognizer2, normalRecognizer2_1,
3729 normalRecognizer2_2, normalRecognizer3, normalRecognizer3_1, normalRecognizer3_1_1,
3730 normalRecognizer3_1_2
3732 NSArray* targetRecognizers = @[ targetRecognizer2_2, targetRecognizer3_1_2 ];
3734 NSArray* expectedEmptyHistory = @[];
3735 NSArray* expectedToggledHistory = @[ @NO, @YES ];
3738 XCTAssertEqualObjects(recognizer.toggleHistory, expectedEmptyHistory);
3742 XCTAssertEqualObjects(recognizer.toggleHistory, expectedToggledHistory);
3748 testFlutterPlatformViewBlockGestureUnderEagerPolicyShouldDisableAndReEnableTouchEventsGestureRecognizerForNestedMultipleWebView {
3749 if (@available(iOS 26.4, *)) {
3751 }
else if (@available(iOS 26.0, *)) {
3752 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
3758 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
3761 flutterPlatformViewsController,
3764 std::make_shared<fml::SyncSwitch>());
3768 [flutterPlatformViewsController
3774 [flutterPlatformViewsController
3779 @"viewType" : @"MockWebView",
3780 @"gestureBlockingPolicy" : @"fallbackToPluginDefault"
3788 XCTAssertNotNil(touchInterceptorView);
3808 root.gestureRecognizers = nil;
3809 for (UIView* subview in root.subviews) {
3810 [subview removeFromSuperview];
3814 [root addGestureRecognizer:normalRecognizer0];
3816 UIView* child1 = [[UIView alloc] init];
3817 [root addSubview:child1];
3819 [child1 addGestureRecognizer:normalRecognizer1];
3821 UIView* child2 = [[UIView alloc] init];
3822 [root addSubview:child2];
3824 [child2 addGestureRecognizer:normalRecognizer2];
3826 UIView* child2_1 = [[UIView alloc] init];
3827 [child2 addSubview:child2_1];
3829 [child2_1 addGestureRecognizer:normalRecognizer2_1];
3831 UIView* child2_2 = [[UIView alloc] init];
3832 [child2 addSubview:child2_2];
3834 [child2_2 addGestureRecognizer:normalRecognizer2_2];
3836 UIView* child3 = [[UIView alloc] init];
3837 [root addSubview:child3];
3839 [child3 addGestureRecognizer:normalRecognizer3];
3841 UIView* child3_1 = [[WKWebView alloc] init];
3842 child3_1.gestureRecognizers = nil;
3843 for (UIView* subview in child3_1.subviews) {
3844 [subview removeFromSuperview];
3846 [child3 addSubview:child3_1];
3848 [child3_1 addGestureRecognizer:normalRecognizer3_1];
3850 UIView* child3_1_1 = [[UIView alloc] init];
3851 [child3_1 addSubview:child3_1_1];
3853 [child3_1_1 addGestureRecognizer:normalRecognizer3_1_1];
3855 UIView* child3_1_2 = [[UIView alloc] init];
3856 [child3_1 addSubview:child3_1_2];
3858 [child3_1_2 addGestureRecognizer:normalRecognizer3_1_2];
3860 UIView* child3_1_2_1 = [[UIView alloc] init];
3861 [child3_1_2 addSubview:child3_1_2_1];
3863 [child3_1_2_1 addGestureRecognizer:normalRecognizer3_1_2_1];
3865 UIView* child3_1_2_2 = [[UIView alloc] init];
3866 [child3_1_2 addSubview:child3_1_2_2];
3868 [child3_1_2_2 addGestureRecognizer:normalRecognizer3_1_2_2];
3874 [child2_2 addGestureRecognizer:targetRecognizer2_2];
3878 [child3_1_2_2 addGestureRecognizer:targetRecognizer3_1_2_2];
3882 NSArray* normalRecognizers = @[
3883 normalRecognizer0, normalRecognizer1, normalRecognizer2, normalRecognizer2_1,
3884 normalRecognizer2_2, normalRecognizer3, normalRecognizer3_1, normalRecognizer3_1_1,
3885 normalRecognizer3_1_2, normalRecognizer3_1_2_1, normalRecognizer3_1_2_2
3888 NSArray* targetRecognizers = @[ targetRecognizer2_2, targetRecognizer3_1_2_2 ];
3890 NSArray* expectedEmptyHistory = @[];
3891 NSArray* expectedToggledHistory = @[ @NO, @YES ];
3894 XCTAssertEqualObjects(recognizer.toggleHistory, expectedEmptyHistory);
3898 XCTAssertEqualObjects(recognizer.toggleHistory, expectedToggledHistory);
3904 testFlutterPlatformViewGestureBlockingPolicy_ShouldNotAddDelayingRecognizerUnderDoNotBlockGesturePolicy {
3905 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
3911 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
3914 flutterPlatformViewsController,
3917 std::make_shared<fml::SyncSwitch>());
3922 withId:@"MockFlutterPlatformView"
3924 FlutterPlatformViewGestureRecognizersBlockingPolicyDoNotBlockGesture];
3927 [flutterPlatformViewsController
3932 @"viewType" : @"MockFlutterPlatformView",
3933 @"gestureBlockingPolicy" : @"doNotBlockGesture"
3940 XCTAssertNotNil(touchInterceptorView);
3942 XCTAssert(touchInterceptorView.gestureRecognizers.count == 1);
3943 UIGestureRecognizer* forwardingRecognizer = touchInterceptorView.gestureRecognizers[0];
3947 - (void)testFlutterPlatformViewGestureBlockingPolicy_ShouldAddDelayingRecognizerUnderEagerPolicy {
3948 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
3954 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
3957 flutterPlatformViewsController,
3960 std::make_shared<fml::SyncSwitch>());
3964 [flutterPlatformViewsController
3966 withId:@"MockFlutterPlatformView"
3970 [flutterPlatformViewsController
3974 @"viewType" : @"MockFlutterPlatformView",
3975 @"gestureBlockingPolicy" : @"eager"
3982 XCTAssertNotNil(touchInterceptorView);
3984 XCTAssert(touchInterceptorView.gestureRecognizers.count == 2);
3985 UIGestureRecognizer* delayingRecognizer = touchInterceptorView.gestureRecognizers[0];
3986 UIGestureRecognizer* forwardingRecognizer = touchInterceptorView.gestureRecognizers[1];
3991 - (void)testFlutterPlatformViewHitTest_AcceptTouchIfInstructedByFramework {
3992 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
4002 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
4005 flutterPlatformViewsController,
4008 std::make_shared<fml::SyncSwitch>());
4013 withId:@"MockFlutterPlatformView"
4015 FlutterPlatformViewGestureRecognizersBlockingPolicyDoNotBlockGesture];
4018 [flutterPlatformViewsController
4023 @"viewType" : @"MockFlutterPlatformView",
4024 @"gestureBlockingPolicy" : @"doNotBlockGesture"
4031 XCTAssertNotNil(touchInterceptorView);
4033 touchInterceptorView.frame = CGRectMake(0, 0, 100, 100);
4034 CGPoint touchBeganLocation = CGPointMake(1, 1);
4036 UIEvent* mockEvent = OCMClassMock([UIEvent
class]);
4037 OCMStub([mockEvent type]).andReturn(UIEventTypeTouches);
4040 OCMStub([mockFlutterViewController
4041 platformViewShouldAcceptTouchAtTouchBeganLocation:touchBeganLocation])
4043 UIView* hitTestResult = [touchInterceptorView hitTest:touchBeganLocation withEvent:mockEvent];
4048 - (void)testFlutterPlatformViewHitTest_RejectTouchIfInstructedByFramework {
4049 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
4059 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
4062 flutterPlatformViewsController,
4065 std::make_shared<fml::SyncSwitch>());
4070 withId:@"MockFlutterPlatformView"
4072 FlutterPlatformViewGestureRecognizersBlockingPolicyDoNotBlockGesture];
4075 [flutterPlatformViewsController
4080 @"viewType" : @"MockFlutterPlatformView",
4081 @"gestureBlockingPolicy" : @"doNotBlockGesture"
4088 XCTAssertNotNil(touchInterceptorView);
4090 touchInterceptorView.frame = CGRectMake(0, 0, 100, 100);
4091 CGPoint touchBeganLocation = CGPointMake(1, 1);
4093 UIEvent* mockEvent = OCMClassMock([UIEvent
class]);
4094 OCMStub([mockEvent type]).andReturn(UIEventTypeTouches);
4097 OCMStub([mockFlutterViewController
4098 platformViewShouldAcceptTouchAtTouchBeganLocation:touchBeganLocation])
4100 UIView* hitTestResult = [touchInterceptorView hitTest:touchBeganLocation withEvent:mockEvent];
4102 XCTAssert(hitTestResult == touchInterceptorView);
4105 - (void)testFlutterPlatformViewGestureBlockingPolicy_PolicyMappingIsCorrect {
4106 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
4116 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
4119 flutterPlatformViewsController,
4122 std::make_shared<fml::SyncSwitch>());
4127 withId:@"MockFlutterPlatformView"
4131 FlutterPlatformViewGestureRecognizersBlockingPolicyWaitUntilTouchesEnded];
4132 __block
id methodResult;
4134 methodResult = result;
4138 [flutterPlatformViewsController
4142 @"viewType" : @"MockFlutterPlatformView",
4143 @"gestureBlockingPolicy" : @"eager"
4152 [flutterPlatformViewsController
4157 @"viewType" : @"MockFlutterPlatformView",
4158 @"gestureBlockingPolicy" : @"waitUntilTouchesEnded"
4165 [flutterPlatformViewsController
4170 @"viewType" : @"MockFlutterPlatformView",
4171 @"gestureBlockingPolicy" : @"doNotBlockGesture"
4177 XCTAssertNil(methodResult);
4180 [flutterPlatformViewsController
4185 @"viewType" : @"MockFlutterPlatformView",
4186 @"gestureBlockingPolicy" : @"fallbackToPluginDefault"
4192 XCTAssertNil(methodResult);
4195 [flutterPlatformViewsController
4199 @"viewType" : @"MockFlutterPlatformView",
4200 @"gestureBlockingPolicy" : @"unknownPolicy"
4203 XCTAssertTrue([methodResult isKindOfClass:[
FlutterError class]]);
4205 XCTAssertEqualObjects(resultError.
code,
@"unknown_gesture_blocking_policy");
4206 XCTAssertEqualObjects(
4208 @"Trying to create a platform view with an unknown gesture blocking policy");
4209 XCTAssertEqualObjects(resultError.
details,
@"view id: '6'");
4212 - (void)testFlutterPlatformViewControllerSubmitFrameWithoutFlutterViewNotCrashing {
4213 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
4219 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
4222 flutterPlatformViewsController,
4225 std::make_shared<fml::SyncSwitch>());
4229 [flutterPlatformViewsController
4231 withId:@"MockFlutterPlatformView"
4235 [flutterPlatformViewsController
4239 @"viewType" : @"MockFlutterPlatformView",
4240 @"gestureBlockingPolicy" : @"eager"
4247 flutter::MutatorsStack stack;
4248 flutter::DlMatrix finalMatrix;
4250 auto embeddedViewParams_1 =
4251 std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, flutter::DlSize(300, 300), stack);
4253 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
4254 withParams:std::move(embeddedViewParams_1)];
4255 [flutterPlatformViewsController
4259 flutter::SurfaceFrame::FramebufferInfo framebuffer_info;
4260 auto mock_surface = std::make_unique<flutter::SurfaceFrame>(
4261 nullptr, framebuffer_info,
4262 [](
const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) {
return false; },
4263 [](
const flutter::SurfaceFrame& surface_frame) {
return true; },
4264 flutter::DlISize(800, 600));
4265 XCTAssertFalse([flutterPlatformViewsController
4266 submitFrame:std::move(mock_surface)
4267 withIosContext:std::make_shared<flutter::IOSContextNoop>()]);
4269 auto embeddedViewParams_2 =
4270 std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, flutter::DlSize(300, 300), stack);
4271 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
4272 withParams:std::move(embeddedViewParams_2)];
4273 [flutterPlatformViewsController
4277 auto mock_surface_submit_true = std::make_unique<flutter::SurfaceFrame>(
4278 nullptr, framebuffer_info,
4279 [](
const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) {
return true; },
4280 [](
const flutter::SurfaceFrame& surface_frame) {
return true; },
4281 flutter::DlISize(800, 600));
4282 XCTAssertTrue([flutterPlatformViewsController
4283 submitFrame:std::move(mock_surface_submit_true)
4284 withIosContext:std::make_shared<flutter::IOSContextNoop>()]);
4288 testFlutterPlatformViewControllerResetDeallocsPlatformViewWhenRootViewsNotBindedToFlutterView {
4289 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
4295 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
4298 flutterPlatformViewsController,
4301 std::make_shared<fml::SyncSwitch>());
4303 UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)];
4304 flutterPlatformViewsController.
flutterView = flutterView;
4308 [flutterPlatformViewsController
4310 withId:@"MockFlutterPlatformView"
4316 [flutterPlatformViewsController
4320 @"viewType" : @"MockFlutterPlatformView",
4321 @"gestureBlockingPolicy" : @"eager"
4325 flutter::MutatorsStack stack;
4326 flutter::DlMatrix finalMatrix;
4327 auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
4328 finalMatrix, flutter::DlSize(300, 300), stack);
4329 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
4330 withParams:std::move(embeddedViewParams)];
4336 [flutterPlatformViewsController
reset];
4341 - (void)testFlutterPlatformViewControllerBeginFrameShouldResetCompisitionOrder {
4342 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
4348 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
4351 flutterPlatformViewsController,
4354 std::make_shared<fml::SyncSwitch>());
4356 UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)];
4357 flutterPlatformViewsController.
flutterView = flutterView;
4361 [flutterPlatformViewsController
4363 withId:@"MockFlutterPlatformView"
4368 [flutterPlatformViewsController
4372 @"viewType" : @"MockFlutterPlatformView",
4373 @"gestureBlockingPolicy" : @"eager"
4379 [flutterPlatformViewsController beginFrameWithSize:flutter::DlISize(300, 300)];
4380 flutter::MutatorsStack stack;
4381 flutter::DlMatrix finalMatrix;
4382 auto embeddedViewParams1 =
4383 std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, flutter::DlSize(300, 300), stack);
4384 [flutterPlatformViewsController prerollCompositeEmbeddedView:0
4385 withParams:std::move(embeddedViewParams1)];
4386 [flutterPlatformViewsController
4393 [flutterPlatformViewsController beginFrameWithSize:flutter::DlISize(300, 300)];
4396 auto embeddedViewParams2 =
4397 std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, flutter::DlSize(300, 300), stack);
4398 [flutterPlatformViewsController prerollCompositeEmbeddedView:0
4399 withParams:std::move(embeddedViewParams2)];
4400 [flutterPlatformViewsController
4408 testFlutterPlatformViewControllerSubmitFrameShouldOrderSubviewsCorrectlyWithDifferentViewHierarchy {
4409 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
4415 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
4418 flutterPlatformViewsController,
4421 std::make_shared<fml::SyncSwitch>());
4423 UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)];
4424 flutterPlatformViewsController.
flutterView = flutterView;
4428 [flutterPlatformViewsController
4430 withId:@"MockFlutterPlatformView"
4434 [flutterPlatformViewsController
4438 @"viewType" : @"MockFlutterPlatformView",
4439 @"gestureBlockingPolicy" : @"eager"
4445 [flutterPlatformViewsController
4449 @"viewType" : @"MockFlutterPlatformView",
4450 @"gestureBlockingPolicy" : @"eager"
4455 [flutterPlatformViewsController beginFrameWithSize:flutter::DlISize(300, 300)];
4456 flutter::MutatorsStack stack;
4457 flutter::DlMatrix finalMatrix;
4458 auto embeddedViewParams1 =
4459 std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, flutter::DlSize(300, 300), stack);
4460 [flutterPlatformViewsController prerollCompositeEmbeddedView:0
4461 withParams:std::move(embeddedViewParams1)];
4463 auto embeddedViewParams2 =
4464 std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, flutter::DlSize(500, 500), stack);
4465 [flutterPlatformViewsController prerollCompositeEmbeddedView:1
4466 withParams:std::move(embeddedViewParams2)];
4468 flutter::SurfaceFrame::FramebufferInfo framebuffer_info;
4469 auto mock_surface = std::make_unique<flutter::SurfaceFrame>(
4470 nullptr, framebuffer_info,
4471 [](
const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) {
return true; },
4472 [](
const flutter::SurfaceFrame& surface_frame) {
return true; },
4473 flutter::DlISize(800, 600),
nullptr,
true);
4474 XCTAssertTrue([flutterPlatformViewsController
4475 submitFrame:std::move(mock_surface)
4476 withIosContext:std::make_shared<flutter::IOSContextNoop>()]);
4479 UIView* clippingView1 = view1.superview.superview;
4480 UIView* clippingView2 = view2.superview.superview;
4481 XCTAssertTrue([flutterView.subviews indexOfObject:clippingView1] <
4482 [flutterView.subviews indexOfObject:clippingView2],
4483 @"The first clipping view should be added before the second clipping view.");
4486 [flutterPlatformViewsController beginFrameWithSize:flutter::DlISize(300, 300)];
4488 embeddedViewParams2 =
4489 std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, flutter::DlSize(500, 500), stack);
4490 [flutterPlatformViewsController prerollCompositeEmbeddedView:1
4491 withParams:std::move(embeddedViewParams2)];
4493 embeddedViewParams1 =
4494 std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, flutter::DlSize(300, 300), stack);
4495 [flutterPlatformViewsController prerollCompositeEmbeddedView:0
4496 withParams:std::move(embeddedViewParams1)];
4498 mock_surface = std::make_unique<flutter::SurfaceFrame>(
4499 nullptr, framebuffer_info,
4500 [](
const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) {
return true; },
4501 [](
const flutter::SurfaceFrame& surface_frame) {
return true; },
4502 flutter::DlISize(800, 600),
nullptr,
true);
4503 XCTAssertTrue([flutterPlatformViewsController
4504 submitFrame:std::move(mock_surface)
4505 withIosContext:std::make_shared<flutter::IOSContextNoop>()]);
4507 XCTAssertTrue([flutterView.subviews indexOfObject:clippingView1] >
4508 [flutterView.subviews indexOfObject:clippingView2],
4509 @"The first clipping view should be added after the second clipping view.");
4513 testFlutterPlatformViewControllerSubmitFrameShouldOrderSubviewsCorrectlyWithSameViewHierarchy {
4514 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
4520 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
4523 flutterPlatformViewsController,
4526 std::make_shared<fml::SyncSwitch>());
4528 UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)];
4529 flutterPlatformViewsController.
flutterView = flutterView;
4533 [flutterPlatformViewsController
4535 withId:@"MockFlutterPlatformView"
4539 [flutterPlatformViewsController
4543 @"viewType" : @"MockFlutterPlatformView",
4544 @"gestureBlockingPolicy" : @"eager"
4550 [flutterPlatformViewsController
4554 @"viewType" : @"MockFlutterPlatformView",
4555 @"gestureBlockingPolicy" : @"eager"
4560 [flutterPlatformViewsController beginFrameWithSize:flutter::DlISize(300, 300)];
4561 flutter::MutatorsStack stack;
4562 flutter::DlMatrix finalMatrix;
4563 auto embeddedViewParams1 =
4564 std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, flutter::DlSize(300, 300), stack);
4565 [flutterPlatformViewsController prerollCompositeEmbeddedView:0
4566 withParams:std::move(embeddedViewParams1)];
4568 auto embeddedViewParams2 =
4569 std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, flutter::DlSize(500, 500), stack);
4570 [flutterPlatformViewsController prerollCompositeEmbeddedView:1
4571 withParams:std::move(embeddedViewParams2)];
4573 flutter::SurfaceFrame::FramebufferInfo framebuffer_info;
4574 auto mock_surface = std::make_unique<flutter::SurfaceFrame>(
4575 nullptr, framebuffer_info,
4576 [](
const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) {
return true; },
4577 [](
const flutter::SurfaceFrame& surface_frame) {
return true; },
4578 flutter::DlISize(800, 600),
nullptr,
true);
4579 XCTAssertTrue([flutterPlatformViewsController
4580 submitFrame:std::move(mock_surface)
4581 withIosContext:std::make_shared<flutter::IOSContextNoop>()]);
4584 UIView* clippingView1 = view1.superview.superview;
4585 UIView* clippingView2 = view2.superview.superview;
4586 XCTAssertTrue([flutterView.subviews indexOfObject:clippingView1] <
4587 [flutterView.subviews indexOfObject:clippingView2],
4588 @"The first clipping view should be added before the second clipping view.");
4591 [flutterPlatformViewsController beginFrameWithSize:flutter::DlISize(300, 300)];
4593 embeddedViewParams1 =
4594 std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, flutter::DlSize(300, 300), stack);
4595 [flutterPlatformViewsController prerollCompositeEmbeddedView:0
4596 withParams:std::move(embeddedViewParams1)];
4598 embeddedViewParams2 =
4599 std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, flutter::DlSize(500, 500), stack);
4600 [flutterPlatformViewsController prerollCompositeEmbeddedView:1
4601 withParams:std::move(embeddedViewParams2)];
4603 mock_surface = std::make_unique<flutter::SurfaceFrame>(
4604 nullptr, framebuffer_info,
4605 [](
const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) {
return true; },
4606 [](
const flutter::SurfaceFrame& surface_frame) {
return true; },
4607 flutter::DlISize(800, 600),
nullptr,
true);
4608 XCTAssertTrue([flutterPlatformViewsController
4609 submitFrame:std::move(mock_surface)
4610 withIosContext:std::make_shared<flutter::IOSContextNoop>()]);
4612 XCTAssertTrue([flutterView.subviews indexOfObject:clippingView1] <
4613 [flutterView.subviews indexOfObject:clippingView2],
4614 @"The first clipping view should be added before the second clipping view.");
4617 - (int)alphaOfPoint:(CGPoint)point onView:(UIView*)view {
4618 unsigned char pixel[4] = {0};
4620 CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
4623 CGContextRef context =
4624 CGBitmapContextCreate(pixel, 1, 1, 8, 4, colorSpace,
4625 static_cast<uint32_t
>(kCGBitmapAlphaInfoMask) &
4626 static_cast<uint32_t
>(kCGImageAlphaPremultipliedLast));
4627 CGContextTranslateCTM(context, -point.x, -point.y);
4628 [view.layer renderInContext:context];
4630 CGContextRelease(context);
4631 CGColorSpaceRelease(colorSpace);
4636 - (void)testHasFirstResponderInViewHierarchySubtree_viewItselfBecomesFirstResponder {
4638 UIWindow* window = [[UIWindow alloc] init];
4639 UITextField* textField = [[UITextField alloc] init];
4640 [window addSubview:textField];
4642 [textField becomeFirstResponder];
4643 XCTAssertTrue(textField.isFirstResponder);
4644 XCTAssertTrue(textField.flt_hasFirstResponderInViewHierarchySubtree);
4645 [textField resignFirstResponder];
4646 XCTAssertFalse(textField.isFirstResponder);
4647 XCTAssertFalse(textField.flt_hasFirstResponderInViewHierarchySubtree);
4650 - (void)testHasFirstResponderInViewHierarchySubtree_descendantViewBecomesFirstResponder {
4652 UIWindow* window = [[UIWindow alloc] init];
4653 UIView* view = [[UIView alloc] init];
4654 UIView* childView = [[UIView alloc] init];
4655 UITextField* textField = [[UITextField alloc] init];
4656 [window addSubview:view];
4657 [view addSubview:childView];
4658 [childView addSubview:textField];
4660 [textField becomeFirstResponder];
4661 XCTAssertTrue(textField.isFirstResponder);
4662 XCTAssertTrue(view.flt_hasFirstResponderInViewHierarchySubtree);
4663 [textField resignFirstResponder];
4664 XCTAssertFalse(textField.isFirstResponder);
4665 XCTAssertFalse(view.flt_hasFirstResponderInViewHierarchySubtree);
4668 - (void)testFlutterClippingMaskViewPoolReuseViewsAfterRecycle {
4674 CGRect newRect = CGRectMake(0, 0, 10, 10);
4678 NSSet* set1 = [NSSet setWithObjects:view1, view2, nil];
4679 NSSet* set2 = [NSSet setWithObjects:view3, view4, nil];
4680 XCTAssertEqualObjects(set1, set2);
4681 XCTAssertTrue(CGRectEqualToRect(view3.frame, newRect));
4682 XCTAssertTrue(CGRectEqualToRect(view4.frame, newRect));
4685 - (void)testFlutterClippingMaskViewPoolAllocsNewMaskViewsAfterReachingCapacity {
4690 XCTAssertNotEqual(view1, view3);
4691 XCTAssertNotEqual(view2, view3);
4694 - (void)testMaskViewsReleasedWhenPoolIsReleased {
4695 __weak UIView* weakView;
4700 XCTAssertNotNil(weakView);
4702 XCTAssertNil(weakView);
4705 - (void)testClipMaskViewIsReused {
4706 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
4712 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
4715 flutterPlatformViewsController,
4718 std::make_shared<fml::SyncSwitch>());
4722 [flutterPlatformViewsController
4724 withId:@"MockFlutterPlatformView"
4728 [flutterPlatformViewsController
4732 @"viewType" : @"MockFlutterPlatformView",
4733 @"gestureBlockingPolicy" : @"eager"
4738 UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
4739 flutterPlatformViewsController.
flutterView = flutterView;
4741 flutter::MutatorsStack stack1;
4743 flutter::DlScalar screenScale = [UIScreen mainScreen].scale;
4744 flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
4745 stack1.PushTransform(screenScaleMatrix);
4747 flutter::DlRect rect = flutter::DlRect::MakeXYWH(2, 2, 3, 3);
4748 stack1.PushClipRect(rect);
4750 auto embeddedViewParams1 = std::make_unique<flutter::EmbeddedViewParams>(
4751 screenScaleMatrix, flutter::DlSize(10, 10), stack1);
4753 [flutterPlatformViewsController prerollCompositeEmbeddedView:1
4754 withParams:std::move(embeddedViewParams1)];
4755 [flutterPlatformViewsController
4760 UIView* maskView1 = childClippingView1.maskView;
4761 XCTAssertNotNil(maskView1);
4764 [flutterPlatformViewsController beginFrameWithSize:flutter::DlISize(100, 100)];
4765 flutter::MutatorsStack stack2;
4766 auto embeddedViewParams2 = std::make_unique<flutter::EmbeddedViewParams>(
4767 screenScaleMatrix, flutter::DlSize(10, 10), stack2);
4768 auto embeddedViewParams3 = std::make_unique<flutter::EmbeddedViewParams>(
4769 screenScaleMatrix, flutter::DlSize(10, 10), stack2);
4770 [flutterPlatformViewsController prerollCompositeEmbeddedView:1
4771 withParams:std::move(embeddedViewParams3)];
4772 [flutterPlatformViewsController
4779 [flutterPlatformViewsController
4783 @"viewType" : @"MockFlutterPlatformView",
4784 @"gestureBlockingPolicy" : @"eager"
4788 auto embeddedViewParams4 = std::make_unique<flutter::EmbeddedViewParams>(
4789 screenScaleMatrix, flutter::DlSize(10, 10), stack1);
4790 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
4791 withParams:std::move(embeddedViewParams4)];
4792 [flutterPlatformViewsController
4798 UIView* maskView2 = childClippingView2.maskView;
4799 XCTAssertEqual(maskView1, maskView2);
4800 XCTAssertNotNil(childClippingView2.maskView);
4801 XCTAssertNil(childClippingView1.maskView);
4804 - (void)testDifferentClipMaskViewIsUsedForEachView {
4805 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
4811 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
4814 flutterPlatformViewsController,
4817 std::make_shared<fml::SyncSwitch>());
4821 [flutterPlatformViewsController
4823 withId:@"MockFlutterPlatformView"
4828 [flutterPlatformViewsController
4832 @"viewType" : @"MockFlutterPlatformView",
4833 @"gestureBlockingPolicy" : @"eager"
4839 [flutterPlatformViewsController
4843 @"viewType" : @"MockFlutterPlatformView",
4844 @"gestureBlockingPolicy" : @"eager"
4850 UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
4851 flutterPlatformViewsController.
flutterView = flutterView;
4853 flutter::MutatorsStack stack1;
4855 flutter::DlScalar screenScale = [UIScreen mainScreen].scale;
4856 flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
4857 stack1.PushTransform(screenScaleMatrix);
4859 flutter::DlRect rect = flutter::DlRect::MakeXYWH(2, 2, 3, 3);
4860 stack1.PushClipRect(rect);
4862 auto embeddedViewParams1 = std::make_unique<flutter::EmbeddedViewParams>(
4863 screenScaleMatrix, flutter::DlSize(10, 10), stack1);
4865 flutter::MutatorsStack stack2;
4866 stack2.PushClipRect(rect);
4867 auto embeddedViewParams2 = std::make_unique<flutter::EmbeddedViewParams>(
4868 screenScaleMatrix, flutter::DlSize(10, 10), stack2);
4870 [flutterPlatformViewsController prerollCompositeEmbeddedView:1
4871 withParams:std::move(embeddedViewParams1)];
4872 [flutterPlatformViewsController
4876 UIView* childClippingView1 = view1.superview.superview;
4878 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
4879 withParams:std::move(embeddedViewParams2)];
4880 [flutterPlatformViewsController
4884 UIView* childClippingView2 = view2.superview.superview;
4885 UIView* maskView1 = childClippingView1.maskView;
4886 UIView* maskView2 = childClippingView2.maskView;
4887 XCTAssertNotEqual(maskView1, maskView2);
4890 - (void)testMaskViewUsesCAShapeLayerAsTheBackingLayer {
4891 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
4897 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
4900 flutterPlatformViewsController,
4903 std::make_shared<fml::SyncSwitch>());
4907 [flutterPlatformViewsController
4909 withId:@"MockFlutterPlatformView"
4914 [flutterPlatformViewsController
4918 @"viewType" : @"MockFlutterPlatformView",
4919 @"gestureBlockingPolicy" : @"eager"
4924 UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
4925 flutterPlatformViewsController.
flutterView = flutterView;
4927 flutter::MutatorsStack stack1;
4929 flutter::DlScalar screenScale = [UIScreen mainScreen].scale;
4930 flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
4931 stack1.PushTransform(screenScaleMatrix);
4933 flutter::DlRect rect = flutter::DlRect::MakeXYWH(2, 2, 3, 3);
4934 stack1.PushClipRect(rect);
4936 auto embeddedViewParams1 = std::make_unique<flutter::EmbeddedViewParams>(
4937 screenScaleMatrix, flutter::DlSize(10, 10), stack1);
4939 flutter::MutatorsStack stack2;
4940 stack2.PushClipRect(rect);
4941 auto embeddedViewParams2 = std::make_unique<flutter::EmbeddedViewParams>(
4942 screenScaleMatrix, flutter::DlSize(10, 10), stack2);
4944 [flutterPlatformViewsController prerollCompositeEmbeddedView:1
4945 withParams:std::move(embeddedViewParams1)];
4946 [flutterPlatformViewsController
4952 UIView* maskView = childClippingView.maskView;
4953 XCTAssert([maskView.layer isKindOfClass:[CAShapeLayer
class]],
4954 @"Mask view must use CAShapeLayer as its backing layer.");
4962 - (BOOL)validateOneVisualEffectView:(UIView*)visualEffectView
4963 expectedFrame:(CGRect)frame
4964 inputRadius:(CGFloat)inputRadius {
4965 XCTAssertTrue(CGRectEqualToRect(visualEffectView.frame, frame));
4966 for (UIView* view in visualEffectView.subviews) {
4967 if (![NSStringFromClass([view
class]) hasSuffix:
@"BackdropView"]) {
4970 XCTAssertEqual(view.layer.filters.count, 1u);
4971 NSObject* filter = view.layer.filters.firstObject;
4973 XCTAssertEqualObjects([filter valueForKey:
@"name"],
@"gaussianBlur");
4975 NSObject* inputRadiusInFilter = [filter valueForKey:@"inputRadius"];
4976 XCTAssertTrue([inputRadiusInFilter isKindOfClass:[NSNumber
class]] &&
4977 flutter::BlurRadiusEqualToBlurRadius(((NSNumber*)inputRadiusInFilter).floatValue,
4984 - (void)testDisposingViewInCompositionOrderDoNotCrash {
4985 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
4991 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
4994 flutterPlatformViewsController,
4997 std::make_shared<fml::SyncSwitch>());
4999 UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)];
5000 flutterPlatformViewsController.
flutterView = flutterView;
5004 [flutterPlatformViewsController
5006 withId:@"MockFlutterPlatformView"
5011 [flutterPlatformViewsController
5015 @"viewType" : @"MockFlutterPlatformView",
5016 @"gestureBlockingPolicy" : @"eager"
5019 [flutterPlatformViewsController
5023 @"viewType" : @"MockFlutterPlatformView",
5024 @"gestureBlockingPolicy" : @"eager"
5031 [flutterPlatformViewsController beginFrameWithSize:flutter::DlISize(300, 300)];
5032 flutter::MutatorsStack stack;
5033 flutter::DlMatrix finalMatrix;
5034 auto embeddedViewParams0 = std::make_unique<flutter::EmbeddedViewParams>(
5035 finalMatrix, flutter::DlSize(300, 300), stack);
5036 [flutterPlatformViewsController prerollCompositeEmbeddedView:0
5037 withParams:std::move(embeddedViewParams0)];
5039 auto embeddedViewParams1 = std::make_unique<flutter::EmbeddedViewParams>(
5040 finalMatrix, flutter::DlSize(300, 300), stack);
5041 [flutterPlatformViewsController prerollCompositeEmbeddedView:1
5042 withParams:std::move(embeddedViewParams1)];
5046 XCTestExpectation* expectation = [
self expectationWithDescription:@"dispose call ended."];
5048 [expectation fulfill];
5051 [flutterPlatformViewsController
5054 [
self waitForExpectationsWithTimeout:30 handler:nil];
5056 flutter::SurfaceFrame::FramebufferInfo framebuffer_info;
5057 auto mock_surface = std::make_unique<flutter::SurfaceFrame>(
5058 nullptr, framebuffer_info,
5059 [](
const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) {
return true; },
5060 [](
const flutter::SurfaceFrame& surface_frame) {
return true; },
5061 flutter::DlISize(800, 600),
nullptr,
5063 XCTAssertTrue([flutterPlatformViewsController
5064 submitFrame:std::move(mock_surface)
5065 withIosContext:std::make_shared<flutter::IOSContextNoop>()]);
5069 XCTAssertNotNil([flutterPlatformViewsController platformViewForId:0]);
5070 XCTAssertNotNil([flutterPlatformViewsController platformViewForId:1]);
5076 [flutterPlatformViewsController beginFrameWithSize:flutter::DlISize(300, 300)];
5077 flutter::MutatorsStack stack;
5078 flutter::DlMatrix finalMatrix;
5079 auto embeddedViewParams1 = std::make_unique<flutter::EmbeddedViewParams>(
5080 finalMatrix, flutter::DlSize(300, 300), stack);
5081 [flutterPlatformViewsController prerollCompositeEmbeddedView:1
5082 withParams:std::move(embeddedViewParams1)];
5084 flutter::SurfaceFrame::FramebufferInfo framebuffer_info;
5085 auto mock_surface = std::make_unique<flutter::SurfaceFrame>(
5086 nullptr, framebuffer_info,
5087 [](
const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) {
return true; },
5088 [](
const flutter::SurfaceFrame& surface_frame) {
return true; },
5089 flutter::DlISize(800, 600),
nullptr,
true);
5090 XCTAssertTrue([flutterPlatformViewsController
5091 submitFrame:std::move(mock_surface)
5092 withIosContext:std::make_shared<flutter::IOSContextNoop>()]);
5096 XCTAssertNil([flutterPlatformViewsController platformViewForId:0]);
5097 XCTAssertNotNil([flutterPlatformViewsController platformViewForId:1]);
5100 - (void)testOnlyPlatformViewsAreRemovedWhenReset {
5101 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
5107 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
5110 flutterPlatformViewsController,
5113 std::make_shared<fml::SyncSwitch>());
5117 [flutterPlatformViewsController
5119 withId:@"MockFlutterPlatformView"
5123 [flutterPlatformViewsController
5127 @"viewType" : @"MockFlutterPlatformView",
5128 @"gestureBlockingPolicy" : @"eager"
5131 UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)];
5132 flutterPlatformViewsController.
flutterView = flutterView;
5134 flutter::MutatorsStack stack;
5136 flutter::DlScalar screenScale = [UIScreen mainScreen].scale;
5137 flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
5138 stack.PushTransform(screenScaleMatrix);
5140 flutter::DlMatrix translateMatrix = flutter::DlMatrix::MakeTranslation({100, 100});
5141 stack.PushTransform(translateMatrix);
5142 flutter::DlMatrix finalMatrix = screenScaleMatrix * translateMatrix;
5144 auto embeddedViewParams =
5145 std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, flutter::DlSize(300, 300), stack);
5147 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
5148 withParams:std::move(embeddedViewParams)];
5150 flutter::SurfaceFrame::FramebufferInfo framebuffer_info;
5151 auto mock_surface = std::make_unique<flutter::SurfaceFrame>(
5152 nullptr, framebuffer_info,
5153 [](
const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) {
return true; },
5154 [](
const flutter::SurfaceFrame& surface_frame) {
return true; },
5155 flutter::DlISize(800, 600),
nullptr,
true);
5156 [flutterPlatformViewsController submitFrame:std::move(mock_surface)
5157 withIosContext:std::make_shared<flutter::IOSContextNoop>()];
5159 UIView* someView = [[UIView alloc] init];
5160 [flutterView addSubview:someView];
5162 [flutterPlatformViewsController
reset];
5163 XCTAssertEqual(flutterView.subviews.count, 1u);
5164 XCTAssertEqual(flutterView.subviews.firstObject, someView);
5167 - (void)testResetClearsPreviousCompositionOrder {
5168 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
5174 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
5177 flutterPlatformViewsController,
5180 std::make_shared<fml::SyncSwitch>());
5184 [flutterPlatformViewsController
5186 withId:@"MockFlutterPlatformView"
5190 [flutterPlatformViewsController
5194 @"viewType" : @"MockFlutterPlatformView",
5195 @"gestureBlockingPolicy" : @"eager"
5198 UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)];
5199 flutterPlatformViewsController.
flutterView = flutterView;
5201 flutter::MutatorsStack stack;
5203 flutter::DlScalar screenScale = [UIScreen mainScreen].scale;
5204 flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
5205 stack.PushTransform(screenScaleMatrix);
5207 flutter::DlMatrix translateMatrix = flutter::DlMatrix::MakeTranslation({100, 100});
5208 stack.PushTransform(translateMatrix);
5209 flutter::DlMatrix finalMatrix = screenScaleMatrix * translateMatrix;
5211 auto embeddedViewParams =
5212 std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, flutter::DlSize(300, 300), stack);
5214 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
5215 withParams:std::move(embeddedViewParams)];
5217 flutter::SurfaceFrame::FramebufferInfo framebuffer_info;
5218 auto mock_surface = std::make_unique<flutter::SurfaceFrame>(
5219 nullptr, framebuffer_info,
5220 [](
const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) {
return true; },
5221 [](
const flutter::SurfaceFrame& surface_frame) {
return true; },
5222 flutter::DlISize(800, 600),
nullptr,
true);
5223 [flutterPlatformViewsController submitFrame:std::move(mock_surface)
5224 withIosContext:std::make_shared<flutter::IOSContextNoop>()];
5230 [flutterPlatformViewsController
reset];
5236 - (void)testNilPlatformViewDoesntCrash {
5237 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
5243 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
5246 flutterPlatformViewsController,
5249 std::make_shared<fml::SyncSwitch>());
5253 [flutterPlatformViewsController
5255 withId:@"MockFlutterPlatformView"
5259 [flutterPlatformViewsController
5263 @"viewType" : @"MockFlutterPlatformView",
5264 @"gestureBlockingPolicy" : @"eager"
5267 UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)];
5268 flutterPlatformViewsController.
flutterView = flutterView;
5271 flutter::MutatorsStack stack;
5273 flutter::DlScalar screenScale = [UIScreen mainScreen].scale;
5274 flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
5275 stack.PushTransform(screenScaleMatrix);
5277 flutter::DlMatrix translateMatrix = flutter::DlMatrix::MakeTranslation({100, 100});
5278 stack.PushTransform(translateMatrix);
5279 flutter::DlMatrix finalMatrix = screenScaleMatrix * translateMatrix;
5281 auto embeddedViewParams =
5282 std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, flutter::DlSize(300, 300), stack);
5284 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
5285 withParams:std::move(embeddedViewParams)];
5287 flutter::SurfaceFrame::FramebufferInfo framebuffer_info;
5288 auto mock_surface = std::make_unique<flutter::SurfaceFrame>(
5289 nullptr, framebuffer_info,
5290 [](
const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) {
return true; },
5291 [](
const flutter::SurfaceFrame& surface_frame) {
return true; },
5292 flutter::DlISize(800, 600),
nullptr,
true);
5293 [flutterPlatformViewsController submitFrame:std::move(mock_surface)
5294 withIosContext:std::make_shared<flutter::IOSContextNoop>()];
5296 XCTAssertEqual(flutterView.subviews.count, 1u);
5299 - (void)testFlutterTouchInterceptingViewLinksToAccessibilityContainer {
5301 NSObject* container = [[NSObject alloc] init];
5302 [touchInterceptorView setFlutterAccessibilityContainer:container];
5303 XCTAssertEqualObjects([touchInterceptorView accessibilityContainer], container);
5306 - (void)testLayerPool {
5310 XCTAssertTrue(
engine.platformView !=
nullptr);
5311 auto ios_context =
engine.platformView->GetIosContext();
5316 pool.
CreateLayer(ios_context, MTLPixelFormatBGRA8Unorm);
5317 XCTAssertEqual(pool.size(), 1u);
5318 pool.CreateLayer(ios_context, MTLPixelFormatBGRA8Unorm);
5319 XCTAssertEqual(pool.size(), 2u);
5322 pool.RecycleLayers();
5323 XCTAssertEqual(pool.size(), 2u);
5326 auto unused_layers = pool.RemoveUnusedLayers();
5327 XCTAssertEqual(unused_layers.size(), 2u);
5328 XCTAssertEqual(pool.size(), 1u);
5331 - (void)testFlutterPlatformViewControllerSubmitFramePreservingFrameDamage {
5332 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
5338 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
5341 flutterPlatformViewsController,
5344 std::make_shared<fml::SyncSwitch>());
5346 UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)];
5347 flutterPlatformViewsController.
flutterView = flutterView;
5351 [flutterPlatformViewsController
5353 withId:@"MockFlutterPlatformView"
5357 [flutterPlatformViewsController
5361 @"viewType" : @"MockFlutterPlatformView",
5362 @"gestureBlockingPolicy" : @"eager"
5367 [flutterPlatformViewsController
5371 @"viewType" : @"MockFlutterPlatformView",
5372 @"gestureBlockingPolicy" : @"eager"
5376 [flutterPlatformViewsController beginFrameWithSize:flutter::DlISize(300, 300)];
5377 flutter::MutatorsStack stack;
5378 flutter::DlMatrix finalMatrix;
5379 auto embeddedViewParams1 =
5380 std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, flutter::DlSize(300, 300), stack);
5381 [flutterPlatformViewsController prerollCompositeEmbeddedView:0
5382 withParams:std::move(embeddedViewParams1)];
5384 auto embeddedViewParams2 =
5385 std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, flutter::DlSize(500, 500), stack);
5386 [flutterPlatformViewsController prerollCompositeEmbeddedView:1
5387 withParams:std::move(embeddedViewParams2)];
5389 flutter::SurfaceFrame::FramebufferInfo framebuffer_info;
5390 std::optional<flutter::SurfaceFrame::SubmitInfo> submit_info;
5391 auto mock_surface = std::make_unique<flutter::SurfaceFrame>(
5392 nullptr, framebuffer_info,
5393 [](
const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) {
return true; },
5394 [&](
const flutter::SurfaceFrame& surface_frame) {
5395 submit_info = surface_frame.submit_info();
5398 flutter::DlISize(800, 600),
nullptr,
5400 mock_surface->set_submit_info({
5401 .frame_damage = flutter::DlIRect::MakeWH(800, 600),
5402 .buffer_damage = flutter::DlIRect::MakeWH(400, 600),
5405 [flutterPlatformViewsController submitFrame:std::move(mock_surface)
5406 withIosContext:std::make_shared<flutter::IOSContextNoop>()];
5408 XCTAssertTrue(submit_info.has_value());
5409 XCTAssertEqual(*submit_info->frame_damage, flutter::DlIRect::MakeWH(800, 600));
5410 XCTAssertEqual(*submit_info->buffer_damage, flutter::DlIRect::MakeWH(400, 600));
5413 - (void)testClipSuperellipse {
5414 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
5420 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
5423 flutterPlatformViewsController,
5426 std::make_shared<fml::SyncSwitch>());
5430 [flutterPlatformViewsController
5432 withId:@"MockFlutterPlatformView"
5436 [flutterPlatformViewsController
5440 @"viewType" : @"MockFlutterPlatformView",
5441 @"gestureBlockingPolicy" : @"eager"
5447 UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
5448 flutterPlatformViewsController.
flutterView = flutterView;
5450 flutter::MutatorsStack stack;
5452 flutter::DlScalar screenScale = [UIScreen mainScreen].scale;
5453 flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
5454 stack.PushTransform(screenScaleMatrix);
5456 flutter::DlRect rect = flutter::DlRect::MakeXYWH(3, 3, 5, 5);
5457 stack.PushClipRSE(flutter::DlRoundSuperellipse::MakeOval(rect));
5459 auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
5460 screenScaleMatrix, flutter::DlSize(10, 10), stack);
5462 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
5463 withParams:std::move(embeddedViewParams)];
5464 [flutterPlatformViewsController
5471 [flutterView addSubview:childClippingView];
5473 [flutterView setNeedsLayout];
5474 [flutterView layoutIfNeeded];
5476 CGPoint corners[] = {CGPointMake(rect.GetLeft(), rect.GetTop()),
5477 CGPointMake(rect.GetRight(), rect.GetTop()),
5478 CGPointMake(rect.GetLeft(), rect.GetBottom()),
5479 CGPointMake(rect.GetRight(), rect.GetBottom())};
5480 for (
auto point : corners) {
5481 int alpha = [
self alphaOfPoint:point onView:flutterView];
5482 XCTAssertNotEqual(alpha, 255);
5485 CGPointMake(rect.GetLeft() + rect.GetWidth() / 2, rect.GetTop() + rect.GetHeight() / 2);
5486 int alpha = [
self alphaOfPoint:center onView:flutterView];
5487 XCTAssertEqual(alpha, 255);
void(^ FlutterResult)(id _Nullable result)
@ FlutterPlatformViewGestureRecognizersBlockingPolicyEager
@ FlutterPlatformViewGestureRecognizersBlockingPolicyWaitUntilTouchesEnded
@ FlutterPlatformViewGestureRecognizersBlockingPolicyDoNotBlockGesture
NSMutableArray * backdropFilterSubviews()
void applyBlurBackdropFilters:(NSArray< PlatformViewFilter * > *filters)
FlutterClippingMaskView * getMaskViewWithFrame:(CGRect frame)
void insertViewToPoolIfNeeded:(FlutterClippingMaskView *maskView)
FlutterPlatformViewGestureRecognizersBlockingPolicy blockingPolicy
Storage for Overlay layers across frames.
void CreateLayer(const std::shared_ptr< IOSContext > &ios_context, MTLPixelFormat pixel_format)
Create a new overlay layer.
const flutter::TaskRunners & taskRunners
instancetype methodCallWithMethodName:arguments:(NSString *method,[arguments] id _Nullable arguments)
FlutterFMLTaskRunner * GetDefaultTaskRunner()
FlutterPlatformViewsController * CreateTestPlatformViewsController(NSString *label)
FlutterFMLTaskRunners * CreateTestTaskRunners(NSString *label)