9#include "gtest/gtest.h"
16class 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(
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,
70TEST_F(WindowManagerTest, WindowingInitialize) {
73 static bool received_message =
false;
80 engine_id(), regular_creation_request());
84 EXPECT_TRUE(received_message);
87TEST_F(WindowManagerTest, CreateRegularWindow) {
92 engine_id(), regular_creation_request());
96TEST_F(WindowManagerTest, GetWindowHandle) {
101 engine_id(), regular_creation_request());
102 const HWND window_handle =
105 EXPECT_NE(window_handle,
nullptr);
108TEST_F(WindowManagerTest, GetWindowSize) {
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);
123 EXPECT_EQ(
size.height,
124 regular_creation_request()->preferred_size.preferred_view_height);
127TEST_F(WindowManagerTest, SetWindowSize) {
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);
152TEST_F(WindowManagerTest, CanConstrainByMinimiumSize) {
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);
175TEST_F(WindowManagerTest, CanConstrainByMaximumSize) {
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);
198TEST_F(WindowManagerTest, CanFullscreenWindow) {
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);
221TEST_F(WindowManagerTest, CanUnfullscreenWindow) {
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);
245TEST_F(WindowManagerTest, CanSetWindowSizeWhileFullscreen) {
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);
276TEST_F(WindowManagerTest, CanSetWindowConstraintsWhileFullscreen) {
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);
306TEST_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};
317 engine_id(), &creation_request);
321TEST_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};
344 engine_id(), &creation_request);
347 const HWND window_handle =
352 parent_window_handle);
355TEST_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};
368 engine_id(), &creation_request);
369 const HWND window_handle =
379TEST_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);
420TEST_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);
462TEST_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);
510TEST_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);
550 reinterpret_cast<WPARAM>(parent_window_handle),
551 MAKELPARAM(HTCLIENT, WM_LBUTTONDOWN));
554 EXPECT_EQ(result, MA_NOACTIVATE);
557TEST_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;
623 view->OnFrameGenerated(150, 100);
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);
HWND GetWindowHandle() const
HostWindow * GetOwnerWindow() const
static HostWindow * GetThisFromHandle(HWND hwnd)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
G_BEGIN_DECLS FlutterViewId view_id
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
TEST_F(DisplayListTest, Defaults)
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
WindowSizeRequest preferred_size
bool has_view_constraints
bool has_preferred_view_size
void(* on_message)(WindowsMessage *)
#define CREATE_NATIVE_ENTRY(native_entry)
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)