Flutter Engine
 
Loading...
Searching...
No Matches
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
7
13#import "third_party/googletest/googletest/include/gtest/gtest.h"
14
15namespace flutter::testing {
16
18 public:
20
21 void SetUp() {
23
24 [GetFlutterEngine() runWithEntrypoint:@"testWindowController"];
25
26 bool signalled = false;
27
28 AddNativeCallback("SignalNativeTest", CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
30 signalled = true;
31 }));
32
33 while (!signalled) {
34 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
35 }
36 }
37
38 void TearDown() {
39 [GetFlutterEngine().windowController closeAllWindows];
41 }
42
43 protected:
45 if (isolate_) {
46 return *isolate_;
47 } else {
48 FML_LOG(ERROR) << "Isolate is not set.";
50 }
51 }
52
53 std::optional<flutter::Isolate> isolate_;
54};
55
56class FlutterWindowControllerRetainTest : public ::testing::Test {};
57
58TEST_F(FlutterWindowControllerTest, CreateRegularWindow) {
60 .has_size = true,
61 .size = {.width = 800, .height = 600},
62 .on_close = [] {},
63 .notify_listeners = [] {},
64 };
65
66 FlutterEngine* engine = GetFlutterEngine();
67 int64_t engineId = reinterpret_cast<int64_t>(engine);
68
69 {
70 IsolateScope isolate_scope(isolate());
71 int64_t handle = InternalFlutter_WindowController_CreateRegularWindow(engineId, &request);
72 EXPECT_EQ(handle, 1);
73
74 FlutterViewController* viewController = [engine viewControllerForIdentifier:handle];
75 EXPECT_NE(viewController, nil);
76 CGSize size = viewController.view.frame.size;
77 EXPECT_EQ(size.width, 800);
78 EXPECT_EQ(size.height, 600);
79 }
80}
81
82TEST_F(FlutterWindowControllerRetainTest, WindowControllerDoesNotRetainEngine) {
84 .has_size = true,
85 .size = {.width = 800, .height = 600},
86 .on_close = [] {},
87 .notify_listeners = [] {},
88 };
89
90 __weak FlutterEngine* weakEngine = nil;
91 @autoreleasepool {
92 NSString* fixtures = @(flutter::testing::GetFixturesPath());
93 NSLog(@"Fixtures path: %@", fixtures);
94 FlutterDartProject* project = [[FlutterDartProject alloc]
95 initWithAssetsPath:fixtures
96 ICUDataPath:[fixtures stringByAppendingString:@"/icudtl.dat"]];
97
98 static std::optional<flutter::Isolate> isolate;
99 isolate = std::nullopt;
100
101 project.rootIsolateCreateCallback = [](void*) { isolate = flutter::Isolate::Current(); };
102 FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test"
103 project:project
104 allowHeadlessExecution:YES];
105 weakEngine = engine;
106 [engine runWithEntrypoint:@"testWindowControllerRetainCycle"];
107
108 int64_t engineId = reinterpret_cast<int64_t>(engine);
109
110 {
111 FML_DCHECK(isolate.has_value());
112 // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
113 IsolateScope isolateScope(*isolate);
114 int64_t handle = InternalFlutter_WindowController_CreateRegularWindow(engineId, &request);
115 EXPECT_EQ(handle, 1);
116 }
117
118 [engine.windowController closeAllWindows];
119 [engine shutDownEngine];
120 }
121 EXPECT_EQ(weakEngine, nil);
122}
123
124TEST_F(FlutterWindowControllerTest, DestroyRegularWindow) {
126 .has_size = true,
127 .size = {.width = 800, .height = 600},
128 .on_close = [] {},
129 .notify_listeners = [] {},
130 };
131
132 FlutterEngine* engine = GetFlutterEngine();
133 int64_t engine_id = reinterpret_cast<int64_t>(engine);
134
135 IsolateScope isolate_scope(isolate());
136 int64_t handle = InternalFlutter_WindowController_CreateRegularWindow(engine_id, &request);
137 FlutterViewController* viewController = [engine viewControllerForIdentifier:handle];
138
139 InternalFlutter_Window_Destroy(engine_id, (__bridge void*)viewController.view.window);
140 viewController = [engine viewControllerForIdentifier:handle];
141 EXPECT_EQ(viewController, nil);
142}
143
146 .has_size = true,
147 .size = {.width = 800, .height = 600},
148 .on_close = [] {},
149 .notify_listeners = [] {},
150 };
151
152 FlutterEngine* engine = GetFlutterEngine();
153 int64_t engine_id = reinterpret_cast<int64_t>(engine);
154
155 IsolateScope isolate_scope(isolate());
156 int64_t handle = InternalFlutter_WindowController_CreateRegularWindow(engine_id, &request);
157 FlutterViewController* viewController = [engine viewControllerForIdentifier:handle];
158
159 void* window_handle = InternalFlutter_Window_GetHandle(engine_id, handle);
160 EXPECT_EQ(window_handle, (__bridge void*)viewController.view.window);
161}
162
165 .has_size = true,
166 .size = {.width = 800, .height = 600},
167 .on_close = [] {},
168 .notify_listeners = [] {},
169 };
170
171 FlutterEngine* engine = GetFlutterEngine();
172 int64_t engine_id = reinterpret_cast<int64_t>(engine);
173
174 IsolateScope isolate_scope(isolate());
175 int64_t handle = InternalFlutter_WindowController_CreateRegularWindow(engine_id, &request);
176
177 FlutterViewController* viewController = [engine viewControllerForIdentifier:handle];
178 NSWindow* window = viewController.view.window;
179 void* windowHandle = (__bridge void*)window;
180
181 EXPECT_EQ(window.zoomed, NO);
182 EXPECT_EQ(window.miniaturized, NO);
183 EXPECT_EQ(window.styleMask & NSWindowStyleMaskFullScreen, 0u);
184
185 InternalFlutter_Window_SetMaximized(windowHandle, true);
186 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.5, false);
187 EXPECT_EQ(window.zoomed, YES);
188
189 InternalFlutter_Window_SetMaximized(windowHandle, false);
190 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.5, false);
191 EXPECT_EQ(window.zoomed, NO);
192
193 // FullScreen toggle does not seem to work when the application is not run from a bundle.
194
196 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.5, false);
197 EXPECT_EQ(window.miniaturized, YES);
198}
199} // namespace flutter::testing
FLUTTER_DARWIN_EXPORT int64_t InternalFlutter_WindowController_CreateRegularWindow(int64_t engine_id, const FlutterWindowCreationRequest *request)
FLUTTER_DARWIN_EXPORT void * InternalFlutter_Window_GetHandle(int64_t engine_id, FlutterViewIdentifier view_id)
FLUTTER_DARWIN_EXPORT void InternalFlutter_Window_SetMaximized(void *window, bool maximized)
FLUTTER_DARWIN_EXPORT void InternalFlutter_Window_Destroy(int64_t engine_id, void *window)
FLUTTER_DARWIN_EXPORT void InternalFlutter_Window_Minimize(void *window)
static Isolate Current()
void AddNativeCallback(const char *name, Dart_NativeFunction function)
GLFWwindow * window
Definition main.cc:60
FlutterEngine engine
Definition main.cc:84
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
#define FML_LOG(severity)
Definition logging.h:101
#define FML_UNREACHABLE()
Definition logging.h:128
#define FML_DCHECK(condition)
Definition logging.h:122
void(* rootIsolateCreateCallback)(void *_Nullable)
FlutterViewController * viewController
TEST_F(DisplayListTest, Defaults)
const char * GetFixturesPath()
Returns the directory containing the test fixture for the target if this target has fixtures configur...
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all 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
#define CREATE_NATIVE_ENTRY(native_entry)