Flutter Windows Embedder
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 
11 #include "flutter/fml/synchronization/count_down_latch.h"
12 #include "flutter/fml/synchronization/waitable_event.h"
14 #include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h"
16 #include "flutter/shell/platform/windows/testing/engine_modifier.h"
17 #include "flutter/shell/platform/windows/testing/windows_test.h"
18 #include "flutter/shell/platform/windows/testing/windows_test_config_builder.h"
19 #include "flutter/shell/platform/windows/testing/windows_test_context.h"
21 #include "flutter/testing/stream_capture.h"
22 #include "gmock/gmock.h"
23 #include "gtest/gtest.h"
24 #include "third_party/tonic/converter/dart_converter.h"
25 
26 namespace flutter {
27 namespace testing {
28 
29 namespace {
30 
31 // An EGL manager that initializes EGL but fails to create surfaces.
32 class HalfBrokenEGLManager : public egl::Manager {
33  public:
34  HalfBrokenEGLManager() : egl::Manager(/*enable_impeller = */ false) {}
35 
36  std::unique_ptr<egl::WindowSurface>
37  CreateWindowSurface(HWND hwnd, size_t width, size_t height) override {
38  return nullptr;
39  }
40 };
41 
42 class MockWindowsLifecycleManager : public WindowsLifecycleManager {
43  public:
44  MockWindowsLifecycleManager(FlutterWindowsEngine* engine)
45  : WindowsLifecycleManager(engine) {}
46 
47  MOCK_METHOD(void, SetLifecycleState, (AppLifecycleState), (override));
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.
52 void PumpMessage() {
53  ::MSG msg;
54  if (::GetMessage(&msg, nullptr, 0, 0)) {
55  ::TranslateMessage(&msg);
56  ::DispatchMessage(&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
64 TEST(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);
70  auto texture_registrar = FlutterDesktopEngineGetTextureRegistrar(engine);
71  EXPECT_NE(texture_registrar, nullptr);
73 }
74 
75 // Verify we can successfully launch main().
76 TEST_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.
84 TEST_F(WindowsTest, LaunchMainHasNoOutput) {
85  // Replace stdout & stderr stream buffers with our own.
86  StreamCapture stdout_capture(&std::cout);
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  stdout_capture.Stop();
95  stderr_capture.Stop();
96 
97  // Verify stdout & stderr have no output.
98  EXPECT_TRUE(stdout_capture.GetOutput().empty());
99  EXPECT_TRUE(stderr_capture.GetOutput().empty());
100 }
101 
102 // Verify we can successfully launch a custom entry point.
103 TEST_F(WindowsTest, LaunchCustomEntrypoint) {
104  auto& context = GetContext();
105  WindowsConfigBuilder builder(context);
106  builder.SetDartEntrypoint("customEntrypoint");
107  ViewControllerPtr controller{builder.Run()};
108  ASSERT_NE(controller, nullptr);
109 }
110 
111 // Verify that engine launches with the custom entrypoint specified in the
112 // FlutterDesktopEngineRun parameter when no entrypoint is specified in
113 // FlutterDesktopEngineProperties.dart_entrypoint.
114 //
115 // TODO(cbracken): https://github.com/flutter/flutter/issues/109285
116 TEST_F(WindowsTest, LaunchCustomEntrypointInEngineRunInvocation) {
117  auto& context = GetContext();
118  WindowsConfigBuilder builder(context);
119  EnginePtr engine{builder.InitializeEngine()};
120  ASSERT_NE(engine, nullptr);
121 
122  ASSERT_TRUE(FlutterDesktopEngineRun(engine.get(), "customEntrypoint"));
123 }
124 
125 // Verify that the engine can launch in headless mode.
126 TEST_F(WindowsTest, LaunchHeadlessEngine) {
127  auto& context = GetContext();
128  WindowsConfigBuilder builder(context);
129  builder.SetDartEntrypoint("signalViewIds");
130  EnginePtr engine{builder.RunHeadless()};
131  ASSERT_NE(engine, nullptr);
132 
133  std::string view_ids;
134  fml::AutoResetWaitableEvent latch;
135  context.AddNativeFunction(
136  "SignalStringValue", CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
137  auto handle = Dart_GetNativeArgument(args, 0);
138  ASSERT_FALSE(Dart_IsError(handle));
139  view_ids = tonic::DartConverter<std::string>::FromDart(handle);
140  latch.Signal();
141  }));
142 
143  ViewControllerPtr controller{builder.Run()};
144  ASSERT_NE(controller, nullptr);
145 
146  // Verify a headless app has the implicit view.
147  latch.Wait();
148  EXPECT_EQ(view_ids, "View IDs: [0]");
149 }
150 
151 // Verify that the engine can return to headless mode.
152 TEST_F(WindowsTest, EngineCanTransitionToHeadless) {
153  auto& context = GetContext();
154  WindowsConfigBuilder builder(context);
155  EnginePtr engine{builder.RunHeadless()};
156  ASSERT_NE(engine, nullptr);
157 
158  // Create and then destroy a view controller that does not own its engine.
159  // This causes the engine to transition back to headless mode.
160  {
162  ViewControllerPtr controller{
163  FlutterDesktopEngineCreateViewController(engine.get(), &properties)};
164 
165  ASSERT_NE(controller, nullptr);
166  }
167 
168  // The engine is back in headless mode now.
169  ASSERT_NE(engine, nullptr);
170 
171  auto engine_ptr = reinterpret_cast<FlutterWindowsEngine*>(engine.get());
172  ASSERT_TRUE(engine_ptr->running());
173 }
174 
175 // Verify that accessibility features are initialized when a view is created.
176 TEST_F(WindowsTest, LaunchRefreshesAccessibility) {
177  auto& context = GetContext();
178  WindowsConfigBuilder builder(context);
179  EnginePtr engine{builder.InitializeEngine()};
180  EngineModifier modifier{
181  reinterpret_cast<FlutterWindowsEngine*>(engine.get())};
182 
183  auto called = false;
184  modifier.embedder_api().UpdateAccessibilityFeatures = MOCK_ENGINE_PROC(
185  UpdateAccessibilityFeatures, ([&called](auto engine, auto flags) {
186  called = true;
187  return kSuccess;
188  }));
189 
190  ViewControllerPtr controller{
191  FlutterDesktopViewControllerCreate(0, 0, engine.release())};
192 
193  ASSERT_TRUE(called);
194 }
195 
196 // Verify that engine fails to launch when a conflicting entrypoint in
197 // FlutterDesktopEngineProperties.dart_entrypoint and the
198 // FlutterDesktopEngineRun parameter.
199 //
200 // TODO(cbracken): https://github.com/flutter/flutter/issues/109285
201 TEST_F(WindowsTest, LaunchConflictingCustomEntrypoints) {
202  auto& context = GetContext();
203  WindowsConfigBuilder builder(context);
204  builder.SetDartEntrypoint("customEntrypoint");
205  EnginePtr engine{builder.InitializeEngine()};
206  ASSERT_NE(engine, nullptr);
207 
208  ASSERT_FALSE(FlutterDesktopEngineRun(engine.get(), "conflictingEntrypoint"));
209 }
210 
211 // Verify that native functions can be registered and resolved.
212 TEST_F(WindowsTest, VerifyNativeFunction) {
213  auto& context = GetContext();
214  WindowsConfigBuilder builder(context);
215  builder.SetDartEntrypoint("verifyNativeFunction");
216 
217  fml::AutoResetWaitableEvent latch;
218  auto native_entry =
219  CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) { latch.Signal(); });
220  context.AddNativeFunction("Signal", native_entry);
221 
222  ViewControllerPtr controller{builder.Run()};
223  ASSERT_NE(controller, nullptr);
224 
225  // Wait until signal has been called.
226  latch.Wait();
227 }
228 
229 // Verify that native functions that pass parameters can be registered and
230 // resolved.
231 TEST_F(WindowsTest, VerifyNativeFunctionWithParameters) {
232  auto& context = GetContext();
233  WindowsConfigBuilder builder(context);
234  builder.SetDartEntrypoint("verifyNativeFunctionWithParameters");
235 
236  bool bool_value = false;
237  fml::AutoResetWaitableEvent latch;
238  auto native_entry = CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
239  auto handle = Dart_GetNativeBooleanArgument(args, 0, &bool_value);
240  ASSERT_FALSE(Dart_IsError(handle));
241  latch.Signal();
242  });
243  context.AddNativeFunction("SignalBoolValue", native_entry);
244 
245  ViewControllerPtr controller{builder.Run()};
246  ASSERT_NE(controller, nullptr);
247 
248  // Wait until signalBoolValue has been called.
249  latch.Wait();
250  EXPECT_TRUE(bool_value);
251 }
252 
253 // Verify that Platform.executable returns the executable name.
254 TEST_F(WindowsTest, PlatformExecutable) {
255  auto& context = GetContext();
256  WindowsConfigBuilder builder(context);
257  builder.SetDartEntrypoint("readPlatformExecutable");
258 
259  std::string executable_name;
260  fml::AutoResetWaitableEvent latch;
261  auto native_entry = CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
262  auto handle = Dart_GetNativeArgument(args, 0);
263  ASSERT_FALSE(Dart_IsError(handle));
264  executable_name = tonic::DartConverter<std::string>::FromDart(handle);
265  latch.Signal();
266  });
267  context.AddNativeFunction("SignalStringValue", native_entry);
268 
269  ViewControllerPtr controller{builder.Run()};
270  ASSERT_NE(controller, nullptr);
271 
272  // Wait until signalStringValue has been called.
273  latch.Wait();
274  EXPECT_EQ(executable_name, "flutter_windows_unittests.exe");
275 }
276 
277 // Verify that native functions that return values can be registered and
278 // resolved.
279 TEST_F(WindowsTest, VerifyNativeFunctionWithReturn) {
280  auto& context = GetContext();
281  WindowsConfigBuilder builder(context);
282  builder.SetDartEntrypoint("verifyNativeFunctionWithReturn");
283 
284  bool bool_value_to_return = true;
285  fml::CountDownLatch latch(2);
286  auto bool_return_entry = CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
287  Dart_SetBooleanReturnValue(args, bool_value_to_return);
288  latch.CountDown();
289  });
290  context.AddNativeFunction("SignalBoolReturn", bool_return_entry);
291 
292  bool bool_value_passed = false;
293  auto bool_pass_entry = CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
294  auto handle = Dart_GetNativeBooleanArgument(args, 0, &bool_value_passed);
295  ASSERT_FALSE(Dart_IsError(handle));
296  latch.CountDown();
297  });
298  context.AddNativeFunction("SignalBoolValue", bool_pass_entry);
299 
300  ViewControllerPtr controller{builder.Run()};
301  ASSERT_NE(controller, nullptr);
302 
303  // Wait until signalBoolReturn and signalBoolValue have been called.
304  latch.Wait();
305  EXPECT_TRUE(bool_value_passed);
306 }
307 
308 // Verify the next frame callback is executed.
309 TEST_F(WindowsTest, NextFrameCallback) {
310  struct Captures {
311  fml::AutoResetWaitableEvent frame_scheduled_latch;
312  fml::AutoResetWaitableEvent frame_drawn_latch;
313  std::thread::id thread_id;
314  bool done = false;
315  };
316  Captures captures;
317 
318  CreateNewThread("test_platform_thread")->PostTask([&]() {
319  captures.thread_id = std::this_thread::get_id();
320 
321  auto& context = GetContext();
322  WindowsConfigBuilder builder(context);
323  builder.SetDartEntrypoint("drawHelloWorld");
324 
325  auto native_entry = CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
326  ASSERT_FALSE(captures.frame_drawn_latch.IsSignaledForTest());
327  captures.frame_scheduled_latch.Signal();
328  });
329  context.AddNativeFunction("NotifyFirstFrameScheduled", native_entry);
330 
331  ViewControllerPtr controller{builder.Run()};
332  ASSERT_NE(controller, nullptr);
333 
334  auto engine = FlutterDesktopViewControllerGetEngine(controller.get());
335 
337  engine,
338  [](void* user_data) {
339  auto captures = static_cast<Captures*>(user_data);
340 
341  ASSERT_TRUE(captures->frame_scheduled_latch.IsSignaledForTest());
342 
343  // Callback should execute on platform thread.
344  ASSERT_EQ(std::this_thread::get_id(), captures->thread_id);
345 
346  // Signal the test passed and end the Windows message loop.
347  captures->done = true;
348  captures->frame_drawn_latch.Signal();
349  },
350  &captures);
351 
352  // Pump messages for the Windows platform task runner.
353  while (!captures.done) {
354  PumpMessage();
355  }
356  });
357 
358  captures.frame_drawn_latch.Wait();
359 }
360 
361 // Verify the embedder ignores presents to the implicit view when there is no
362 // implicit view.
363 TEST_F(WindowsTest, PresentHeadless) {
364  auto& context = GetContext();
365  WindowsConfigBuilder builder(context);
366  builder.SetDartEntrypoint("renderImplicitView");
367 
368  EnginePtr engine{builder.RunHeadless()};
369  ASSERT_NE(engine, nullptr);
370 
371  bool done = false;
373  engine.get(),
374  [](void* user_data) {
375  // This executes on the platform thread.
376  auto done = reinterpret_cast<std::atomic<bool>*>(user_data);
377  *done = true;
378  },
379  &done);
380 
381  // This app is in headless mode, however, the engine assumes the implicit
382  // view always exists. Send window metrics for the implicit view, causing
383  // the engine to present to the implicit view. The embedder must not crash.
384  auto engine_ptr = reinterpret_cast<FlutterWindowsEngine*>(engine.get());
385  FlutterWindowMetricsEvent metrics = {};
386  metrics.struct_size = sizeof(FlutterWindowMetricsEvent);
387  metrics.width = 100;
388  metrics.height = 100;
389  metrics.pixel_ratio = 1.0;
390  metrics.view_id = kImplicitViewId;
391  engine_ptr->SendWindowMetricsEvent(metrics);
392 
393  // Pump messages for the Windows platform task runner.
394  while (!done) {
395  PumpMessage();
396  }
397 }
398 
399 // Implicit view has the implicit view ID.
400 TEST_F(WindowsTest, GetViewId) {
401  auto& context = GetContext();
402  WindowsConfigBuilder builder(context);
403  ViewControllerPtr controller{builder.Run()};
404  ASSERT_NE(controller, nullptr);
405  FlutterDesktopViewId view_id =
406  FlutterDesktopViewControllerGetViewId(controller.get());
407 
408  ASSERT_EQ(view_id, static_cast<FlutterDesktopViewId>(kImplicitViewId));
409 }
410 
411 TEST_F(WindowsTest, GetGraphicsAdapter) {
412  auto& context = GetContext();
413  WindowsConfigBuilder builder(context);
414  ViewControllerPtr controller{builder.Run()};
415  ASSERT_NE(controller, nullptr);
416  auto view = FlutterDesktopViewControllerGetView(controller.get());
417 
418  Microsoft::WRL::ComPtr<IDXGIAdapter> dxgi_adapter;
419  dxgi_adapter = FlutterDesktopViewGetGraphicsAdapter(view);
420  ASSERT_NE(dxgi_adapter, nullptr);
421  DXGI_ADAPTER_DESC desc{};
422  ASSERT_TRUE(SUCCEEDED(dxgi_adapter->GetDesc(&desc)));
423 }
424 
425 // Implicit view has the implicit view ID.
426 TEST_F(WindowsTest, PluginRegistrarGetImplicitView) {
427  auto& context = GetContext();
428  WindowsConfigBuilder builder(context);
429  ViewControllerPtr controller{builder.Run()};
430  ASSERT_NE(controller, nullptr);
431 
432  FlutterDesktopEngineRef engine =
433  FlutterDesktopViewControllerGetEngine(controller.get());
435  FlutterDesktopEngineGetPluginRegistrar(engine, "foo_bar");
436  FlutterDesktopViewRef implicit_view =
438 
439  ASSERT_NE(implicit_view, nullptr);
440 }
441 
442 TEST_F(WindowsTest, PluginRegistrarGetView) {
443  auto& context = GetContext();
444  WindowsConfigBuilder builder(context);
445  ViewControllerPtr controller{builder.Run()};
446  ASSERT_NE(controller, nullptr);
447 
448  FlutterDesktopEngineRef engine =
449  FlutterDesktopViewControllerGetEngine(controller.get());
451  FlutterDesktopEngineGetPluginRegistrar(engine, "foo_bar");
452 
453  FlutterDesktopViewId view_id =
454  FlutterDesktopViewControllerGetViewId(controller.get());
455  FlutterDesktopViewRef view =
456  FlutterDesktopPluginRegistrarGetViewById(registrar, view_id);
457 
459  registrar, static_cast<FlutterDesktopViewId>(123));
460 
461  ASSERT_NE(view, nullptr);
462  ASSERT_EQ(view_123, nullptr);
463 }
464 
465 TEST_F(WindowsTest, PluginRegistrarGetViewHeadless) {
466  auto& context = GetContext();
467  WindowsConfigBuilder builder(context);
468  EnginePtr engine{builder.RunHeadless()};
469  ASSERT_NE(engine, nullptr);
470 
472  FlutterDesktopEngineGetPluginRegistrar(engine.get(), "foo_bar");
473 
474  FlutterDesktopViewRef implicit_view =
477  registrar, static_cast<FlutterDesktopViewId>(123));
478 
479  ASSERT_EQ(implicit_view, nullptr);
480  ASSERT_EQ(view_123, nullptr);
481 }
482 
483 // Verify the app does not crash if EGL initializes successfully but
484 // the rendering surface cannot be created.
485 TEST_F(WindowsTest, SurfaceOptional) {
486  auto& context = GetContext();
487  WindowsConfigBuilder builder(context);
488  EnginePtr engine{builder.InitializeEngine()};
489  EngineModifier modifier{
490  reinterpret_cast<FlutterWindowsEngine*>(engine.get())};
491 
492  auto egl_manager = std::make_unique<HalfBrokenEGLManager>();
493  ASSERT_TRUE(egl_manager->IsValid());
494  modifier.SetEGLManager(std::move(egl_manager));
495 
496  ViewControllerPtr controller{
497  FlutterDesktopViewControllerCreate(0, 0, engine.release())};
498 
499  ASSERT_NE(controller, nullptr);
500 }
501 
502 // Verify the app produces the expected lifecycle events.
503 TEST_F(WindowsTest, Lifecycle) {
504  auto& context = GetContext();
505  WindowsConfigBuilder builder(context);
506  EnginePtr engine{builder.InitializeEngine()};
507  auto windows_engine = reinterpret_cast<FlutterWindowsEngine*>(engine.get());
508  EngineModifier modifier{windows_engine};
509 
510  auto lifecycle_manager =
511  std::make_unique<MockWindowsLifecycleManager>(windows_engine);
512  auto lifecycle_manager_ptr = lifecycle_manager.get();
513  modifier.SetLifecycleManager(std::move(lifecycle_manager));
514 
515  EXPECT_CALL(*lifecycle_manager_ptr,
516  SetLifecycleState(AppLifecycleState::kResumed))
517  .WillOnce([lifecycle_manager_ptr](AppLifecycleState state) {
518  lifecycle_manager_ptr->WindowsLifecycleManager::SetLifecycleState(
519  state);
520  });
521 
522  EXPECT_CALL(*lifecycle_manager_ptr,
523  SetLifecycleState(AppLifecycleState::kHidden))
524  .WillOnce([lifecycle_manager_ptr](AppLifecycleState state) {
525  lifecycle_manager_ptr->WindowsLifecycleManager::SetLifecycleState(
526  state);
527  });
528 
529  // Create a controller. This launches the engine and sets the app lifecycle
530  // to the "resumed" state.
531  ViewControllerPtr controller{
532  FlutterDesktopViewControllerCreate(0, 0, engine.release())};
533 
534  FlutterDesktopViewRef view =
535  FlutterDesktopViewControllerGetView(controller.get());
536  ASSERT_NE(view, nullptr);
537 
538  HWND hwnd = FlutterDesktopViewGetHWND(view);
539  ASSERT_NE(hwnd, nullptr);
540 
541  // Give the window a non-zero size to show it. This does not change the app
542  // lifecycle directly. However, destroying the view will now result in a
543  // "hidden" app lifecycle event.
544  ::MoveWindow(hwnd, /* X */ 0, /* Y */ 0, /* nWidth*/ 100, /* nHeight*/ 100,
545  /* bRepaint*/ false);
546 }
547 
548 TEST_F(WindowsTest, GetKeyboardStateHeadless) {
549  auto& context = GetContext();
550  WindowsConfigBuilder builder(context);
551  builder.SetDartEntrypoint("sendGetKeyboardState");
552 
553  std::atomic<bool> done = false;
554  context.AddNativeFunction(
555  "SignalStringValue", CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
556  auto handle = Dart_GetNativeArgument(args, 0);
557  ASSERT_FALSE(Dart_IsError(handle));
558  auto value = tonic::DartConverter<std::string>::FromDart(handle);
559  EXPECT_EQ(value, "Success");
560  done = true;
561  }));
562 
563  ViewControllerPtr controller{builder.Run()};
564  ASSERT_NE(controller, nullptr);
565 
566  // Pump messages for the Windows platform task runner.
567  ::MSG msg;
568  while (!done) {
569  PumpMessage();
570  }
571 }
572 
573 // Verify the embedder can add and remove views.
574 TEST_F(WindowsTest, AddRemoveView) {
575  std::mutex mutex;
576  std::string view_ids;
577 
578  auto& context = GetContext();
579  WindowsConfigBuilder builder(context);
580  builder.SetDartEntrypoint("onMetricsChangedSignalViewIds");
581 
582  fml::AutoResetWaitableEvent ready_latch;
583  context.AddNativeFunction(
584  "Signal", CREATE_NATIVE_ENTRY(
585  [&](Dart_NativeArguments args) { ready_latch.Signal(); }));
586 
587  context.AddNativeFunction(
588  "SignalStringValue", CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
589  auto handle = Dart_GetNativeArgument(args, 0);
590  ASSERT_FALSE(Dart_IsError(handle));
591 
592  std::scoped_lock lock{mutex};
593  view_ids = tonic::DartConverter<std::string>::FromDart(handle);
594  }));
595 
596  // Create the implicit view.
597  ViewControllerPtr first_controller{builder.Run()};
598  ASSERT_NE(first_controller, nullptr);
599 
600  ready_latch.Wait();
601 
602  // Create a second view.
603  FlutterDesktopEngineRef engine =
604  FlutterDesktopViewControllerGetEngine(first_controller.get());
606  properties.width = 100;
607  properties.height = 100;
608  ViewControllerPtr second_controller{
609  FlutterDesktopEngineCreateViewController(engine, &properties)};
610  ASSERT_NE(second_controller, nullptr);
611 
612  // Pump messages for the Windows platform task runner until the view is added.
613  while (true) {
614  PumpMessage();
615  std::scoped_lock lock{mutex};
616  if (view_ids == "View IDs: [0, 1]") {
617  break;
618  }
619  }
620 
621  // Delete the second view and pump messages for the Windows platform task
622  // runner until the view is removed.
623  second_controller.reset();
624  while (true) {
625  PumpMessage();
626  std::scoped_lock lock{mutex};
627  if (view_ids == "View IDs: [0]") {
628  break;
629  }
630  }
631 }
632 
633 } // namespace testing
634 } // namespace flutter
FlutterDesktopViewControllerProperties::height
int height
Definition: flutter_windows_internal.h:23
flutter::kImplicitViewId
constexpr FlutterViewId kImplicitViewId
Definition: flutter_windows_engine.h:55
FlutterDesktopViewGetHWND
HWND FlutterDesktopViewGetHWND(FlutterDesktopViewRef view)
Definition: flutter_windows.cc:246
flutter::AppLifecycleState::kHidden
@ kHidden
FlutterDesktopViewControllerGetView
FlutterDesktopViewRef FlutterDesktopViewControllerGetView(FlutterDesktopViewControllerRef ref)
Definition: flutter_windows.cc:153
FlutterDesktopEngineGetTextureRegistrar
FlutterDesktopTextureRegistrarRef FlutterDesktopEngineGetTextureRegistrar(FlutterDesktopEngineRef engine)
Definition: flutter_windows.cc:233
FlutterDesktopPluginRegistrarGetView
FlutterDesktopViewRef FlutterDesktopPluginRegistrarGetView(FlutterDesktopPluginRegistrarRef registrar)
Definition: flutter_windows.cc:290
FlutterDesktopEngineProperties
Definition: flutter_windows.h:39
windows_lifecycle_manager.h
FlutterDesktopViewId
int64_t FlutterDesktopViewId
Definition: flutter_windows.h:36
user_data
void * user_data
Definition: flutter_windows_view_unittests.cc:53
flutter::FlutterWindowsEngine
Definition: flutter_windows_engine.h:90
FlutterDesktopViewControllerProperties
Definition: flutter_windows_internal.h:18
FlutterDesktopEngineProperties::icu_data_path
const wchar_t * icu_data_path
Definition: flutter_windows.h:48
FlutterDesktopEngineGetPluginRegistrar
FlutterDesktopPluginRegistrarRef FlutterDesktopEngineGetPluginRegistrar(FlutterDesktopEngineRef engine, const char *plugin_name)
Definition: flutter_windows.cc:218
flutter::FlutterWindowsEngine::UpdateAccessibilityFeatures
void UpdateAccessibilityFeatures()
Definition: flutter_windows_engine.cc:916
FlutterDesktopViewControllerGetViewId
FlutterDesktopViewId FlutterDesktopViewControllerGetViewId(FlutterDesktopViewControllerRef ref)
Definition: flutter_windows.cc:141
flutter::testing::MockWindowsLifecycleManager::MockWindowsLifecycleManager
MockWindowsLifecycleManager(FlutterWindowsEngine *engine)
Definition: flutter_windows_engine_unittests.cc:751
app_lifecycle_state.h
FlutterDesktopViewRef
struct FlutterDesktopView * FlutterDesktopViewRef
Definition: flutter_windows.h:29
FlutterDesktopEngineRef
struct FlutterDesktopEngine * FlutterDesktopEngineRef
Definition: flutter_windows.h:33
flutter::WindowsLifecycleManager::SetLifecycleState
virtual void SetLifecycleState(AppLifecycleState state)
Definition: windows_lifecycle_manager.cc:195
flutter::WindowsLifecycleManager::WindowsLifecycleManager
WindowsLifecycleManager(FlutterWindowsEngine *engine)
Definition: windows_lifecycle_manager.cc:16
flutter
Definition: accessibility_bridge_windows.cc:11
FlutterDesktopViewControllerCreate
FlutterDesktopViewControllerRef FlutterDesktopViewControllerCreate(int width, int height, FlutterDesktopEngineRef engine)
Definition: flutter_windows.cc:121
FlutterDesktopEngineDestroy
bool FlutterDesktopEngineDestroy(FlutterDesktopEngineRef engine_ref)
Definition: flutter_windows.cc:190
manager.h
FlutterDesktopEngineCreate
FlutterDesktopEngineRef FlutterDesktopEngineCreate(const FlutterDesktopEngineProperties *engine_properties)
Definition: flutter_windows.cc:183
FlutterDesktopViewControllerGetEngine
FlutterDesktopEngineRef FlutterDesktopViewControllerGetEngine(FlutterDesktopViewControllerRef ref)
Definition: flutter_windows.cc:147
flutter::AppLifecycleState::kResumed
@ kResumed
flutter_windows.h
flutter::testing::TEST
TEST(AccessibilityBridgeWindows, GetParent)
Definition: accessibility_bridge_windows_unittests.cc:237
flutter::AppLifecycleState
AppLifecycleState
Definition: app_lifecycle_state.h:32
FlutterDesktopEngineSetNextFrameCallback
void FlutterDesktopEngineSetNextFrameCallback(FlutterDesktopEngineRef engine, VoidCallback callback, void *user_data)
Definition: flutter_windows.cc:239
FlutterDesktopEngineCreateViewController
FlutterDesktopViewControllerRef FlutterDesktopEngineCreateViewController(FlutterDesktopEngineRef engine, const FlutterDesktopViewControllerProperties *properties)
Definition: flutter_windows.cc:128
FlutterDesktopViewControllerProperties::width
int width
Definition: flutter_windows_internal.h:20
flutter::testing::MockWindowsLifecycleManager::MOCK_METHOD
MOCK_METHOD(void, Quit,(std::optional< HWND >, std::optional< WPARAM >, std::optional< LPARAM >, UINT),(override))
flutter::testing::TEST_F
TEST_F(CompositorOpenGLTest, CreateBackingStore)
Definition: compositor_opengl_unittests.cc:125
FlutterDesktopViewGetGraphicsAdapter
IDXGIAdapter * FlutterDesktopViewGetGraphicsAdapter(FlutterDesktopViewRef view)
Definition: flutter_windows.cc:250
FlutterDesktopEngineProperties::assets_path
const wchar_t * assets_path
Definition: flutter_windows.h:43
FlutterDesktopPluginRegistrar
Definition: window_state.h:23
FlutterDesktopEngineRun
bool FlutterDesktopEngineRun(FlutterDesktopEngineRef engine, const char *entry_point)
Definition: flutter_windows.cc:200
FlutterDesktopPluginRegistrarGetViewById
FlutterDesktopViewRef FlutterDesktopPluginRegistrarGetViewById(FlutterDesktopPluginRegistrarRef registrar, FlutterDesktopViewId view_id)
Definition: flutter_windows.cc:295