Flutter macOS Embedder
FlutterViewTest.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 
6 
7 #import <Metal/Metal.h>
8 
9 #import "flutter/testing/testing.h"
10 
11 constexpr int64_t kImplicitViewId = 0ll;
12 
14 
15 @end
16 
17 @implementation TestFlutterViewDelegate
18 
19 - (void)viewDidReshape:(nonnull NSView*)view {
20 }
21 
22 - (BOOL)viewShouldAcceptFirstResponder:(NSView*)view {
23  return YES;
24 }
25 
26 @end
27 
28 TEST(FlutterView, ShouldInheritContentsScaleReturnsYes) {
29  id<MTLDevice> device = MTLCreateSystemDefaultDevice();
30  id<MTLCommandQueue> queue = [device newCommandQueue];
31  TestFlutterViewDelegate* delegate = [[TestFlutterViewDelegate alloc] init];
32  FlutterThreadSynchronizer* threadSynchronizer = [[FlutterThreadSynchronizer alloc] init];
33  FlutterView* view = [[FlutterView alloc] initWithMTLDevice:device
34  commandQueue:queue
35  delegate:delegate
36  threadSynchronizer:threadSynchronizer
37  viewIdentifier:kImplicitViewId];
38  EXPECT_EQ([view layer:view.layer shouldInheritContentsScale:3.0 fromWindow:view.window], YES);
39 }
40 
42 
43 @property(readwrite, nonatomic) NSView* (^onHitTest)(NSPoint point);
44 
45 @end
46 
47 @implementation TestFlutterView
48 
49 @synthesize onHitTest;
50 
51 - (NSView*)hitTest:(NSPoint)point {
52  return self.onHitTest(point);
53 }
54 
55 - (void)reshaped {
56  // Disable resize synchronization for testing.
57 }
58 
59 @end
60 
61 @interface TestCursor : NSCursor
62 @property(readwrite, nonatomic) BOOL setCalled;
63 @end
64 
65 @implementation TestCursor
66 
67 - (void)set {
68  self.setCalled = YES;
69 }
70 
71 @end
72 
73 TEST(FlutterView, CursorUpdateDoesHitTest) {
74  id<MTLDevice> device = MTLCreateSystemDefaultDevice();
75  id<MTLCommandQueue> queue = [device newCommandQueue];
76  TestFlutterViewDelegate* delegate = [[TestFlutterViewDelegate alloc] init];
77  FlutterThreadSynchronizer* threadSynchronizer = [[FlutterThreadSynchronizer alloc] init];
78  TestFlutterView* view = [[TestFlutterView alloc] initWithMTLDevice:device
79  commandQueue:queue
80  delegate:delegate
81  threadSynchronizer:threadSynchronizer
82  viewIdentifier:kImplicitViewId];
83  NSWindow* window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 800, 600)
84  styleMask:NSBorderlessWindowMask
85  backing:NSBackingStoreBuffered
86  defer:NO];
87 
88  TestCursor* cursor = [[TestCursor alloc] init];
89 
90  window.contentView = view;
91  __weak NSView* weakView = view;
92  __block BOOL hitTestCalled = NO;
93  __block NSPoint hitTestCoordinate = NSZeroPoint;
94  view.onHitTest = ^NSView*(NSPoint point) {
95  hitTestCalled = YES;
96  hitTestCoordinate = point;
97  return weakView;
98  };
99  NSEvent* mouseEvent = [NSEvent mouseEventWithType:NSEventTypeMouseMoved
100  location:NSMakePoint(100, 100)
101  modifierFlags:0
102  timestamp:0
103  windowNumber:0
104  context:nil
105  eventNumber:0
106  clickCount:0
107  pressure:0];
108  [view didUpdateMouseCursor:cursor];
109  [view cursorUpdate:mouseEvent];
110 
111  EXPECT_TRUE(hitTestCalled);
112  // The hit test coordinate should be in the window coordinate system.
113  EXPECT_TRUE(CGPointEqualToPoint(hitTestCoordinate, CGPointMake(100, 100)));
114  EXPECT_TRUE(cursor.setCalled);
115 }
116 
117 TEST(FlutterView, CursorUpdateDoesNotOverridePlatformView) {
118  id<MTLDevice> device = MTLCreateSystemDefaultDevice();
119  id<MTLCommandQueue> queue = [device newCommandQueue];
120  TestFlutterViewDelegate* delegate = [[TestFlutterViewDelegate alloc] init];
121  FlutterThreadSynchronizer* threadSynchronizer = [[FlutterThreadSynchronizer alloc] init];
122  TestFlutterView* view = [[TestFlutterView alloc] initWithMTLDevice:device
123  commandQueue:queue
124  delegate:delegate
125  threadSynchronizer:threadSynchronizer
126  viewIdentifier:kImplicitViewId];
127  NSWindow* window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 800, 600)
128  styleMask:NSBorderlessWindowMask
129  backing:NSBackingStoreBuffered
130  defer:NO];
131 
132  TestCursor* cursor = [[TestCursor alloc] init];
133 
134  NSView* platformView = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)];
135 
136  window.contentView = view;
137  __block BOOL hitTestCalled = NO;
138  __block NSPoint hitTestCoordinate = NSZeroPoint;
139  view.onHitTest = ^NSView*(NSPoint point) {
140  hitTestCalled = YES;
141  hitTestCoordinate = point;
142  return platformView;
143  };
144  NSEvent* mouseEvent = [NSEvent mouseEventWithType:NSEventTypeMouseMoved
145  location:NSMakePoint(100, 100)
146  modifierFlags:0
147  timestamp:0
148  windowNumber:0
149  context:nil
150  eventNumber:0
151  clickCount:0
152  pressure:0];
153  [view didUpdateMouseCursor:cursor];
154  [view cursorUpdate:mouseEvent];
155 
156  EXPECT_TRUE(hitTestCalled);
157  // The hit test coordinate should be in the window coordinate system.
158  EXPECT_TRUE(CGPointEqualToPoint(hitTestCoordinate, CGPointMake(100, 100)));
159  EXPECT_FALSE(cursor.setCalled);
160 }
TestCursor
Definition: FlutterViewTest.mm:61
TEST
TEST(FlutterView, ShouldInheritContentsScaleReturnsYes)
Definition: FlutterViewTest.mm:28
FlutterThreadSynchronizer
Definition: FlutterThreadSynchronizer.h:18
-[FlutterView didUpdateMouseCursor:]
void didUpdateMouseCursor:(nonnull NSCursor *cursor)
TestFlutterView::onHitTest
NSView *(^ onHitTest)(NSPoint point)
TestFlutterViewDelegate
Definition: FlutterViewTest.mm:13
FlutterView
Definition: FlutterView.h:35
kImplicitViewId
constexpr int64_t kImplicitViewId
Definition: FlutterViewTest.mm:11
FlutterView.h
TestFlutterView
Definition: FlutterViewTest.mm:41
TestCursor::setCalled
BOOL setCalled
Definition: FlutterViewTest.mm:62
FlutterViewDelegate-p
Definition: FlutterView.h:18