diff --git a/packages/desktop_multi_window/windows/flutter_window.cc b/packages/desktop_multi_window/windows/flutter_window.cc index b91a6e90..21fd7d66 100644 --- a/packages/desktop_multi_window/windows/flutter_window.cc +++ b/packages/desktop_multi_window/windows/flutter_window.cc @@ -18,6 +18,9 @@ bool FlutterWindow::OnCreate() { RECT frame = GetClientArea(); flutter::DartProject project(L"data"); + // Avoid Windows fullscreen freezes in recent Flutter engines when + // window_manager changes styles from a platform-channel call. + project.set_ui_thread_policy(flutter::UIThreadPolicy::RunOnSeparateThread); std::vector entrypoint_args = {"multi_window", id_, window_argument_}; project.set_dart_entrypoint_arguments(entrypoint_args); diff --git a/packages/desktop_multi_window/windows/win32_window.cpp b/packages/desktop_multi_window/windows/win32_window.cpp index df4f92a2..ba63631d 100644 --- a/packages/desktop_multi_window/windows/win32_window.cpp +++ b/packages/desktop_multi_window/windows/win32_window.cpp @@ -18,6 +18,8 @@ namespace { constexpr const wchar_t kWindowClassName[] = L"FLUTTER_MULTI_WINDOW_WIN32_WINDOW"; +constexpr UINT kResizeChildContentMessage = WM_APP + 0x3D1; + /// Registry key for app theme preference. /// /// A value of 0 indicates apps should use dark mode. A non-zero or missing @@ -207,18 +209,21 @@ Win32Window::MessageHandler(HWND hwnd, SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + QueueChildContentResize(); return 0; } case WM_SIZE: { - RECT rect = GetClientArea(); - if (child_content_ != nullptr) { - // Size and position the child window. - MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, - rect.bottom - rect.top, TRUE); - } + ResizeChildContent(); return 0; } + case WM_WINDOWPOSCHANGED: + QueueChildContentResize(); + break; + case kResizeChildContentMessage: + child_resize_pending_ = false; + ResizeChildContent(); + return 0; case WM_ACTIVATE: if (child_content_ != nullptr) { @@ -254,10 +259,7 @@ Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { void Win32Window::SetChildContent(HWND content) { child_content_ = content; SetParent(content, window_handle_); - RECT frame = GetClientArea(); - - MoveWindow(content, frame.left, frame.top, frame.right - frame.left, - frame.bottom - frame.top, true); + ResizeChildContent(); SetFocus(child_content_); } @@ -276,6 +278,26 @@ void Win32Window::SetQuitOnClose(bool quit_on_close) { quit_on_close_ = quit_on_close; } +void Win32Window::QueueChildContentResize() { + if (window_handle_ == nullptr || child_content_ == nullptr || + child_resize_pending_) { + return; + } + child_resize_pending_ = true; + if (!PostMessage(window_handle_, kResizeChildContentMessage, 0, 0)) { + child_resize_pending_ = false; + } +} + +void Win32Window::ResizeChildContent() { + if (child_content_ == nullptr) { + return; + } + RECT frame = GetClientArea(); + MoveWindow(child_content_, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, TRUE); +} + bool Win32Window::OnCreate() { // No-op; provided for subclasses. return true; diff --git a/packages/desktop_multi_window/windows/win32_window.h b/packages/desktop_multi_window/windows/win32_window.h index e901dde6..38cc22f2 100644 --- a/packages/desktop_multi_window/windows/win32_window.h +++ b/packages/desktop_multi_window/windows/win32_window.h @@ -90,7 +90,11 @@ class Win32Window { // Update the window frame's theme to match the system theme. static void UpdateTheme(HWND const window); + void QueueChildContentResize(); + void ResizeChildContent(); + bool quit_on_close_ = false; + bool child_resize_pending_ = false; // window handle for top level window. HWND window_handle_ = nullptr;