diff --git a/shell/platform/windows/flutter_windows_view.cc b/shell/platform/windows/flutter_windows_view.cc index e0ccb8cab6eab..0e5e5541e5555 100644 --- a/shell/platform/windows/flutter_windows_view.cc +++ b/shell/platform/windows/flutter_windows_view.cc @@ -13,16 +13,21 @@ namespace flutter { +namespace { +// The maximum duration to block the platform thread for while waiting +// for a window resize operation to complete. +constexpr std::chrono::milliseconds kWindowResizeTimeout{100}; + /// Returns true if the surface will be updated as part of the resize process. /// /// This is called on window resize to determine if the platform thread needs /// to be blocked until the frame with the right size has been rendered. It /// should be kept in-sync with how the engine deals with a new surface request /// as seen in `CreateOrUpdateSurface` in `GPUSurfaceGL`. -static bool SurfaceWillUpdate(size_t cur_width, - size_t cur_height, - size_t target_width, - size_t target_height) { +bool SurfaceWillUpdate(size_t cur_width, + size_t cur_height, + size_t target_width, + size_t target_height) { // TODO (https://github.com/flutter/flutter/issues/65061) : Avoid special // handling for zero dimensions. bool non_zero_target_dims = target_height > 0 && target_width > 0; @@ -30,6 +35,7 @@ static bool SurfaceWillUpdate(size_t cur_width, (cur_height != target_height) || (cur_width != target_width); return non_zero_target_dims && not_same_size; } +} // namespace FlutterWindowsView::FlutterWindowsView( std::unique_ptr window_binding) { @@ -150,9 +156,10 @@ void FlutterWindowsView::OnWindowSizeChanged(size_t width, size_t height) { // Block the platform thread until: // 1. GetFrameBufferId is called with the right frame size. // 2. Any pending SwapBuffers calls have been invoked. - resize_cv_.wait(lock, [&resize_status = resize_status_] { - return resize_status == ResizeState::kDone; - }); + resize_cv_.wait_for(lock, kWindowResizeTimeout, + [&resize_status = resize_status_] { + return resize_status == ResizeState::kDone; + }); } } diff --git a/shell/platform/windows/flutter_windows_view_unittests.cc b/shell/platform/windows/flutter_windows_view_unittests.cc index 006d4eaadb887..a263c215cc729 100644 --- a/shell/platform/windows/flutter_windows_view_unittests.cc +++ b/shell/platform/windows/flutter_windows_view_unittests.cc @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -546,5 +547,35 @@ TEST(FlutterWindowsViewTest, AccessibilityHitTesting) { EXPECT_EQ(varchild.pdispVal, node3_delegate->GetNativeViewAccessible()); } +TEST(FlutterWindowsViewTest, WindowResizeTests) { + std::unique_ptr engine = GetTestEngine(); + EngineModifier modifier(engine.get()); + + auto window_binding_handler = + std::make_unique<::testing::NiceMock>(); + + FlutterWindowsView view(std::move(window_binding_handler)); + view.SetEngine(std::move(engine)); + + bool send_window_metrics_event_called = false; + modifier.embedder_api().SendWindowMetricsEvent = MOCK_ENGINE_PROC( + SendWindowMetricsEvent, + ([&send_window_metrics_event_called]( + auto engine, const FlutterWindowMetricsEvent* even) { + send_window_metrics_event_called = true; + return kSuccess; + })); + + std::promise resize_completed; + std::thread([&resize_completed, &view]() { + view.OnWindowSizeChanged(500, 500); + resize_completed.set_value(true); + }).detach(); + + auto result = resize_completed.get_future().wait_for(std::chrono::seconds(1)); + EXPECT_EQ(std::future_status::ready, result); + EXPECT_TRUE(send_window_metrics_event_called); +} + } // namespace testing } // namespace flutter