Flutter Engine
FlutterPlatformViewsTest.mm
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #import <OCMock/OCMock.h>
6 #import <XCTest/XCTest.h>
7 
8 #import "flutter/shell/platform/darwin/common/framework/Headers/FlutterBinaryMessenger.h"
9 #import "flutter/shell/platform/darwin/common/framework/Headers/FlutterMacros.h"
10 #import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterPlatformViews.h"
11 #import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h"
12 #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h"
13 #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h"
14 #import "flutter/shell/platform/darwin/ios/platform_view_ios.h"
15 
19 const float kFloatCompareEpsilon = 0.001;
20 
22 @end
24 
25 - (instancetype)init {
26  self = [super init];
27  if (self) {
28  gMockPlatformView = self;
29  }
30  return self;
31 }
32 
33 - (void)dealloc {
34  gMockPlatformView = nil;
35  [super dealloc];
36 }
37 
38 @end
39 
40 @interface FlutterPlatformViewsTestMockFlutterPlatformView : NSObject <FlutterPlatformView>
41 @property(nonatomic, strong) UIView* view;
42 @property(nonatomic, assign) BOOL viewCreated;
43 @end
44 
46 
47 - (instancetype)init {
48  if (self = [super init]) {
49  _view = [[FlutterPlatformViewsTestMockPlatformView alloc] init];
50  _viewCreated = NO;
51  }
52  return self;
53 }
54 
55 - (UIView*)view {
56  [self checkViewCreatedOnce];
57  return _view;
58 }
59 
60 - (void)checkViewCreatedOnce {
61  if (self.viewCreated) {
62  abort();
63  }
64  self.viewCreated = YES;
65 }
66 
67 - (void)dealloc {
68  [_view release];
69  _view = nil;
70  [super dealloc];
71 }
72 
73 @end
74 
76  : NSObject <FlutterPlatformViewFactory>
77 @end
78 
80 - (NSObject<FlutterPlatformView>*)createWithFrame:(CGRect)frame
81  viewIdentifier:(int64_t)viewId
82  arguments:(id _Nullable)args {
83  return [[[FlutterPlatformViewsTestMockFlutterPlatformView alloc] init] autorelease];
84 }
85 
86 @end
87 
88 namespace flutter {
89 namespace {
90 class FlutterPlatformViewsTestMockPlatformViewDelegate : public PlatformView::Delegate {
91  void OnPlatformViewCreated(std::unique_ptr<Surface> surface) override {}
92  void OnPlatformViewDestroyed() override {}
93  void OnPlatformViewSetNextFrameCallback(const fml::closure& closure) override {}
94  void OnPlatformViewSetViewportMetrics(const ViewportMetrics& metrics) override {}
95  void OnPlatformViewDispatchPlatformMessage(std::unique_ptr<PlatformMessage> message) override {}
96  void OnPlatformViewDispatchPointerDataPacket(std::unique_ptr<PointerDataPacket> packet) override {
97  }
98  void OnPlatformViewDispatchKeyDataPacket(std::unique_ptr<KeyDataPacket> packet,
99  std::function<void(bool)> callback) override {}
100  void OnPlatformViewDispatchSemanticsAction(int32_t id,
102  fml::MallocMapping args) override {}
103  void OnPlatformViewSetSemanticsEnabled(bool enabled) override {}
104  void OnPlatformViewSetAccessibilityFeatures(int32_t flags) override {}
105  void OnPlatformViewRegisterTexture(std::shared_ptr<Texture> texture) override {}
106  void OnPlatformViewUnregisterTexture(int64_t texture_id) override {}
107  void OnPlatformViewMarkTextureFrameAvailable(int64_t texture_id) override {}
108 
109  void LoadDartDeferredLibrary(intptr_t loading_unit_id,
110  std::unique_ptr<const fml::Mapping> snapshot_data,
111  std::unique_ptr<const fml::Mapping> snapshot_instructions) override {
112  }
113  void LoadDartDeferredLibraryError(intptr_t loading_unit_id,
114  const std::string error_message,
115  bool transient) override {}
116  void UpdateAssetResolverByType(std::unique_ptr<flutter::AssetResolver> updated_asset_resolver,
118 };
119 
120 } // namespace
121 } // namespace flutter
122 
123 namespace {
124 fml::RefPtr<fml::TaskRunner> CreateNewThread(std::string name) {
125  auto thread = std::make_unique<fml::Thread>(name);
126  auto runner = thread->GetTaskRunner();
127  return runner;
128 }
129 } // namespace
130 
131 @interface FlutterPlatformViewsTest : XCTestCase
132 @end
133 
134 @implementation FlutterPlatformViewsTest
135 
136 - (void)testFlutterViewOnlyCreateOnceInOneFrame {
137  flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
138  auto thread_task_runner = CreateNewThread("FlutterPlatformViewsTest");
139  flutter::TaskRunners runners(/*label=*/self.name.UTF8String,
140  /*platform=*/thread_task_runner,
141  /*raster=*/thread_task_runner,
142  /*ui=*/thread_task_runner,
143  /*io=*/thread_task_runner);
144  auto flutterPlatformViewsController = std::make_shared<flutter::FlutterPlatformViewsController>();
145  auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
146  /*delegate=*/mock_delegate,
147  /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware,
148  /*platform_views_controller=*/flutterPlatformViewsController,
149  /*task_runners=*/runners);
150 
153  flutterPlatformViewsController->RegisterViewFactory(
154  factory, @"MockFlutterPlatformView",
156  FlutterResult result = ^(id result) {
157  };
158  flutterPlatformViewsController->OnMethodCall(
160  methodCallWithMethodName:@"create"
161  arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}],
162  result);
163  UIView* mockFlutterView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)] autorelease];
164  flutterPlatformViewsController->SetFlutterView(mockFlutterView);
165  // Create embedded view params
167  // Layer tree always pushes a screen scale factor to the stack
168  SkMatrix screenScaleMatrix =
169  SkMatrix::Scale([UIScreen mainScreen].scale, [UIScreen mainScreen].scale);
170  stack.PushTransform(screenScaleMatrix);
171  // Push a translate matrix
172  SkMatrix translateMatrix = SkMatrix::Translate(100, 100);
173  stack.PushTransform(translateMatrix);
174  SkMatrix finalMatrix;
175  finalMatrix.setConcat(screenScaleMatrix, translateMatrix);
176 
177  auto embeddedViewParams =
178  std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(300, 300), stack);
179 
180  flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams));
181  flutterPlatformViewsController->CompositeEmbeddedView(2);
182 
183  flutterPlatformViewsController->GetPlatformViewRect(2);
184 
185  XCTAssertNotNil(gMockPlatformView);
186 
187  flutterPlatformViewsController->Reset();
188 }
189 
190 - (void)testCanCreatePlatformViewWithoutFlutterView {
191  flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
192  auto thread_task_runner = CreateNewThread("FlutterPlatformViewsTest");
193  flutter::TaskRunners runners(/*label=*/self.name.UTF8String,
194  /*platform=*/thread_task_runner,
195  /*raster=*/thread_task_runner,
196  /*ui=*/thread_task_runner,
197  /*io=*/thread_task_runner);
198  auto flutterPlatformViewsController = std::make_shared<flutter::FlutterPlatformViewsController>();
199  auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
200  /*delegate=*/mock_delegate,
201  /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware,
202  /*platform_views_controller=*/flutterPlatformViewsController,
203  /*task_runners=*/runners);
204 
207  flutterPlatformViewsController->RegisterViewFactory(
208  factory, @"MockFlutterPlatformView",
210  FlutterResult result = ^(id result) {
211  };
212  flutterPlatformViewsController->OnMethodCall(
214  methodCallWithMethodName:@"create"
215  arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}],
216  result);
217 
218  XCTAssertNotNil(gMockPlatformView);
219 }
220 
221 - (void)testChildClippingViewHitTests {
222  ChildClippingView* childClippingView =
223  [[[ChildClippingView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)] autorelease];
224  UIView* childView = [[[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)] autorelease];
225  [childClippingView addSubview:childView];
226 
227  XCTAssertFalse([childClippingView pointInside:CGPointMake(50, 50) withEvent:nil]);
228  XCTAssertFalse([childClippingView pointInside:CGPointMake(99, 100) withEvent:nil]);
229  XCTAssertFalse([childClippingView pointInside:CGPointMake(100, 99) withEvent:nil]);
230  XCTAssertFalse([childClippingView pointInside:CGPointMake(201, 200) withEvent:nil]);
231  XCTAssertFalse([childClippingView pointInside:CGPointMake(200, 201) withEvent:nil]);
232  XCTAssertFalse([childClippingView pointInside:CGPointMake(99, 200) withEvent:nil]);
233  XCTAssertFalse([childClippingView pointInside:CGPointMake(200, 299) withEvent:nil]);
234 
235  XCTAssertTrue([childClippingView pointInside:CGPointMake(150, 150) withEvent:nil]);
236  XCTAssertTrue([childClippingView pointInside:CGPointMake(100, 100) withEvent:nil]);
237  XCTAssertTrue([childClippingView pointInside:CGPointMake(199, 100) withEvent:nil]);
238  XCTAssertTrue([childClippingView pointInside:CGPointMake(100, 199) withEvent:nil]);
239  XCTAssertTrue([childClippingView pointInside:CGPointMake(199, 199) withEvent:nil]);
240 }
241 
242 - (void)testCompositePlatformView {
243  flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
244  auto thread_task_runner = CreateNewThread("FlutterPlatformViewsTest");
245  flutter::TaskRunners runners(/*label=*/self.name.UTF8String,
246  /*platform=*/thread_task_runner,
247  /*raster=*/thread_task_runner,
248  /*ui=*/thread_task_runner,
249  /*io=*/thread_task_runner);
250  auto flutterPlatformViewsController = std::make_shared<flutter::FlutterPlatformViewsController>();
251  auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
252  /*delegate=*/mock_delegate,
253  /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware,
254  /*platform_views_controller=*/flutterPlatformViewsController,
255  /*task_runners=*/runners);
256 
259  flutterPlatformViewsController->RegisterViewFactory(
260  factory, @"MockFlutterPlatformView",
262  FlutterResult result = ^(id result) {
263  };
264  flutterPlatformViewsController->OnMethodCall(
266  methodCallWithMethodName:@"create"
267  arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}],
268  result);
269 
270  XCTAssertNotNil(gMockPlatformView);
271 
272  UIView* mockFlutterView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)] autorelease];
273  flutterPlatformViewsController->SetFlutterView(mockFlutterView);
274  // Create embedded view params
276  // Layer tree always pushes a screen scale factor to the stack
277  SkMatrix screenScaleMatrix =
278  SkMatrix::Scale([UIScreen mainScreen].scale, [UIScreen mainScreen].scale);
279  stack.PushTransform(screenScaleMatrix);
280  // Push a translate matrix
281  SkMatrix translateMatrix = SkMatrix::Translate(100, 100);
282  stack.PushTransform(translateMatrix);
283  SkMatrix finalMatrix;
284  finalMatrix.setConcat(screenScaleMatrix, translateMatrix);
285 
286  auto embeddedViewParams =
287  std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(300, 300), stack);
288 
289  flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams));
290  flutterPlatformViewsController->CompositeEmbeddedView(2);
291  CGRect platformViewRectInFlutterView = [gMockPlatformView convertRect:gMockPlatformView.bounds
292  toView:mockFlutterView];
293  XCTAssertTrue(CGRectEqualToRect(platformViewRectInFlutterView, CGRectMake(100, 100, 300, 300)));
294 }
295 
296 - (void)testChildClippingViewShouldBeTheBoundingRectOfPlatformView {
297  flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
298  auto thread_task_runner = CreateNewThread("FlutterPlatformViewsTest");
299  flutter::TaskRunners runners(/*label=*/self.name.UTF8String,
300  /*platform=*/thread_task_runner,
301  /*raster=*/thread_task_runner,
302  /*ui=*/thread_task_runner,
303  /*io=*/thread_task_runner);
304  auto flutterPlatformViewsController = std::make_shared<flutter::FlutterPlatformViewsController>();
305  auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
306  /*delegate=*/mock_delegate,
307  /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware,
308  /*platform_views_controller=*/flutterPlatformViewsController,
309  /*task_runners=*/runners);
310 
313  flutterPlatformViewsController->RegisterViewFactory(
314  factory, @"MockFlutterPlatformView",
316  FlutterResult result = ^(id result) {
317  };
318  flutterPlatformViewsController->OnMethodCall(
320  methodCallWithMethodName:@"create"
321  arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}],
322  result);
323 
324  XCTAssertNotNil(gMockPlatformView);
325 
326  UIView* mockFlutterView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)] autorelease];
327  flutterPlatformViewsController->SetFlutterView(mockFlutterView);
328  // Create embedded view params
330  // Layer tree always pushes a screen scale factor to the stack
331  SkMatrix screenScaleMatrix =
332  SkMatrix::Scale([UIScreen mainScreen].scale, [UIScreen mainScreen].scale);
333  stack.PushTransform(screenScaleMatrix);
334  // Push a rotate matrix
335  SkMatrix rotateMatrix;
336  rotateMatrix.setRotate(10);
337  stack.PushTransform(rotateMatrix);
338  SkMatrix finalMatrix;
339  finalMatrix.setConcat(screenScaleMatrix, rotateMatrix);
340 
341  auto embeddedViewParams =
342  std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(300, 300), stack);
343 
344  flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams));
345  flutterPlatformViewsController->CompositeEmbeddedView(2);
346  CGRect platformViewRectInFlutterView = [gMockPlatformView convertRect:gMockPlatformView.bounds
347  toView:mockFlutterView];
348  XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:ChildClippingView.class]);
349  ChildClippingView* childClippingView = (ChildClippingView*)gMockPlatformView.superview.superview;
350  // The childclippingview's frame is set based on flow, but the platform view's frame is set based
351  // on quartz. Although they should be the same, but we should tolerate small floating point
352  // errors.
353  XCTAssertLessThan(fabs(platformViewRectInFlutterView.origin.x - childClippingView.frame.origin.x),
355  XCTAssertLessThan(fabs(platformViewRectInFlutterView.origin.y - childClippingView.frame.origin.y),
357  XCTAssertLessThan(
358  fabs(platformViewRectInFlutterView.size.width - childClippingView.frame.size.width),
360  XCTAssertLessThan(
361  fabs(platformViewRectInFlutterView.size.height - childClippingView.frame.size.height),
363 }
364 
365 - (void)testClipRect {
366  flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
367  auto thread_task_runner = CreateNewThread("FlutterPlatformViewsTest");
368  flutter::TaskRunners runners(/*label=*/self.name.UTF8String,
369  /*platform=*/thread_task_runner,
370  /*raster=*/thread_task_runner,
371  /*ui=*/thread_task_runner,
372  /*io=*/thread_task_runner);
373  auto flutterPlatformViewsController = std::make_shared<flutter::FlutterPlatformViewsController>();
374  auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
375  /*delegate=*/mock_delegate,
376  /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware,
377  /*platform_views_controller=*/flutterPlatformViewsController,
378  /*task_runners=*/runners);
379 
382  flutterPlatformViewsController->RegisterViewFactory(
383  factory, @"MockFlutterPlatformView",
385  FlutterResult result = ^(id result) {
386  };
387  flutterPlatformViewsController->OnMethodCall(
389  methodCallWithMethodName:@"create"
390  arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}],
391  result);
392 
393  XCTAssertNotNil(gMockPlatformView);
394 
395  UIView* mockFlutterView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)] autorelease];
396  flutterPlatformViewsController->SetFlutterView(mockFlutterView);
397  // Create embedded view params
399  // Layer tree always pushes a screen scale factor to the stack
400  SkMatrix screenScaleMatrix =
401  SkMatrix::Scale([UIScreen mainScreen].scale, [UIScreen mainScreen].scale);
402  stack.PushTransform(screenScaleMatrix);
403  // Push a clip rect
404  SkRect rect = SkRect::MakeXYWH(2, 2, 3, 3);
405  stack.PushClipRect(rect);
406 
407  auto embeddedViewParams =
408  std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, SkSize::Make(10, 10), stack);
409 
410  flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams));
411  flutterPlatformViewsController->CompositeEmbeddedView(2);
412  gMockPlatformView.backgroundColor = UIColor.redColor;
413  XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:ChildClippingView.class]);
414  ChildClippingView* childClippingView = (ChildClippingView*)gMockPlatformView.superview.superview;
415  [mockFlutterView addSubview:childClippingView];
416 
417  [mockFlutterView setNeedsLayout];
418  [mockFlutterView layoutIfNeeded];
419 
420  for (int i = 0; i < 10; i++) {
421  for (int j = 0; j < 10; j++) {
422  CGPoint point = CGPointMake(i, j);
423  int alpha = [self alphaOfPoint:CGPointMake(i, j) onView:mockFlutterView];
424  // Edges of the clipping might have a semi transparent pixel, we only check the pixels that
425  // are fully inside the clipped area.
426  CGRect insideClipping = CGRectMake(3, 3, 1, 1);
427  if (CGRectContainsPoint(insideClipping, point)) {
428  XCTAssertEqual(alpha, 255);
429  } else {
430  XCTAssertLessThan(alpha, 255);
431  }
432  }
433  }
434 }
435 
436 - (void)testClipRRect {
437  flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
438  auto thread_task_runner = CreateNewThread("FlutterPlatformViewsTest");
439  flutter::TaskRunners runners(/*label=*/self.name.UTF8String,
440  /*platform=*/thread_task_runner,
441  /*raster=*/thread_task_runner,
442  /*ui=*/thread_task_runner,
443  /*io=*/thread_task_runner);
444  auto flutterPlatformViewsController = std::make_shared<flutter::FlutterPlatformViewsController>();
445  auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
446  /*delegate=*/mock_delegate,
447  /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware,
448  /*platform_views_controller=*/flutterPlatformViewsController,
449  /*task_runners=*/runners);
450 
453  flutterPlatformViewsController->RegisterViewFactory(
454  factory, @"MockFlutterPlatformView",
456  FlutterResult result = ^(id result) {
457  };
458  flutterPlatformViewsController->OnMethodCall(
460  methodCallWithMethodName:@"create"
461  arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}],
462  result);
463 
464  XCTAssertNotNil(gMockPlatformView);
465 
466  UIView* mockFlutterView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)] autorelease];
467  flutterPlatformViewsController->SetFlutterView(mockFlutterView);
468  // Create embedded view params
470  // Layer tree always pushes a screen scale factor to the stack
471  SkMatrix screenScaleMatrix =
472  SkMatrix::Scale([UIScreen mainScreen].scale, [UIScreen mainScreen].scale);
473  stack.PushTransform(screenScaleMatrix);
474  // Push a clip rrect
475  SkRRect rrect = SkRRect::MakeRectXY(SkRect::MakeXYWH(2, 2, 6, 6), 1, 1);
476  stack.PushClipRRect(rrect);
477 
478  auto embeddedViewParams =
479  std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, SkSize::Make(10, 10), stack);
480 
481  flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams));
482  flutterPlatformViewsController->CompositeEmbeddedView(2);
483  gMockPlatformView.backgroundColor = UIColor.redColor;
484  XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:ChildClippingView.class]);
485  ChildClippingView* childClippingView = (ChildClippingView*)gMockPlatformView.superview.superview;
486  [mockFlutterView addSubview:childClippingView];
487 
488  [mockFlutterView setNeedsLayout];
489  [mockFlutterView layoutIfNeeded];
490 
491  for (int i = 0; i < 10; i++) {
492  for (int j = 0; j < 10; j++) {
493  CGPoint point = CGPointMake(i, j);
494  int alpha = [self alphaOfPoint:CGPointMake(i, j) onView:mockFlutterView];
495  // Edges of the clipping might have a semi transparent pixel, we only check the pixels that
496  // are fully inside the clipped area.
497  CGRect insideClipping = CGRectMake(3, 3, 4, 4);
498  if (CGRectContainsPoint(insideClipping, point)) {
499  XCTAssertEqual(alpha, 255);
500  } else {
501  XCTAssertLessThan(alpha, 255);
502  }
503  }
504  }
505 }
506 
507 - (void)testClipPath {
508  flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
509  auto thread_task_runner = CreateNewThread("FlutterPlatformViewsTest");
510  flutter::TaskRunners runners(/*label=*/self.name.UTF8String,
511  /*platform=*/thread_task_runner,
512  /*raster=*/thread_task_runner,
513  /*ui=*/thread_task_runner,
514  /*io=*/thread_task_runner);
515  auto flutterPlatformViewsController = std::make_shared<flutter::FlutterPlatformViewsController>();
516  auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
517  /*delegate=*/mock_delegate,
518  /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware,
519  /*platform_views_controller=*/flutterPlatformViewsController,
520  /*task_runners=*/runners);
521 
524  flutterPlatformViewsController->RegisterViewFactory(
525  factory, @"MockFlutterPlatformView",
527  FlutterResult result = ^(id result) {
528  };
529  flutterPlatformViewsController->OnMethodCall(
531  methodCallWithMethodName:@"create"
532  arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}],
533  result);
534 
535  XCTAssertNotNil(gMockPlatformView);
536 
537  UIView* mockFlutterView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)] autorelease];
538  flutterPlatformViewsController->SetFlutterView(mockFlutterView);
539  // Create embedded view params
541  // Layer tree always pushes a screen scale factor to the stack
542  SkMatrix screenScaleMatrix =
543  SkMatrix::Scale([UIScreen mainScreen].scale, [UIScreen mainScreen].scale);
544  stack.PushTransform(screenScaleMatrix);
545  // Push a clip path
546  SkPath path;
547  path.addRoundRect(SkRect::MakeXYWH(2, 2, 6, 6), 1, 1);
548  stack.PushClipPath(path);
549 
550  auto embeddedViewParams =
551  std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, SkSize::Make(10, 10), stack);
552 
553  flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams));
554  flutterPlatformViewsController->CompositeEmbeddedView(2);
555  gMockPlatformView.backgroundColor = UIColor.redColor;
556  XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:ChildClippingView.class]);
557  ChildClippingView* childClippingView = (ChildClippingView*)gMockPlatformView.superview.superview;
558  [mockFlutterView addSubview:childClippingView];
559 
560  [mockFlutterView setNeedsLayout];
561  [mockFlutterView layoutIfNeeded];
562 
563  for (int i = 0; i < 10; i++) {
564  for (int j = 0; j < 10; j++) {
565  CGPoint point = CGPointMake(i, j);
566  int alpha = [self alphaOfPoint:CGPointMake(i, j) onView:mockFlutterView];
567  // Edges of the clipping might have a semi transparent pixel, we only check the pixels that
568  // are fully inside the clipped area.
569  CGRect insideClipping = CGRectMake(3, 3, 4, 4);
570  if (CGRectContainsPoint(insideClipping, point)) {
571  XCTAssertEqual(alpha, 255);
572  } else {
573  XCTAssertLessThan(alpha, 255);
574  }
575  }
576  }
577 }
578 
579 - (void)testSetFlutterViewControllerAfterCreateCanStillDispatchTouchEvents {
580  flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
581  auto thread_task_runner = CreateNewThread("FlutterPlatformViewsTest");
582  flutter::TaskRunners runners(/*label=*/self.name.UTF8String,
583  /*platform=*/thread_task_runner,
584  /*raster=*/thread_task_runner,
585  /*ui=*/thread_task_runner,
586  /*io=*/thread_task_runner);
587  auto flutterPlatformViewsController = std::make_shared<flutter::FlutterPlatformViewsController>();
588  auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
589  /*delegate=*/mock_delegate,
590  /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware,
591  /*platform_views_controller=*/flutterPlatformViewsController,
592  /*task_runners=*/runners);
593 
596  flutterPlatformViewsController->RegisterViewFactory(
597  factory, @"MockFlutterPlatformView",
599  FlutterResult result = ^(id result) {
600  };
601  flutterPlatformViewsController->OnMethodCall(
603  methodCallWithMethodName:@"create"
604  arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}],
605  result);
606 
607  XCTAssertNotNil(gMockPlatformView);
608 
609  // Find touch inteceptor view
610  UIView* touchInteceptorView = gMockPlatformView;
611  while (touchInteceptorView != nil &&
612  ![touchInteceptorView isKindOfClass:[FlutterTouchInterceptingView class]]) {
613  touchInteceptorView = touchInteceptorView.superview;
614  }
615  XCTAssertNotNil(touchInteceptorView);
616 
617  // Find ForwardGestureRecognizer
618  UIGestureRecognizer* forwardGectureRecognizer = nil;
619  for (UIGestureRecognizer* gestureRecognizer in touchInteceptorView.gestureRecognizers) {
620  if ([gestureRecognizer isKindOfClass:NSClassFromString(@"ForwardingGestureRecognizer")]) {
621  forwardGectureRecognizer = gestureRecognizer;
622  break;
623  }
624  }
625 
626  // Before setting flutter view controller, events are not dispatched.
627  NSSet* touches1 = [[[NSSet alloc] init] autorelease];
628  id event1 = OCMClassMock([UIEvent class]);
629  id mockFlutterViewContoller = OCMClassMock([FlutterViewController class]);
630  [forwardGectureRecognizer touchesBegan:touches1 withEvent:event1];
631  OCMReject([mockFlutterViewContoller touchesBegan:touches1 withEvent:event1]);
632 
633  // Set flutter view controller allows events to be dispatched.
634  NSSet* touches2 = [[[NSSet alloc] init] autorelease];
635  id event2 = OCMClassMock([UIEvent class]);
636  flutterPlatformViewsController->SetFlutterViewController(mockFlutterViewContoller);
637  [forwardGectureRecognizer touchesBegan:touches2 withEvent:event2];
638  OCMVerify([mockFlutterViewContoller touchesBegan:touches2 withEvent:event2]);
639 }
640 
641 - (void)testSetFlutterViewControllerInTheMiddleOfTouchEventShouldStillAllowGesturesToBeHandled {
642  flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
643  auto thread_task_runner = CreateNewThread("FlutterPlatformViewsTest");
644  flutter::TaskRunners runners(/*label=*/self.name.UTF8String,
645  /*platform=*/thread_task_runner,
646  /*raster=*/thread_task_runner,
647  /*ui=*/thread_task_runner,
648  /*io=*/thread_task_runner);
649  auto flutterPlatformViewsController = std::make_shared<flutter::FlutterPlatformViewsController>();
650  auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
651  /*delegate=*/mock_delegate,
652  /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware,
653  /*platform_views_controller=*/flutterPlatformViewsController,
654  /*task_runners=*/runners);
655 
658  flutterPlatformViewsController->RegisterViewFactory(
659  factory, @"MockFlutterPlatformView",
661  FlutterResult result = ^(id result) {
662  };
663  flutterPlatformViewsController->OnMethodCall(
665  methodCallWithMethodName:@"create"
666  arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}],
667  result);
668 
669  XCTAssertNotNil(gMockPlatformView);
670 
671  // Find touch inteceptor view
672  UIView* touchInteceptorView = gMockPlatformView;
673  while (touchInteceptorView != nil &&
674  ![touchInteceptorView isKindOfClass:[FlutterTouchInterceptingView class]]) {
675  touchInteceptorView = touchInteceptorView.superview;
676  }
677  XCTAssertNotNil(touchInteceptorView);
678 
679  // Find ForwardGestureRecognizer
680  UIGestureRecognizer* forwardGectureRecognizer = nil;
681  for (UIGestureRecognizer* gestureRecognizer in touchInteceptorView.gestureRecognizers) {
682  if ([gestureRecognizer isKindOfClass:NSClassFromString(@"ForwardingGestureRecognizer")]) {
683  forwardGectureRecognizer = gestureRecognizer;
684  break;
685  }
686  }
687  id mockFlutterViewContoller = OCMClassMock([FlutterViewController class]);
688  {
689  // ***** Sequence 1, finishing touch event with touchEnded ***** //
690  flutterPlatformViewsController->SetFlutterViewController(mockFlutterViewContoller);
691 
692  NSSet* touches1 = [[[NSSet alloc] init] autorelease];
693  id event1 = OCMClassMock([UIEvent class]);
694  [forwardGectureRecognizer touchesBegan:touches1 withEvent:event1];
695  OCMVerify([mockFlutterViewContoller touchesBegan:touches1 withEvent:event1]);
696 
697  flutterPlatformViewsController->SetFlutterViewController(nil);
698 
699  // Allow the touch events to finish
700  NSSet* touches2 = [[[NSSet alloc] init] autorelease];
701  id event2 = OCMClassMock([UIEvent class]);
702  [forwardGectureRecognizer touchesMoved:touches2 withEvent:event2];
703  OCMVerify([mockFlutterViewContoller touchesMoved:touches2 withEvent:event2]);
704 
705  NSSet* touches3 = [[[NSSet alloc] init] autorelease];
706  id event3 = OCMClassMock([UIEvent class]);
707  [forwardGectureRecognizer touchesEnded:touches3 withEvent:event3];
708  OCMVerify([mockFlutterViewContoller touchesEnded:touches3 withEvent:event3]);
709 
710  // Now the 2nd touch sequence should not be allowed.
711  NSSet* touches4 = [[[NSSet alloc] init] autorelease];
712  id event4 = OCMClassMock([UIEvent class]);
713  [forwardGectureRecognizer touchesBegan:touches4 withEvent:event4];
714  OCMReject([mockFlutterViewContoller touchesBegan:touches4 withEvent:event4]);
715 
716  NSSet* touches5 = [[[NSSet alloc] init] autorelease];
717  id event5 = OCMClassMock([UIEvent class]);
718  [forwardGectureRecognizer touchesEnded:touches5 withEvent:event5];
719  OCMReject([mockFlutterViewContoller touchesEnded:touches5 withEvent:event5]);
720  }
721 
722  {
723  // ***** Sequence 2, finishing touch event with touchCancelled ***** //
724  flutterPlatformViewsController->SetFlutterViewController(mockFlutterViewContoller);
725 
726  NSSet* touches1 = [[[NSSet alloc] init] autorelease];
727  id event1 = OCMClassMock([UIEvent class]);
728  [forwardGectureRecognizer touchesBegan:touches1 withEvent:event1];
729  OCMVerify([mockFlutterViewContoller touchesBegan:touches1 withEvent:event1]);
730 
731  flutterPlatformViewsController->SetFlutterViewController(nil);
732 
733  // Allow the touch events to finish
734  NSSet* touches2 = [[[NSSet alloc] init] autorelease];
735  id event2 = OCMClassMock([UIEvent class]);
736  [forwardGectureRecognizer touchesMoved:touches2 withEvent:event2];
737  OCMVerify([mockFlutterViewContoller touchesMoved:touches2 withEvent:event2]);
738 
739  NSSet* touches3 = [[[NSSet alloc] init] autorelease];
740  id event3 = OCMClassMock([UIEvent class]);
741  [forwardGectureRecognizer touchesCancelled:touches3 withEvent:event3];
742  OCMVerify([mockFlutterViewContoller forceTouchesCancelled:touches3]);
743 
744  // Now the 2nd touch sequence should not be allowed.
745  NSSet* touches4 = [[[NSSet alloc] init] autorelease];
746  id event4 = OCMClassMock([UIEvent class]);
747  [forwardGectureRecognizer touchesBegan:touches4 withEvent:event4];
748  OCMReject([mockFlutterViewContoller touchesBegan:touches4 withEvent:event4]);
749 
750  NSSet* touches5 = [[[NSSet alloc] init] autorelease];
751  id event5 = OCMClassMock([UIEvent class]);
752  [forwardGectureRecognizer touchesEnded:touches5 withEvent:event5];
753  OCMReject([mockFlutterViewContoller touchesEnded:touches5 withEvent:event5]);
754  }
755 
756  flutterPlatformViewsController->Reset();
757 }
758 
759 - (void)
760  testSetFlutterViewControllerInTheMiddleOfTouchEventAllowsTheNewControllerToHandleSecondTouchSequence {
761  flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
762  auto thread_task_runner = CreateNewThread("FlutterPlatformViewsTest");
763  flutter::TaskRunners runners(/*label=*/self.name.UTF8String,
764  /*platform=*/thread_task_runner,
765  /*raster=*/thread_task_runner,
766  /*ui=*/thread_task_runner,
767  /*io=*/thread_task_runner);
768  auto flutterPlatformViewsController = std::make_shared<flutter::FlutterPlatformViewsController>();
769  auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
770  /*delegate=*/mock_delegate,
771  /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware,
772  /*platform_views_controller=*/flutterPlatformViewsController,
773  /*task_runners=*/runners);
774 
777  flutterPlatformViewsController->RegisterViewFactory(
778  factory, @"MockFlutterPlatformView",
780  FlutterResult result = ^(id result) {
781  };
782  flutterPlatformViewsController->OnMethodCall(
784  methodCallWithMethodName:@"create"
785  arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}],
786  result);
787 
788  XCTAssertNotNil(gMockPlatformView);
789 
790  // Find touch inteceptor view
791  UIView* touchInteceptorView = gMockPlatformView;
792  while (touchInteceptorView != nil &&
793  ![touchInteceptorView isKindOfClass:[FlutterTouchInterceptingView class]]) {
794  touchInteceptorView = touchInteceptorView.superview;
795  }
796  XCTAssertNotNil(touchInteceptorView);
797 
798  // Find ForwardGestureRecognizer
799  UIGestureRecognizer* forwardGectureRecognizer = nil;
800  for (UIGestureRecognizer* gestureRecognizer in touchInteceptorView.gestureRecognizers) {
801  if ([gestureRecognizer isKindOfClass:NSClassFromString(@"ForwardingGestureRecognizer")]) {
802  forwardGectureRecognizer = gestureRecognizer;
803  break;
804  }
805  }
806  id mockFlutterViewContoller = OCMClassMock([FlutterViewController class]);
807 
808  flutterPlatformViewsController->SetFlutterViewController(mockFlutterViewContoller);
809 
810  // The touches in this sequence requires 1 touch object, we always create the NSSet with one item.
811  NSSet* touches1 = [NSSet setWithObject:@1];
812  id event1 = OCMClassMock([UIEvent class]);
813  [forwardGectureRecognizer touchesBegan:touches1 withEvent:event1];
814  OCMVerify([mockFlutterViewContoller touchesBegan:touches1 withEvent:event1]);
815 
816  UIViewController* mockFlutterViewContoller2 = OCMClassMock([UIViewController class]);
817  flutterPlatformViewsController->SetFlutterViewController(mockFlutterViewContoller2);
818 
819  // Touch events should still send to the old FlutterViewController if FlutterViewController
820  // is updated in between.
821  NSSet* touches2 = [NSSet setWithObject:@1];
822  id event2 = OCMClassMock([UIEvent class]);
823  [forwardGectureRecognizer touchesBegan:touches2 withEvent:event2];
824  OCMVerify([mockFlutterViewContoller touchesBegan:touches2 withEvent:event2]);
825  OCMReject([mockFlutterViewContoller2 touchesBegan:touches2 withEvent:event2]);
826 
827  NSSet* touches3 = [NSSet setWithObject:@1];
828  id event3 = OCMClassMock([UIEvent class]);
829  [forwardGectureRecognizer touchesMoved:touches3 withEvent:event3];
830  OCMVerify([mockFlutterViewContoller touchesMoved:touches3 withEvent:event3]);
831  OCMReject([mockFlutterViewContoller2 touchesMoved:touches3 withEvent:event3]);
832 
833  NSSet* touches4 = [NSSet setWithObject:@1];
834  id event4 = OCMClassMock([UIEvent class]);
835  [forwardGectureRecognizer touchesEnded:touches4 withEvent:event4];
836  OCMVerify([mockFlutterViewContoller touchesEnded:touches4 withEvent:event4]);
837  OCMReject([mockFlutterViewContoller2 touchesEnded:touches4 withEvent:event4]);
838 
839  NSSet* touches5 = [NSSet setWithObject:@1];
840  id event5 = OCMClassMock([UIEvent class]);
841  [forwardGectureRecognizer touchesEnded:touches5 withEvent:event5];
842  OCMVerify([mockFlutterViewContoller touchesEnded:touches5 withEvent:event5]);
843  OCMReject([mockFlutterViewContoller2 touchesEnded:touches5 withEvent:event5]);
844 
845  // Now the 2nd touch sequence should go to the new FlutterViewController
846 
847  NSSet* touches6 = [NSSet setWithObject:@1];
848  id event6 = OCMClassMock([UIEvent class]);
849  [forwardGectureRecognizer touchesBegan:touches6 withEvent:event6];
850  OCMVerify([mockFlutterViewContoller2 touchesBegan:touches6 withEvent:event6]);
851  OCMReject([mockFlutterViewContoller touchesBegan:touches6 withEvent:event6]);
852 
853  // Allow the touch events to finish
854  NSSet* touches7 = [NSSet setWithObject:@1];
855  id event7 = OCMClassMock([UIEvent class]);
856  [forwardGectureRecognizer touchesMoved:touches7 withEvent:event7];
857  OCMVerify([mockFlutterViewContoller2 touchesMoved:touches7 withEvent:event7]);
858  OCMReject([mockFlutterViewContoller touchesMoved:touches7 withEvent:event7]);
859 
860  NSSet* touches8 = [NSSet setWithObject:@1];
861  id event8 = OCMClassMock([UIEvent class]);
862  [forwardGectureRecognizer touchesEnded:touches8 withEvent:event8];
863  OCMVerify([mockFlutterViewContoller2 touchesEnded:touches8 withEvent:event8]);
864  OCMReject([mockFlutterViewContoller touchesEnded:touches8 withEvent:event8]);
865 
866  flutterPlatformViewsController->Reset();
867 }
868 
869 - (void)testFlutterPlatformViewTouchesCancelledEventAreForcedToBeCancelled {
870  flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
871  auto thread_task_runner = CreateNewThread("FlutterPlatformViewsTest");
872  flutter::TaskRunners runners(/*label=*/self.name.UTF8String,
873  /*platform=*/thread_task_runner,
874  /*raster=*/thread_task_runner,
875  /*ui=*/thread_task_runner,
876  /*io=*/thread_task_runner);
877  auto flutterPlatformViewsController = std::make_shared<flutter::FlutterPlatformViewsController>();
878  auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
879  /*delegate=*/mock_delegate,
880  /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware,
881  /*platform_views_controller=*/flutterPlatformViewsController,
882  /*task_runners=*/runners);
883 
886  flutterPlatformViewsController->RegisterViewFactory(
887  factory, @"MockFlutterPlatformView",
889  FlutterResult result = ^(id result) {
890  };
891  flutterPlatformViewsController->OnMethodCall(
893  methodCallWithMethodName:@"create"
894  arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}],
895  result);
896 
897  XCTAssertNotNil(gMockPlatformView);
898 
899  // Find touch inteceptor view
900  UIView* touchInteceptorView = gMockPlatformView;
901  while (touchInteceptorView != nil &&
902  ![touchInteceptorView isKindOfClass:[FlutterTouchInterceptingView class]]) {
903  touchInteceptorView = touchInteceptorView.superview;
904  }
905  XCTAssertNotNil(touchInteceptorView);
906 
907  // Find ForwardGestureRecognizer
908  UIGestureRecognizer* forwardGectureRecognizer = nil;
909  for (UIGestureRecognizer* gestureRecognizer in touchInteceptorView.gestureRecognizers) {
910  if ([gestureRecognizer isKindOfClass:NSClassFromString(@"ForwardingGestureRecognizer")]) {
911  forwardGectureRecognizer = gestureRecognizer;
912  break;
913  }
914  }
915  id mockFlutterViewContoller = OCMClassMock([FlutterViewController class]);
916 
917  flutterPlatformViewsController->SetFlutterViewController(mockFlutterViewContoller);
918 
919  NSSet* touches1 = [NSSet setWithObject:@1];
920  id event1 = OCMClassMock([UIEvent class]);
921  [forwardGectureRecognizer touchesBegan:touches1 withEvent:event1];
922 
923  [forwardGectureRecognizer touchesCancelled:touches1 withEvent:event1];
924  OCMVerify([mockFlutterViewContoller forceTouchesCancelled:touches1]);
925 
926  flutterPlatformViewsController->Reset();
927 }
928 
929 - (void)testFlutterPlatformViewControllerSubmitFrameWithoutFlutterViewNotCrashing {
930  flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
931  auto thread_task_runner = CreateNewThread("FlutterPlatformViewsTest");
932  flutter::TaskRunners runners(/*label=*/self.name.UTF8String,
933  /*platform=*/thread_task_runner,
934  /*raster=*/thread_task_runner,
935  /*ui=*/thread_task_runner,
936  /*io=*/thread_task_runner);
937  auto flutterPlatformViewsController = std::make_shared<flutter::FlutterPlatformViewsController>();
938  auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
939  /*delegate=*/mock_delegate,
940  /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware,
941  /*platform_views_controller=*/flutterPlatformViewsController,
942  /*task_runners=*/runners);
943 
946  flutterPlatformViewsController->RegisterViewFactory(
947  factory, @"MockFlutterPlatformView",
949  FlutterResult result = ^(id result) {
950  };
951  flutterPlatformViewsController->OnMethodCall(
953  methodCallWithMethodName:@"create"
954  arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}],
955  result);
956 
957  XCTAssertNotNil(gMockPlatformView);
958 
959  // Create embedded view params
961  SkMatrix finalMatrix;
962 
963  auto embeddedViewParams_1 =
964  std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(300, 300), stack);
965 
966  flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams_1));
967  flutterPlatformViewsController->CompositeEmbeddedView(2);
968  auto mock_surface = std::make_unique<flutter::SurfaceFrame>(
969  nullptr, true,
970  [](const flutter::SurfaceFrame& surface_frame, SkCanvas* canvas) { return false; });
971  XCTAssertFalse(
972  flutterPlatformViewsController->SubmitFrame(nullptr, nullptr, std::move(mock_surface)));
973 
974  auto embeddedViewParams_2 =
975  std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(300, 300), stack);
976  flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams_2));
977  flutterPlatformViewsController->CompositeEmbeddedView(2);
978  auto mock_surface_submit_false = std::make_unique<flutter::SurfaceFrame>(
979  nullptr, true,
980  [](const flutter::SurfaceFrame& surface_frame, SkCanvas* canvas) { return true; });
981  XCTAssertTrue(flutterPlatformViewsController->SubmitFrame(nullptr, nullptr,
982  std::move(mock_surface_submit_false)));
983 }
984 
985 - (void)
986  testFlutterPlatformViewControllerResetDeallocsPlatformViewWhenRootViewsNotBindedToFlutterView {
987  flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
988  auto thread_task_runner = CreateNewThread("FlutterPlatformViewsTest");
989  flutter::TaskRunners runners(/*label=*/self.name.UTF8String,
990  /*platform=*/thread_task_runner,
991  /*raster=*/thread_task_runner,
992  /*ui=*/thread_task_runner,
993  /*io=*/thread_task_runner);
994  auto flutterPlatformViewsController = std::make_shared<flutter::FlutterPlatformViewsController>();
995  auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
996  /*delegate=*/mock_delegate,
997  /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware,
998  /*platform_views_controller=*/flutterPlatformViewsController,
999  /*task_runners=*/runners);
1000 
1001  UIView* mockFlutterView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)] autorelease];
1002  flutterPlatformViewsController->SetFlutterView(mockFlutterView);
1003 
1006  flutterPlatformViewsController->RegisterViewFactory(
1007  factory, @"MockFlutterPlatformView",
1009  FlutterResult result = ^(id result) {
1010  };
1011  // autorelease pool to trigger an autorelease for all the root_views_ and touch_interceptors_.
1012  @autoreleasepool {
1013  flutterPlatformViewsController->OnMethodCall(
1015  methodCallWithMethodName:@"create"
1016  arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}],
1017  result);
1018 
1019  flutter::MutatorsStack stack;
1020  SkMatrix finalMatrix;
1021  auto embeddedViewParams =
1022  std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(300, 300), stack);
1023  flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams));
1024  flutterPlatformViewsController->CompositeEmbeddedView(2);
1025  // Not calling |flutterPlatformViewsController::SubmitFrame| so that the platform views are not
1026  // added to flutter_view_.
1027 
1028  XCTAssertNotNil(gMockPlatformView);
1029  flutterPlatformViewsController->Reset();
1030  }
1031  XCTAssertNil(gMockPlatformView);
1032 }
1033 
1034 - (void)testFlutterPlatformViewControllerBeginFrameShouldResetCompisitionOrder {
1035  flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
1036  auto thread_task_runner = CreateNewThread("FlutterPlatformViewsTest");
1037  flutter::TaskRunners runners(/*label=*/self.name.UTF8String,
1038  /*platform=*/thread_task_runner,
1039  /*raster=*/thread_task_runner,
1040  /*ui=*/thread_task_runner,
1041  /*io=*/thread_task_runner);
1042  auto flutterPlatformViewsController = std::make_shared<flutter::FlutterPlatformViewsController>();
1043  auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
1044  /*delegate=*/mock_delegate,
1045  /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware,
1046  /*platform_views_controller=*/flutterPlatformViewsController,
1047  /*task_runners=*/runners);
1048 
1049  UIView* mockFlutterView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)] autorelease];
1050  flutterPlatformViewsController->SetFlutterView(mockFlutterView);
1051 
1054  flutterPlatformViewsController->RegisterViewFactory(
1055  factory, @"MockFlutterPlatformView",
1057  FlutterResult result = ^(id result) {
1058  };
1059 
1060  flutterPlatformViewsController->OnMethodCall(
1062  methodCallWithMethodName:@"create"
1063  arguments:@{@"id" : @0, @"viewType" : @"MockFlutterPlatformView"}],
1064  result);
1065 
1066  // First frame, |GetCurrentCanvases| is not empty after composite.
1067  flutterPlatformViewsController->BeginFrame(SkISize::Make(300, 300));
1068  flutter::MutatorsStack stack;
1069  SkMatrix finalMatrix;
1070  auto embeddedViewParams1 =
1071  std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(300, 300), stack);
1072  flutterPlatformViewsController->PrerollCompositeEmbeddedView(0, std::move(embeddedViewParams1));
1073  flutterPlatformViewsController->CompositeEmbeddedView(0);
1074  XCTAssertEqual(flutterPlatformViewsController->GetCurrentCanvases().size(), 1UL);
1075 
1076  // Second frame, |GetCurrentCanvases| should be empty at the start
1077  flutterPlatformViewsController->BeginFrame(SkISize::Make(300, 300));
1078  XCTAssertTrue(flutterPlatformViewsController->GetCurrentCanvases().empty());
1079 
1080  auto embeddedViewParams2 =
1081  std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(300, 300), stack);
1082  flutterPlatformViewsController->PrerollCompositeEmbeddedView(0, std::move(embeddedViewParams2));
1083  flutterPlatformViewsController->CompositeEmbeddedView(0);
1084  XCTAssertEqual(flutterPlatformViewsController->GetCurrentCanvases().size(), 1UL);
1085 }
1086 
1087 - (int)alphaOfPoint:(CGPoint)point onView:(UIView*)view {
1088  unsigned char pixel[4] = {0};
1089 
1090  CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
1091 
1092  // Draw the pixel on `point` in the context.
1093  CGContextRef context = CGBitmapContextCreate(
1094  pixel, 1, 1, 8, 4, colorSpace, kCGBitmapAlphaInfoMask & kCGImageAlphaPremultipliedLast);
1095  CGContextTranslateCTM(context, -point.x, -point.y);
1096  [view.layer renderInContext:context];
1097 
1098  CGContextRelease(context);
1099  CGColorSpaceRelease(colorSpace);
1100  // Get the alpha from the pixel that we just rendered.
1101  return pixel[3];
1102 }
1103 
1104 @end
G_BEGIN_DECLS FlValue * args
DEF_SWITCHES_START snapshot asset path
Definition: switches.h:32
KeyCallType type
G_BEGIN_DECLS FlTexture * texture
#define FLUTTER_ASSERT_NOT_ARC
Definition: FlutterMacros.h:45
void PushClipPath(const SkPath &path)
std::unique_ptr< flutter::PlatformViewIOS > platform_view
void PushTransform(const SkMatrix &matrix)
Dart_NativeFunction function
Definition: fuchsia.cc:51
int64_t texture_id
BOOL _viewCreated
GAsyncResult * result
FlKeyEvent FlKeyResponderAsyncCallback callback
FlutterSemanticsFlag flags
AssetResolverType
Identifies the type of AssetResolver an instance is.
std::function< void()> closure
Definition: closure.h:14
const float kFloatCompareEpsilon
SemanticsAction action
static void LoadDartDeferredLibrary(JNIEnv *env, jobject obj, jlong shell_holder, jint jLoadingUnitId, jobjectArray jSearchPaths)
void(^ FlutterResult)(id _Nullable result)
void PushClipRect(const SkRect &rect)
int BOOL
Definition: windows_types.h:37
void PushClipRRect(const SkRRect &rrect)
const char * name
Definition: fuchsia.cc:50
FlView * view
A Mapping like NonOwnedMapping, but uses Free as its release proc.
Definition: mapping.h:129
static MockSurface mock_surface
Definition: mock_epoxy.cc:52
static FlutterPlatformViewsTestMockPlatformView * gMockPlatformView