Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions shell/platform/windows/flutter_windows_engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,7 @@ std::unique_ptr<FlutterWindowsView> FlutterWindowsEngine::CreateView(
auto view = std::make_unique<FlutterWindowsView>(
kImplicitViewId, this, std::move(window), windows_proc_table_);

view_ = view.get();
views_[kImplicitViewId] = view.get();
InitializeKeyboard();

return std::move(view);
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.";
}

Expand Down Expand Up @@ -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();
}
}
Expand Down Expand Up @@ -827,7 +830,9 @@ void FlutterWindowsEngine::OnQuit(std::optional<HWND> hwnd,
}

void FlutterWindowsEngine::OnDwmCompositionChanged() {
view_->OnDwmCompositionChanged();
for (auto iterator = views_.begin(); iterator != views_.end(); iterator++) {
iterator->second->OnDwmCompositionChanged();
}
}

void FlutterWindowsEngine::OnWindowStateEvent(HWND hwnd,
Expand Down
12 changes: 7 additions & 5 deletions shell/platform/windows/flutter_windows_engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <optional>
#include <string>
#include <string_view>
#include <unordered_map>
#include <vector>

#include "flutter/fml/closure.h"
Expand Down Expand Up @@ -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<FlutterWindowsView> CreateView(
std::unique_ptr<WindowBindingHandler> 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.
Expand Down Expand Up @@ -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<FlutterViewId, FlutterWindowsView*> views_;

// Task runner for tasks posted from the engine.
std::unique_ptr<TaskRunner> task_runner_;
Expand Down
13 changes: 13 additions & 0 deletions shell/platform/windows/flutter_windows_engine_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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<FlutterWindowsEngine> 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");
Expand Down
4 changes: 3 additions & 1 deletion shell/platform/windows/testing/engine_modifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down