5#import <OCMock/OCMock.h>
6#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterMutatorView.h"
7#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterView.h"
9#include "third_party/googletest/googletest/include/gtest/gtest.h"
11#import "flutter/shell/platform/darwin/macos/framework/Source/NSView+ClipsToBounds.h"
15@property(readonly, nonatomic, nonnull) NSMutableArray<NSView*>* pathClipViews;
16@property(readonly, nonatomic, nullable) NSView* platformViewContainer;
25 const std::vector<FlutterPlatformViewMutation>& mutations) {
40void ExpectTransform3DEqual(
const CATransform3D& t,
const CATransform3D& u) {
41 EXPECT_NEAR(t.m11, u.m11,
kMaxErr);
42 EXPECT_NEAR(t.m12, u.m12,
kMaxErr);
43 EXPECT_NEAR(t.m13, u.m13,
kMaxErr);
44 EXPECT_NEAR(t.m14, u.m14,
kMaxErr);
46 EXPECT_NEAR(t.m21, u.m21,
kMaxErr);
47 EXPECT_NEAR(t.m22, u.m22,
kMaxErr);
48 EXPECT_NEAR(t.m23, u.m23,
kMaxErr);
49 EXPECT_NEAR(t.m24, u.m24,
kMaxErr);
51 EXPECT_NEAR(t.m31, u.m31,
kMaxErr);
52 EXPECT_NEAR(t.m32, u.m32,
kMaxErr);
53 EXPECT_NEAR(t.m33, u.m33,
kMaxErr);
54 EXPECT_NEAR(t.m34, u.m34,
kMaxErr);
56 EXPECT_NEAR(t.m41, u.m41,
kMaxErr);
57 EXPECT_NEAR(t.m42, u.m42,
kMaxErr);
58 EXPECT_NEAR(t.m43, u.m43,
kMaxErr);
59 EXPECT_NEAR(t.m44, u.m44,
kMaxErr);
63TEST(FlutterMutatorViewTest, BasicFrameIsCorrect) {
64 NSView* platformView = [[NSView alloc] init];
69 std::vector<FlutterPlatformViewMutation> mutations{
82 ApplyFlutterLayer(mutatorView,
FlutterSize{30, 20}, mutations);
84 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(100, 50, 30, 20)));
85 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
90TEST(FlutterMutatorViewTest, ClipsToBounds) {
91 NSView* platformView = [[NSView alloc] init];
96TEST(FlutterMutatorViewTest, TransformedFrameIsCorrect) {
97 NSView* platformView = [[NSView alloc] init];
99 NSView* mutatorViewParent = [[NSView alloc] init];
100 mutatorViewParent.wantsLayer = YES;
102 [mutatorViewParent addSubview:mutatorView];
104 std::vector<FlutterPlatformViewMutation> mutations{
136 ApplyFlutterLayer(mutatorView,
FlutterSize{30 * 2, 20 * 2}, mutations);
137 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(92.5, 45, 45, 30)));
138 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
141 CATransform3DMakeScale(1.5, 1.5, 1));
144TEST(FlutterMutatorViewTest, FrameWithLooseClipIsCorrect) {
145 NSView* platformView = [[NSView alloc] init];
150 std::vector<FlutterPlatformViewMutation> mutations{
167 ApplyFlutterLayer(mutatorView,
FlutterSize{30, 20}, mutations);
169 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(100, 50, 30, 20)));
170 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
173TEST(FlutterMutatorViewTest, FrameWithTightClipIsCorrect) {
174 NSView* platformView = [[NSView alloc] init];
179 std::vector<FlutterPlatformViewMutation> mutations{
200 ApplyFlutterLayer(mutatorView,
FlutterSize{30, 20}, mutations);
202 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(110, 55, 10, 10)));
204 CGRectEqualToRect(mutatorView.subviews.firstObject.frame, CGRectMake(-10, -5, 30, 20)));
205 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
208TEST(FlutterMutatorViewTest, FrameWithTightClipAndTransformIsCorrect) {
209 NSView* platformView = [[NSView alloc] init];
211 NSView* mutatorViewParent = [[NSView alloc] init];
212 mutatorViewParent.wantsLayer = YES;
214 [mutatorViewParent addSubview:mutatorView];
216 std::vector<FlutterPlatformViewMutation> mutations{
255 ApplyFlutterLayer(mutatorView,
FlutterSize{30 * 2, 20 * 2}, mutations);
257 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(110, 55, 10, 10)));
259 CGRectEqualToRect(mutatorView.subviews.firstObject.frame, CGRectMake(-17.5, -10, 45, 30)));
260 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
264TEST(FlutterMutatorViewTest, RoundRectClipsToSimpleRectangle) {
265 NSView* platformView = [[NSView alloc] init];
268 std::vector<FlutterPlatformViewMutation> mutations{
292 ApplyFlutterLayer(mutatorView,
FlutterSize{30, 20}, mutations);
294 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(110, 50, 10, 20)));
296 CGRectEqualToRect(mutatorView.subviews.firstObject.frame, CGRectMake(-10, 0, 30, 20)));
297 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
304TEST(FlutterMutatorViewTest, ViewsSetIsFlipped) {
305 NSView* platformView = [[NSView alloc] init];
308 std::vector<FlutterPlatformViewMutation> mutations{
332 ApplyFlutterLayer(mutatorView,
FlutterSize{30, 20}, mutations);
340TEST(FlutterMutatorViewTest, RectsClipsToPathWhenRotated) {
341 NSView* platformView = [[NSView alloc] init];
343 std::vector<FlutterPlatformViewMutation> mutations{
349 .
scaleX = 0.9238795325112867,
350 .skewX = -0.3826834323650898,
351 .skewY = 0.3826834323650898,
352 .scaleY = 0.9238795325112867,
370 ApplyFlutterLayer(mutatorView,
FlutterSize{30, 20}, mutations);
376TEST(FlutterMutatorViewTest, RoundRectClipsToPath) {
377 NSView* platformView = [[NSView alloc] init];
380 std::vector<FlutterPlatformViewMutation> mutations{
404 ApplyFlutterLayer(mutatorView,
FlutterSize{30, 20}, mutations);
406 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(110, 60, 20, 10)));
408 CGRectEqualToRect(mutatorView.subviews.firstObject.frame, CGRectMake(-10, -10, 30, 20)));
409 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
411 ExpectTransform3DEqual(mutatorView.
pathClipViews.firstObject.layer.mask.transform,
412 CATransform3DMakeTranslation(-100, -50, 0));
415TEST(FlutterMutatorViewTest, PathClipViewsAreAddedAndRemoved) {
416 NSView* platformView = [[NSView alloc] init];
419 std::vector<FlutterPlatformViewMutation> mutations{
432 ApplyFlutterLayer(mutatorView,
FlutterSize{30, 20}, mutations);
434 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(100, 50, 30, 20)));
437 std::vector<FlutterPlatformViewMutation> mutations2{
461 ApplyFlutterLayer(mutatorView,
FlutterSize{30, 20}, mutations2);
463 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(110, 60, 20, 10)));
465 CGRectEqualToRect(mutatorView.subviews.firstObject.frame, CGRectMake(-10, -10, 30, 20)));
466 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
471 EXPECT_EQ(mutatorView.
pathClipViews[0].superview, mutatorView);
473 std::vector<FlutterPlatformViewMutation> mutations3{
508 ApplyFlutterLayer(mutatorView,
FlutterSize{30, 20}, mutations3);
510 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(110, 55, 10, 10)));
512 CGRectEqualToRect(mutatorView.subviews.firstObject.frame, CGRectMake(-10, -5, 30, 20)));
518 EXPECT_EQ(mutatorView.
pathClipViews[0].superview, mutatorView);
520 ApplyFlutterLayer(mutatorView,
FlutterSize{30, 20}, mutations2);
522 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(110, 60, 20, 10)));
524 CGRectEqualToRect(mutatorView.subviews.firstObject.frame, CGRectMake(-10, -10, 30, 20)));
525 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
530 EXPECT_EQ(mutatorView.
pathClipViews[0].superview, mutatorView);
532 ApplyFlutterLayer(mutatorView,
FlutterSize{30, 20}, mutations);
534 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(100, 50, 30, 20)));
538TEST(FlutterMutatorViewTest, HitTestIgnoreRegion) {
539 NSView* platformView = [[NSView alloc] init];
541 ApplyFlutterLayer(mutatorView,
FlutterSize{100, 100}, {});
542 EXPECT_EQ([mutatorView hitTest:NSMakePoint(10, 10)], platformView);
543 EXPECT_EQ([mutatorView hitTest:NSMakePoint(50, 10)], platformView);
549 EXPECT_EQ([mutatorView hitTest:NSMakePoint(10, 10)], nil);
550 EXPECT_EQ([mutatorView hitTest:NSMakePoint(49, 10)], nil);
551 EXPECT_EQ([mutatorView hitTest:NSMakePoint(10, 49)], nil);
552 EXPECT_EQ([mutatorView hitTest:NSMakePoint(50, 50)], nil);
553 EXPECT_EQ([mutatorView hitTest:NSMakePoint(50, 10)], platformView);
554 EXPECT_EQ([mutatorView hitTest:NSMakePoint(10, 50)], platformView);
557 EXPECT_EQ([mutatorView hitTest:NSMakePoint(10, 10)], platformView);
558 EXPECT_EQ([mutatorView hitTest:NSMakePoint(49, 10)], platformView);
559 EXPECT_EQ([mutatorView hitTest:NSMakePoint(10, 49)], platformView);
560 EXPECT_EQ([mutatorView hitTest:NSMakePoint(50, 50)], platformView);
561 EXPECT_EQ([mutatorView hitTest:NSMakePoint(50, 10)], platformView);
562 EXPECT_EQ([mutatorView hitTest:NSMakePoint(10, 50)], platformView);
565TEST(FlutterMutatorViewTest, ReparentingPlatformView) {
566 NSView* platformView = [[NSView alloc] init];
568 ApplyFlutterLayer(mutatorView,
FlutterSize{100, 100}, {});
570 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 100, 100)));
573 NSView* newParent = [[NSView alloc] init];
574 [newParent addSubview:platformView];
575 platformView.frame = CGRectMake(10, 10, 200, 200);
577 NSView* placeholderView = [[NSView alloc] init];
578 [mutatorView.platformViewContainer addSubview:placeholderView];
579 ApplyFlutterLayer(mutatorView,
FlutterSize{100, 100}, {});
583 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(10, 10, 200, 200)));
584 EXPECT_TRUE(CGRectEqualToRect(placeholderView.frame, CGRectMake(0, 0, 100, 100)));
593 id flutterView = OCMClassMock([
FlutterView class]);
597 id platformView = OCMClassMock([NSView
class]);
598 OCMStub([flutterView cursorUpdate:[OCMArg
any]]);
600 OCMStub([mutatorView platformView]).andReturn(platformView);
601 CGPoint location = NSMakePoint(50, 50);
602 OCMStub([mutatorView convertPoint:location fromView:[OCMArg
any]]).andReturn(location);
603 NSEvent*
event = [NSEvent mouseEventWithType:NSEventTypeMouseMoved
615 OCMVerify([flutterView cursorUpdate:
event]);
618 id platformView = OCMClassMock([NSView
class]);
620 OCMReject([flutterView cursorUpdate:[OCMArg
any]]);
622 OCMStub([mutatorView platformView]).andReturn(platformView);
623 CGPoint location = NSMakePoint(50, 50);
624 OCMStub([mutatorView convertPoint:location fromView:[OCMArg
any]]).andReturn(location);
625 NSEvent*
event = [NSEvent mouseEventWithType:NSEventTypeMouseMoved
639 [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
644 id flutterView = OCMClassMock([
FlutterView class]);
645 OCMReject([flutterView cursorUpdate:[OCMArg
any]]);
648 id platformViewWindow = OCMClassMock([NSWindow
class]);
650 id platformView = OCMClassMock([NSView
class]);
651 OCMStub([platformViewWindow invalidateCursorRectsForView:platformView]);
652 OCMStub([platformView
window]).andReturn(platformViewWindow);
653 OCMStub([flutterView cursorUpdate:[OCMArg
any]]);
655 OCMStub([mutatorView platformView]).andReturn(platformView);
656 CGPoint location = NSMakePoint(150, 150);
657 OCMStub([mutatorView convertPoint:location fromView:[OCMArg
any]]).andReturn(location);
658 NSEvent*
event = [NSEvent mouseEventWithType:NSEventTypeMouseMoved
670 OCMVerify([platformViewWindow invalidateCursorRectsForView:platformView]);
674 OCMReject([platformViewWindow invalidateCursorRectsForView:[OCMArg
any]]);
676 id platformView = OCMClassMock([NSView
class]);
677 OCMStub([platformViewWindow invalidateCursorRectsForView:platformView]);
678 OCMStub([platformView
window]).andReturn(platformViewWindow);
679 OCMStub([flutterView cursorUpdate:[OCMArg
any]]);
681 OCMStub([mutatorView platformView]).andReturn(platformView);
682 CGPoint location = NSMakePoint(150, 150);
683 OCMStub([mutatorView convertPoint:location fromView:[OCMArg
any]]).andReturn(location);
684 NSEvent*
event = [NSEvent mouseEventWithType:NSEventTypeMouseMoved
698 [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
702 platformViewWindow = OCMClassMock([NSWindow
class]);
704 id platformView = OCMClassMock([NSView
class]);
705 OCMStub([platformViewWindow invalidateCursorRectsForView:platformView]);
706 OCMStub([platformView
window]).andReturn(platformViewWindow);
707 OCMStub([flutterView cursorUpdate:[OCMArg
any]]);
709 OCMStub([mutatorView platformView]).andReturn(platformView);
710 CGPoint location = NSMakePoint(150, 150);
711 OCMStub([mutatorView convertPoint:location fromView:[OCMArg
any]]).andReturn(location);
712 NSEvent*
event = [NSEvent mouseEventWithType:NSEventTypeMouseMoved
724 OCMVerify([platformViewWindow invalidateCursorRectsForView:platformView]);
726 [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
730TEST(FlutterMutatorViewTest, CursorCoordinator) {
static constexpr float kMaxErr
TEST(FlutterMutatorViewTest, BasicFrameIsCorrect)
@ kFlutterPlatformViewMutationTypeClipRoundedRect
@ kFlutterPlatformViewMutationTypeClipRect
@ kFlutterPlatformViewMutationTypeTransformation
void testCoordinatorEventOutsideFlutterContent()
void testCoordinatorEventWithinFlutterContent()
void processMouseMoveEvent:forMutatorView:overlayRegion:(NSEvent *event, [forMutatorView] FlutterMutatorView *view, [overlayRegion] const std::vector< CGRect > ®ion)
NSMutableArray * pathClipViews()
NSView * platformView
Returns wrapped platform view.
void resetHitTestRegion()
Resets hit hit testing region for this mutator view.
void applyFlutterLayer:(nonnull const flutter::PlatformViewLayer *layer)
CGFloat contentsScale()
Returns the scale factor to translate logical pixels to physical pixels for this view.
NSView * platformViewContainer()
void addHitTestIgnoreRegion:(CGRect region)
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
SIT bool any(const Vec< 1, T > &x)
A structure to represent a 2D point.
A structure to represent a rectangle.
A structure to represent a rounded rectangle.
A structure to represent the width and height.
#define EXPECT_TRUE(handle)