Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
flutter_windows_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
6
7#include <dxgi.h>
8#include <wrl/client.h>
9#include <thread>
10
22#include "gmock/gmock.h"
23#include "gtest/gtest.h"
25
26namespace flutter {
27namespace testing {
28
29namespace {
30
31// An EGL manager that initializes EGL but fails to create surfaces.
32class HalfBrokenEGLManager : public egl::Manager {
33 public:
34 HalfBrokenEGLManager() : egl::Manager(egl::GpuPreference::NoPreference) {}
35
36 std::unique_ptr<egl::WindowSurface>
37 CreateWindowSurface(HWND hwnd, size_t width, size_t height) override {
38 return nullptr;
39 }
40};
41
42class MockWindowsLifecycleManager : public WindowsLifecycleManager {
43 public:
44 MockWindowsLifecycleManager(FlutterWindowsEngine* engine)
46
48};
49
50// Process the next win32 message if there is one. This can be used to
51// pump the Windows platform thread task runner.
52void PumpMessage() {
53 ::MSG msg;
54 if (::GetMessage(&msg, nullptr, 0, 0)) {
55 ::TranslateMessage(&msg);
57 }
58}
59
60} // namespace
61
62// Verify that we can fetch a texture registrar.
63// Prevent regression: https://github.com/flutter/flutter/issues/86617
64TEST(WindowsNoFixtureTest, GetTextureRegistrar) {
65 FlutterDesktopEngineProperties properties = {};
66 properties.assets_path = L"";
67 properties.icu_data_path = L"icudtl.dat";
68 auto engine = FlutterDesktopEngineCreate(&properties);
69 ASSERT_NE(engine, nullptr);
71 EXPECT_NE(texture_registrar, nullptr);
73}
74
75// Verify we can successfully launch main().
76TEST_F(WindowsTest, LaunchMain) {
77 auto& context = GetContext();
78 WindowsConfigBuilder builder(context);
79 ViewControllerPtr controller{builder.Run()};
80 ASSERT_NE(controller, nullptr);
81}
82
83// Verify there is no unexpected output from launching main.
84TEST_F(WindowsTest, LaunchMainHasNoOutput) {
85 // Replace stderr stream buffer with our own. (stdout may contain expected
86 // output printed by Dart, such as the Dart VM service startup message)
87 StreamCapture stderr_capture(&std::cerr);
88
89 auto& context = GetContext();
90 WindowsConfigBuilder builder(context);
91 ViewControllerPtr controller{builder.Run()};
92 ASSERT_NE(controller, nullptr);
93
94 stderr_capture.Stop();
95
96 // Verify stderr has no output.
97 EXPECT_TRUE(stderr_capture.GetOutput().empty());
98}
99
100// Verify we can successfully launch a custom entry point.
101TEST_F(WindowsTest, LaunchCustomEntrypoint) {
102 auto& context = GetContext();
103 WindowsConfigBuilder builder(context);
104 builder.SetDartEntrypoint("customEntrypoint");
105 ViewControllerPtr controller{builder.Run()};
106 ASSERT_NE(controller, nullptr);
107}
108
109// Verify that engine launches with the custom entrypoint specified in the
110// FlutterDesktopEngineRun parameter when no entrypoint is specified in
111// FlutterDesktopEngineProperties.dart_entrypoint.
112//
113// TODO(cbracken): https://github.com/flutter/flutter/issues/109285
114TEST_F(WindowsTest, LaunchCustomEntrypointInEngineRunInvocation) {
115 auto& context = GetContext();
116 WindowsConfigBuilder builder(context);
118 ASSERT_NE(engine, nullptr);
119
120 ASSERT_TRUE(FlutterDesktopEngineRun(engine.get(), "customEntrypoint"));
121}
122
123// Verify that the engine can launch in headless mode.
124TEST_F(WindowsTest, LaunchHeadlessEngine) {
125 auto& context = GetContext();
126 WindowsConfigBuilder builder(context);
127 builder.SetDartEntrypoint("signalViewIds");
128 EnginePtr engine{builder.RunHeadless()};
129 ASSERT_NE(engine, nullptr);
130
131 std::string view_ids;
132 bool signaled = false;
133 context.AddNativeFunction(
134 "SignalStringValue", CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
135 auto handle = Dart_GetNativeArgument(args, 0);
136 ASSERT_FALSE(Dart_IsError(handle));
138 signaled = true;
139 }));
140
141 ViewControllerPtr controller{builder.Run()};
142 ASSERT_NE(controller, nullptr);
143
144 while (!signaled) {
145 PumpMessage();
146 }
147
148 // Verify a headless app has the implicit view.
149 EXPECT_EQ(view_ids, "View IDs: [0]");
150}
151
152// Verify that the engine can return to headless mode.
153TEST_F(WindowsTest, EngineCanTransitionToHeadless) {
154 auto& context = GetContext();
155 WindowsConfigBuilder builder(context);
156 EnginePtr engine{builder.RunHeadless()};
157 ASSERT_NE(engine, nullptr);
158
159 // Create and then destroy a view controller that does not own its engine.
160 // This causes the engine to transition back to headless mode.
161 {
163 ViewControllerPtr controller{
165
166 ASSERT_NE(controller, nullptr);
167 }
168
169 // The engine is back in headless mode now.
170 ASSERT_NE(engine, nullptr);
171
172 auto engine_ptr = reinterpret_cast<FlutterWindowsEngine*>(engine.get());
173 ASSERT_TRUE(engine_ptr->running());
174}
175
176// Verify that accessibility features are initialized when a view is created.
177TEST_F(WindowsTest, LaunchRefreshesAccessibility) {
178 auto& context = GetContext();
179 WindowsConfigBuilder builder(context);
181 EngineModifier modifier{
182 reinterpret_cast<FlutterWindowsEngine*>(engine.get())};
183
184 auto called = false;
185 modifier.embedder_api().UpdateAccessibilityFeatures = MOCK_ENGINE_PROC(
186 UpdateAccessibilityFeatures, ([&called](auto engine, auto flags) {
187 called = true;
188 return kSuccess;
189 }));
190
191 ViewControllerPtr controller{
193
194 ASSERT_TRUE(called);
195}
196
197// Verify that engine fails to launch when a conflicting entrypoint in
198// FlutterDesktopEngineProperties.dart_entrypoint and the
199// FlutterDesktopEngineRun parameter.
200//
201// TODO(cbracken): https://github.com/flutter/flutter/issues/109285
202TEST_F(WindowsTest, LaunchConflictingCustomEntrypoints) {
203 auto& context = GetContext();
204 WindowsConfigBuilder builder(context);
205 builder.SetDartEntrypoint("customEntrypoint");
207 ASSERT_NE(engine, nullptr);
208
209 ASSERT_FALSE(FlutterDesktopEngineRun(engine.get(), "conflictingEntrypoint"));
210}
211
212// Verify that native functions can be registered and resolved.
213TEST_F(WindowsTest, VerifyNativeFunction) {
214 auto& context = GetContext();
215 WindowsConfigBuilder builder(context);
216 builder.SetDartEntrypoint("verifyNativeFunction");
217
218 bool signaled = false;
219 auto native_entry =
220 CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) { signaled = true; });
221 context.AddNativeFunction("Signal", native_entry);
222
223 ViewControllerPtr controller{builder.Run()};
224 ASSERT_NE(controller, nullptr);
225
226 // Wait until signal has been called.
227 while (!signaled) {
228 PumpMessage();
229 }
230}
231
232// Verify that native functions that pass parameters can be registered and
233// resolved.
234TEST_F(WindowsTest, VerifyNativeFunctionWithParameters) {
235 auto& context = GetContext();
236 WindowsConfigBuilder builder(context);
237 builder.SetDartEntrypoint("verifyNativeFunctionWithParameters");
238
239 bool bool_value = false;
240 bool signaled = false;
241 auto native_entry = CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
242 auto handle = Dart_GetNativeBooleanArgument(args, 0, &bool_value);
243 ASSERT_FALSE(Dart_IsError(handle));
244 signaled = true;
245 });
246 context.AddNativeFunction("SignalBoolValue", native_entry);
247
248 ViewControllerPtr controller{builder.Run()};
249 ASSERT_NE(controller, nullptr);
250
251 // Wait until signalBoolValue has been called.
252 while (!signaled) {
253 PumpMessage();
254 }
255 EXPECT_TRUE(bool_value);
256}
257
258// Verify that Platform.executable returns the executable name.
259TEST_F(WindowsTest, PlatformExecutable) {
260 auto& context = GetContext();
261 WindowsConfigBuilder builder(context);
262 builder.SetDartEntrypoint("readPlatformExecutable");
263
264 std::string executable_name;
265 bool signaled = false;
266 auto native_entry = CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
267 auto handle = Dart_GetNativeArgument(args, 0);
268 ASSERT_FALSE(Dart_IsError(handle));
269 executable_name = tonic::DartConverter<std::string>::FromDart(handle);
270 signaled = true;
271 });
272 context.AddNativeFunction("SignalStringValue", native_entry);
273
274 ViewControllerPtr controller{builder.Run()};
275 ASSERT_NE(controller, nullptr);
276
277 // Wait until signalStringValue has been called.
278 while (!signaled) {
279 PumpMessage();
280 }
281 EXPECT_EQ(executable_name, "flutter_windows_unittests.exe");
282}
283
284// Verify that native functions that return values can be registered and
285// resolved.
286TEST_F(WindowsTest, VerifyNativeFunctionWithReturn) {
287 auto& context = GetContext();
288 WindowsConfigBuilder builder(context);
289 builder.SetDartEntrypoint("verifyNativeFunctionWithReturn");
290
291 bool bool_value_to_return = true;
292 int count = 2;
293 auto bool_return_entry = CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
294 Dart_SetBooleanReturnValue(args, bool_value_to_return);
295 --count;
296 });
297 context.AddNativeFunction("SignalBoolReturn", bool_return_entry);
298
299 bool bool_value_passed = false;
300 auto bool_pass_entry = CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
301 auto handle = Dart_GetNativeBooleanArgument(args, 0, &bool_value_passed);
302 ASSERT_FALSE(Dart_IsError(handle));
303 --count;
304 });
305 context.AddNativeFunction("SignalBoolValue", bool_pass_entry);
306
307 ViewControllerPtr controller{builder.Run()};
308 ASSERT_NE(controller, nullptr);
309
310 // Wait until signalBoolReturn and signalBoolValue have been called.
311 while (count > 0) {
312 PumpMessage();
313 }
314 EXPECT_TRUE(bool_value_passed);
315}
316
317// Verify the next frame callback is executed.
318TEST_F(WindowsTest, NextFrameCallback) {
319 struct Captures {
320 fml::AutoResetWaitableEvent frame_scheduled_latch;
321 std::thread::id thread_id;
322 bool done = false;
323 };
324 Captures captures;
325
326 auto platform_thread = std::make_unique<fml::Thread>("test_platform_thread");
327 platform_thread->GetTaskRunner()->PostTask([&]() {
328 captures.thread_id = std::this_thread::get_id();
329
330 auto& context = GetContext();
331 WindowsConfigBuilder builder(context);
332 builder.SetDartEntrypoint("drawHelloWorld");
333
334 auto native_entry = CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
335 captures.frame_scheduled_latch.Signal();
336 });
337 context.AddNativeFunction("NotifyFirstFrameScheduled", native_entry);
338
339 ViewControllerPtr controller{builder.Run()};
340 EXPECT_NE(controller, nullptr);
341
342 auto engine = FlutterDesktopViewControllerGetEngine(controller.get());
343
345 engine,
346 [](void* user_data) {
347 auto captures = static_cast<Captures*>(user_data);
348
349 EXPECT_TRUE(captures->frame_scheduled_latch.IsSignaledForTest());
350
351 // Callback should execute on platform thread.
352 EXPECT_EQ(std::this_thread::get_id(), captures->thread_id);
353
354 // Signal the test passed and end the Windows message loop.
355 captures->done = true;
356 },
357 &captures);
358
359 // Pump messages for the Windows platform task runner.
360 while (!captures.done) {
361 PumpMessage();
362 }
363 });
364
365 // Wait for the platform thread to exit.
366 platform_thread->Join();
367}
368
369// Verify the embedder ignores presents to the implicit view when there is no
370// implicit view.
371TEST_F(WindowsTest, PresentHeadless) {
372 auto& context = GetContext();
373 WindowsConfigBuilder builder(context);
374 builder.SetDartEntrypoint("renderImplicitView");
375
376 EnginePtr engine{builder.RunHeadless()};
377 ASSERT_NE(engine, nullptr);
378
379 bool done = false;
381 engine.get(),
382 [](void* user_data) {
383 // This executes on the platform thread.
384 auto done = reinterpret_cast<std::atomic<bool>*>(user_data);
385 *done = true;
386 },
387 &done);
388
389 // This app is in headless mode, however, the engine assumes the implicit
390 // view always exists. Send window metrics for the implicit view, causing
391 // the engine to present to the implicit view. The embedder must not crash.
392 auto engine_ptr = reinterpret_cast<FlutterWindowsEngine*>(engine.get());
393 FlutterWindowMetricsEvent metrics = {};
394 metrics.struct_size = sizeof(FlutterWindowMetricsEvent);
395 metrics.width = 100;
396 metrics.height = 100;
397 metrics.pixel_ratio = 1.0;
398 metrics.view_id = kImplicitViewId;
399 engine_ptr->SendWindowMetricsEvent(metrics);
400
401 // Pump messages for the Windows platform task runner.
402 while (!done) {
403 PumpMessage();
404 }
405}
406
407// Implicit view has the implicit view ID.
408TEST_F(WindowsTest, GetViewId) {
409 auto& context = GetContext();
410 WindowsConfigBuilder builder(context);
411 ViewControllerPtr controller{builder.Run()};
412 ASSERT_NE(controller, nullptr);
415
416 ASSERT_EQ(view_id, static_cast<FlutterDesktopViewId>(kImplicitViewId));
417}
418
419TEST_F(WindowsTest, GetGraphicsAdapter) {
420 auto& context = GetContext();
421 WindowsConfigBuilder builder(context);
422 ViewControllerPtr controller{builder.Run()};
423 ASSERT_NE(controller, nullptr);
424 auto view = FlutterDesktopViewControllerGetView(controller.get());
425
426 Microsoft::WRL::ComPtr<IDXGIAdapter> dxgi_adapter;
428 ASSERT_NE(dxgi_adapter, nullptr);
429 DXGI_ADAPTER_DESC desc{};
430 ASSERT_TRUE(SUCCEEDED(dxgi_adapter->GetDesc(&desc)));
431}
432
433TEST_F(WindowsTest, GetGraphicsAdapterWithLowPowerPreference) {
434 std::optional<LUID> luid = egl::Manager::GetLowPowerGpuLuid();
435 if (!luid) {
436 GTEST_SKIP() << "Not able to find low power GPU, nothing to check.";
437 }
438
439 auto& context = GetContext();
440 WindowsConfigBuilder builder(context);
442 ViewControllerPtr controller{builder.Run()};
443 ASSERT_NE(controller, nullptr);
444 auto view = FlutterDesktopViewControllerGetView(controller.get());
445
446 Microsoft::WRL::ComPtr<IDXGIAdapter> dxgi_adapter;
448 ASSERT_NE(dxgi_adapter, nullptr);
449 DXGI_ADAPTER_DESC desc{};
450 ASSERT_TRUE(SUCCEEDED(dxgi_adapter->GetDesc(&desc)));
451 ASSERT_EQ(desc.AdapterLuid.HighPart, luid->HighPart);
452 ASSERT_EQ(desc.AdapterLuid.LowPart, luid->LowPart);
453}
454
455TEST_F(WindowsTest, GetGraphicsAdapterWithHighPerformancePreference) {
456 std::optional<LUID> luid = egl::Manager::GetHighPerformanceGpuLuid();
457 if (!luid) {
458 GTEST_SKIP() << "Not able to find high performance GPU, nothing to check.";
459 }
460
461 auto& context = GetContext();
462 WindowsConfigBuilder builder(context);
463 builder.SetGpuPreference(
465 ViewControllerPtr controller{builder.Run()};
466 ASSERT_NE(controller, nullptr);
467 auto view = FlutterDesktopViewControllerGetView(controller.get());
468
469 Microsoft::WRL::ComPtr<IDXGIAdapter> dxgi_adapter;
471 ASSERT_NE(dxgi_adapter, nullptr);
472 DXGI_ADAPTER_DESC desc{};
473 ASSERT_TRUE(SUCCEEDED(dxgi_adapter->GetDesc(&desc)));
474 ASSERT_EQ(desc.AdapterLuid.HighPart, luid->HighPart);
475 ASSERT_EQ(desc.AdapterLuid.LowPart, luid->LowPart);
476}
477
478// Implicit view has the implicit view ID.
479TEST_F(WindowsTest, PluginRegistrarGetImplicitView) {
480 auto& context = GetContext();
481 WindowsConfigBuilder builder(context);
482 ViewControllerPtr controller{builder.Run()};
483 ASSERT_NE(controller, nullptr);
484
489 FlutterDesktopViewRef implicit_view =
491
492 ASSERT_NE(implicit_view, nullptr);
493}
494
495TEST_F(WindowsTest, PluginRegistrarGetView) {
496 auto& context = GetContext();
497 WindowsConfigBuilder builder(context);
498 ViewControllerPtr controller{builder.Run()};
499 ASSERT_NE(controller, nullptr);
500
505
510
512 registrar, static_cast<FlutterDesktopViewId>(123));
513
514 ASSERT_NE(view, nullptr);
515 ASSERT_EQ(view_123, nullptr);
516}
517
518TEST_F(WindowsTest, PluginRegistrarGetViewHeadless) {
519 auto& context = GetContext();
520 WindowsConfigBuilder builder(context);
521 EnginePtr engine{builder.RunHeadless()};
522 ASSERT_NE(engine, nullptr);
523
526
527 FlutterDesktopViewRef implicit_view =
530 registrar, static_cast<FlutterDesktopViewId>(123));
531
532 ASSERT_EQ(implicit_view, nullptr);
533 ASSERT_EQ(view_123, nullptr);
534}
535
536// Verify the app does not crash if EGL initializes successfully but
537// the rendering surface cannot be created.
538TEST_F(WindowsTest, SurfaceOptional) {
539 auto& context = GetContext();
540 WindowsConfigBuilder builder(context);
542 EngineModifier modifier{
543 reinterpret_cast<FlutterWindowsEngine*>(engine.get())};
544
545 auto egl_manager = std::make_unique<HalfBrokenEGLManager>();
546 ASSERT_TRUE(egl_manager->IsValid());
547 modifier.SetEGLManager(std::move(egl_manager));
548
549 ViewControllerPtr controller{
551
552 ASSERT_NE(controller, nullptr);
553}
554
555// Verify the app produces the expected lifecycle events.
556TEST_F(WindowsTest, Lifecycle) {
557 auto& context = GetContext();
558 WindowsConfigBuilder builder(context);
560 auto windows_engine = reinterpret_cast<FlutterWindowsEngine*>(engine.get());
561 EngineModifier modifier{windows_engine};
562
563 auto lifecycle_manager =
564 std::make_unique<MockWindowsLifecycleManager>(windows_engine);
565 auto lifecycle_manager_ptr = lifecycle_manager.get();
566 modifier.SetLifecycleManager(std::move(lifecycle_manager));
567
568 EXPECT_CALL(*lifecycle_manager_ptr,
569 SetLifecycleState(AppLifecycleState::kInactive))
570 .WillOnce([lifecycle_manager_ptr](AppLifecycleState state) {
571 lifecycle_manager_ptr->WindowsLifecycleManager::SetLifecycleState(
572 state);
573 });
574
575 EXPECT_CALL(*lifecycle_manager_ptr,
576 SetLifecycleState(AppLifecycleState::kHidden))
577 .WillOnce([lifecycle_manager_ptr](AppLifecycleState state) {
578 lifecycle_manager_ptr->WindowsLifecycleManager::SetLifecycleState(
579 state);
580 });
581
582 FlutterDesktopViewControllerProperties properties = {0, 0};
583
584 // Create a controller. This launches the engine and sets the app lifecycle
585 // to the "resumed" state.
586 ViewControllerPtr controller{
588
590 FlutterDesktopViewControllerGetView(controller.get());
591 ASSERT_NE(view, nullptr);
592
593 HWND hwnd = FlutterDesktopViewGetHWND(view);
594 ASSERT_NE(hwnd, nullptr);
595
596 // Give the window a non-zero size to show it. This does not change the app
597 // lifecycle directly. However, destroying the view will now result in a
598 // "hidden" app lifecycle event.
599 ::MoveWindow(hwnd, /* X */ 0, /* Y */ 0, /* nWidth*/ 100, /* nHeight*/ 100,
600 /* bRepaint*/ false);
601
602 while (lifecycle_manager_ptr->IsUpdateStateScheduled()) {
603 PumpMessage();
604 }
605
606 // Resets the view, simulating the window being hidden.
607 controller.reset();
608
609 while (lifecycle_manager_ptr->IsUpdateStateScheduled()) {
610 PumpMessage();
611 }
612}
613
614TEST_F(WindowsTest, GetKeyboardStateHeadless) {
615 auto& context = GetContext();
616 WindowsConfigBuilder builder(context);
617 builder.SetDartEntrypoint("sendGetKeyboardState");
618
619 std::atomic<bool> done = false;
620 context.AddNativeFunction(
621 "SignalStringValue", CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
622 auto handle = Dart_GetNativeArgument(args, 0);
623 ASSERT_FALSE(Dart_IsError(handle));
625 EXPECT_EQ(value, "Success");
626 done = true;
627 }));
628
629 ViewControllerPtr controller{builder.Run()};
630 ASSERT_NE(controller, nullptr);
631
632 // Pump messages for the Windows platform task runner.
633 ::MSG msg;
634 while (!done) {
635 PumpMessage();
636 }
637}
638
639// Verify the embedder can add and remove views.
640TEST_F(WindowsTest, AddRemoveView) {
641 std::mutex mutex;
642 std::string view_ids;
643
644 auto& context = GetContext();
645 WindowsConfigBuilder builder(context);
646 builder.SetDartEntrypoint("onMetricsChangedSignalViewIds");
647
648 bool ready = false;
649 context.AddNativeFunction(
650 "Signal",
651 CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) { ready = true; }));
652
653 context.AddNativeFunction(
654 "SignalStringValue", CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
655 auto handle = Dart_GetNativeArgument(args, 0);
656 ASSERT_FALSE(Dart_IsError(handle));
657
658 std::scoped_lock lock{mutex};
660 }));
661
662 // Create the implicit view.
663 ViewControllerPtr first_controller{builder.Run()};
664 ASSERT_NE(first_controller, nullptr);
665
666 while (!ready) {
667 PumpMessage();
668 }
669
670 // Create a second view.
672 FlutterDesktopViewControllerGetEngine(first_controller.get());
674 properties.width = 100;
675 properties.height = 100;
676 ViewControllerPtr second_controller{
678 ASSERT_NE(second_controller, nullptr);
679
680 // Pump messages for the Windows platform task runner until the view is added.
681 while (true) {
682 PumpMessage();
683 std::scoped_lock lock{mutex};
684 if (view_ids == "View IDs: [0, 1]") {
685 break;
686 }
687 }
688
689 // Delete the second view and pump messages for the Windows platform task
690 // runner until the view is removed.
691 second_controller.reset();
692 while (true) {
693 PumpMessage();
694 std::scoped_lock lock{mutex};
695 if (view_ids == "View IDs: [0]") {
696 break;
697 }
698 }
699}
700
701TEST_F(WindowsTest, EngineId) {
702 auto& context = GetContext();
703 WindowsConfigBuilder builder(context);
704 builder.SetDartEntrypoint("testEngineId");
705
706 std::optional<int64_t> engineId;
707 context.AddNativeFunction(
708 "NotifyEngineId", CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
709 const auto argument = Dart_GetNativeArgument(args, 0);
710 if (!Dart_IsNull(argument)) {
711 const auto handle = tonic::DartConverter<int64_t>::FromDart(argument);
712 engineId = handle;
713 }
714 }));
715 // Create the implicit view.
716 ViewControllerPtr first_controller{builder.Run()};
717 ASSERT_NE(first_controller, nullptr);
718
719 while (!engineId.has_value()) {
720 PumpMessage();
721 }
722
723 auto engine = FlutterDesktopViewControllerGetEngine(first_controller.get());
724 EXPECT_EQ(engine, FlutterDesktopEngineForId(*engineId));
725}
726
727} // namespace testing
728} // namespace flutter
WindowsLifecycleManager(FlutterWindowsEngine *engine)
virtual void SetLifecycleState(AppLifecycleState state)
static std::optional< LUID > GetLowPowerGpuLuid()
Definition manager.cc:376
static std::optional< LUID > GetHighPerformanceGpuLuid()
Definition manager.cc:380
MOCK_METHOD(void, Quit,(std::optional< HWND >, std::optional< WPARAM >, std::optional< LPARAM >, UINT),(override))
void SetDartEntrypoint(std::string_view entrypoint)
void SetGpuPreference(FlutterDesktopGpuPreference gpu_preference)
int32_t value
FlutterEngine engine
Definition main.cc:84
FlView * view
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
G_BEGIN_DECLS FlutterViewId view_id
FLUTTER_EXPORT FlutterDesktopEngineRef FlutterDesktopEngineForId(int64_t engine_id)
FlutterDesktopViewControllerRef FlutterDesktopEngineCreateViewController(FlutterDesktopEngineRef engine, const FlutterDesktopViewControllerProperties *properties)
int64_t FlutterDesktopViewId
struct FlutterDesktopView * FlutterDesktopViewRef
@ LowPowerPreference
@ HighPerformancePreference
G_BEGIN_DECLS FlTextureRegistrar * texture_registrar
TEST_F(DisplayListTest, Defaults)
std::unique_ptr< FlutterDesktopEngine, EngineDeleter > EnginePtr
std::unique_ptr< FlutterDesktopViewController, ViewControllerDeleter > ViewControllerPtr
TEST(NativeAssetsManagerTest, NoAvailableAssets)
constexpr int64_t kImplicitViewId
#define MOCK_ENGINE_PROC(proc, mock_impl)
int32_t height
int32_t width
size_t struct_size
The size of this struct. Must be sizeof(FlutterWindowMetricsEvent).
Definition embedder.h:1047
size_t height
Physical height of the window.
Definition embedder.h:1051
int64_t view_id
The view that this event is describing.
Definition embedder.h:1069
double pixel_ratio
Scale factor for the physical screen.
Definition embedder.h:1053
size_t width
Physical width of the window.
Definition embedder.h:1049
HWND FlutterDesktopViewGetHWND(FlutterDesktopViewRef controller)
FlutterDesktopEngineRef FlutterDesktopEngineCreate(const FlutterDesktopEngineProperties *engine_properties)
FlutterDesktopViewId FlutterDesktopViewControllerGetViewId(FlutterDesktopViewControllerRef controller)
FlutterDesktopPluginRegistrarRef FlutterDesktopEngineGetPluginRegistrar(FlutterDesktopEngineRef engine, const char *plugin_name)
FlutterDesktopViewControllerRef FlutterDesktopViewControllerCreate(int width, int height, FlutterDesktopEngineRef engine)
bool FlutterDesktopEngineDestroy(FlutterDesktopEngineRef engine_ref)
FlutterDesktopEngineRef FlutterDesktopViewControllerGetEngine(FlutterDesktopViewControllerRef controller)
FlutterDesktopViewRef FlutterDesktopViewControllerGetView(FlutterDesktopViewControllerRef controller)
FlutterDesktopTextureRegistrarRef FlutterDesktopEngineGetTextureRegistrar(FlutterDesktopEngineRef engine)
FlutterDesktopViewRef FlutterDesktopPluginRegistrarGetView(FlutterDesktopPluginRegistrarRef controller)
IDXGIAdapter * FlutterDesktopViewGetGraphicsAdapter(FlutterDesktopViewRef view)
void FlutterDesktopEngineSetNextFrameCallback(FlutterDesktopEngineRef engine, VoidCallback callback, void *user_data)
FlutterDesktopViewRef FlutterDesktopPluginRegistrarGetViewById(FlutterDesktopPluginRegistrarRef controller, FlutterDesktopViewId view_id)
bool FlutterDesktopEngineRun(FlutterDesktopEngineRef engine, const char *entry_point)
#define CREATE_NATIVE_ENTRY(native_entry)
#define SUCCEEDED(hr)
struct tagMSG MSG
#define GetMessage
#define DispatchMessage