13#include "gmock/gmock.h"
14#include "gtest/gtest.h"
21using ::testing::NiceMock;
22using ::testing::Return;
28std::unique_ptr<egl::MockWindowSurface> CreateMockWindowSurface() {
29 auto surface = std::make_unique<NiceMock<egl::MockWindowSurface>>();
30 ON_CALL(*surface, IsValid).WillByDefault(Return(
true));
31 ON_CALL(*surface, MakeCurrent).WillByDefault(Return(
true));
32 ON_CALL(*surface, SetVSyncEnabled).WillByDefault(Return(
true));
33 ON_CALL(*surface, Destroy).WillByDefault(Return(
true));
37class WindowManagerTest :
public WindowsTest {
39 WindowManagerTest() =
default;
40 virtual ~WindowManagerTest() =
default;
43 void SetUp()
override {
45 FlutterWindowsEngineBuilder builder(
context);
46 ::CoInitializeEx(
nullptr, COINIT_APARTMENTTHREADED);
48 engine_ = builder.Build();
51 engine_->SetRootIsolateCreateCallback(
context.GetRootIsolateCallback());
52 ASSERT_TRUE(engine_->Run(
"testWindowController"));
54 bool signalled =
false;
61 engine_->task_runner()->ProcessTasks();
71 auto egl_manager = std::make_unique<NiceMock<egl::MockManager>>();
72 ON_CALL(*egl_manager, CreateWindowSurface)
74 [](HWND,
size_t,
size_t) {
return CreateMockWindowSurface(); });
75 ON_CALL(*egl_manager, render_context)
76 .WillByDefault(Return(&mock_egl_context_));
77 ON_CALL(mock_egl_context_, ClearCurrent).WillByDefault(Return(
true));
78 ON_CALL(mock_egl_context_, MakeCurrent).WillByDefault(Return(
true));
79 EngineModifier{engine_.get()}.SetEGLManager(std::move(egl_manager));
82 void TearDown()
override { engine_->Stop(); }
84 int64_t engine_id() {
return reinterpret_cast<int64_t
>(engine_.get()); }
86 RegularWindowCreationRequest* regular_creation_request() {
87 return ®ular_creation_request_;
89 FlutterWindowsEngine*
engine() {
return engine_.get(); }
92 std::unique_ptr<FlutterWindowsEngine> engine_;
93 NiceMock<egl::MockContext> mock_egl_context_;
94 std::optional<flutter::Isolate> isolate_;
95 RegularWindowCreationRequest regular_creation_request_{
98 .has_preferred_view_size =
true,
99 .preferred_view_width = 800,
100 .preferred_view_height = 600,
109TEST_F(WindowManagerTest, WindowingInitialize) {
112 static bool received_message =
false;
119 engine_id(), regular_creation_request());
123 EXPECT_TRUE(received_message);
126TEST_F(WindowManagerTest, CreateRegularWindow) {
131 engine_id(), regular_creation_request());
135TEST_F(WindowManagerTest, GetWindowHandle) {
140 engine_id(), regular_creation_request());
141 const HWND window_handle =
144 EXPECT_NE(window_handle,
nullptr);
147TEST_F(WindowManagerTest, GetWindowSize) {
152 engine_id(), regular_creation_request());
153 const HWND window_handle =
160 EXPECT_EQ(
size.width,
161 regular_creation_request()->preferred_size.preferred_view_width);
162 EXPECT_EQ(
size.height,
163 regular_creation_request()->preferred_size.preferred_view_height);
166TEST_F(WindowManagerTest, SetWindowSize) {
171 engine_id(), regular_creation_request());
172 const HWND window_handle =
179 .preferred_view_width = 640,
180 .preferred_view_height = 480,
187 EXPECT_EQ(actual_size.
width, 640);
188 EXPECT_EQ(actual_size.
height, 480);
191TEST_F(WindowManagerTest, CanConstrainByMinimiumSize) {
196 engine_id(), regular_creation_request());
197 const HWND window_handle =
201 .view_min_width = 900,
202 .view_min_height = 700,
203 .view_max_width = 10000,
204 .view_max_height = 10000};
210 EXPECT_EQ(actual_size.
width, 900);
211 EXPECT_EQ(actual_size.
height, 700);
214TEST_F(WindowManagerTest, CanConstrainByMaximumSize) {
219 engine_id(), regular_creation_request());
220 const HWND window_handle =
225 .view_min_height = 0,
226 .view_max_width = 500,
227 .view_max_height = 500};
233 EXPECT_EQ(actual_size.
width, 500);
234 EXPECT_EQ(actual_size.
height, 500);
237TEST_F(WindowManagerTest, CanFullscreenWindow) {
242 engine_id(), regular_creation_request());
243 const HWND window_handle =
250 int screen_width = GetSystemMetrics(SM_CXSCREEN);
251 int screen_height = GetSystemMetrics(SM_CYSCREEN);
254 EXPECT_EQ(actual_size.
width, screen_width);
255 EXPECT_EQ(actual_size.
height, screen_height);
260TEST_F(WindowManagerTest, CanUnfullscreenWindow) {
265 engine_id(), regular_creation_request());
266 const HWND window_handle =
273 request.fullscreen =
false;
278 EXPECT_EQ(actual_size.
width, 800);
279 EXPECT_EQ(actual_size.
height, 600);
284TEST_F(WindowManagerTest, CanSetWindowSizeWhileFullscreen) {
289 engine_id(), regular_creation_request());
290 const HWND window_handle =
300 .preferred_view_width = 500,
301 .preferred_view_height = 500,
306 request.fullscreen =
false;
311 EXPECT_EQ(actual_size.
width, 500);
312 EXPECT_EQ(actual_size.
height, 500);
315TEST_F(WindowManagerTest, CanSetWindowConstraintsWhileFullscreen) {
320 engine_id(), regular_creation_request());
321 const HWND window_handle =
330 .view_min_height = 0,
331 .view_max_width = 500,
332 .view_max_height = 500};
336 request.fullscreen =
false;
341 EXPECT_EQ(actual_size.
width, 500);
342 EXPECT_EQ(actual_size.
height, 500);
345TEST_F(WindowManagerTest, CreateModelessDialogWindow) {
349 .preferred_view_width = 800,
350 .preferred_view_height = 600},
351 .preferred_constraints = {.has_view_constraints =
false},
352 .title = L
"Hello World",
353 .parent_or_null =
nullptr};
356 engine_id(), &creation_request);
360TEST_F(WindowManagerTest, CreateModalDialogWindow) {
363 const int64_t parent_view_id =
365 engine_id(), regular_creation_request());
366 const HWND parent_window_handle =
368 engine_id(), parent_view_id);
374 .preferred_view_width = 800,
375 .preferred_view_height = 600,
377 .preferred_constraints = {.has_view_constraints =
false},
378 .title = L
"Hello World",
379 .parent_or_null = parent_window_handle};
383 engine_id(), &creation_request);
386 const HWND window_handle =
391 parent_window_handle);
394TEST_F(WindowManagerTest, DeactivatedRegularWindowDoesNotReactivateItself) {
400 const int64_t window_view_id =
402 engine_id(), regular_creation_request());
403 const HWND window_handle =
405 engine_id(), window_view_id);
407 const int64_t active_view_id =
409 engine_id(), regular_creation_request());
410 const HWND active_window_handle =
412 engine_id(), active_view_id);
414 SetActiveWindow(active_window_handle);
415 ASSERT_EQ(GetActiveWindow(), active_window_handle);
421 SendMessage(window_handle, WM_ACTIVATE, MAKEWPARAM(WA_INACTIVE, 0), 0);
423 EXPECT_EQ(GetActiveWindow(), active_window_handle);
426TEST_F(WindowManagerTest, DialogCanNeverBeFullscreen) {
431 .preferred_view_width = 800,
432 .preferred_view_height = 600},
433 .preferred_constraints = {.has_view_constraints =
false},
434 .title = L
"Hello World",
435 .parent_or_null =
nullptr};
439 engine_id(), &creation_request);
440 const HWND window_handle =
450TEST_F(WindowManagerTest, CreateTooltipWindow) {
453 const int64_t parent_view_id =
455 engine_id(), regular_creation_request());
456 const HWND parent_window_handle =
458 engine_id(), parent_view_id);
460 auto position_callback = [](
const WindowSize& child_size,
464 rect->
left = parent_rect.left + 10;
465 rect->
top = parent_rect.top + 10;
473 .view_min_width = 100,
474 .view_min_height = 50,
475 .view_max_width = 300,
476 .view_max_height = 200},
477 .parent = parent_window_handle,
478 .get_position_callback = position_callback};
480 const int64_t tooltip_view_id =
482 engine_id(), &creation_request);
484 EXPECT_NE(tooltip_view_id, -1);
485 HWND tooltip_window_handle =
487 engine_id(), tooltip_view_id);
488 EXPECT_NE(tooltip_window_handle,
nullptr);
491TEST_F(WindowManagerTest, TooltipWindowHasNoActivateStyle) {
494 const int64_t parent_view_id =
496 engine_id(), regular_creation_request());
497 const HWND parent_window_handle =
499 engine_id(), parent_view_id);
501 auto position_callback = [](
const WindowSize& child_size,
505 rect->
left = parent_rect.left + 10;
506 rect->
top = parent_rect.top + 10;
514 .view_min_width = 100,
515 .view_min_height = 50,
516 .view_max_width = 300,
517 .view_max_height = 200},
518 .parent = parent_window_handle,
519 .get_position_callback = position_callback};
521 const int64_t tooltip_view_id =
523 engine_id(), &creation_request);
525 HWND tooltip_window_handle =
527 engine_id(), tooltip_view_id);
529 DWORD ex_style = GetWindowLong(tooltip_window_handle, GWL_EXSTYLE);
530 EXPECT_TRUE(ex_style & WS_EX_NOACTIVATE);
533TEST_F(WindowManagerTest, TooltipWindowDoesNotStealFocus) {
536 const int64_t parent_view_id =
538 engine_id(), regular_creation_request());
539 const HWND parent_window_handle =
541 engine_id(), parent_view_id);
544 SetFocus(parent_window_handle);
545 HWND focused_before = GetFocus();
547 auto position_callback = [](
const WindowSize& child_size,
551 rect->
left = parent_rect.left + 10;
552 rect->
top = parent_rect.top + 10;
560 .view_min_width = 100,
561 .view_min_height = 50,
562 .view_max_width = 300,
563 .view_max_height = 200},
564 .parent = parent_window_handle,
565 .get_position_callback = position_callback};
567 const int64_t tooltip_view_id =
569 engine_id(), &creation_request);
571 HWND tooltip_window_handle =
573 engine_id(), tooltip_view_id);
576 HWND focused_after = GetFocus();
577 EXPECT_EQ(focused_before, focused_after);
578 EXPECT_NE(focused_after, tooltip_window_handle);
581TEST_F(WindowManagerTest, TooltipWindowReturnsNoActivateOnMouseClick) {
584 const int64_t parent_view_id =
586 engine_id(), regular_creation_request());
587 const HWND parent_window_handle =
589 engine_id(), parent_view_id);
591 auto position_callback = [](
const WindowSize& child_size,
595 rect->
left = parent_rect.left + 10;
596 rect->
top = parent_rect.top + 10;
604 .view_min_width = 100,
605 .view_min_height = 50,
606 .view_max_width = 300,
607 .view_max_height = 200},
608 .parent = parent_window_handle,
609 .get_position_callback = position_callback};
611 const int64_t tooltip_view_id =
613 engine_id(), &creation_request);
615 HWND tooltip_window_handle =
617 engine_id(), tooltip_view_id);
621 reinterpret_cast<WPARAM>(parent_window_handle),
622 MAKELPARAM(HTCLIENT, WM_LBUTTONDOWN));
625 EXPECT_EQ(result, MA_NOACTIVATE);
628TEST_F(WindowManagerTest, TooltipWindowUpdatesPositionOnViewSizeChange) {
631 const int64_t parent_view_id =
633 engine_id(), regular_creation_request());
634 const HWND parent_window_handle =
636 engine_id(), parent_view_id);
639 static int callback_count = 0;
640 static int last_width = 0;
641 static int last_height = 0;
643 auto position_callback = [](
const WindowSize& child_size,
647 last_width = child_size.
width;
648 last_height = child_size.
height;
652 rect->
left = parent_rect.left + callback_count * 5;
653 rect->
top = parent_rect.top + callback_count * 5;
661 .view_min_width = 100,
662 .view_min_height = 50,
663 .view_max_width = 300,
664 .view_max_height = 200},
665 .parent = parent_window_handle,
666 .get_position_callback = position_callback};
673 const int64_t tooltip_view_id =
675 engine_id(), &creation_request);
677 HWND tooltip_window_handle =
679 engine_id(), tooltip_view_id);
683 engine()->GetViewFromTopLevelWindow(tooltip_window_handle);
684 ASSERT_NE(
view,
nullptr);
688 GetWindowRect(tooltip_window_handle, &initial_rect);
689 int initial_callback_count = callback_count;
693 view->OnFrameGenerated(150, 100);
696 engine()->task_runner()->ProcessTasks();
699 EXPECT_GT(callback_count, initial_callback_count);
700 EXPECT_EQ(last_width, 150);
701 EXPECT_EQ(last_height, 100);
705 GetWindowRect(tooltip_window_handle, &new_rect);
709 EXPECT_NE(initial_rect.left, new_rect.left);
710 EXPECT_NE(initial_rect.top, new_rect.top);
713TEST_F(WindowManagerTest, CreatePopupWindow) {
716 const int64_t parent_view_id =
718 engine_id(), regular_creation_request());
719 const HWND parent_window_handle =
721 engine_id(), parent_view_id);
723 auto position_callback = [](
const WindowSize& child_size,
727 rect->
left = parent_rect.left + 10;
728 rect->
top = parent_rect.top + 10;
736 .view_min_width = 100,
737 .view_min_height = 50,
738 .view_max_width = 300,
739 .view_max_height = 200},
740 .parent = parent_window_handle,
741 .get_position_callback = position_callback};
743 const int64_t popup_view_id =
747 EXPECT_NE(popup_view_id, -1);
748 HWND popup_window_handle =
750 engine_id(), popup_view_id);
751 EXPECT_NE(popup_window_handle,
nullptr);
754TEST_F(WindowManagerTest, PopupWindowHasNoActivateStyle) {
757 const int64_t parent_view_id =
759 engine_id(), regular_creation_request());
760 const HWND parent_window_handle =
762 engine_id(), parent_view_id);
764 auto position_callback = [](
const WindowSize& child_size,
768 rect->
left = parent_rect.left + 10;
769 rect->
top = parent_rect.top + 10;
777 .view_min_width = 100,
778 .view_min_height = 50,
779 .view_max_width = 300,
780 .view_max_height = 200},
781 .parent = parent_window_handle,
782 .get_position_callback = position_callback};
784 const int64_t popup_view_id =
788 HWND popup_window_handle =
790 engine_id(), popup_view_id);
792 DWORD ex_style = GetWindowLong(popup_window_handle, GWL_EXSTYLE);
793 EXPECT_TRUE(ex_style & WS_EX_NOACTIVATE);
796TEST_F(WindowManagerTest, PopupWindowDoesNotStealFocus) {
799 const int64_t parent_view_id =
801 engine_id(), regular_creation_request());
802 const HWND parent_window_handle =
804 engine_id(), parent_view_id);
807 SetFocus(parent_window_handle);
808 HWND focused_before = GetFocus();
810 auto position_callback = [](
const WindowSize& child_size,
814 rect->
left = parent_rect.left + 10;
815 rect->
top = parent_rect.top + 10;
823 .view_min_width = 100,
824 .view_min_height = 50,
825 .view_max_width = 300,
826 .view_max_height = 200},
827 .parent = parent_window_handle,
828 .get_position_callback = position_callback};
830 const int64_t popup_view_id =
834 HWND popup_window_handle =
836 engine_id(), popup_view_id);
839 HWND focused_after = GetFocus();
840 EXPECT_EQ(focused_before, focused_after);
841 EXPECT_NE(focused_after, popup_window_handle);
844TEST_F(WindowManagerTest, PopupWindowUpdatesPositionOnViewSizeChange) {
847 const int64_t parent_view_id =
849 engine_id(), regular_creation_request());
850 const HWND parent_window_handle =
852 engine_id(), parent_view_id);
855 static int callback_count = 0;
856 static int last_width = 0;
857 static int last_height = 0;
859 auto position_callback = [](
const WindowSize& child_size,
863 last_width = child_size.
width;
864 last_height = child_size.
height;
868 rect->
left = parent_rect.left + callback_count * 5;
869 rect->
top = parent_rect.top + callback_count * 5;
877 .view_min_width = 100,
878 .view_min_height = 50,
879 .view_max_width = 300,
880 .view_max_height = 200},
881 .parent = parent_window_handle,
882 .get_position_callback = position_callback};
889 const int64_t popup_view_id =
893 HWND popup_window_handle =
895 engine_id(), popup_view_id);
899 engine()->GetViewFromTopLevelWindow(popup_window_handle);
900 ASSERT_NE(
view,
nullptr);
904 GetWindowRect(popup_window_handle, &initial_rect);
905 int initial_callback_count = callback_count;
909 view->OnFrameGenerated(150, 100);
912 engine()->task_runner()->ProcessTasks();
915 EXPECT_GT(callback_count, initial_callback_count);
916 EXPECT_EQ(last_width, 150);
917 EXPECT_EQ(last_height, 100);
921 GetWindowRect(popup_window_handle, &new_rect);
925 EXPECT_NE(initial_rect.left, new_rect.left);
926 EXPECT_NE(initial_rect.top, new_rect.top);
929TEST_F(WindowManagerTest, CreateRegularWindowSizedToContent) {
934 .preferred_constraints = {.has_view_constraints =
false},
935 .title = L
"Sized To Content",
936 .sized_to_content =
true,
941 engine_id(), &creation_request);
945TEST_F(WindowManagerTest, RegularWindowSizedToContentResizesToContent) {
950 .preferred_constraints = {.has_view_constraints =
false},
951 .title = L
"Sized To Content",
952 .sized_to_content =
true,
957 engine_id(), &creation_request);
958 const HWND window_handle =
963 ASSERT_NE(
view,
nullptr);
965 view->OnFrameGenerated(300, 200);
966 engine()->task_runner()->ProcessTasks();
970 EXPECT_EQ(
size.width, 300);
971 EXPECT_EQ(
size.height, 200);
975 RegularWindowSizedToContentNonResizableHasNoThickFrame) {
980 .preferred_constraints = {.has_view_constraints =
false},
981 .title = L
"Sized To Content Non-Resizable",
982 .sized_to_content =
true,
987 engine_id(), &creation_request);
988 const HWND window_handle =
992 const LONG style = GetWindowLong(window_handle, GWL_STYLE);
993 EXPECT_EQ(style & WS_THICKFRAME, 0L);
994 EXPECT_EQ(style & WS_MAXIMIZEBOX, 0L);
997TEST_F(WindowManagerTest, RegularWindowSizedToContentResizableHasThickFrame) {
1002 .preferred_constraints = {.has_view_constraints =
false},
1003 .title = L
"Sized To Content Resizable",
1004 .sized_to_content =
true,
1009 engine_id(), &creation_request);
1010 const HWND window_handle =
1014 const LONG style = GetWindowLong(window_handle, GWL_STYLE);
1015 EXPECT_NE(style & WS_THICKFRAME, 0L);
1016 EXPECT_NE(style & WS_MAXIMIZEBOX, 0L);
1020 RegularWindowSizedToContentResizableStopsTrackingAfterFirstFrame) {
1025 .preferred_constraints = {.has_view_constraints =
false},
1026 .title = L
"Sized To Content Resizable",
1027 .sized_to_content =
true,
1032 engine_id(), &creation_request);
1033 const HWND window_handle =
1038 ASSERT_NE(
view,
nullptr);
1040 view->OnFrameGenerated(300, 200);
1041 engine()->task_runner()->ProcessTasks();
1043 EXPECT_FALSE(
view->IsSizedToContent());
1046TEST_F(WindowManagerTest, CreateModelessDialogSizedToContent) {
1051 .preferred_constraints = {.has_view_constraints =
false},
1052 .title = L
"Modeless Dialog Sized To Content",
1053 .parent_or_null =
nullptr,
1054 .sized_to_content =
true,
1055 .resizable =
false};
1059 engine_id(), &creation_request);
1063TEST_F(WindowManagerTest, CreateModalDialogSizedToContent) {
1066 const int64_t parent_view_id =
1068 engine_id(), regular_creation_request());
1069 const HWND parent_window_handle =
1071 engine_id(), parent_view_id);
1075 .preferred_constraints = {.has_view_constraints =
false},
1076 .title = L
"Modal Dialog Sized To Content",
1077 .parent_or_null = parent_window_handle,
1078 .sized_to_content =
true,
1079 .resizable =
false};
1083 engine_id(), &creation_request);
1087TEST_F(WindowManagerTest, DialogWindowSizedToContentResizesToContent) {
1092 .preferred_constraints = {.has_view_constraints =
false},
1093 .title = L
"Dialog Sized To Content",
1094 .parent_or_null =
nullptr,
1095 .sized_to_content =
true,
1096 .resizable =
false};
1100 engine_id(), &creation_request);
1101 const HWND window_handle =
1106 ASSERT_NE(
view,
nullptr);
1108 view->OnFrameGenerated(300, 200);
1109 engine()->task_runner()->ProcessTasks();
1113 EXPECT_EQ(
size.width, 300);
1114 EXPECT_EQ(
size.height, 200);
1118 DialogWindowSizedToContentNonResizableHasNoThickFrame) {
1123 .preferred_constraints = {.has_view_constraints =
false},
1124 .title = L
"Dialog Sized To Content Non-Resizable",
1125 .parent_or_null =
nullptr,
1126 .sized_to_content =
true,
1127 .resizable =
false};
1131 engine_id(), &creation_request);
1132 const HWND window_handle =
1136 const LONG style = GetWindowLong(window_handle, GWL_STYLE);
1137 EXPECT_EQ(style & WS_THICKFRAME, 0L);
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
std::shared_ptr< ContextGLES > context
WindowSizeRequest preferred_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)
FLUTTER_EXPORT FlutterViewId InternalFlutterWindows_WindowManager_CreatePopupWindow(int64_t engine_id, const flutter::PopupWindowCreationRequest *request)
HWND InternalFlutterWindows_WindowManager_GetTopLevelWindowHandle(int64_t engine_id, FlutterViewId view_id)