| Flutter Windows Embedder |

window_manager_unittests.cc
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 #include "flutter/shell/platform/windows/testing/flutter_windows_engine_builder.h"
6 #include "flutter/shell/platform/windows/testing/windows_test.h"
7 #include "flutter/shell/platform/windows/window_manager.h"
8 #include "gtest/gtest.h"
9
10 namespace flutter {
11 namespace testing {
12
13 namespace {
14
15 class WindowManagerTest : public WindowsTest {
16 public:
17 WindowManagerTest() = default;
18 virtual ~WindowManagerTest() = default;
19
20 protected:
21 void SetUp() override {
22 auto& context = GetContext();
23 FlutterWindowsEngineBuilder builder(context);
24 ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
25
26 engine_ = builder.Build();
27 ASSERT_TRUE(engine_);
28
29 engine_->SetRootIsolateCreateCallback(context.GetRootIsolateCallback());
30 ASSERT_TRUE(engine_->Run("testWindowController"));
31
32 bool signalled = false;
33 context.AddNativeFunction(
34 "Signal", CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
35 isolate_ = flutter::Isolate::Current();
36 signalled = true;
37 }));
38 while (!signalled) {
39 engine_->task_runner()->ProcessTasks();
40 }
41 }
42
43 void TearDown() override { engine_->Stop(); }
44
45 int64_t engine_id() { return reinterpret_cast<int64_t>(engine_.get()); }
46 flutter::Isolate& isolate() { return *isolate_; }
47 RegularWindowCreationRequest* regular_creation_request() {
48 return &regular_creation_request_;
49 }
50
51 private:
52 std::unique_ptr<FlutterWindowsEngine> engine_;
53 std::optional<flutter::Isolate> isolate_;
54 RegularWindowCreationRequest regular_creation_request_{
55 .preferred_size =
56 {
57 .has_preferred_view_size = true,
58 .preferred_view_width = 800,
59 .preferred_view_height = 600,
60 },
61 };
62
63 FML_DISALLOW_COPY_AND_ASSIGN(WindowManagerTest);
64 };
65
66 } // namespace
67
68 TEST_F(WindowManagerTest, WindowingInitialize) {
69 IsolateScope isolate_scope(isolate());
70
71 static bool received_message = false;
72 WindowingInitRequest init_request{
73 .on_message = [](WindowsMessage* message) { received_message = true; }};
74
75 InternalFlutterWindows_WindowManager_Initialize(engine_id(), &init_request);
76 const int64_t view_id =
77 InternalFlutterWindows_WindowManager_CreateRegularWindow(
78 engine_id(), regular_creation_request());
79 DestroyWindow(InternalFlutterWindows_WindowManager_GetTopLevelWindowHandle(
80 engine_id(), view_id));
81
82 EXPECT_TRUE(received_message);
83 }
84
85 TEST_F(WindowManagerTest, CreateRegularWindow) {
86 IsolateScope isolate_scope(isolate());
87
88 const int64_t view_id =
89 InternalFlutterWindows_WindowManager_CreateRegularWindow(
90 engine_id(), regular_creation_request());
91 EXPECT_EQ(view_id, 0);
92 }
93
94 TEST_F(WindowManagerTest, GetWindowHandle) {
95 IsolateScope isolate_scope(isolate());
96
97 const int64_t view_id =
98 InternalFlutterWindows_WindowManager_CreateRegularWindow(
99 engine_id(), regular_creation_request());
100 const HWND window_handle =
101 InternalFlutterWindows_WindowManager_GetTopLevelWindowHandle(engine_id(),
102 view_id);
103 EXPECT_NE(window_handle, nullptr);
104 }
105
106 TEST_F(WindowManagerTest, GetWindowSize) {
107 IsolateScope isolate_scope(isolate());
108
109 const int64_t view_id =
110 InternalFlutterWindows_WindowManager_CreateRegularWindow(
111 engine_id(), regular_creation_request());
112 const HWND window_handle =
113 InternalFlutterWindows_WindowManager_GetTopLevelWindowHandle(engine_id(),
114 view_id);
115
116 ActualWindowSize size =
117 InternalFlutterWindows_WindowManager_GetWindowContentSize(window_handle);
118
119 EXPECT_EQ(size.width,
120 regular_creation_request()->preferred_size.preferred_view_width);
121 EXPECT_EQ(size.height,
122 regular_creation_request()->preferred_size.preferred_view_height);
123 }
124
125 TEST_F(WindowManagerTest, SetWindowSize) {
126 IsolateScope isolate_scope(isolate());
127
128 const int64_t view_id =
129 InternalFlutterWindows_WindowManager_CreateRegularWindow(
130 engine_id(), regular_creation_request());
131 const HWND window_handle =
132 InternalFlutterWindows_WindowManager_GetTopLevelWindowHandle(engine_id(),
133 view_id);
134
135 WindowSizeRequest requestedSize{
136
137 .has_preferred_view_size = true,
138 .preferred_view_width = 640,
139 .preferred_view_height = 480,
140 };
141 InternalFlutterWindows_WindowManager_SetWindowSize(window_handle,
142 &requestedSize);
143
144 ActualWindowSize actual_size =
145 InternalFlutterWindows_WindowManager_GetWindowContentSize(window_handle);
146 EXPECT_EQ(actual_size.width, 640);
147 EXPECT_EQ(actual_size.height, 480);
148 }
149
150 TEST_F(WindowManagerTest, CanConstrainByMinimiumSize) {
151 IsolateScope isolate_scope(isolate());
152
153 const int64_t view_id =
154 InternalFlutterWindows_WindowManager_CreateRegularWindow(
155 engine_id(), regular_creation_request());
156 const HWND window_handle =
157 InternalFlutterWindows_WindowManager_GetTopLevelWindowHandle(engine_id(),
158 view_id);
159 WindowConstraints constraints{.has_view_constraints = true,
160 .view_min_width = 900,
161 .view_min_height = 700,
162 .view_max_width = 10000,
163 .view_max_height = 10000};
164 InternalFlutterWindows_WindowManager_SetWindowConstraints(window_handle,
165 &constraints);
166
167 ActualWindowSize actual_size =
168 InternalFlutterWindows_WindowManager_GetWindowContentSize(window_handle);
169 EXPECT_EQ(actual_size.width, 900);
170 EXPECT_EQ(actual_size.height, 700);
171 }
172
173 TEST_F(WindowManagerTest, CanConstrainByMaximumSize) {
174 IsolateScope isolate_scope(isolate());
175
176 const int64_t view_id =
177 InternalFlutterWindows_WindowManager_CreateRegularWindow(
178 engine_id(), regular_creation_request());
179 const HWND window_handle =
180 InternalFlutterWindows_WindowManager_GetTopLevelWindowHandle(engine_id(),
181 view_id);
182 WindowConstraints constraints{.has_view_constraints = true,
183 .view_min_width = 0,
184 .view_min_height = 0,
185 .view_max_width = 500,
186 .view_max_height = 500};
187 InternalFlutterWindows_WindowManager_SetWindowConstraints(window_handle,
188 &constraints);
189
190 ActualWindowSize actual_size =
191 InternalFlutterWindows_WindowManager_GetWindowContentSize(window_handle);
192 EXPECT_EQ(actual_size.width, 500);
193 EXPECT_EQ(actual_size.height, 500);
194 }
195
196 TEST_F(WindowManagerTest, CanFullscreenWindow) {
197 IsolateScope isolate_scope(isolate());
198
199 const int64_t view_id =
200 InternalFlutterWindows_WindowManager_CreateRegularWindow(
201 engine_id(), regular_creation_request());
202 const HWND window_handle =
203 InternalFlutterWindows_WindowManager_GetTopLevelWindowHandle(engine_id(),
204 view_id);
205
206 FullscreenRequest request{.fullscreen = true, .has_display_id = false};
207 InternalFlutterWindows_WindowManager_SetFullscreen(window_handle, &request);
208
209 int screen_width = GetSystemMetrics(SM_CXSCREEN);
210 int screen_height = GetSystemMetrics(SM_CYSCREEN);
211 ActualWindowSize actual_size =
212 InternalFlutterWindows_WindowManager_GetWindowContentSize(window_handle);
213 EXPECT_EQ(actual_size.width, screen_width);
214 EXPECT_EQ(actual_size.height, screen_height);
215 EXPECT_TRUE(
216 InternalFlutterWindows_WindowManager_GetFullscreen(window_handle));
217 }
218
219 TEST_F(WindowManagerTest, CanUnfullscreenWindow) {
220 IsolateScope isolate_scope(isolate());
221
222 const int64_t view_id =
223 InternalFlutterWindows_WindowManager_CreateRegularWindow(
224 engine_id(), regular_creation_request());
225 const HWND window_handle =
226 InternalFlutterWindows_WindowManager_GetTopLevelWindowHandle(engine_id(),
227 view_id);
228
229 FullscreenRequest request{.fullscreen = true, .has_display_id = false};
230 InternalFlutterWindows_WindowManager_SetFullscreen(window_handle, &request);
231
232 request.fullscreen = false;
233 InternalFlutterWindows_WindowManager_SetFullscreen(window_handle, &request);
234
235 ActualWindowSize actual_size =
236 InternalFlutterWindows_WindowManager_GetWindowContentSize(window_handle);
237 EXPECT_EQ(actual_size.width, 800);
238 EXPECT_EQ(actual_size.height, 600);
239 EXPECT_FALSE(
240 InternalFlutterWindows_WindowManager_GetFullscreen(window_handle));
241 }
242
243 TEST_F(WindowManagerTest, CanSetWindowSizeWhileFullscreen) {
244 IsolateScope isolate_scope(isolate());
245
246 const int64_t view_id =
247 InternalFlutterWindows_WindowManager_CreateRegularWindow(
248 engine_id(), regular_creation_request());
249 const HWND window_handle =
250 InternalFlutterWindows_WindowManager_GetTopLevelWindowHandle(engine_id(),
251 view_id);
252
253 FullscreenRequest request{.fullscreen = true, .has_display_id = false};
254 InternalFlutterWindows_WindowManager_SetFullscreen(window_handle, &request);
255
256 WindowSizeRequest requestedSize{
257
258 .has_preferred_view_size = true,
259 .preferred_view_width = 500,
260 .preferred_view_height = 500,
261 };
262 InternalFlutterWindows_WindowManager_SetWindowSize(window_handle,
263 &requestedSize);
264
265 request.fullscreen = false;
266 InternalFlutterWindows_WindowManager_SetFullscreen(window_handle, &request);
267
268 ActualWindowSize actual_size =
269 InternalFlutterWindows_WindowManager_GetWindowContentSize(window_handle);
270 EXPECT_EQ(actual_size.width, 500);
271 EXPECT_EQ(actual_size.height, 500);
272 }
273
274 TEST_F(WindowManagerTest, CanSetWindowConstraintsWhileFullscreen) {
275 IsolateScope isolate_scope(isolate());
276
277 const int64_t view_id =
278 InternalFlutterWindows_WindowManager_CreateRegularWindow(
279 engine_id(), regular_creation_request());
280 const HWND window_handle =
281 InternalFlutterWindows_WindowManager_GetTopLevelWindowHandle(engine_id(),
282 view_id);
283
284 FullscreenRequest request{.fullscreen = true, .has_display_id = false};
285 InternalFlutterWindows_WindowManager_SetFullscreen(window_handle, &request);
286
287 WindowConstraints constraints{.has_view_constraints = true,
288 .view_min_width = 0,
289 .view_min_height = 0,
290 .view_max_width = 500,
291 .view_max_height = 500};
292 InternalFlutterWindows_WindowManager_SetWindowConstraints(window_handle,
293 &constraints);
294
295 request.fullscreen = false;
296 InternalFlutterWindows_WindowManager_SetFullscreen(window_handle, &request);
297
298 ActualWindowSize actual_size =
299 InternalFlutterWindows_WindowManager_GetWindowContentSize(window_handle);
300 EXPECT_EQ(actual_size.width, 500);
301 EXPECT_EQ(actual_size.height, 500);
302 }
303
304 TEST_F(WindowManagerTest, CreateModelessDialogWindow) {
305 IsolateScope isolate_scope(isolate());
306 DialogWindowCreationRequest creation_request{
307 .preferred_size = {.has_preferred_view_size = true,
308 .preferred_view_width = 800,
309 .preferred_view_height = 600},
310 .preferred_constraints = {.has_view_constraints = false},
311 .title = L"Hello World",
312 .parent_or_null = nullptr};
313 const int64_t view_id =
314 InternalFlutterWindows_WindowManager_CreateDialogWindow(
315 engine_id(), &creation_request);
316 EXPECT_EQ(view_id, 0);
317 }
318
319 TEST_F(WindowManagerTest, CreateModalDialogWindow) {
320 IsolateScope isolate_scope(isolate());
321
322 const int64_t parent_view_id =
323 InternalFlutterWindows_WindowManager_CreateRegularWindow(
324 engine_id(), regular_creation_request());
325 const HWND parent_window_handle =
326 InternalFlutterWindows_WindowManager_GetTopLevelWindowHandle(
327 engine_id(), parent_view_id);
328
329 DialogWindowCreationRequest creation_request{
330 .preferred_size =
331 {
332 .has_preferred_view_size = true,
333 .preferred_view_width = 800,
334 .preferred_view_height = 600,
335 },
336 .preferred_constraints = {.has_view_constraints = false},
337 .title = L"Hello World",
338 .parent_or_null = parent_window_handle};
339
340 const int64_t view_id =
341 InternalFlutterWindows_WindowManager_CreateDialogWindow(
342 engine_id(), &creation_request);
343 EXPECT_EQ(view_id, 1);
344
345 const HWND window_handle =
346 InternalFlutterWindows_WindowManager_GetTopLevelWindowHandle(engine_id(),
347 view_id);
348 HostWindow* host_window = HostWindow::GetThisFromHandle(window_handle);
349 EXPECT_EQ(host_window->GetOwnerWindow()->GetWindowHandle(),
350 parent_window_handle);
351 }
352
353 TEST_F(WindowManagerTest, DialogCanNeverBeFullscreen) {
354 IsolateScope isolate_scope(isolate());
355
356 DialogWindowCreationRequest creation_request{
357 .preferred_size = {.has_preferred_view_size = true,
358 .preferred_view_width = 800,
359 .preferred_view_height = 600},
360 .preferred_constraints = {.has_view_constraints = false},
361 .title = L"Hello World",
362 .parent_or_null = nullptr};
363
364 const int64_t view_id =
365 InternalFlutterWindows_WindowManager_CreateDialogWindow(
366 engine_id(), &creation_request);
367 const HWND window_handle =
368 InternalFlutterWindows_WindowManager_GetTopLevelWindowHandle(engine_id(),
369 view_id);
370
371 FullscreenRequest request{.fullscreen = true, .has_display_id = false};
372 InternalFlutterWindows_WindowManager_SetFullscreen(window_handle, &request);
373 EXPECT_FALSE(
374 InternalFlutterWindows_WindowManager_GetFullscreen(window_handle));
375 }
376
377 } // namespace testing
378 } // namespace flutter
flutter::HostWindow
Definition: host_window.h:27
flutter::HostWindow::GetWindowHandle
HWND GetWindowHandle() const
Definition: host_window.cc:342
flutter::HostWindow::GetOwnerWindow
HostWindow * GetOwnerWindow() const
Definition: host_window.cc:817
flutter::HostWindow::GetThisFromHandle
static HostWindow * GetThisFromHandle(HWND hwnd)
Definition: host_window.cc:327
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
message
Win32Message message
Definition: keyboard_unittests.cc:137
flutter::testing::TEST_F
TEST_F(AccessibilityPluginTest, DirectAnnounceCall)
Definition: accessibility_plugin_unittests.cc:98
flutter
Definition: accessibility_bridge_windows.cc:11
flutter::ActualWindowSize
Definition: window_manager.h:71
flutter::ActualWindowSize::width
double width
Definition: window_manager.h:72
flutter::ActualWindowSize::height
double height
Definition: window_manager.h:73
flutter::DialogWindowCreationRequest
Definition: window_manager.h:48
flutter::DialogWindowCreationRequest::preferred_size
WindowSizeRequest preferred_size
Definition: window_manager.h:49
flutter::FullscreenRequest
Definition: window_manager.h:76
flutter::FullscreenRequest::fullscreen
bool fullscreen
Definition: window_manager.h:77
flutter::WindowConstraints
Definition: window_manager.h:33
flutter::WindowConstraints::has_view_constraints
bool has_view_constraints
Definition: window_manager.h:34
flutter::WindowSizeRequest
Definition: window_manager.h:26
flutter::WindowSizeRequest::has_preferred_view_size
bool has_preferred_view_size
Definition: window_manager.h:27
flutter::WindowingInitRequest
Definition: window_manager.h:65
flutter::WindowingInitRequest::on_message
void(* on_message)(WindowsMessage *)
Definition: window_manager.h:66
flutter::WindowsMessage
Definition: window_manager.h:55
InternalFlutterWindows_WindowManager_Initialize
void InternalFlutterWindows_WindowManager_Initialize(int64_t engine_id, const flutter::WindowingInitRequest *request)
Definition: window_manager.cc:112
InternalFlutterWindows_WindowManager_SetWindowConstraints
void InternalFlutterWindows_WindowManager_SetWindowConstraints(HWND hwnd, const flutter::WindowConstraints *constraints)
Definition: window_manager.cc:164
InternalFlutterWindows_WindowManager_GetFullscreen
bool InternalFlutterWindows_WindowManager_GetFullscreen(HWND hwnd)
Definition: window_manager.cc:186
InternalFlutterWindows_WindowManager_SetWindowSize
void InternalFlutterWindows_WindowManager_SetWindowSize(HWND hwnd, const flutter::WindowSizeRequest *size)
Definition: window_manager.cc:155
InternalFlutterWindows_WindowManager_CreateRegularWindow
FlutterViewId InternalFlutterWindows_WindowManager_CreateRegularWindow(int64_t engine_id, const flutter::RegularWindowCreationRequest *request)
Definition: window_manager.cc:120
InternalFlutterWindows_WindowManager_CreateDialogWindow
FLUTTER_EXPORT FlutterViewId InternalFlutterWindows_WindowManager_CreateDialogWindow(int64_t engine_id, const flutter::DialogWindowCreationRequest *request)
Definition: window_manager.cc:129
InternalFlutterWindows_WindowManager_SetFullscreen
void InternalFlutterWindows_WindowManager_SetFullscreen(HWND hwnd, const flutter::FullscreenRequest *request)
Definition: window_manager.cc:173
InternalFlutterWindows_WindowManager_GetWindowContentSize
flutter::ActualWindowSize InternalFlutterWindows_WindowManager_GetWindowContentSize(HWND hwnd)
Definition: window_manager.cc:151
InternalFlutterWindows_WindowManager_GetTopLevelWindowHandle
HWND InternalFlutterWindows_WindowManager_GetTopLevelWindowHandle(int64_t engine_id, FlutterViewId view_id)
Definition: window_manager.cc:137
window_manager.h