From b1fb925231c45034c2d686ad8196c9bc925c6e91 Mon Sep 17 00:00:00 2001 From: Loic Sharma Date: Wed, 14 Feb 2024 17:45:22 -0800 Subject: [PATCH 1/2] [Windows] Make the engine create the view --- .../accessibility_bridge_windows_unittests.cc | 55 ++-- .../windows/compositor_opengl_unittests.cc | 8 +- .../windows/compositor_software_unittests.cc | 11 +- .../windows/cursor_handler_unittests.cc | 11 +- .../windows/flutter_window_unittests.cc | 16 +- shell/platform/windows/flutter_windows.cc | 5 +- .../windows/flutter_windows_engine.cc | 10 +- .../platform/windows/flutter_windows_engine.h | 5 +- .../flutter_windows_engine_unittests.cc | 68 ++-- .../platform/windows/flutter_windows_view.cc | 37 +-- shell/platform/windows/flutter_windows_view.h | 8 +- .../windows/flutter_windows_view_unittests.cc | 305 ++++++++---------- shell/platform/windows/keyboard_unittests.cc | 19 +- .../windows/platform_handler_unittests.cc | 8 +- .../windows/testing/engine_modifier.h | 8 + .../windows/text_input_plugin_unittest.cc | 12 +- 16 files changed, 289 insertions(+), 297 deletions(-) diff --git a/shell/platform/windows/accessibility_bridge_windows_unittests.cc b/shell/platform/windows/accessibility_bridge_windows_unittests.cc index 5b839720c4682..ca540e2d50b09 100644 --- a/shell/platform/windows/accessibility_bridge_windows_unittests.cc +++ b/shell/platform/windows/accessibility_bridge_windows_unittests.cc @@ -26,6 +26,7 @@ namespace flutter { namespace testing { namespace { +using ::testing::NiceMock; // A structure representing a Win32 MSAA event targeting a specified node. struct MsaaEvent { @@ -88,8 +89,9 @@ class AccessibilityBridgeWindowsSpy : public AccessibilityBridgeWindows { // AccessibilityBridgeWindowsSpy. class FlutterWindowsViewSpy : public FlutterWindowsView { public: - explicit FlutterWindowsViewSpy(std::unique_ptr handler) - : FlutterWindowsView(std::move(handler)) {} + FlutterWindowsViewSpy(FlutterWindowsEngine* engine, + std::unique_ptr handler) + : FlutterWindowsView(engine, std::move(handler)) {} protected: virtual std::shared_ptr @@ -187,10 +189,10 @@ void ExpectWinEventFromAXEvent(int32_t node_id, ui::AXEventGenerator::Event ax_event, ax::mojom::Event expected_event) { auto engine = GetTestEngine(); - auto window_binding_handler = - std::make_unique<::testing::NiceMock>(); - FlutterWindowsViewSpy view(std::move(window_binding_handler)); - view.SetEngine(engine.get()); + FlutterWindowsViewSpy view{ + engine.get(), std::make_unique>()}; + EngineModifier modifier{engine.get()}; + modifier.SetImplicitView(&view); view.OnUpdateSemanticsEnabled(true); auto bridge = GetAccessibilityBridgeSpy(view); @@ -208,10 +210,10 @@ void ExpectWinEventFromAXEventOnFocusNode(int32_t node_id, ax::mojom::Event expected_event, int32_t focus_id) { auto engine = GetTestEngine(); - auto window_binding_handler = - std::make_unique<::testing::NiceMock>(); - FlutterWindowsViewSpy view(std::move(window_binding_handler)); - view.SetEngine(engine.get()); + FlutterWindowsViewSpy view{ + engine.get(), std::make_unique>()}; + EngineModifier modifier{engine.get()}; + modifier.SetImplicitView(&view); view.OnUpdateSemanticsEnabled(true); auto bridge = GetAccessibilityBridgeSpy(view); @@ -234,10 +236,10 @@ void ExpectWinEventFromAXEventOnFocusNode(int32_t node_id, TEST(AccessibilityBridgeWindows, GetParent) { auto engine = GetTestEngine(); - auto window_binding_handler = - std::make_unique<::testing::NiceMock>(); - FlutterWindowsViewSpy view(std::move(window_binding_handler)); - view.SetEngine(engine.get()); + FlutterWindowsViewSpy view{ + engine.get(), std::make_unique>()}; + EngineModifier modifier{engine.get()}; + modifier.SetImplicitView(&view); view.OnUpdateSemanticsEnabled(true); auto bridge = view.accessibility_bridge().lock(); @@ -251,10 +253,10 @@ TEST(AccessibilityBridgeWindows, GetParent) { TEST(AccessibilityBridgeWindows, GetParentOnRootRetunsNullptr) { auto engine = GetTestEngine(); - auto window_binding_handler = - std::make_unique<::testing::NiceMock>(); - FlutterWindowsViewSpy view(std::move(window_binding_handler)); - view.SetEngine(engine.get()); + FlutterWindowsViewSpy view{ + engine.get(), std::make_unique>()}; + EngineModifier modifier{engine.get()}; + modifier.SetImplicitView(&view); view.OnUpdateSemanticsEnabled(true); auto bridge = view.accessibility_bridge().lock(); @@ -266,17 +268,16 @@ TEST(AccessibilityBridgeWindows, GetParentOnRootRetunsNullptr) { TEST(AccessibilityBridgeWindows, DispatchAccessibilityAction) { auto engine = GetTestEngine(); - auto window_binding_handler = - std::make_unique<::testing::NiceMock>(); - FlutterWindowsViewSpy view(std::move(window_binding_handler)); - view.SetEngine(engine.get()); + FlutterWindowsViewSpy view{ + engine.get(), std::make_unique>()}; + EngineModifier modifier{engine.get()}; + modifier.SetImplicitView(&view); view.OnUpdateSemanticsEnabled(true); auto bridge = view.accessibility_bridge().lock(); PopulateAXTree(bridge); FlutterSemanticsAction actual_action = kFlutterSemanticsActionTap; - EngineModifier modifier(view.GetEngine()); modifier.embedder_api().DispatchSemanticsAction = MOCK_ENGINE_PROC( DispatchSemanticsAction, ([&actual_action](FLUTTER_API_SYMBOL(FlutterEngine) engine, uint64_t id, @@ -303,10 +304,10 @@ TEST(AccessibilityBridgeWindows, OnAccessibilityEventChildrenChanged) { TEST(AccessibilityBridgeWindows, OnAccessibilityEventFocusChanged) { auto engine = GetTestEngine(); - auto window_binding_handler = - std::make_unique<::testing::NiceMock>(); - FlutterWindowsViewSpy view(std::move(window_binding_handler)); - view.SetEngine(engine.get()); + FlutterWindowsViewSpy view{ + engine.get(), std::make_unique>()}; + EngineModifier modifier{engine.get()}; + modifier.SetImplicitView(&view); view.OnUpdateSemanticsEnabled(true); auto bridge = GetAccessibilityBridgeSpy(view); diff --git a/shell/platform/windows/compositor_opengl_unittests.cc b/shell/platform/windows/compositor_opengl_unittests.cc index bfa307533e715..9a596f9cc0ed5 100644 --- a/shell/platform/windows/compositor_opengl_unittests.cc +++ b/shell/platform/windows/compositor_opengl_unittests.cc @@ -84,7 +84,7 @@ class CompositorOpenGLTest : public WindowsTest { FlutterWindowsEngineBuilder builder{GetContext()}; engine_ = builder.Build(); - EngineModifier modifier(engine_.get()); + EngineModifier modifier{engine_.get()}; modifier.SetEGLManager(std::move(egl_manager)); } @@ -95,7 +95,8 @@ class CompositorOpenGLTest : public WindowsTest { EXPECT_CALL(*window.get(), SetView).Times(1); EXPECT_CALL(*window.get(), GetWindowHandle).WillRepeatedly(Return(nullptr)); - view_ = std::make_unique(std::move(window)); + view_ = + std::make_unique(engine_.get(), std::move(window)); if (add_surface) { auto surface = std::make_unique(); @@ -107,7 +108,8 @@ class CompositorOpenGLTest : public WindowsTest { modifier.SetSurface(std::move(surface)); } - engine_->SetView(view_.get()); + EngineModifier modifier{engine_.get()}; + modifier.SetImplicitView(view_.get()); } private: diff --git a/shell/platform/windows/compositor_software_unittests.cc b/shell/platform/windows/compositor_software_unittests.cc index bef9fca3061b7..27b0f48533863 100644 --- a/shell/platform/windows/compositor_software_unittests.cc +++ b/shell/platform/windows/compositor_software_unittests.cc @@ -22,8 +22,9 @@ using ::testing::Return; class MockFlutterWindowsView : public FlutterWindowsView { public: - MockFlutterWindowsView(std::unique_ptr window) - : FlutterWindowsView(std::move(window)) {} + MockFlutterWindowsView(FlutterWindowsEngine* engine, + std::unique_ptr window) + : FlutterWindowsView(engine, std::move(window)) {} virtual ~MockFlutterWindowsView() = default; MOCK_METHOD(bool, @@ -59,9 +60,11 @@ class CompositorSoftwareTest : public WindowsTest { EXPECT_CALL(*window.get(), GetWindowHandle).WillRepeatedly(Return(nullptr)); engine_ = builder.Build(); - view_ = std::make_unique(std::move(window)); + view_ = std::make_unique(engine_.get(), + std::move(window)); - engine_->SetView(view_.get()); + EngineModifier modifier{engine_.get()}; + modifier.SetImplicitView(view_.get()); } private: diff --git a/shell/platform/windows/cursor_handler_unittests.cc b/shell/platform/windows/cursor_handler_unittests.cc index 459ea0635b8fa..d7dfda4230acd 100644 --- a/shell/platform/windows/cursor_handler_unittests.cc +++ b/shell/platform/windows/cursor_handler_unittests.cc @@ -11,6 +11,7 @@ #include "flutter/shell/platform/common/client_wrapper/include/flutter/standard_message_codec.h" #include "flutter/shell/platform/common/client_wrapper/include/flutter/standard_method_codec.h" #include "flutter/shell/platform/windows/flutter_windows_view.h" +#include "flutter/shell/platform/windows/testing/engine_modifier.h" #include "flutter/shell/platform/windows/testing/flutter_windows_engine_builder.h" #include "flutter/shell/platform/windows/testing/mock_window_binding_handler.h" #include "flutter/shell/platform/windows/testing/test_binary_messenger.h" @@ -73,14 +74,16 @@ class CursorHandlerTest : public WindowsTest { FlutterWindowsEngineBuilder builder{GetContext()}; auto window = std::make_unique(); + EXPECT_CALL(*window.get(), SetView).Times(1); + EXPECT_CALL(*window.get(), GetWindowHandle).WillRepeatedly(Return(nullptr)); window_ = window.get(); - EXPECT_CALL(*window_, SetView).Times(1); - engine_ = builder.Build(); - view_ = std::make_unique(std::move(window)); + view_ = + std::make_unique(engine_.get(), std::move(window)); - engine_->SetView(view_.get()); + EngineModifier modifier{engine_.get()}; + modifier.SetImplicitView(view_.get()); } private: diff --git a/shell/platform/windows/flutter_window_unittests.cc b/shell/platform/windows/flutter_window_unittests.cc index 270f4fe718c80..4e4893039a619 100644 --- a/shell/platform/windows/flutter_window_unittests.cc +++ b/shell/platform/windows/flutter_window_unittests.cc @@ -4,6 +4,7 @@ #include "flutter/fml/macros.h" #include "flutter/shell/platform/windows/flutter_window.h" +#include "flutter/shell/platform/windows/testing/flutter_windows_engine_builder.h" #include "flutter/shell/platform/windows/testing/mock_window_binding_handler.h" #include "flutter/shell/platform/windows/testing/mock_window_binding_handler_delegate.h" #include "flutter/shell/platform/windows/testing/windows_test.h" @@ -26,7 +27,7 @@ static constexpr int32_t kDefaultPointerDeviceId = 0; class MockFlutterWindow : public FlutterWindow { public: MockFlutterWindow(bool reset_view_on_exit = true) - : FlutterWindow(), reset_view_on_exit_(reset_view_on_exit) { + : reset_view_on_exit_(reset_view_on_exit) { ON_CALL(*this, GetDpiScale()) .WillByDefault(Return(this->FlutterWindow::GetDpiScale())); } @@ -95,8 +96,9 @@ class MockFlutterWindow : public FlutterWindow { class MockFlutterWindowsView : public FlutterWindowsView { public: - MockFlutterWindowsView(std::unique_ptr window_binding) - : FlutterWindowsView(std::move(window_binding)) {} + MockFlutterWindowsView(FlutterWindowsEngine* engine, + std::unique_ptr window_binding) + : FlutterWindowsView(engine, std::move(window_binding)) {} ~MockFlutterWindowsView() {} MOCK_METHOD(void, @@ -313,12 +315,14 @@ TEST_F(FlutterWindowTest, AccessibilityNodeWithoutView) { // Ensure that announcing the alert propagates the message to the alert node. // Different screen readers use different properties for alerts. TEST_F(FlutterWindowTest, AlertNode) { - std::unique_ptr win32window = - std::make_unique(); + std::unique_ptr engine = + FlutterWindowsEngineBuilder{GetContext()}.Build(); + auto win32window = std::make_unique(); EXPECT_CALL(*win32window.get(), GetAxFragmentRootDelegate()) .WillRepeatedly(Return(nullptr)); EXPECT_CALL(*win32window.get(), OnWindowStateEvent).Times(AnyNumber()); - MockFlutterWindowsView view(std::move(win32window)); + EXPECT_CALL(*win32window.get(), GetWindowHandle).Times(AnyNumber()); + MockFlutterWindowsView view(engine.get(), std::move(win32window)); std::wstring message = L"Test alert"; EXPECT_CALL(view, NotifyWinEventWrapper(_, ax::mojom::Event::kAlert)) .Times(1); diff --git a/shell/platform/windows/flutter_windows.cc b/shell/platform/windows/flutter_windows.cc index 0f293c497c670..baed42490d3af 100644 --- a/shell/platform/windows/flutter_windows.cc +++ b/shell/platform/windows/flutter_windows.cc @@ -82,12 +82,11 @@ FlutterDesktopViewControllerRef FlutterDesktopViewControllerCreate( width, height, engine_ptr->windows_proc_table()); auto engine = std::unique_ptr(engine_ptr); - auto view = std::make_unique( - std::move(window_wrapper), engine_ptr->windows_proc_table()); + std::unique_ptr view = + engine->CreateView(std::move(window_wrapper)); auto controller = std::make_unique( std::move(engine), std::move(view)); - controller->view()->SetEngine(controller->engine()); controller->view()->CreateRenderSurface(); if (!controller->engine()->running()) { if (!controller->engine()->Run()) { diff --git a/shell/platform/windows/flutter_windows_engine.cc b/shell/platform/windows/flutter_windows_engine.cc index a5766c16577cd..89a806a40f5d0 100644 --- a/shell/platform/windows/flutter_windows_engine.cc +++ b/shell/platform/windows/flutter_windows_engine.cc @@ -483,9 +483,15 @@ bool FlutterWindowsEngine::Stop() { return false; } -void FlutterWindowsEngine::SetView(FlutterWindowsView* view) { - view_ = view; +std::unique_ptr FlutterWindowsEngine::CreateView( + std::unique_ptr window) { + auto view = std::make_unique(this, std::move(window), + windows_proc_table_); + + view_ = view.get(); InitializeKeyboard(); + + return std::move(view); } void FlutterWindowsEngine::OnVsync(intptr_t baton) { diff --git a/shell/platform/windows/flutter_windows_engine.h b/shell/platform/windows/flutter_windows_engine.h index 3914978f9fc1d..24f07658862d6 100644 --- a/shell/platform/windows/flutter_windows_engine.h +++ b/shell/platform/windows/flutter_windows_engine.h @@ -111,8 +111,9 @@ class FlutterWindowsEngine { // Returns false if stopping the engine fails, or if it was not running. virtual bool Stop(); - // Sets the view that is displaying this engine's content. - void SetView(FlutterWindowsView* view); + // Create the view that is displaying 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. diff --git a/shell/platform/windows/flutter_windows_engine_unittests.cc b/shell/platform/windows/flutter_windows_engine_unittests.cc index e44a5592dc1be..8862fe2e5f9de 100644 --- a/shell/platform/windows/flutter_windows_engine_unittests.cc +++ b/shell/platform/windows/flutter_windows_engine_unittests.cc @@ -578,6 +578,9 @@ TEST_F(FlutterWindowsEngineTest, UpdateHighContrastFeature) { engine_flags = flags; return kSuccess; })); + modifier.embedder_api().SendPlatformMessage = MOCK_ENGINE_PROC( + SendPlatformMessage, + [](auto engine, const auto message) { return kSuccess; }); // 1: High contrast is enabled. engine->UpdateHighContrastMode(); @@ -618,8 +621,9 @@ TEST_F(FlutterWindowsEngineTest, PostRasterThreadTask) { class MockFlutterWindowsView : public FlutterWindowsView { public: - MockFlutterWindowsView(std::unique_ptr wbh) - : FlutterWindowsView(std::move(wbh)) {} + MockFlutterWindowsView(FlutterWindowsEngine* engine, + std::unique_ptr wbh) + : FlutterWindowsView(engine, std::move(wbh)) {} ~MockFlutterWindowsView() {} MOCK_METHOD(void, @@ -643,10 +647,10 @@ TEST_F(FlutterWindowsEngineTest, AlertPlatformMessage) { AlertPlatformNodeDelegate delegate(parent_delegate); EXPECT_CALL(*window_binding_handler, GetAlertDelegate) .WillRepeatedly(Return(&delegate)); - MockFlutterWindowsView view(std::move(window_binding_handler)); - view.SetEngine(engine.get()); + MockFlutterWindowsView view(engine.get(), std::move(window_binding_handler)); EngineModifier modifier(engine.get()); + modifier.SetImplicitView(&view); modifier.embedder_api().RunsAOTCompiledDartCode = []() { return false; }; auto binary_messenger = @@ -706,10 +710,10 @@ TEST_F(FlutterWindowsEngineTest, TestExit) { auto engine = builder.Build(); auto window_binding_handler = std::make_unique<::testing::NiceMock>(); - MockFlutterWindowsView view(std::move(window_binding_handler)); - view.SetEngine(engine.get()); + MockFlutterWindowsView view(engine.get(), std::move(window_binding_handler)); EngineModifier modifier(engine.get()); + modifier.SetImplicitView(&view); modifier.embedder_api().RunsAOTCompiledDartCode = []() { return false; }; auto handler = std::make_unique(engine.get()); EXPECT_CALL(*handler, SetLifecycleState(AppLifecycleState::kResumed)); @@ -743,10 +747,10 @@ TEST_F(FlutterWindowsEngineTest, TestExitCancel) { auto engine = builder.Build(); auto window_binding_handler = std::make_unique<::testing::NiceMock>(); - MockFlutterWindowsView view(std::move(window_binding_handler)); - view.SetEngine(engine.get()); + MockFlutterWindowsView view(engine.get(), std::move(window_binding_handler)); EngineModifier modifier(engine.get()); + modifier.SetImplicitView(&view); modifier.embedder_api().RunsAOTCompiledDartCode = []() { return false; }; auto handler = std::make_unique(engine.get()); EXPECT_CALL(*handler, SetLifecycleState(AppLifecycleState::kResumed)); @@ -791,10 +795,10 @@ TEST_F(FlutterWindowsEngineTest, TestExitSecondCloseMessage) { auto engine = builder.Build(); auto window_binding_handler = std::make_unique<::testing::NiceMock>(); - MockFlutterWindowsView view(std::move(window_binding_handler)); - view.SetEngine(engine.get()); + MockFlutterWindowsView view(engine.get(), std::move(window_binding_handler)); EngineModifier modifier(engine.get()); + modifier.SetImplicitView(&view); modifier.embedder_api().RunsAOTCompiledDartCode = []() { return false; }; auto handler = std::make_unique(engine.get()); EXPECT_CALL(*handler, SetLifecycleState(AppLifecycleState::kResumed)); @@ -853,10 +857,10 @@ TEST_F(FlutterWindowsEngineTest, TestExitCloseMultiWindow) { auto engine = builder.Build(); auto window_binding_handler = std::make_unique<::testing::NiceMock>(); - MockFlutterWindowsView view(std::move(window_binding_handler)); - view.SetEngine(engine.get()); + MockFlutterWindowsView view(engine.get(), std::move(window_binding_handler)); EngineModifier modifier(engine.get()); + modifier.SetImplicitView(&view); modifier.embedder_api().RunsAOTCompiledDartCode = []() { return false; }; auto handler = std::make_unique(engine.get()); EXPECT_CALL(*handler, SetLifecycleState(AppLifecycleState::kResumed)); @@ -885,10 +889,10 @@ TEST_F(FlutterWindowsEngineTest, LifecycleManagerDisabledByDefault) { auto engine = builder.Build(); auto window_binding_handler = std::make_unique<::testing::NiceMock>(); - MockFlutterWindowsView view(std::move(window_binding_handler)); - view.SetEngine(engine.get()); + MockFlutterWindowsView view(engine.get(), std::move(window_binding_handler)); EngineModifier modifier(engine.get()); + modifier.SetImplicitView(&view); modifier.embedder_api().RunsAOTCompiledDartCode = []() { return false; }; auto handler = std::make_unique(engine.get()); EXPECT_CALL(*handler, IsLastWindowOfProcess).Times(0); @@ -904,10 +908,10 @@ TEST_F(FlutterWindowsEngineTest, EnableApplicationLifecycle) { auto engine = builder.Build(); auto window_binding_handler = std::make_unique<::testing::NiceMock>(); - MockFlutterWindowsView view(std::move(window_binding_handler)); - view.SetEngine(engine.get()); + MockFlutterWindowsView view(engine.get(), std::move(window_binding_handler)); EngineModifier modifier(engine.get()); + modifier.SetImplicitView(&view); modifier.embedder_api().RunsAOTCompiledDartCode = []() { return false; }; auto handler = std::make_unique(engine.get()); EXPECT_CALL(*handler, IsLastWindowOfProcess).WillOnce(Return(false)); @@ -924,10 +928,10 @@ TEST_F(FlutterWindowsEngineTest, ApplicationLifecycleExternalWindow) { auto engine = builder.Build(); auto window_binding_handler = std::make_unique<::testing::NiceMock>(); - MockFlutterWindowsView view(std::move(window_binding_handler)); - view.SetEngine(engine.get()); + MockFlutterWindowsView view(engine.get(), std::move(window_binding_handler)); EngineModifier modifier(engine.get()); + modifier.SetImplicitView(&view); modifier.embedder_api().RunsAOTCompiledDartCode = []() { return false; }; auto handler = std::make_unique(engine.get()); EXPECT_CALL(*handler, IsLastWindowOfProcess).WillOnce(Return(false)); @@ -943,10 +947,10 @@ TEST_F(FlutterWindowsEngineTest, AppStartsInResumedState) { auto engine = builder.Build(); auto window_binding_handler = std::make_unique<::testing::NiceMock>(); - MockFlutterWindowsView view(std::move(window_binding_handler)); - view.SetEngine(engine.get()); + MockFlutterWindowsView view(engine.get(), std::move(window_binding_handler)); EngineModifier modifier(engine.get()); + modifier.SetImplicitView(&view); modifier.embedder_api().RunsAOTCompiledDartCode = []() { return false; }; auto handler = std::make_unique(engine.get()); EXPECT_CALL(*handler, SetLifecycleState(AppLifecycleState::kResumed)) @@ -961,10 +965,10 @@ TEST_F(FlutterWindowsEngineTest, LifecycleStateTransition) { auto engine = builder.Build(); auto window_binding_handler = std::make_unique<::testing::NiceMock>(); - MockFlutterWindowsView view(std::move(window_binding_handler)); - view.SetEngine(engine.get()); + MockFlutterWindowsView view(engine.get(), std::move(window_binding_handler)); EngineModifier modifier(engine.get()); + modifier.SetImplicitView(&view); modifier.embedder_api().RunsAOTCompiledDartCode = []() { return false; }; engine->Run(); @@ -990,10 +994,10 @@ TEST_F(FlutterWindowsEngineTest, ExternalWindowMessage) { auto engine = builder.Build(); auto window_binding_handler = std::make_unique<::testing::NiceMock>(); - MockFlutterWindowsView view(std::move(window_binding_handler)); - view.SetEngine(engine.get()); + MockFlutterWindowsView view(engine.get(), std::move(window_binding_handler)); EngineModifier modifier(engine.get()); + modifier.SetImplicitView(&view); modifier.embedder_api().RunsAOTCompiledDartCode = []() { return false; }; // Sets lifecycle state to resumed. engine->Run(); @@ -1016,11 +1020,11 @@ TEST_F(FlutterWindowsEngineTest, InnerWindowHidden) { auto engine = builder.Build(); auto window_binding_handler = std::make_unique<::testing::NiceMock>(); - MockFlutterWindowsView view(std::move(window_binding_handler)); + MockFlutterWindowsView view(engine.get(), std::move(window_binding_handler)); ON_CALL(view, GetWindowHandle).WillByDefault([=]() { return inner; }); - view.SetEngine(engine.get()); EngineModifier modifier(engine.get()); + modifier.SetImplicitView(&view); modifier.embedder_api().RunsAOTCompiledDartCode = []() { return false; }; // Sets lifecycle state to resumed. engine->Run(); @@ -1050,10 +1054,10 @@ TEST_F(FlutterWindowsEngineTest, EnableLifecycleState) { auto engine = builder.Build(); auto window_binding_handler = std::make_unique<::testing::NiceMock>(); - MockFlutterWindowsView view(std::move(window_binding_handler)); - view.SetEngine(engine.get()); + MockFlutterWindowsView view(engine.get(), std::move(window_binding_handler)); EngineModifier modifier(engine.get()); + modifier.SetImplicitView(&view); modifier.embedder_api().RunsAOTCompiledDartCode = []() { return false; }; auto handler = std::make_unique(engine.get()); EXPECT_CALL(*handler, SetLifecycleState) @@ -1103,10 +1107,10 @@ TEST_F(FlutterWindowsEngineTest, LifecycleStateToFrom) { auto engine = builder.Build(); auto window_binding_handler = std::make_unique<::testing::NiceMock>(); - MockFlutterWindowsView view(std::move(window_binding_handler)); - view.SetEngine(engine.get()); + MockFlutterWindowsView view(engine.get(), std::move(window_binding_handler)); EngineModifier modifier(engine.get()); + modifier.SetImplicitView(&view); modifier.embedder_api().RunsAOTCompiledDartCode = []() { return false; }; auto handler = std::make_unique(engine.get()); EXPECT_CALL(*handler, SetLifecycleState) @@ -1150,10 +1154,10 @@ TEST_F(FlutterWindowsEngineTest, ChannelListenedTo) { auto engine = builder.Build(); auto window_binding_handler = std::make_unique<::testing::NiceMock>(); - MockFlutterWindowsView view(std::move(window_binding_handler)); - view.SetEngine(engine.get()); + MockFlutterWindowsView view(engine.get(), std::move(window_binding_handler)); EngineModifier modifier(engine.get()); + modifier.SetImplicitView(&view); modifier.embedder_api().RunsAOTCompiledDartCode = []() { return false; }; bool lifecycle_began = false; diff --git a/shell/platform/windows/flutter_windows_view.cc b/shell/platform/windows/flutter_windows_view.cc index a373bc244ba61..5c8d209feb9e6 100644 --- a/shell/platform/windows/flutter_windows_view.cc +++ b/shell/platform/windows/flutter_windows_view.cc @@ -84,9 +84,10 @@ void UpdateVsync(const FlutterWindowsEngine& engine, } // namespace FlutterWindowsView::FlutterWindowsView( + FlutterWindowsEngine* engine, std::unique_ptr window_binding, std::shared_ptr windows_proc_table) - : windows_proc_table_(std::move(windows_proc_table)) { + : engine_(engine), windows_proc_table_(std::move(windows_proc_table)) { if (windows_proc_table_ == nullptr) { windows_proc_table_ = std::make_shared(); } @@ -97,33 +98,17 @@ FlutterWindowsView::FlutterWindowsView( } FlutterWindowsView::~FlutterWindowsView() { - if (engine_) { - // The view owns the child window. - // Notify the engine the view's child window will no longer be visible. - engine_->OnWindowStateEvent(GetWindowHandle(), WindowStateEvent::kHide); + // The view owns the child window. + // Notify the engine the view's child window will no longer be visible. + engine_->OnWindowStateEvent(GetWindowHandle(), WindowStateEvent::kHide); - // The engine renders into the view's surface. The engine must be - // shutdown before the view's resources can be destroyed. - engine_->Stop(); - } + // The engine renders into the view's surface. The engine must be + // shutdown before the view's resources can be destroyed. + engine_->Stop(); DestroyRenderSurface(); } -void FlutterWindowsView::SetEngine(FlutterWindowsEngine* engine) { - FML_DCHECK(engine_ == nullptr); - FML_DCHECK(engine != nullptr); - - engine_ = engine; - - engine_->SetView(this); - - PhysicalWindowBounds bounds = binding_handler_->GetPhysicalWindowBounds(); - - SendWindowMetrics(bounds.width, bounds.height, - binding_handler_->GetDpiScale()); -} - bool FlutterWindowsView::OnEmptyFrameGenerated() { // Called on the raster thread. std::unique_lock lock(resize_mutex_); @@ -670,7 +655,7 @@ bool FlutterWindowsView::PresentSoftwareBitmap(const void* allocation, void FlutterWindowsView::CreateRenderSurface() { FML_DCHECK(surface_ == nullptr); - if (engine_ && engine_->egl_manager()) { + if (engine_->egl_manager()) { PhysicalWindowBounds bounds = binding_handler_->GetPhysicalWindowBounds(); surface_ = engine_->egl_manager()->CreateWindowSurface( GetWindowHandle(), bounds.width, bounds.height); @@ -789,9 +774,7 @@ void FlutterWindowsView::OnDwmCompositionChanged() { } void FlutterWindowsView::OnWindowStateEvent(HWND hwnd, WindowStateEvent event) { - if (engine_) { - engine_->OnWindowStateEvent(hwnd, event); - } + engine_->OnWindowStateEvent(hwnd, event); } bool FlutterWindowsView::NeedsVsync() const { diff --git a/shell/platform/windows/flutter_windows_view.h b/shell/platform/windows/flutter_windows_view.h index 62ccb70c3943f..787197df98b2a 100644 --- a/shell/platform/windows/flutter_windows_view.h +++ b/shell/platform/windows/flutter_windows_view.h @@ -32,19 +32,13 @@ class FlutterWindowsView : public WindowBindingHandlerDelegate { public: // Creates a FlutterWindowsView with the given implementor of // WindowBindingHandler. - // - // In order for object to render Flutter content the SetEngine method must be - // called with a valid FlutterWindowsEngine instance. FlutterWindowsView( + FlutterWindowsEngine* engine, std::unique_ptr window_binding, std::shared_ptr windows_proc_table = nullptr); virtual ~FlutterWindowsView(); - // Configures the window instance with an instance of a running Flutter - // engine. - void SetEngine(FlutterWindowsEngine* engine); - // Creates rendering surface for Flutter engine to draw into. // Should be called before calling FlutterEngineRun using this view. void CreateRenderSurface(); diff --git a/shell/platform/windows/flutter_windows_view_unittests.cc b/shell/platform/windows/flutter_windows_view_unittests.cc index 92c0416ec69b2..6ea1ee286baa9 100644 --- a/shell/platform/windows/flutter_windows_view_unittests.cc +++ b/shell/platform/windows/flutter_windows_view_unittests.cc @@ -80,8 +80,10 @@ FlutterProjectBundle GetTestProject() { // Returns an engine instance configured with test project path values, and // overridden methods for sending platform messages, so that the engine can // respond as if the framework were connected. -std::unique_ptr GetTestEngine() { - auto engine = std::make_unique(GetTestProject()); +std::unique_ptr GetTestEngine( + std::shared_ptr windows_proc_table = nullptr) { + auto engine = std::make_unique( + GetTestProject(), std::move(windows_proc_table)); EngineModifier modifier(engine.get()); @@ -113,7 +115,9 @@ std::unique_ptr GetTestEngine() { class MockFlutterWindowsEngine : public FlutterWindowsEngine { public: - MockFlutterWindowsEngine() : FlutterWindowsEngine(GetTestProject()) {} + explicit MockFlutterWindowsEngine( + std::shared_ptr windows_proc_table = nullptr) + : FlutterWindowsEngine(GetTestProject(), std::move(windows_proc_table)) {} MOCK_METHOD(bool, running, (), (const)); MOCK_METHOD(bool, Stop, (), ()); @@ -137,13 +141,13 @@ TEST(FlutterWindowsViewTest, SubMenuExpandedState) { auto window_binding_handler = std::make_unique>(); - FlutterWindowsView view(std::move(window_binding_handler)); - view.SetEngine(engine.get()); + std::unique_ptr view = + engine->CreateView(std::move(window_binding_handler)); // Enable semantics to instantiate accessibility bridge. - view.OnUpdateSemanticsEnabled(true); + view->OnUpdateSemanticsEnabled(true); - auto bridge = view.accessibility_bridge().lock(); + auto bridge = view->accessibility_bridge().lock(); ASSERT_TRUE(bridge); FlutterSemanticsNode2 root{sizeof(FlutterSemanticsNode2), 0}; @@ -237,19 +241,23 @@ TEST(FlutterWindowsViewTest, Shutdown) { std::make_unique>(); auto egl_manager = std::make_unique(); auto surface = std::make_unique(); + auto surface_ptr = surface.get(); - FlutterWindowsView view(std::move(window_binding_handler)); - EngineModifier engine_modifier(engine.get()); - ViewModifier view_modifier(&view); + EngineModifier modifier{engine.get()}; + modifier.SetEGLManager(std::move(egl_manager)); - // The engine must be stopped before the surface can be destroyed. - InSequence s; - EXPECT_CALL(*engine.get(), Stop).Times(1); - EXPECT_CALL(*surface.get(), Destroy).Times(1); + { + std::unique_ptr view = + engine->CreateView(std::move(window_binding_handler)); - engine_modifier.SetEGLManager(std::move(egl_manager)); - view.SetEngine(engine.get()); - view_modifier.SetSurface(std::move(surface)); + ViewModifier view_modifier{view.get()}; + view_modifier.SetSurface(std::move(surface)); + + // The engine must be stopped before the surface can be destroyed. + InSequence s; + EXPECT_CALL(*engine.get(), Stop).Times(1); + EXPECT_CALL(*surface_ptr, Destroy).Times(1); + } } TEST(FlutterWindowsViewTest, KeySequence) { @@ -257,13 +265,11 @@ TEST(FlutterWindowsViewTest, KeySequence) { test_response = false; - auto window_binding_handler = - std::make_unique>(); - FlutterWindowsView view(std::move(window_binding_handler)); - view.SetEngine(engine.get()); + std::unique_ptr view = engine->CreateView( + std::make_unique>()); - view.OnKey(kVirtualKeyA, kScanCodeKeyA, WM_KEYDOWN, 'a', false, false, - [](bool handled) {}); + view->OnKey(kVirtualKeyA, kScanCodeKeyA, WM_KEYDOWN, 'a', false, false, + [](bool handled) {}); EXPECT_EQ(key_event_logs.size(), 2); EXPECT_EQ(key_event_logs[0], kKeyEventFromEmbedder); @@ -287,10 +293,10 @@ TEST(FlutterWindowsViewTest, EnableSemantics) { auto window_binding_handler = std::make_unique>(); - FlutterWindowsView view(std::move(window_binding_handler)); - view.SetEngine(engine.get()); + std::unique_ptr view = + engine->CreateView(std::move(window_binding_handler)); - view.OnUpdateSemanticsEnabled(true); + view->OnUpdateSemanticsEnabled(true); EXPECT_TRUE(semantics_enabled); } @@ -304,13 +310,13 @@ TEST(FlutterWindowsViewTest, AddSemanticsNodeUpdate) { auto window_binding_handler = std::make_unique>(); - FlutterWindowsView view(std::move(window_binding_handler)); - view.SetEngine(engine.get()); + std::unique_ptr view = + engine->CreateView(std::move(window_binding_handler)); // Enable semantics to instantiate accessibility bridge. - view.OnUpdateSemanticsEnabled(true); + view->OnUpdateSemanticsEnabled(true); - auto bridge = view.accessibility_bridge().lock(); + auto bridge = view->accessibility_bridge().lock(); ASSERT_TRUE(bridge); // Add root node. @@ -401,15 +407,13 @@ TEST(FlutterWindowsViewTest, AddSemanticsNodeUpdateWithChildren) { return kSuccess; }; - auto window_binding_handler = - std::make_unique>(); - FlutterWindowsView view(std::move(window_binding_handler)); - view.SetEngine(engine.get()); + std::unique_ptr view = engine->CreateView( + std::make_unique>()); // Enable semantics to instantiate accessibility bridge. - view.OnUpdateSemanticsEnabled(true); + view->OnUpdateSemanticsEnabled(true); - auto bridge = view.accessibility_bridge().lock(); + auto bridge = view->accessibility_bridge().lock(); ASSERT_TRUE(bridge); // Add root node. @@ -599,15 +603,13 @@ TEST(FlutterWindowsViewTest, NonZeroSemanticsRoot) { return kSuccess; }; - auto window_binding_handler = - std::make_unique>(); - FlutterWindowsView view(std::move(window_binding_handler)); - view.SetEngine(engine.get()); + std::unique_ptr view = engine->CreateView( + std::make_unique>()); // Enable semantics to instantiate accessibility bridge. - view.OnUpdateSemanticsEnabled(true); + view->OnUpdateSemanticsEnabled(true); - auto bridge = view.accessibility_bridge().lock(); + auto bridge = view->accessibility_bridge().lock(); ASSERT_TRUE(bridge); // Add root node. @@ -731,15 +733,13 @@ TEST(FlutterWindowsViewTest, AccessibilityHitTesting) { return kSuccess; }; - auto window_binding_handler = - std::make_unique>(); - FlutterWindowsView view(std::move(window_binding_handler)); - view.SetEngine(engine.get()); + std::unique_ptr view = engine->CreateView( + std::make_unique>()); // Enable semantics to instantiate accessibility bridge. - view.OnUpdateSemanticsEnabled(true); + view->OnUpdateSemanticsEnabled(true); - auto bridge = view.accessibility_bridge().lock(); + auto bridge = view->accessibility_bridge().lock(); ASSERT_TRUE(bridge); // Add root node at origin. Size 500x500. @@ -814,12 +814,11 @@ TEST(FlutterWindowsViewTest, AccessibilityHitTesting) { } TEST(FlutterWindowsViewTest, WindowResizeTests) { - std::unique_ptr engine = GetTestEngine(); - EngineModifier engine_modifier(engine.get()); + auto windows_proc_table = std::make_shared>(); + std::unique_ptr engine = + GetTestEngine(windows_proc_table); + EngineModifier engine_modifier{engine.get()}; - auto window_binding_handler = - std::make_unique>(); - auto windows_proc_table = std::make_shared(); auto egl_manager = std::make_unique(); auto surface = std::make_unique(); auto resized_surface = std::make_unique(); @@ -837,11 +836,12 @@ TEST(FlutterWindowsViewTest, WindowResizeTests) { EXPECT_CALL(*resized_surface_ptr, Destroy).WillOnce(Return(true)); - FlutterWindowsView view(std::move(window_binding_handler), - std::move(windows_proc_table)); - ViewModifier view_modifier(&view); engine_modifier.SetEGLManager(std::move(egl_manager)); - view.SetEngine(engine.get()); + + std::unique_ptr view = engine->CreateView( + std::make_unique>()); + + ViewModifier view_modifier{view.get()}; view_modifier.SetSurface(std::move(surface)); fml::AutoResetWaitableEvent metrics_sent_latch; @@ -857,7 +857,7 @@ TEST(FlutterWindowsViewTest, WindowResizeTests) { std::thread([&resized_latch, &view]() { // Start the window resize. This sends the new window metrics // and then blocks until another thread completes the window resize. - EXPECT_TRUE(view.OnWindowSizeChanged(500, 500)); + EXPECT_TRUE(view->OnWindowSizeChanged(500, 500)); resized_latch.Signal(); }).detach(); @@ -865,19 +865,18 @@ TEST(FlutterWindowsViewTest, WindowResizeTests) { metrics_sent_latch.Wait(); // Complete the window resize by reporting a frame with the new window size. - ASSERT_TRUE(view.OnFrameGenerated(500, 500)); - view.OnFramePresented(); + ASSERT_TRUE(view->OnFrameGenerated(500, 500)); + view->OnFramePresented(); resized_latch.Wait(); } // Verify that an empty frame completes a view resize. TEST(FlutterWindowsViewTest, TestEmptyFrameResizes) { - std::unique_ptr engine = GetTestEngine(); - EngineModifier engine_modifier(engine.get()); + auto windows_proc_table = std::make_shared>(); + std::unique_ptr engine = + GetTestEngine(windows_proc_table); + EngineModifier engine_modifier{engine.get()}; - auto window_binding_handler = - std::make_unique>(); - auto windows_proc_table = std::make_shared(); auto egl_manager = std::make_unique(); auto surface = std::make_unique(); auto resized_surface = std::make_unique(); @@ -895,13 +894,6 @@ TEST(FlutterWindowsViewTest, TestEmptyFrameResizes) { EXPECT_CALL(*resized_surface_ptr, Destroy).WillOnce(Return(true)); - FlutterWindowsView view(std::move(window_binding_handler), - std::move(windows_proc_table)); - ViewModifier view_modifier(&view); - engine_modifier.SetEGLManager(std::move(egl_manager)); - view.SetEngine(engine.get()); - view_modifier.SetSurface(std::move(surface)); - fml::AutoResetWaitableEvent metrics_sent_latch; engine_modifier.embedder_api().SendWindowMetricsEvent = MOCK_ENGINE_PROC( SendWindowMetricsEvent, @@ -911,11 +903,18 @@ TEST(FlutterWindowsViewTest, TestEmptyFrameResizes) { return kSuccess; })); + std::unique_ptr view = engine->CreateView( + std::make_unique>()); + + ViewModifier view_modifier(view.get()); + engine_modifier.SetEGLManager(std::move(egl_manager)); + view_modifier.SetSurface(std::move(surface)); + fml::AutoResetWaitableEvent resized_latch; std::thread([&resized_latch, &view]() { // Start the window resize. This sends the new window metrics // and then blocks until another thread completes the window resize. - EXPECT_TRUE(view.OnWindowSizeChanged(500, 500)); + EXPECT_TRUE(view->OnWindowSizeChanged(500, 500)); resized_latch.Signal(); }).detach(); @@ -923,8 +922,8 @@ TEST(FlutterWindowsViewTest, TestEmptyFrameResizes) { metrics_sent_latch.Wait(); // Complete the window resize by reporting an empty frame. - view.OnEmptyFrameGenerated(); - view.OnFramePresented(); + view->OnEmptyFrameGenerated(); + view->OnFramePresented(); resized_latch.Wait(); } @@ -935,31 +934,28 @@ TEST(FlutterWindowsViewTest, WindowResizeRace) { std::unique_ptr engine = GetTestEngine(); EngineModifier engine_modifier(engine.get()); - auto window_binding_handler = - std::make_unique>(); - auto windows_proc_table = std::make_shared(); auto egl_manager = std::make_unique(); auto surface = std::make_unique(); EXPECT_CALL(*surface.get(), IsValid).WillRepeatedly(Return(true)); EXPECT_CALL(*surface.get(), Destroy).WillOnce(Return(true)); - FlutterWindowsView view(std::move(window_binding_handler), - std::move(windows_proc_table)); - ViewModifier view_modifier(&view); + std::unique_ptr view = engine->CreateView( + std::make_unique>()); + + ViewModifier view_modifier(view.get()); engine_modifier.SetEGLManager(std::move(egl_manager)); view_modifier.SetSurface(std::move(surface)); - view.SetEngine(engine.get()); // Begin a frame. - ASSERT_TRUE(view.OnFrameGenerated(100, 100)); + ASSERT_TRUE(view->OnFrameGenerated(100, 100)); // Inject a window resize between the frame generation and // frame presentation. The new size invalidates the current frame. fml::AutoResetWaitableEvent resized_latch; std::thread([&resized_latch, &view]() { // The resize is never completed. The view times out and returns false. - EXPECT_FALSE(view.OnWindowSizeChanged(500, 500)); + EXPECT_FALSE(view->OnWindowSizeChanged(500, 500)); resized_latch.Signal(); }).detach(); @@ -969,7 +965,7 @@ TEST(FlutterWindowsViewTest, WindowResizeRace) { // Complete the invalidated frame while a resize is pending. Although this // might mean that we presented a frame with the wrong size, this should not // crash the app. - view.OnFramePresented(); + view->OnFramePresented(); } // Window resize should succeed even if the render surface could not be created @@ -978,9 +974,6 @@ TEST(FlutterWindowsViewTest, WindowResizeInvalidSurface) { std::unique_ptr engine = GetTestEngine(); EngineModifier engine_modifier(engine.get()); - auto window_binding_handler = - std::make_unique>(); - auto windows_proc_table = std::make_shared(); auto egl_manager = std::make_unique(); auto surface = std::make_unique(); @@ -988,12 +981,12 @@ TEST(FlutterWindowsViewTest, WindowResizeInvalidSurface) { EXPECT_CALL(*surface.get(), IsValid).WillRepeatedly(Return(false)); EXPECT_CALL(*surface.get(), Destroy).WillOnce(Return(false)); - FlutterWindowsView view(std::move(window_binding_handler), - std::move(windows_proc_table)); - ViewModifier view_modifier(&view); + std::unique_ptr view = engine->CreateView( + std::make_unique>()); + + ViewModifier view_modifier(view.get()); engine_modifier.SetEGLManager(std::move(egl_manager)); view_modifier.SetSurface(std::move(surface)); - view.SetEngine(engine.get()); auto metrics_sent = false; engine_modifier.embedder_api().SendWindowMetricsEvent = MOCK_ENGINE_PROC( @@ -1003,7 +996,7 @@ TEST(FlutterWindowsViewTest, WindowResizeInvalidSurface) { return kSuccess; })); - view.OnWindowSizeChanged(500, 500); + view->OnWindowSizeChanged(500, 500); } // Window resize should succeed even if EGL initialized successfully @@ -1012,17 +1005,14 @@ TEST(FlutterWindowsViewTest, WindowResizeWithoutSurface) { std::unique_ptr engine = GetTestEngine(); EngineModifier modifier(engine.get()); - auto window_binding_handler = - std::make_unique>(); - auto windows_proc_table = std::make_shared(); auto egl_manager = std::make_unique(); EXPECT_CALL(*egl_manager.get(), CreateWindowSurface).Times(0); - FlutterWindowsView view(std::move(window_binding_handler), - std::move(windows_proc_table)); + std::unique_ptr view = engine->CreateView( + std::make_unique>()); + modifier.SetEGLManager(std::move(egl_manager)); - view.SetEngine(engine.get()); auto metrics_sent = false; modifier.embedder_api().SendWindowMetricsEvent = MOCK_ENGINE_PROC( @@ -1032,15 +1022,15 @@ TEST(FlutterWindowsViewTest, WindowResizeWithoutSurface) { return kSuccess; })); - view.OnWindowSizeChanged(500, 500); + view->OnWindowSizeChanged(500, 500); } TEST(FlutterWindowsViewTest, WindowRepaintTests) { std::unique_ptr engine = GetTestEngine(); EngineModifier modifier(engine.get()); - FlutterWindowsView view(std::make_unique(100, 100)); - view.SetEngine(engine.get()); + FlutterWindowsView view(engine.get(), + std::make_unique(100, 100)); bool schedule_frame_called = false; modifier.embedder_api().ScheduleFrame = @@ -1067,15 +1057,13 @@ TEST(FlutterWindowsViewTest, CheckboxNativeState) { return kSuccess; }; - auto window_binding_handler = - std::make_unique>(); - FlutterWindowsView view(std::move(window_binding_handler)); - view.SetEngine(engine.get()); + std::unique_ptr view = engine->CreateView( + std::make_unique>()); // Enable semantics to instantiate accessibility bridge. - view.OnUpdateSemanticsEnabled(true); + view->OnUpdateSemanticsEnabled(true); - auto bridge = view.accessibility_bridge().lock(); + auto bridge = view->accessibility_bridge().lock(); ASSERT_TRUE(bridge); FlutterSemanticsNode2 root{sizeof(FlutterSemanticsNode2), 0}; @@ -1213,15 +1201,13 @@ TEST(FlutterWindowsViewTest, SwitchNativeState) { return kSuccess; }; - auto window_binding_handler = - std::make_unique>(); - FlutterWindowsView view(std::move(window_binding_handler)); - view.SetEngine(engine.get()); + std::unique_ptr view = engine->CreateView( + std::make_unique>()); // Enable semantics to instantiate accessibility bridge. - view.OnUpdateSemanticsEnabled(true); + view->OnUpdateSemanticsEnabled(true); - auto bridge = view.accessibility_bridge().lock(); + auto bridge = view->accessibility_bridge().lock(); ASSERT_TRUE(bridge); FlutterSemanticsNode2 root{sizeof(FlutterSemanticsNode2), 0}; @@ -1332,15 +1318,13 @@ TEST(FlutterWindowsViewTest, TooltipNodeData) { return kSuccess; }; - auto window_binding_handler = - std::make_unique>(); - FlutterWindowsView view(std::move(window_binding_handler)); - view.SetEngine(engine.get()); + std::unique_ptr view = engine->CreateView( + std::make_unique>()); // Enable semantics to instantiate accessibility bridge. - view.OnUpdateSemanticsEnabled(true); + view->OnUpdateSemanticsEnabled(true); - auto bridge = view.accessibility_bridge().lock(); + auto bridge = view->accessibility_bridge().lock(); ASSERT_TRUE(bridge); FlutterSemanticsNode2 root{sizeof(FlutterSemanticsNode2), 0}; @@ -1384,10 +1368,8 @@ TEST(FlutterWindowsViewTest, TooltipNodeData) { // Don't block until the v-blank if it is disabled by the window. // The surface is updated on the platform thread at startup. TEST(FlutterWindowsViewTest, DisablesVSyncAtStartup) { - auto engine = std::make_unique(); - auto window_binding_handler = - std::make_unique>(); auto windows_proc_table = std::make_shared(); + auto engine = std::make_unique(windows_proc_table); auto egl_manager = std::make_unique(); egl::MockContext render_context; auto surface = std::make_unique(); @@ -1403,10 +1385,6 @@ TEST(FlutterWindowsViewTest, DisablesVSyncAtStartup) { .WillOnce(Return(&render_context)); EXPECT_CALL(*surface_ptr, IsValid).WillOnce(Return(true)); - EngineModifier engine_modifier(engine.get()); - FlutterWindowsView view(std::move(window_binding_handler), - std::move(windows_proc_table)); - InSequence s; EXPECT_CALL(*egl_manager.get(), CreateWindowSurface) .WillOnce(Return(std::move(surface))); @@ -1417,19 +1395,20 @@ TEST(FlutterWindowsViewTest, DisablesVSyncAtStartup) { EXPECT_CALL(*engine.get(), Stop).Times(1); EXPECT_CALL(*surface_ptr, Destroy).Times(1); - engine_modifier.SetEGLManager(std::move(egl_manager)); - view.SetEngine(engine.get()); + EngineModifier modifier{engine.get()}; + modifier.SetEGLManager(std::move(egl_manager)); + + std::unique_ptr view = engine->CreateView( + std::make_unique>()); - view.CreateRenderSurface(); + view->CreateRenderSurface(); } // Blocks until the v-blank if it is enabled by the window. // The surface is updated on the platform thread at startup. TEST(FlutterWindowsViewTest, EnablesVSyncAtStartup) { - auto engine = std::make_unique(); - auto window_binding_handler = - std::make_unique>(); auto windows_proc_table = std::make_shared(); + auto engine = std::make_unique(windows_proc_table); auto egl_manager = std::make_unique(); egl::MockContext render_context; auto surface = std::make_unique(); @@ -1444,10 +1423,6 @@ TEST(FlutterWindowsViewTest, EnablesVSyncAtStartup) { .WillOnce(Return(&render_context)); EXPECT_CALL(*surface_ptr, IsValid).WillOnce(Return(true)); - EngineModifier modifier(engine.get()); - FlutterWindowsView view(std::move(window_binding_handler), - std::move(windows_proc_table)); - InSequence s; EXPECT_CALL(*egl_manager.get(), CreateWindowSurface) .WillOnce(Return(std::move(surface))); @@ -1458,19 +1433,20 @@ TEST(FlutterWindowsViewTest, EnablesVSyncAtStartup) { EXPECT_CALL(*engine.get(), Stop).Times(1); EXPECT_CALL(*surface_ptr, Destroy).Times(1); + EngineModifier modifier{engine.get()}; modifier.SetEGLManager(std::move(egl_manager)); - view.SetEngine(engine.get()); - view.CreateRenderSurface(); + std::unique_ptr view = engine->CreateView( + std::make_unique>()); + + view->CreateRenderSurface(); } // Don't block until the v-blank if it is disabled by the window. // The surface is updated on the raster thread if the engine is running. TEST(FlutterWindowsViewTest, DisablesVSyncAfterStartup) { - auto engine = std::make_unique(); - auto window_binding_handler = - std::make_unique>(); auto windows_proc_table = std::make_shared(); + auto engine = std::make_unique(windows_proc_table); auto egl_manager = std::make_unique(); egl::MockContext render_context; auto surface = std::make_unique(); @@ -1484,10 +1460,6 @@ TEST(FlutterWindowsViewTest, DisablesVSyncAfterStartup) { .WillOnce(Return(&render_context)); EXPECT_CALL(*surface_ptr, IsValid).WillOnce(Return(true)); - EngineModifier modifier(engine.get()); - FlutterWindowsView view(std::move(window_binding_handler), - std::move(windows_proc_table)); - InSequence s; EXPECT_CALL(*egl_manager.get(), CreateWindowSurface) .WillOnce(Return(std::move(surface))); @@ -1502,19 +1474,20 @@ TEST(FlutterWindowsViewTest, DisablesVSyncAfterStartup) { EXPECT_CALL(*engine.get(), Stop).Times(1); EXPECT_CALL(*surface_ptr, Destroy).Times(1); + EngineModifier modifier{engine.get()}; modifier.SetEGLManager(std::move(egl_manager)); - view.SetEngine(engine.get()); - view.CreateRenderSurface(); + std::unique_ptr view = engine->CreateView( + std::make_unique>()); + + view->CreateRenderSurface(); } // Blocks until the v-blank if it is enabled by the window. // The surface is updated on the raster thread if the engine is running. TEST(FlutterWindowsViewTest, EnablesVSyncAfterStartup) { - auto engine = std::make_unique(); - auto window_binding_handler = - std::make_unique>(); auto windows_proc_table = std::make_shared(); + auto engine = std::make_unique(windows_proc_table); auto egl_manager = std::make_unique(); egl::MockContext render_context; auto surface = std::make_unique(); @@ -1529,10 +1502,6 @@ TEST(FlutterWindowsViewTest, EnablesVSyncAfterStartup) { .WillOnce(Return(&render_context)); EXPECT_CALL(*surface_ptr, IsValid).WillOnce(Return(true)); - EngineModifier modifier(engine.get()); - FlutterWindowsView view(std::move(window_binding_handler), - std::move(windows_proc_table)); - InSequence s; EXPECT_CALL(*egl_manager.get(), CreateWindowSurface) .WillOnce(Return(std::move(surface))); @@ -1548,20 +1517,21 @@ TEST(FlutterWindowsViewTest, EnablesVSyncAfterStartup) { EXPECT_CALL(*engine.get(), Stop).Times(1); EXPECT_CALL(*surface_ptr, Destroy).Times(1); + EngineModifier modifier{engine.get()}; modifier.SetEGLManager(std::move(egl_manager)); - view.SetEngine(engine.get()); - view.CreateRenderSurface(); + std::unique_ptr view = engine->CreateView( + std::make_unique>()); + + view->CreateRenderSurface(); } // Desktop Window Manager composition can be disabled on Windows 7. // If this happens, the app must synchronize with the vsync to prevent // screen tearing. TEST(FlutterWindowsViewTest, UpdatesVSyncOnDwmUpdates) { - auto engine = std::make_unique(); - auto window_binding_handler = - std::make_unique>(); auto windows_proc_table = std::make_shared(); + auto engine = std::make_unique(windows_proc_table); auto egl_manager = std::make_unique(); egl::MockContext render_context; auto surface = std::make_unique(); @@ -1584,11 +1554,6 @@ TEST(FlutterWindowsViewTest, UpdatesVSyncOnDwmUpdates) { EXPECT_CALL(*surface_ptr, IsValid).WillRepeatedly(Return(true)); - EngineModifier engine_modifier(engine.get()); - FlutterWindowsView view(std::move(window_binding_handler), - std::move(windows_proc_table)); - ViewModifier view_modifier(&view); - InSequence s; EXPECT_CALL(*surface_ptr, MakeCurrent).WillOnce(Return(true)); EXPECT_CALL(*surface_ptr, SetVSyncEnabled(true)).WillOnce(Return(true)); @@ -1601,12 +1566,16 @@ TEST(FlutterWindowsViewTest, UpdatesVSyncOnDwmUpdates) { EXPECT_CALL(*engine.get(), Stop).Times(1); EXPECT_CALL(*surface_ptr, Destroy).Times(1); + EngineModifier engine_modifier{engine.get()}; engine_modifier.SetEGLManager(std::move(egl_manager)); - view.SetEngine(engine.get()); + + std::unique_ptr view = engine->CreateView( + std::make_unique>()); + ViewModifier view_modifier{view.get()}; view_modifier.SetSurface(std::move(surface)); - view.GetEngine()->OnDwmCompositionChanged(); - view.GetEngine()->OnDwmCompositionChanged(); + engine->OnDwmCompositionChanged(); + engine->OnDwmCompositionChanged(); } } // namespace testing diff --git a/shell/platform/windows/keyboard_unittests.cc b/shell/platform/windows/keyboard_unittests.cc index 7265dd5d2dbbd..fff6b6e7dcc07 100644 --- a/shell/platform/windows/keyboard_unittests.cc +++ b/shell/platform/windows/keyboard_unittests.cc @@ -336,9 +336,11 @@ typedef struct { // A FlutterWindowsView that spies on text. class TestFlutterWindowsView : public FlutterWindowsView { public: - TestFlutterWindowsView(std::function on_key_call, - std::unique_ptr window) - : on_key_call_(on_key_call), FlutterWindowsView(std::move(window)) {} + TestFlutterWindowsView(FlutterWindowsEngine* engine, + std::unique_ptr window, + std::function on_key_call) + : on_key_call_(on_key_call), + FlutterWindowsView(engine, std::move(window)) {} void OnText(const std::u16string& text) override { on_key_call_(KeyCall{ @@ -363,11 +365,16 @@ class KeyboardTester { map_virtual_key_layout_(LayoutDefault) { engine_ = GetTestEngine(context); view_ = std::make_unique( - [this](KeyCall key_call) { key_calls.push_back(key_call); }, + engine_.get(), // The WindowBindingHandler is used for window size and such, and // doesn't affect keyboard. - std::make_unique<::testing::NiceMock>()); - view_->SetEngine(engine_.get()); + std::make_unique<::testing::NiceMock>(), + [this](KeyCall key_call) { key_calls.push_back(key_call); }); + + EngineModifier modifier{engine_.get()}; + modifier.SetImplicitView(view_.get()); + modifier.InitializeKeyboard(); + window_ = std::make_unique( view_.get(), [this](UINT virtual_key) -> SHORT { return map_virtual_key_layout_(virtual_key, MAPVK_VK_TO_CHAR); diff --git a/shell/platform/windows/platform_handler_unittests.cc b/shell/platform/windows/platform_handler_unittests.cc index 35cb70368c1ec..ca99d1779a136 100644 --- a/shell/platform/windows/platform_handler_unittests.cc +++ b/shell/platform/windows/platform_handler_unittests.cc @@ -9,6 +9,7 @@ #include "flutter/fml/macros.h" #include "flutter/shell/platform/common/json_method_codec.h" #include "flutter/shell/platform/windows/flutter_windows_view.h" +#include "flutter/shell/platform/windows/testing/engine_modifier.h" #include "flutter/shell/platform/windows/testing/flutter_windows_engine_builder.h" #include "flutter/shell/platform/windows/testing/mock_window_binding_handler.h" #include "flutter/shell/platform/windows/testing/test_binary_messenger.h" @@ -152,10 +153,13 @@ class PlatformHandlerTest : public WindowsTest { FlutterWindowsEngineBuilder builder{GetContext()}; auto window = std::make_unique>(); - view_ = std::make_unique(std::move(window)); + engine_ = builder.Build(); + view_ = + std::make_unique(engine_.get(), std::move(window)); - engine_->SetView(view_.get()); + EngineModifier modifier{engine_.get()}; + modifier.SetImplicitView(view_.get()); } private: diff --git a/shell/platform/windows/testing/engine_modifier.h b/shell/platform/windows/testing/engine_modifier.h index e9fd3b8833ec6..d070dc10993fe 100644 --- a/shell/platform/windows/testing/engine_modifier.h +++ b/shell/platform/windows/testing/engine_modifier.h @@ -37,6 +37,10 @@ class EngineModifier { engine_->egl_manager_ = std::move(egl_manager); } + // Override the engine's implicit view. This is the "default" view + // that Flutter apps render to. + void SetImplicitView(FlutterWindowsView* view) { engine_->view_ = view; } + /// Reset the start_time field that is used to align vsync events. void SetStartTime(uint64_t start_time_nanos) { engine_->start_time_ = std::chrono::nanoseconds(start_time_nanos); @@ -64,6 +68,10 @@ class EngineModifier { // restart. This resets the keyboard's state if it exists. void Restart() { engine_->OnPreEngineRestart(); } + // Initialize they keyboard and text input subsystems or reset them them if + // they are already initialized. + void InitializeKeyboard() { engine_->InitializeKeyboard(); } + void SetLifecycleManager(std::unique_ptr&& handler) { engine_->lifecycle_manager_ = std::move(handler); } diff --git a/shell/platform/windows/text_input_plugin_unittest.cc b/shell/platform/windows/text_input_plugin_unittest.cc index de8104454da31..2e078cc086448 100644 --- a/shell/platform/windows/text_input_plugin_unittest.cc +++ b/shell/platform/windows/text_input_plugin_unittest.cc @@ -11,6 +11,7 @@ #include "flutter/shell/platform/common/json_message_codec.h" #include "flutter/shell/platform/common/json_method_codec.h" #include "flutter/shell/platform/windows/flutter_windows_view.h" +#include "flutter/shell/platform/windows/testing/engine_modifier.h" #include "flutter/shell/platform/windows/testing/flutter_windows_engine_builder.h" #include "flutter/shell/platform/windows/testing/mock_window_binding_handler.h" #include "flutter/shell/platform/windows/testing/test_binary_messenger.h" @@ -104,8 +105,9 @@ static std::unique_ptr EncodedEditingState( class MockFlutterWindowsView : public FlutterWindowsView { public: - MockFlutterWindowsView(std::unique_ptr window) - : FlutterWindowsView(std::move(window)) {} + MockFlutterWindowsView(FlutterWindowsEngine* engine, + std::unique_ptr window) + : FlutterWindowsView(engine, std::move(window)) {} virtual ~MockFlutterWindowsView() = default; MOCK_METHOD(void, OnCursorRectUpdated, (const Rect&), (override)); @@ -143,9 +145,11 @@ class TextInputPluginTest : public WindowsTest { EXPECT_CALL(*window, GetWindowHandle).WillRepeatedly(Return(nullptr)); engine_ = builder.Build(); - view_ = std::make_unique(std::move(window)); + view_ = std::make_unique(engine_.get(), + std::move(window)); - engine_->SetView(view_.get()); + EngineModifier modifier{engine_.get()}; + modifier.SetImplicitView(view_.get()); } private: From 9d522dc3f6380e326d67e652faeb5783fb10fd20 Mon Sep 17 00:00:00 2001 From: Loic Sharma Date: Fri, 16 Feb 2024 10:29:19 -0800 Subject: [PATCH 2/2] Format --- shell/platform/windows/flutter_window_unittests.cc | 2 +- .../platform/windows/flutter_windows_view_unittests.cc | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/shell/platform/windows/flutter_window_unittests.cc b/shell/platform/windows/flutter_window_unittests.cc index 4e4893039a619..7589e1e89cc76 100644 --- a/shell/platform/windows/flutter_window_unittests.cc +++ b/shell/platform/windows/flutter_window_unittests.cc @@ -322,7 +322,7 @@ TEST_F(FlutterWindowTest, AlertNode) { .WillRepeatedly(Return(nullptr)); EXPECT_CALL(*win32window.get(), OnWindowStateEvent).Times(AnyNumber()); EXPECT_CALL(*win32window.get(), GetWindowHandle).Times(AnyNumber()); - MockFlutterWindowsView view(engine.get(), std::move(win32window)); + MockFlutterWindowsView view{engine.get(), std::move(win32window)}; std::wstring message = L"Test alert"; EXPECT_CALL(view, NotifyWinEventWrapper(_, ax::mojom::Event::kAlert)) .Times(1); diff --git a/shell/platform/windows/flutter_windows_view_unittests.cc b/shell/platform/windows/flutter_windows_view_unittests.cc index 6ea1ee286baa9..d8810c5066d7b 100644 --- a/shell/platform/windows/flutter_windows_view_unittests.cc +++ b/shell/platform/windows/flutter_windows_view_unittests.cc @@ -906,7 +906,7 @@ TEST(FlutterWindowsViewTest, TestEmptyFrameResizes) { std::unique_ptr view = engine->CreateView( std::make_unique>()); - ViewModifier view_modifier(view.get()); + ViewModifier view_modifier{view.get()}; engine_modifier.SetEGLManager(std::move(egl_manager)); view_modifier.SetSurface(std::move(surface)); @@ -943,7 +943,7 @@ TEST(FlutterWindowsViewTest, WindowResizeRace) { std::unique_ptr view = engine->CreateView( std::make_unique>()); - ViewModifier view_modifier(view.get()); + ViewModifier view_modifier{view.get()}; engine_modifier.SetEGLManager(std::move(egl_manager)); view_modifier.SetSurface(std::move(surface)); @@ -984,7 +984,7 @@ TEST(FlutterWindowsViewTest, WindowResizeInvalidSurface) { std::unique_ptr view = engine->CreateView( std::make_unique>()); - ViewModifier view_modifier(view.get()); + ViewModifier view_modifier{view.get()}; engine_modifier.SetEGLManager(std::move(egl_manager)); view_modifier.SetSurface(std::move(surface)); @@ -1029,8 +1029,8 @@ TEST(FlutterWindowsViewTest, WindowRepaintTests) { std::unique_ptr engine = GetTestEngine(); EngineModifier modifier(engine.get()); - FlutterWindowsView view(engine.get(), - std::make_unique(100, 100)); + FlutterWindowsView view{engine.get(), + std::make_unique(100, 100)}; bool schedule_frame_called = false; modifier.embedder_api().ScheduleFrame =