| Flutter macOS Embedder |

FlutterWindowControllerTest.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 "flutter/shell/platform/common/isolate_scope.h"
6 #import "flutter/shell/platform/common/windowing.h"
7
8 #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterDartProject_Internal.h"
9 #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterEngineTestUtils.h"
10 #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h"
11 #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterWindowController.h"
12 #import "flutter/testing/testing.h"
13 #import "third_party/googletest/googletest/include/gtest/gtest.h"
14
15 namespace flutter::testing {
16
17 class FlutterWindowControllerTest : public FlutterEngineTest {
18 public:
19 FlutterWindowControllerTest() = default;
20
21 void SetUp() {
22 FlutterEngineTest::SetUp();
23
24 [GetFlutterEngine() runWithEntrypoint:@"testWindowController"];
25
26 bool signalled = false;
27
28 AddNativeCallback("SignalNativeTest", CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
29 isolate_ = Isolate::Current();
30 signalled = true;
31 }));
32
33 while (!signalled) {
34 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
35 }
36 }
37
38 void TearDown() {
39 [GetFlutterEngine().windowController closeAllWindows];
40 FlutterEngineTest::TearDown();
41 }
42
43 protected:
44 flutter::Isolate& isolate() {
45 if (isolate_) {
46 return *isolate_;
47 } else {
48 FML_LOG(ERROR) << "Isolate is not set.";
49 FML_UNREACHABLE();
50 }
51 }
52
53 std::optional<flutter::Isolate> isolate_;
54 };
55
56 class FlutterWindowControllerRetainTest : public ::testing::Test {};
57
58 TEST_F(FlutterWindowControllerTest, CreateRegularWindow) {
59 FlutterWindowCreationRequest request{
60 .has_size = true,
61 .size = {.width = 800, .height = 600},
62 .on_should_close = [] {},
63 .on_will_close = [] {},
64 .notify_listeners = [] {},
65 };
66
67 FlutterEngine* engine = GetFlutterEngine();
68 int64_t engineId = reinterpret_cast<int64_t>(engine);
69
70 {
71 IsolateScope isolate_scope(isolate());
72 int64_t handle = InternalFlutter_WindowController_CreateRegularWindow(engineId, &request);
73 EXPECT_EQ(handle, 1);
74
75 FlutterViewController* viewController = [engine viewControllerForIdentifier:handle];
76 EXPECT_NE(viewController, nil);
77 CGSize size = viewController.view.frame.size;
78 EXPECT_EQ(size.width, 800);
79 EXPECT_EQ(size.height, 600);
80 }
81 }
82
83 TEST_F(FlutterWindowControllerRetainTest, WindowControllerDoesNotRetainEngine) {
84 FlutterWindowCreationRequest request{
85 .has_size = true,
86 .size = {.width = 800, .height = 600},
87 .on_should_close = [] {},
88 .on_will_close = [] {},
89 .notify_listeners = [] {},
90 };
91
92 __weak FlutterEngine* weakEngine = nil;
93 @autoreleasepool {
94 NSString* fixtures = @(flutter::testing::GetFixturesPath());
95 NSLog(@"Fixtures path: %@", fixtures);
96 FlutterDartProject* project = [[FlutterDartProject alloc]
97 initWithAssetsPath:fixtures
98 ICUDataPath:[fixtures stringByAppendingString:@"/icudtl.dat"]];
99
100 static std::optional<flutter::Isolate> isolate;
101 isolate = std::nullopt;
102
103 project.rootIsolateCreateCallback = [](void*) { isolate = flutter::Isolate::Current(); };
104 FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test"
105 project:project
106 allowHeadlessExecution:YES];
107 weakEngine = engine;
108 [engine runWithEntrypoint:@"testWindowControllerRetainCycle"];
109
110 int64_t engineId = reinterpret_cast<int64_t>(engine);
111
112 {
113 FML_DCHECK(isolate.has_value());
114 // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
115 IsolateScope isolateScope(*isolate);
116 int64_t handle = InternalFlutter_WindowController_CreateRegularWindow(engineId, &request);
117 EXPECT_EQ(handle, 1);
118 }
119
120 [engine.windowController closeAllWindows];
121 [engine shutDownEngine];
122 }
123 EXPECT_EQ(weakEngine, nil);
124 }
125
126 TEST_F(FlutterWindowControllerTest, DestroyRegularWindow) {
127 FlutterWindowCreationRequest request{
128 .has_size = true,
129 .size = {.width = 800, .height = 600},
130 .on_should_close = [] {},
131 .on_will_close = [] {},
132 .notify_listeners = [] {},
133 };
134
135 FlutterEngine* engine = GetFlutterEngine();
136 int64_t engine_id = reinterpret_cast<int64_t>(engine);
137
138 IsolateScope isolate_scope(isolate());
139 int64_t handle = InternalFlutter_WindowController_CreateRegularWindow(engine_id, &request);
140 FlutterViewController* viewController = [engine viewControllerForIdentifier:handle];
141
142 InternalFlutter_Window_Destroy(engine_id, (__bridge void*)viewController.view.window);
143 viewController = [engine viewControllerForIdentifier:handle];
144 EXPECT_EQ(viewController, nil);
145 }
146
147 TEST_F(FlutterWindowControllerTest, InternalFlutter_Window_GetHandle) {
148 FlutterWindowCreationRequest request{
149 .has_size = true,
150 .size = {.width = 800, .height = 600},
151 .on_should_close = [] {},
152 .on_will_close = [] {},
153 .notify_listeners = [] {},
154 };
155
156 FlutterEngine* engine = GetFlutterEngine();
157 int64_t engine_id = reinterpret_cast<int64_t>(engine);
158
159 IsolateScope isolate_scope(isolate());
160 int64_t handle = InternalFlutter_WindowController_CreateRegularWindow(engine_id, &request);
161 FlutterViewController* viewController = [engine viewControllerForIdentifier:handle];
162
163 void* window_handle = InternalFlutter_Window_GetHandle(engine_id, handle);
164 EXPECT_EQ(window_handle, (__bridge void*)viewController.view.window);
165 }
166
167 TEST_F(FlutterWindowControllerTest, WindowStates) {
168 FlutterWindowCreationRequest request{
169 .has_size = true,
170 .size = {.width = 800, .height = 600},
171 .on_should_close = [] {},
172 .on_will_close = [] {},
173 .notify_listeners = [] {},
174 };
175
176 FlutterEngine* engine = GetFlutterEngine();
177 int64_t engine_id = reinterpret_cast<int64_t>(engine);
178
179 IsolateScope isolate_scope(isolate());
180 int64_t handle = InternalFlutter_WindowController_CreateRegularWindow(engine_id, &request);
181
182 FlutterViewController* viewController = [engine viewControllerForIdentifier:handle];
183 NSWindow* window = viewController.view.window;
184 void* windowHandle = (__bridge void*)window;
185
186 EXPECT_EQ(window.zoomed, NO);
187 EXPECT_EQ(window.miniaturized, NO);
188 EXPECT_EQ(window.styleMask & NSWindowStyleMaskFullScreen, 0u);
189
190 InternalFlutter_Window_SetMaximized(windowHandle, true);
191 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.5, false);
192 EXPECT_EQ(window.zoomed, YES);
193
194 InternalFlutter_Window_SetMaximized(windowHandle, false);
195 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.5, false);
196 EXPECT_EQ(window.zoomed, NO);
197
198 // FullScreen toggle does not seem to work when the application is not run from a bundle.
199
200 InternalFlutter_Window_Minimize(windowHandle);
201 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.5, false);
202 EXPECT_EQ(window.miniaturized, YES);
203 }
204 } // namespace flutter::testing
FlutterDartProject_Internal.h
FlutterEngine_Internal.h
FlutterEngineTestUtils.h
FlutterWindowController.h
InternalFlutter_WindowController_CreateRegularWindow
FLUTTER_DARWIN_EXPORT int64_t InternalFlutter_WindowController_CreateRegularWindow(int64_t engine_id, const FlutterWindowCreationRequest *request)
Definition: FlutterWindowController.mm:272
InternalFlutter_Window_SetMaximized
FLUTTER_DARWIN_EXPORT void InternalFlutter_Window_SetMaximized(void *window, bool maximized)
Definition: FlutterWindowController.mm:326
InternalFlutter_Window_Destroy
FLUTTER_DARWIN_EXPORT void InternalFlutter_Window_Destroy(int64_t engine_id, void *window)
Definition: FlutterWindowController.mm:288
InternalFlutter_Window_GetHandle
FLUTTER_DARWIN_EXPORT void * InternalFlutter_Window_GetHandle(int64_t engine_id, FlutterViewIdentifier view_id)
Definition: FlutterWindowController.mm:294
InternalFlutter_Window_Minimize
FLUTTER_DARWIN_EXPORT void InternalFlutter_Window_Minimize(void *window)
Definition: FlutterWindowController.mm:340
FlutterDartProject
Definition: FlutterDartProject.mm:24
flutter::Isolate
Definition: isolate_scope.h:15
flutter::Isolate::Current
static Isolate Current()
Definition: isolate_scope.cc:9
flutter::IsolateScope
Definition: isolate_scope.h:33
flutter::testing::FlutterEngineTest
Definition: FlutterEngineTestUtils.h:18
flutter::testing::FlutterEngineTest::AddNativeCallback
void AddNativeCallback(const char *name, Dart_NativeFunction function)
Definition: FlutterEngineTestUtils.mm:72
flutter::testing::FlutterEngineTest::TearDown
void TearDown() override
Definition: FlutterEngineTestUtils.mm:57
flutter::testing::FlutterEngineTest::SetUp
void SetUp() override
Definition: FlutterEngineTestUtils.mm:45
flutter::testing::FlutterEngineTest::GetFlutterEngine
FlutterEngine * GetFlutterEngine()
Definition: FlutterEngineTestUtils.h:22
flutter::testing::FlutterWindowControllerRetainTest
Definition: FlutterWindowControllerTest.mm:56
flutter::testing::FlutterWindowControllerTest
Definition: FlutterWindowControllerTest.mm:17
flutter::testing::FlutterWindowControllerTest::SetUp
void SetUp()
Definition: FlutterWindowControllerTest.mm:21
flutter::testing::FlutterWindowControllerTest::isolate_
std::optional< flutter::Isolate > isolate_
Definition: FlutterWindowControllerTest.mm:53
flutter::testing::FlutterWindowControllerTest::FlutterWindowControllerTest
FlutterWindowControllerTest()=default
flutter::testing::FlutterWindowControllerTest::isolate
flutter::Isolate & isolate()
Definition: FlutterWindowControllerTest.mm:44
flutter::testing::FlutterWindowControllerTest::TearDown
void TearDown()
Definition: FlutterWindowControllerTest.mm:38
FlutterEngine
Definition: FlutterEngine.h:32
FlutterViewController
Definition: FlutterViewController.h:73
isolate_scope.h
flutter::testing
Definition: AccessibilityBridgeMacTest.mm:13
flutter::testing::TEST_F
TEST_F(AccessibilityBridgeMacWindowTest, SendsAccessibilityCreateNotificationFlutterViewWindow)
Definition: AccessibilityBridgeMacTest.mm:90
FlutterWindowCreationRequest
Definition: FlutterWindowController.h:39
FlutterWindowCreationRequest::has_size
bool has_size
Definition: FlutterWindowController.h:40
windowing.h