6 #include "flutter/shell/platform/windows/testing/flutter_windows_engine_builder.h"
7 #include "flutter/shell/platform/windows/testing/windows_test.h"
9 #include "gtest/gtest.h"
16 class WindowManagerTest :
public WindowsTest {
18 WindowManagerTest() =
default;
19 virtual ~WindowManagerTest() =
default;
22 void SetUp()
override {
23 auto& context = GetContext();
24 FlutterWindowsEngineBuilder builder(context);
25 ::CoInitializeEx(
nullptr, COINIT_APARTMENTTHREADED);
27 engine_ = builder.Build();
30 engine_->SetRootIsolateCreateCallback(context.GetRootIsolateCallback());
31 ASSERT_TRUE(engine_->Run(
"testWindowController"));
33 bool signalled =
false;
34 context.AddNativeFunction(
35 "Signal", CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
40 engine_->task_runner()->ProcessTasks();
44 void TearDown()
override { engine_->Stop(); }
46 int64_t engine_id() {
return reinterpret_cast<int64_t
>(engine_.get()); }
48 RegularWindowCreationRequest* regular_creation_request() {
49 return ®ular_creation_request_;
51 FlutterWindowsEngine* engine() {
return engine_.get(); }
54 std::unique_ptr<FlutterWindowsEngine> engine_;
55 std::optional<flutter::Isolate> isolate_;
56 RegularWindowCreationRequest regular_creation_request_{
59 .has_preferred_view_size =
true,
60 .preferred_view_width = 800,
61 .preferred_view_height = 600,
65 FML_DISALLOW_COPY_AND_ASSIGN(WindowManagerTest);
70 TEST_F(WindowManagerTest, WindowingInitialize) {
73 static bool received_message =
false;
78 const int64_t view_id =
80 engine_id(), regular_creation_request());
82 engine_id(), view_id));
84 EXPECT_TRUE(received_message);
87 TEST_F(WindowManagerTest, CreateRegularWindow) {
90 const int64_t view_id =
92 engine_id(), regular_creation_request());
93 EXPECT_EQ(view_id, 0);
96 TEST_F(WindowManagerTest, GetWindowHandle) {
99 const int64_t view_id =
101 engine_id(), regular_creation_request());
102 const HWND window_handle =
105 EXPECT_NE(window_handle,
nullptr);
108 TEST_F(WindowManagerTest, GetWindowSize) {
111 const int64_t view_id =
113 engine_id(), regular_creation_request());
114 const HWND window_handle =
121 EXPECT_EQ(size.
width,
122 regular_creation_request()->preferred_size.preferred_view_width);
124 regular_creation_request()->preferred_size.preferred_view_height);
127 TEST_F(WindowManagerTest, SetWindowSize) {
130 const int64_t view_id =
132 engine_id(), regular_creation_request());
133 const HWND window_handle =
140 .preferred_view_width = 640,
141 .preferred_view_height = 480,
148 EXPECT_EQ(actual_size.
width, 640);
149 EXPECT_EQ(actual_size.
height, 480);
152 TEST_F(WindowManagerTest, CanConstrainByMinimiumSize) {
155 const int64_t view_id =
157 engine_id(), regular_creation_request());
158 const HWND window_handle =
162 .view_min_width = 900,
163 .view_min_height = 700,
164 .view_max_width = 10000,
165 .view_max_height = 10000};
171 EXPECT_EQ(actual_size.
width, 900);
172 EXPECT_EQ(actual_size.
height, 700);
175 TEST_F(WindowManagerTest, CanConstrainByMaximumSize) {
178 const int64_t view_id =
180 engine_id(), regular_creation_request());
181 const HWND window_handle =
186 .view_min_height = 0,
187 .view_max_width = 500,
188 .view_max_height = 500};
194 EXPECT_EQ(actual_size.
width, 500);
195 EXPECT_EQ(actual_size.
height, 500);
198 TEST_F(WindowManagerTest, CanFullscreenWindow) {
201 const int64_t view_id =
203 engine_id(), regular_creation_request());
204 const HWND window_handle =
211 int screen_width = GetSystemMetrics(SM_CXSCREEN);
212 int screen_height = GetSystemMetrics(SM_CYSCREEN);
215 EXPECT_EQ(actual_size.
width, screen_width);
216 EXPECT_EQ(actual_size.
height, screen_height);
221 TEST_F(WindowManagerTest, CanUnfullscreenWindow) {
224 const int64_t view_id =
226 engine_id(), regular_creation_request());
227 const HWND window_handle =
234 request.fullscreen =
false;
239 EXPECT_EQ(actual_size.
width, 800);
240 EXPECT_EQ(actual_size.
height, 600);
245 TEST_F(WindowManagerTest, CanSetWindowSizeWhileFullscreen) {
248 const int64_t view_id =
250 engine_id(), regular_creation_request());
251 const HWND window_handle =
261 .preferred_view_width = 500,
262 .preferred_view_height = 500,
267 request.fullscreen =
false;
272 EXPECT_EQ(actual_size.
width, 500);
273 EXPECT_EQ(actual_size.
height, 500);
276 TEST_F(WindowManagerTest, CanSetWindowConstraintsWhileFullscreen) {
279 const int64_t view_id =
281 engine_id(), regular_creation_request());
282 const HWND window_handle =
291 .view_min_height = 0,
292 .view_max_width = 500,
293 .view_max_height = 500};
297 request.fullscreen =
false;
302 EXPECT_EQ(actual_size.
width, 500);
303 EXPECT_EQ(actual_size.
height, 500);
306 TEST_F(WindowManagerTest, CreateModelessDialogWindow) {
310 .preferred_view_width = 800,
311 .preferred_view_height = 600},
312 .preferred_constraints = {.has_view_constraints =
false},
313 .title = L
"Hello World",
314 .parent_or_null =
nullptr};
315 const int64_t view_id =
317 engine_id(), &creation_request);
318 EXPECT_EQ(view_id, 0);
321 TEST_F(WindowManagerTest, CreateModalDialogWindow) {
324 const int64_t parent_view_id =
326 engine_id(), regular_creation_request());
327 const HWND parent_window_handle =
329 engine_id(), parent_view_id);
335 .preferred_view_width = 800,
336 .preferred_view_height = 600,
338 .preferred_constraints = {.has_view_constraints =
false},
339 .title = L
"Hello World",
340 .parent_or_null = parent_window_handle};
342 const int64_t view_id =
344 engine_id(), &creation_request);
345 EXPECT_EQ(view_id, 1);
347 const HWND window_handle =
352 parent_window_handle);
355 TEST_F(WindowManagerTest, DialogCanNeverBeFullscreen) {
360 .preferred_view_width = 800,
361 .preferred_view_height = 600},
362 .preferred_constraints = {.has_view_constraints =
false},
363 .title = L
"Hello World",
364 .parent_or_null =
nullptr};
366 const int64_t view_id =
368 engine_id(), &creation_request);
369 const HWND window_handle =
379 TEST_F(WindowManagerTest, CreateTooltipWindow) {
382 const int64_t parent_view_id =
384 engine_id(), regular_creation_request());
385 const HWND parent_window_handle =
387 engine_id(), parent_view_id);
389 auto position_callback = [](
const WindowSize& child_size,
393 rect->
left = parent_rect.left + 10;
394 rect->
top = parent_rect.top + 10;
402 .view_min_width = 100,
403 .view_min_height = 50,
404 .view_max_width = 300,
405 .view_max_height = 200},
406 .parent = parent_window_handle,
407 .get_position_callback = position_callback};
409 const int64_t tooltip_view_id =
411 engine_id(), &creation_request);
413 EXPECT_NE(tooltip_view_id, -1);
414 HWND tooltip_window_handle =
416 engine_id(), tooltip_view_id);
417 EXPECT_NE(tooltip_window_handle,
nullptr);
420 TEST_F(WindowManagerTest, TooltipWindowHasNoActivateStyle) {
423 const int64_t parent_view_id =
425 engine_id(), regular_creation_request());
426 const HWND parent_window_handle =
428 engine_id(), parent_view_id);
430 auto position_callback = [](
const WindowSize& child_size,
434 rect->
left = parent_rect.left + 10;
435 rect->
top = parent_rect.top + 10;
443 .view_min_width = 100,
444 .view_min_height = 50,
445 .view_max_width = 300,
446 .view_max_height = 200},
447 .parent = parent_window_handle,
448 .get_position_callback = position_callback};
450 const int64_t tooltip_view_id =
452 engine_id(), &creation_request);
454 HWND tooltip_window_handle =
456 engine_id(), tooltip_view_id);
458 DWORD ex_style = GetWindowLong(tooltip_window_handle, GWL_EXSTYLE);
459 EXPECT_TRUE(ex_style & WS_EX_NOACTIVATE);
462 TEST_F(WindowManagerTest, TooltipWindowDoesNotStealFocus) {
465 const int64_t parent_view_id =
467 engine_id(), regular_creation_request());
468 const HWND parent_window_handle =
470 engine_id(), parent_view_id);
473 SetFocus(parent_window_handle);
474 HWND focused_before = GetFocus();
476 auto position_callback = [](
const WindowSize& child_size,
480 rect->
left = parent_rect.left + 10;
481 rect->
top = parent_rect.top + 10;
489 .view_min_width = 100,
490 .view_min_height = 50,
491 .view_max_width = 300,
492 .view_max_height = 200},
493 .parent = parent_window_handle,
494 .get_position_callback = position_callback};
496 const int64_t tooltip_view_id =
498 engine_id(), &creation_request);
500 HWND tooltip_window_handle =
502 engine_id(), tooltip_view_id);
505 HWND focused_after = GetFocus();
506 EXPECT_EQ(focused_before, focused_after);
507 EXPECT_NE(focused_after, tooltip_window_handle);
510 TEST_F(WindowManagerTest, TooltipWindowReturnsNoActivateOnMouseClick) {
513 const int64_t parent_view_id =
515 engine_id(), regular_creation_request());
516 const HWND parent_window_handle =
518 engine_id(), parent_view_id);
520 auto position_callback = [](
const WindowSize& child_size,
524 rect->
left = parent_rect.left + 10;
525 rect->
top = parent_rect.top + 10;
533 .view_min_width = 100,
534 .view_min_height = 50,
535 .view_max_width = 300,
536 .view_max_height = 200},
537 .parent = parent_window_handle,
538 .get_position_callback = position_callback};
540 const int64_t tooltip_view_id =
542 engine_id(), &creation_request);
544 HWND tooltip_window_handle =
546 engine_id(), tooltip_view_id);
549 LRESULT result = SendMessage(tooltip_window_handle, WM_MOUSEACTIVATE,
550 reinterpret_cast<WPARAM
>(parent_window_handle),
551 MAKELPARAM(HTCLIENT, WM_LBUTTONDOWN));
554 EXPECT_EQ(result, MA_NOACTIVATE);
557 TEST_F(WindowManagerTest, TooltipWindowUpdatesPositionOnViewSizeChange) {
560 const int64_t parent_view_id =
562 engine_id(), regular_creation_request());
563 const HWND parent_window_handle =
565 engine_id(), parent_view_id);
568 static int callback_count = 0;
569 static int last_width = 0;
570 static int last_height = 0;
572 auto position_callback = [](
const WindowSize& child_size,
576 last_width = child_size.
width;
577 last_height = child_size.
height;
581 rect->
left = parent_rect.left + callback_count * 5;
582 rect->
top = parent_rect.top + callback_count * 5;
590 .view_min_width = 100,
591 .view_min_height = 50,
592 .view_max_width = 300,
593 .view_max_height = 200},
594 .is_sized_to_content =
true,
595 .parent = parent_window_handle,
596 .get_position_callback = position_callback};
603 const int64_t tooltip_view_id =
605 engine_id(), &creation_request);
607 HWND tooltip_window_handle =
609 engine_id(), tooltip_view_id);
613 engine()->GetViewFromTopLevelWindow(tooltip_window_handle);
614 ASSERT_NE(view,
nullptr);
618 GetWindowRect(tooltip_window_handle, &initial_rect);
619 int initial_callback_count = callback_count;
626 engine()->task_runner()->ProcessTasks();
629 EXPECT_GT(callback_count, initial_callback_count);
630 EXPECT_EQ(last_width, 150);
631 EXPECT_EQ(last_height, 100);
635 GetWindowRect(tooltip_window_handle, &new_rect);
639 EXPECT_NE(initial_rect.left, new_rect.left);
640 EXPECT_NE(initial_rect.top, new_rect.top);
bool OnFrameGenerated(size_t width, size_t height)
HWND GetWindowHandle() const
HostWindow * GetOwnerWindow() const
static HostWindow * GetThisFromHandle(HWND hwnd)
TEST_F(AccessibilityPluginTest, DirectAnnounceCall)
WindowSizeRequest preferred_size
bool has_view_constraints
bool has_preferred_view_size
void(* on_message)(WindowsMessage *)
void InternalFlutterWindows_WindowManager_Initialize(int64_t engine_id, const flutter::WindowingInitRequest *request)
void InternalFlutterWindows_WindowManager_SetWindowConstraints(HWND hwnd, const flutter::WindowConstraints *constraints)
bool InternalFlutterWindows_WindowManager_GetFullscreen(HWND hwnd)
void InternalFlutterWindows_WindowManager_SetWindowSize(HWND hwnd, const flutter::WindowSizeRequest *size)
FlutterViewId InternalFlutterWindows_WindowManager_CreateRegularWindow(int64_t engine_id, const flutter::RegularWindowCreationRequest *request)
FLUTTER_EXPORT FlutterViewId InternalFlutterWindows_WindowManager_CreateDialogWindow(int64_t engine_id, const flutter::DialogWindowCreationRequest *request)
void InternalFlutterWindows_WindowManager_SetFullscreen(HWND hwnd, const flutter::FullscreenRequest *request)
flutter::ActualWindowSize InternalFlutterWindows_WindowManager_GetWindowContentSize(HWND hwnd)
FLUTTER_EXPORT FlutterViewId InternalFlutterWindows_WindowManager_CreateTooltipWindow(int64_t engine_id, const flutter::TooltipWindowCreationRequest *request)
HWND InternalFlutterWindows_WindowManager_GetTopLevelWindowHandle(int64_t engine_id, FlutterViewId view_id)