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);
631 DISABLED_TooltipWindowUpdatesPositionOnViewSizeChange) {
634 const int64_t parent_view_id =
636 engine_id(), regular_creation_request());
637 const HWND parent_window_handle =
639 engine_id(), parent_view_id);
642 static int callback_count = 0;
643 static int last_width = 0;
644 static int last_height = 0;
646 auto position_callback = [](
const WindowSize& child_size,
650 last_width = child_size.
width;
651 last_height = child_size.
height;
655 rect->
left = parent_rect.left + callback_count * 5;
656 rect->
top = parent_rect.top + callback_count * 5;
664 .view_min_width = 100,
665 .view_min_height = 50,
666 .view_max_width = 300,
667 .view_max_height = 200},
668 .parent = parent_window_handle,
669 .get_position_callback = position_callback};
676 const int64_t tooltip_view_id =
678 engine_id(), &creation_request);
680 HWND tooltip_window_handle =
682 engine_id(), tooltip_view_id);
686 engine()->GetViewFromTopLevelWindow(tooltip_window_handle);
687 ASSERT_NE(
view,
nullptr);
691 GetWindowRect(tooltip_window_handle, &initial_rect);
692 int initial_callback_count = callback_count;
696 view->OnFrameGenerated(150, 100);
699 engine()->task_runner()->ProcessTasks();
702 EXPECT_GT(callback_count, initial_callback_count);
703 EXPECT_EQ(last_width, 150);
704 EXPECT_EQ(last_height, 100);
708 GetWindowRect(tooltip_window_handle, &new_rect);
712 EXPECT_NE(initial_rect.left, new_rect.left);
713 EXPECT_NE(initial_rect.top, new_rect.top);
716TEST_F(WindowManagerTest, CreatePopupWindow) {
719 const int64_t parent_view_id =
721 engine_id(), regular_creation_request());
722 const HWND parent_window_handle =
724 engine_id(), parent_view_id);
726 auto position_callback = [](
const WindowSize& child_size,
730 rect->
left = parent_rect.left + 10;
731 rect->
top = parent_rect.top + 10;
739 .view_min_width = 100,
740 .view_min_height = 50,
741 .view_max_width = 300,
742 .view_max_height = 200},
743 .parent = parent_window_handle,
744 .get_position_callback = position_callback};
746 const int64_t popup_view_id =
750 EXPECT_NE(popup_view_id, -1);
751 HWND popup_window_handle =
753 engine_id(), popup_view_id);
754 EXPECT_NE(popup_window_handle,
nullptr);
757TEST_F(WindowManagerTest, PopupWindowHasNoActivateStyle) {
760 const int64_t parent_view_id =
762 engine_id(), regular_creation_request());
763 const HWND parent_window_handle =
765 engine_id(), parent_view_id);
767 auto position_callback = [](
const WindowSize& child_size,
771 rect->
left = parent_rect.left + 10;
772 rect->
top = parent_rect.top + 10;
780 .view_min_width = 100,
781 .view_min_height = 50,
782 .view_max_width = 300,
783 .view_max_height = 200},
784 .parent = parent_window_handle,
785 .get_position_callback = position_callback};
787 const int64_t popup_view_id =
791 HWND popup_window_handle =
793 engine_id(), popup_view_id);
795 DWORD ex_style = GetWindowLong(popup_window_handle, GWL_EXSTYLE);
796 EXPECT_TRUE(ex_style & WS_EX_NOACTIVATE);
799TEST_F(WindowManagerTest, PopupWindowDoesNotStealFocus) {
802 const int64_t parent_view_id =
804 engine_id(), regular_creation_request());
805 const HWND parent_window_handle =
807 engine_id(), parent_view_id);
810 SetFocus(parent_window_handle);
811 HWND focused_before = GetFocus();
813 auto position_callback = [](
const WindowSize& child_size,
817 rect->
left = parent_rect.left + 10;
818 rect->
top = parent_rect.top + 10;
826 .view_min_width = 100,
827 .view_min_height = 50,
828 .view_max_width = 300,
829 .view_max_height = 200},
830 .parent = parent_window_handle,
831 .get_position_callback = position_callback};
833 const int64_t popup_view_id =
837 HWND popup_window_handle =
839 engine_id(), popup_view_id);
842 HWND focused_after = GetFocus();
843 EXPECT_EQ(focused_before, focused_after);
844 EXPECT_NE(focused_after, popup_window_handle);
849TEST_F(WindowManagerTest, DISABLED_PopupWindowUpdatesPositionOnViewSizeChange) {
852 const int64_t parent_view_id =
854 engine_id(), regular_creation_request());
855 const HWND parent_window_handle =
857 engine_id(), parent_view_id);
860 static int callback_count = 0;
861 static int last_width = 0;
862 static int last_height = 0;
864 auto position_callback = [](
const WindowSize& child_size,
868 last_width = child_size.
width;
869 last_height = child_size.
height;
873 rect->
left = parent_rect.left + callback_count * 5;
874 rect->
top = parent_rect.top + callback_count * 5;
882 .view_min_width = 100,
883 .view_min_height = 50,
884 .view_max_width = 300,
885 .view_max_height = 200},
886 .parent = parent_window_handle,
887 .get_position_callback = position_callback};
894 const int64_t popup_view_id =
898 HWND popup_window_handle =
900 engine_id(), popup_view_id);
904 engine()->GetViewFromTopLevelWindow(popup_window_handle);
905 ASSERT_NE(
view,
nullptr);
909 GetWindowRect(popup_window_handle, &initial_rect);
910 int initial_callback_count = callback_count;
914 view->OnFrameGenerated(150, 100);
917 engine()->task_runner()->ProcessTasks();
920 EXPECT_GT(callback_count, initial_callback_count);
921 EXPECT_EQ(last_width, 150);
922 EXPECT_EQ(last_height, 100);
926 GetWindowRect(popup_window_handle, &new_rect);
930 EXPECT_NE(initial_rect.left, new_rect.left);
931 EXPECT_NE(initial_rect.top, new_rect.top);
934TEST_F(WindowManagerTest, CreateRegularWindowSizedToContent) {
939 .preferred_constraints = {.has_view_constraints =
false},
940 .title = L
"Sized To Content",
941 .sized_to_content =
true,
946 engine_id(), &creation_request);
950TEST_F(WindowManagerTest, RegularWindowSizedToContentResizesToContent) {
955 .preferred_constraints = {.has_view_constraints =
false},
956 .title = L
"Sized To Content",
957 .sized_to_content =
true,
962 engine_id(), &creation_request);
963 const HWND window_handle =
968 ASSERT_NE(
view,
nullptr);
970 view->OnFrameGenerated(300, 200);
971 engine()->task_runner()->ProcessTasks();
975 EXPECT_EQ(
size.width, 300);
976 EXPECT_EQ(
size.height, 200);
980 RegularWindowSizedToContentNonResizableHasNoThickFrame) {
985 .preferred_constraints = {.has_view_constraints =
false},
986 .title = L
"Sized To Content Non-Resizable",
987 .sized_to_content =
true,
992 engine_id(), &creation_request);
993 const HWND window_handle =
997 const LONG style = GetWindowLong(window_handle, GWL_STYLE);
998 EXPECT_EQ(style & WS_THICKFRAME, 0L);
999 EXPECT_EQ(style & WS_MAXIMIZEBOX, 0L);
1002TEST_F(WindowManagerTest, RegularWindowSizedToContentResizableHasThickFrame) {
1007 .preferred_constraints = {.has_view_constraints =
false},
1008 .title = L
"Sized To Content Resizable",
1009 .sized_to_content =
true,
1014 engine_id(), &creation_request);
1015 const HWND window_handle =
1019 const LONG style = GetWindowLong(window_handle, GWL_STYLE);
1020 EXPECT_NE(style & WS_THICKFRAME, 0L);
1021 EXPECT_NE(style & WS_MAXIMIZEBOX, 0L);
1025 RegularWindowSizedToContentResizableStopsTrackingAfterFirstFrame) {
1030 .preferred_constraints = {.has_view_constraints =
false},
1031 .title = L
"Sized To Content Resizable",
1032 .sized_to_content =
true,
1037 engine_id(), &creation_request);
1038 const HWND window_handle =
1043 ASSERT_NE(
view,
nullptr);
1045 view->OnFrameGenerated(300, 200);
1046 engine()->task_runner()->ProcessTasks();
1048 EXPECT_FALSE(
view->IsSizedToContent());
1051TEST_F(WindowManagerTest, CreateModelessDialogSizedToContent) {
1056 .preferred_constraints = {.has_view_constraints =
false},
1057 .title = L
"Modeless Dialog Sized To Content",
1058 .parent_or_null =
nullptr,
1059 .sized_to_content =
true,
1060 .resizable =
false};
1064 engine_id(), &creation_request);
1068TEST_F(WindowManagerTest, CreateModalDialogSizedToContent) {
1071 const int64_t parent_view_id =
1073 engine_id(), regular_creation_request());
1074 const HWND parent_window_handle =
1076 engine_id(), parent_view_id);
1080 .preferred_constraints = {.has_view_constraints =
false},
1081 .title = L
"Modal Dialog Sized To Content",
1082 .parent_or_null = parent_window_handle,
1083 .sized_to_content =
true,
1084 .resizable =
false};
1088 engine_id(), &creation_request);
1092TEST_F(WindowManagerTest, DialogWindowSizedToContentResizesToContent) {
1097 .preferred_constraints = {.has_view_constraints =
false},
1098 .title = L
"Dialog Sized To Content",
1099 .parent_or_null =
nullptr,
1100 .sized_to_content =
true,
1101 .resizable =
false};
1105 engine_id(), &creation_request);
1106 const HWND window_handle =
1111 ASSERT_NE(
view,
nullptr);
1113 view->OnFrameGenerated(300, 200);
1114 engine()->task_runner()->ProcessTasks();
1118 EXPECT_EQ(
size.width, 300);
1119 EXPECT_EQ(
size.height, 200);
1123 DialogWindowSizedToContentNonResizableHasNoThickFrame) {
1128 .preferred_constraints = {.has_view_constraints =
false},
1129 .title = L
"Dialog Sized To Content Non-Resizable",
1130 .parent_or_null =
nullptr,
1131 .sized_to_content =
true,
1132 .resizable =
false};
1136 engine_id(), &creation_request);
1137 const HWND window_handle =
1141 const LONG style = GetWindowLong(window_handle, GWL_STYLE);
1142 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)