From 57353a87c8ba708bd60f339fdbe2d8e8157720f0 Mon Sep 17 00:00:00 2001 From: Loic Sharma Date: Tue, 27 Feb 2024 13:43:57 -0800 Subject: [PATCH] [Windows] Make the engine own a map of views --- .../windows/flutter_windows_engine.cc | 21 ++++++++++++------- .../platform/windows/flutter_windows_engine.h | 12 ++++++----- .../flutter_windows_engine_unittests.cc | 13 ++++++++++++ .../windows/testing/engine_modifier.h | 4 +++- 4 files changed, 36 insertions(+), 14 deletions(-) diff --git a/shell/platform/windows/flutter_windows_engine.cc b/shell/platform/windows/flutter_windows_engine.cc index 79f4bef83906b..8cafb0fcf497e 100644 --- a/shell/platform/windows/flutter_windows_engine.cc +++ b/shell/platform/windows/flutter_windows_engine.cc @@ -496,7 +496,7 @@ std::unique_ptr FlutterWindowsEngine::CreateView( auto view = std::make_unique( kImplicitViewId, this, std::move(window), windows_proc_table_); - view_ = view.get(); + views_[kImplicitViewId] = view.get(); InitializeKeyboard(); return std::move(view); @@ -531,9 +531,12 @@ std::chrono::nanoseconds FlutterWindowsEngine::FrameInterval() { } FlutterWindowsView* FlutterWindowsEngine::view(FlutterViewId view_id) const { - FML_DCHECK(view_id == kImplicitViewId); + auto iterator = views_.find(view_id); + if (iterator == views_.end()) { + return nullptr; + } - return view_; + return iterator->second; } // Returns the currently configured Plugin Registrar. @@ -672,7 +675,7 @@ void FlutterWindowsEngine::SendSystemLocales() { } void FlutterWindowsEngine::InitializeKeyboard() { - if (view_ == nullptr) { + if (views_.empty()) { FML_LOG(ERROR) << "Cannot initialize keyboard on Windows headless mode."; } @@ -762,15 +765,15 @@ void FlutterWindowsEngine::UpdateSemanticsEnabled(bool enabled) { if (engine_ && semantics_enabled_ != enabled) { semantics_enabled_ = enabled; embedder_api_.UpdateSemanticsEnabled(engine_, enabled); - if (view_) { - view_->UpdateSemanticsEnabled(enabled); + for (auto iterator = views_.begin(); iterator != views_.end(); iterator++) { + iterator->second->UpdateSemanticsEnabled(enabled); } } } void FlutterWindowsEngine::OnPreEngineRestart() { // Reset the keyboard's state on hot restart. - if (view_) { + if (!views_.empty()) { InitializeKeyboard(); } } @@ -827,7 +830,9 @@ void FlutterWindowsEngine::OnQuit(std::optional hwnd, } void FlutterWindowsEngine::OnDwmCompositionChanged() { - view_->OnDwmCompositionChanged(); + for (auto iterator = views_.begin(); iterator != views_.end(); iterator++) { + iterator->second->OnDwmCompositionChanged(); + } } void FlutterWindowsEngine::OnWindowStateEvent(HWND hwnd, diff --git a/shell/platform/windows/flutter_windows_engine.h b/shell/platform/windows/flutter_windows_engine.h index a89898aa803d7..018dc82a3c7c3 100644 --- a/shell/platform/windows/flutter_windows_engine.h +++ b/shell/platform/windows/flutter_windows_engine.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "flutter/fml/closure.h" @@ -119,12 +120,13 @@ class FlutterWindowsEngine { // Returns false if stopping the engine fails, or if it was not running. virtual bool Stop(); - // Create the view that is displaying this engine's content. + // Create a view that can display this engine's content. std::unique_ptr CreateView( std::unique_ptr window); - // The view displaying this engine's content, if any. This will be null for - // headless engines. + // Get a view that displays this engine's content. + // + // Returns null if the view does not exist. FlutterWindowsView* view(FlutterViewId view_id) const; // Returns the currently configured Plugin Registrar. @@ -349,8 +351,8 @@ class FlutterWindowsEngine { // AOT data, if any. UniqueAotDataPtr aot_data_; - // The view displaying the content running in this engine, if any. - FlutterWindowsView* view_ = nullptr; + // The views displaying the content running in this engine, if any. + std::unordered_map views_; // Task runner for tasks posted from the engine. std::unique_ptr task_runner_; diff --git a/shell/platform/windows/flutter_windows_engine_unittests.cc b/shell/platform/windows/flutter_windows_engine_unittests.cc index 42026f49ba5c6..fe7c4fb33674d 100644 --- a/shell/platform/windows/flutter_windows_engine_unittests.cc +++ b/shell/platform/windows/flutter_windows_engine_unittests.cc @@ -34,6 +34,19 @@ using ::testing::Return; class FlutterWindowsEngineTest : public WindowsTest {}; +// The engine can be run without any views. +TEST_F(FlutterWindowsEngineTest, RunHeadless) { + FlutterWindowsEngineBuilder builder{GetContext()}; + std::unique_ptr engine = builder.Build(); + + EngineModifier modifier(engine.get()); + modifier.embedder_api().RunsAOTCompiledDartCode = []() { return false; }; + + ASSERT_TRUE(engine->Run()); + ASSERT_EQ(engine->view(kImplicitViewId), nullptr); + ASSERT_EQ(engine->view(123), nullptr); +} + TEST_F(FlutterWindowsEngineTest, RunDoesExpectedInitialization) { FlutterWindowsEngineBuilder builder{GetContext()}; builder.AddDartEntrypointArgument("arg1"); diff --git a/shell/platform/windows/testing/engine_modifier.h b/shell/platform/windows/testing/engine_modifier.h index 8244ca16e5125..de9e5455a46ec 100644 --- a/shell/platform/windows/testing/engine_modifier.h +++ b/shell/platform/windows/testing/engine_modifier.h @@ -39,7 +39,9 @@ class EngineModifier { // Override the engine's implicit view. This is the "default" view // that Flutter apps render to. - void SetImplicitView(FlutterWindowsView* view) { engine_->view_ = view; } + void SetImplicitView(FlutterWindowsView* view) { + engine_->views_[kImplicitViewId] = view; + } /// Reset the start_time field that is used to align vsync events. void SetStartTime(uint64_t start_time_nanos) {