From 4372c1ce7b57a94a0b52d757db2fcbfd5bcb10ef Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Wed, 22 Apr 2026 14:47:48 +0800 Subject: [PATCH] refactor(new_editor): centralize window lifecycle ownership --- new_editor/CMakeLists.txt | 1 + new_editor/app/Platform/Win32/EditorWindow.h | 2 + .../app/Platform/Win32/EditorWindowManager.h | 2 + .../WindowManager/EditorWindowHostRuntime.cpp | 99 +------ .../WindowManager/EditorWindowHostRuntime.h | 8 +- .../EditorWindowLifecycleCoordinator.cpp | 253 ++++++++++++++++++ .../EditorWindowLifecycleCoordinator.h | 34 +++ .../WindowManager/EditorWindowManager.cpp | 11 +- .../EditorWindowMessageDispatcher.cpp | 42 +-- .../EditorWindowMessageDispatcher.h | 2 + .../EditorWindowWorkspaceCoordinator.cpp | 34 +-- .../EditorWindowWorkspaceCoordinator.h | 5 +- 12 files changed, 337 insertions(+), 156 deletions(-) create mode 100644 new_editor/app/Platform/Win32/WindowManager/EditorWindowLifecycleCoordinator.cpp create mode 100644 new_editor/app/Platform/Win32/WindowManager/EditorWindowLifecycleCoordinator.h diff --git a/new_editor/CMakeLists.txt b/new_editor/CMakeLists.txt index eeff30bb..c06e6139 100644 --- a/new_editor/CMakeLists.txt +++ b/new_editor/CMakeLists.txt @@ -275,6 +275,7 @@ if(XCENGINE_BUILD_XCUI_EDITOR_APP) app/Platform/Win32/EditorWindowRuntimeController.cpp app/Platform/Win32/Win32SystemInteractionHost.cpp app/Platform/Win32/WindowManager/EditorWindowHostRuntime.cpp + app/Platform/Win32/WindowManager/EditorWindowLifecycleCoordinator.cpp app/Platform/Win32/WindowManager/EditorWindowManager.cpp app/Platform/Win32/WindowManager/EditorWindowMessageDispatcher.cpp app/Platform/Win32/WindowManager/EditorWindowWorkspaceCoordinator.cpp diff --git a/new_editor/app/Platform/Win32/EditorWindow.h b/new_editor/app/Platform/Win32/EditorWindow.h index b571ad1f..cea1f14b 100644 --- a/new_editor/app/Platform/Win32/EditorWindow.h +++ b/new_editor/app/Platform/Win32/EditorWindow.h @@ -66,6 +66,7 @@ class EditorWindowFrameDriver; class EditorWindowFrameOrchestrator; class EditorWindowHostRuntime; class EditorWindowInputController; +class EditorWindowLifecycleCoordinator; class EditorWindowMessageDispatcher; class EditorWindowRuntimeController; class EditorWindowWorkspaceCoordinator; @@ -100,6 +101,7 @@ private: friend class EditorWindowFrameDriver; friend class EditorWindowHostRuntime; friend class EditorWindowMessageDispatcher; + friend class EditorWindowLifecycleCoordinator; friend class EditorWindowWorkspaceCoordinator; bool IsRenderReady() const; diff --git a/new_editor/app/Platform/Win32/EditorWindowManager.h b/new_editor/app/Platform/Win32/EditorWindowManager.h index 3e0d6b7e..aa47abb5 100644 --- a/new_editor/app/Platform/Win32/EditorWindowManager.h +++ b/new_editor/app/Platform/Win32/EditorWindowManager.h @@ -27,6 +27,7 @@ namespace XCEngine::UI::Editor::App { class EditorContext; class EditorWindow; class EditorWindowHostRuntime; +class EditorWindowLifecycleCoordinator; class EditorWindowWorkspaceCoordinator; struct EditorWindowPanelTransferRequest; struct EditorWindowFrameTransferRequests; @@ -89,6 +90,7 @@ public: private: std::unique_ptr m_hostRuntime = {}; + std::unique_ptr m_lifecycleCoordinator = {}; std::unique_ptr m_workspaceCoordinator = {}; }; diff --git a/new_editor/app/Platform/Win32/WindowManager/EditorWindowHostRuntime.cpp b/new_editor/app/Platform/Win32/WindowManager/EditorWindowHostRuntime.cpp index 955c3222..9c86f62a 100644 --- a/new_editor/app/Platform/Win32/WindowManager/EditorWindowHostRuntime.cpp +++ b/new_editor/app/Platform/Win32/WindowManager/EditorWindowHostRuntime.cpp @@ -4,6 +4,7 @@ #include "Composition/EditorContext.h" #include "Platform/Win32/EditorWindow.h" #include "Platform/Win32/EditorWindowFrameDriver.h" +#include "Platform/Win32/WindowManager/EditorWindowLifecycleCoordinator.h" #include "Platform/Win32/WindowManager/EditorWindowWorkspaceCoordinator.h" #include @@ -109,8 +110,7 @@ EditorWindow* EditorWindowHostRuntime::CreateEditorWindow( auto failWindowInitialization = [&](std::string_view message) { LogRuntimeTrace("window", std::string(message)); - DestroyEditorWindow(*rawWindow); - eraseRawWindow(); + m_lifecycleCoordinator->AbortUnregisteredWindow(*rawWindow); return static_cast(nullptr); }; @@ -150,72 +150,21 @@ EditorWindow* EditorWindowHostRuntime::CreateEditorWindow( return rawWindow; } +void EditorWindowHostRuntime::BindLifecycleCoordinator( + EditorWindowLifecycleCoordinator& lifecycleCoordinator) { + m_lifecycleCoordinator = &lifecycleCoordinator; +} + void EditorWindowHostRuntime::HandlePendingNativeWindowCreated(HWND hwnd) { if (m_pendingCreateWindow != nullptr && !m_pendingCreateWindow->HasHwnd()) { m_pendingCreateWindow->AttachHwnd(hwnd); } } -void EditorWindowHostRuntime::Shutdown() { - for (const std::unique_ptr& window : m_windows) { - if (window != nullptr) { - DestroyEditorWindow(*window); - } - } - m_windows.clear(); - m_pendingCreateWindow = nullptr; -} - bool EditorWindowHostRuntime::HasWindows() const { return !m_windows.empty(); } -void EditorWindowHostRuntime::DestroyEditorWindow(EditorWindow& window) { - const HWND hwnd = window.GetHwnd(); - LogRuntimeTrace( - "window-close", - "DestroyEditorWindow begin windowId='" + std::string(window.GetWindowId()) + - "' hwnd=" + DescribeHwnd(hwnd) + - " primary=" + (window.IsPrimary() ? "1" : "0") + - " closing=" + (window.IsClosing() ? "1" : "0") + - " host=" + DescribeHostWindows(m_windows)); - window.ForceReleasePointerCapture(); - - window.Shutdown(); - if (hwnd != nullptr && IsWindow(hwnd)) { - DestroyWindow(hwnd); - } - window.MarkDestroyed(); - LogRuntimeTrace( - "window-close", - "DestroyEditorWindow end windowId='" + std::string(window.GetWindowId()) + - "' host=" + DescribeHostWindows(m_windows)); -} - -void EditorWindowHostRuntime::DestroyClosedWindows() { - for (auto it = m_windows.begin(); it != m_windows.end();) { - EditorWindow* const window = it->get(); - if (window == nullptr || window->GetHwnd() != nullptr) { - ++it; - continue; - } - - if (m_pendingCreateWindow == window) { - m_pendingCreateWindow = nullptr; - } - - LogRuntimeTrace( - "window-close", - "DestroyClosedWindows reap begin windowId='" + std::string(window->GetWindowId()) + - "' hostBefore=" + DescribeHostWindows(m_windows)); - window->Shutdown(); - it = m_windows.erase(it); - LogRuntimeTrace( - "window-close", - "DestroyClosedWindows reap end hostAfter=" + DescribeHostWindows(m_windows)); - } -} - void EditorWindowHostRuntime::RenderAllWindows( bool globalTabDragActive, EditorWindowWorkspaceCoordinator& workspaceCoordinator) { @@ -263,40 +212,6 @@ void EditorWindowHostRuntime::RenderAllWindows( } } -void EditorWindowHostRuntime::HandleDestroyedWindow(EditorWindow& window, bool destroyedPrimary) { - LogRuntimeTrace( - "window-close", - "HandleDestroyedWindow begin windowId='" + std::string(window.GetWindowId()) + - "' destroyedPrimary=" + (destroyedPrimary ? "1" : "0") + - " hostBefore=" + DescribeHostWindows(m_windows)); - window.MarkDestroyed(); - if (!destroyedPrimary) { - LogRuntimeTrace( - "window-close", - "HandleDestroyedWindow end windowId='" + std::string(window.GetWindowId()) + - "' no primary cascade hostAfter=" + DescribeHostWindows(m_windows)); - return; - } - - for (const std::unique_ptr& otherWindow : m_windows) { - if (otherWindow != nullptr && - otherWindow.get() != &window && - otherWindow->GetHwnd() != nullptr && - !otherWindow->IsClosing()) { - otherWindow->MarkClosing(); - LogRuntimeTrace( - "window-close", - "HandleDestroyedWindow posting WM_CLOSE to windowId='" + - std::string(otherWindow->GetWindowId()) + "'"); - PostMessageW(otherWindow->GetHwnd(), WM_CLOSE, 0, 0); - } - } - LogRuntimeTrace( - "window-close", - "HandleDestroyedWindow end windowId='" + std::string(window.GetWindowId()) + - "' hostAfter=" + DescribeHostWindows(m_windows)); -} - EditorWindow* EditorWindowHostRuntime::FindWindow(HWND hwnd) { if (hwnd == nullptr) { return nullptr; diff --git a/new_editor/app/Platform/Win32/WindowManager/EditorWindowHostRuntime.h b/new_editor/app/Platform/Win32/WindowManager/EditorWindowHostRuntime.h index 373938ff..ee2e8d51 100644 --- a/new_editor/app/Platform/Win32/WindowManager/EditorWindowHostRuntime.h +++ b/new_editor/app/Platform/Win32/WindowManager/EditorWindowHostRuntime.h @@ -11,6 +11,7 @@ namespace XCEngine::UI::Editor::App { class EditorContext; class EditorWindow; +class EditorWindowLifecycleCoordinator; class EditorWindowWorkspaceCoordinator; class EditorWindowHostRuntime final { @@ -26,8 +27,8 @@ public: EditorWindow* CreateEditorWindow( UIEditorWorkspaceController workspaceController, const CreateParams& params); + void BindLifecycleCoordinator(EditorWindowLifecycleCoordinator& lifecycleCoordinator); void HandlePendingNativeWindowCreated(HWND hwnd); - void Shutdown(); EditorWindow* FindWindow(HWND hwnd); const EditorWindow* FindWindow(HWND hwnd) const; @@ -37,11 +38,9 @@ public: const EditorWindow* FindPrimaryWindow() const; bool HasWindows() const; - void DestroyClosedWindows(); void RenderAllWindows( bool globalTabDragActive, EditorWindowWorkspaceCoordinator& workspaceCoordinator); - void HandleDestroyedWindow(EditorWindow& window, bool destroyedPrimary); EditorContext& GetEditorContext() { return m_editorContext; @@ -70,13 +69,14 @@ public: void LogRuntimeTrace(std::string_view channel, std::string_view message) const; private: - void DestroyEditorWindow(EditorWindow& window); + friend class EditorWindowLifecycleCoordinator; EditorWindowHostConfig m_hostConfig = {}; std::filesystem::path m_repoRoot = {}; EditorContext& m_editorContext; std::vector> m_windows = {}; EditorWindow* m_pendingCreateWindow = nullptr; + EditorWindowLifecycleCoordinator* m_lifecycleCoordinator = nullptr; }; } // namespace XCEngine::UI::Editor::App diff --git a/new_editor/app/Platform/Win32/WindowManager/EditorWindowLifecycleCoordinator.cpp b/new_editor/app/Platform/Win32/WindowManager/EditorWindowLifecycleCoordinator.cpp new file mode 100644 index 00000000..3e2e43ba --- /dev/null +++ b/new_editor/app/Platform/Win32/WindowManager/EditorWindowLifecycleCoordinator.cpp @@ -0,0 +1,253 @@ +#include "Platform/Win32/WindowManager/EditorWindowLifecycleCoordinator.h" + +#include "Platform/Win32/EditorWindow.h" +#include "Platform/Win32/WindowManager/EditorWindowHostRuntime.h" +#include "Platform/Win32/WindowManager/EditorWindowWorkspaceCoordinator.h" + +#include +#include +#include +#include + +namespace XCEngine::UI::Editor::App { + +namespace { + +std::string DescribeHwnd(HWND hwnd) { + std::ostringstream stream = {}; + stream << "0x" << std::hex << std::uppercase + << reinterpret_cast(hwnd); + return stream.str(); +} + +std::string DescribeHostWindows( + const std::vector>& windows) { + std::ostringstream stream = {}; + stream << "count=" << windows.size() << " ["; + bool first = true; + for (const std::unique_ptr& window : windows) { + if (!first) { + stream << ", "; + } + first = false; + if (window == nullptr) { + stream << ""; + continue; + } + + stream << window->GetWindowId() + << "{hwnd=" << DescribeHwnd(window->GetHwnd()) + << ",primary=" << (window->IsPrimary() ? '1' : '0') + << ",closing=" << (window->IsClosing() ? '1' : '0') + << '}'; + } + stream << ']'; + return stream.str(); +} + +} // namespace + +EditorWindowLifecycleCoordinator::EditorWindowLifecycleCoordinator( + EditorWindowHostRuntime& hostRuntime, + EditorWindowWorkspaceCoordinator& workspaceCoordinator) + : m_hostRuntime(hostRuntime), + m_workspaceCoordinator(workspaceCoordinator) {} + +EditorWindowLifecycleCoordinator::~EditorWindowLifecycleCoordinator() = default; + +void EditorWindowLifecycleCoordinator::PostCloseRequest(EditorWindow& window) { + const HWND hwnd = window.GetHwnd(); + if (!window.IsClosing()) { + window.MarkClosing(); + } + + if (hwnd == nullptr || !IsWindow(hwnd)) { + ShutdownRuntimeIfNeeded(window); + window.MarkDestroyed(); + return; + } + + LogRuntimeTrace( + "window-close", + "PostCloseRequest windowId='" + std::string(window.GetWindowId()) + + "' hwnd=" + DescribeHwnd(hwnd) + + " primary=" + (window.IsPrimary() ? "1" : "0") + + " host=" + DescribeHostWindows(m_hostRuntime.GetWindows())); + PostMessageW(hwnd, WM_CLOSE, 0, 0); +} + +void EditorWindowLifecycleCoordinator::ExecuteCloseRequest(EditorWindow& window) { + const HWND hwnd = window.GetHwnd(); + LogRuntimeTrace( + "window-close", + "ExecuteCloseRequest begin windowId='" + std::string(window.GetWindowId()) + + "' hwnd=" + DescribeHwnd(hwnd) + + " primary=" + (window.IsPrimary() ? "1" : "0") + + " closingBefore=" + (window.IsClosing() ? "1" : "0") + + " workspace=" + m_workspaceCoordinator.DescribeWindowSet() + + " host=" + DescribeHostWindows(m_hostRuntime.GetWindows())); + + if (!window.IsClosing()) { + window.MarkClosing(); + } + + ShutdownRuntimeIfNeeded(window); + + if (hwnd != nullptr && IsWindow(hwnd)) { + DestroyWindow(hwnd); + } else { + window.MarkDestroyed(); + } + + LogRuntimeTrace( + "window-close", + "ExecuteCloseRequest end windowId='" + std::string(window.GetWindowId()) + + "' host=" + DescribeHostWindows(m_hostRuntime.GetWindows())); +} + +void EditorWindowLifecycleCoordinator::HandleNativeWindowDestroyed(EditorWindow& window) { + const bool destroyedPrimary = + m_workspaceCoordinator.IsPrimaryWindowId(window.GetWindowId()); + LogRuntimeTrace( + "window-close", + "HandleNativeWindowDestroyed begin windowId='" + std::string(window.GetWindowId()) + + "' hwnd=" + DescribeHwnd(window.GetHwnd()) + + " destroyedPrimary=" + (destroyedPrimary ? "1" : "0") + + " localPrimary=" + (window.IsPrimary() ? "1" : "0") + + " workspaceBefore=" + m_workspaceCoordinator.DescribeWindowSet() + + " hostBefore=" + DescribeHostWindows(m_hostRuntime.GetWindows())); + + if (m_workspaceCoordinator.OwnsActiveGlobalTabDrag(window.GetWindowId())) { + m_workspaceCoordinator.EndGlobalTabDragSession(); + } + + ShutdownRuntimeIfNeeded(window); + m_workspaceCoordinator.RemoveWindowProjection(window.GetWindowId(), destroyedPrimary); + window.MarkDestroyed(); + + if (destroyedPrimary) { + std::vector closeTargets = {}; + closeTargets.reserve(m_hostRuntime.GetWindows().size()); + for (const std::unique_ptr& otherWindow : m_hostRuntime.GetWindows()) { + if (otherWindow == nullptr || + otherWindow.get() == &window || + otherWindow->GetHwnd() == nullptr || + otherWindow->IsClosing()) { + continue; + } + closeTargets.push_back(otherWindow.get()); + } + + for (EditorWindow* closeTarget : closeTargets) { + if (closeTarget != nullptr) { + PostCloseRequest(*closeTarget); + } + } + } + + LogRuntimeTrace( + "window-close", + "HandleNativeWindowDestroyed end windowId='" + std::string(window.GetWindowId()) + + "' workspaceAfter=" + m_workspaceCoordinator.DescribeWindowSet() + + " hostAfter=" + DescribeHostWindows(m_hostRuntime.GetWindows())); +} + +void EditorWindowLifecycleCoordinator::AbortUnregisteredWindow(EditorWindow& window) { + const HWND hwnd = window.GetHwnd(); + LogRuntimeTrace( + "window-close", + "AbortUnregisteredWindow begin windowId='" + std::string(window.GetWindowId()) + + "' hwnd=" + DescribeHwnd(hwnd) + + " hostBefore=" + DescribeHostWindows(m_hostRuntime.GetWindows())); + + if (!window.IsClosing()) { + window.MarkClosing(); + } + + ShutdownRuntimeIfNeeded(window); + window.MarkDestroyed(); + if (hwnd != nullptr && IsWindow(hwnd)) { + DestroyWindow(hwnd); + } + EraseWindow(window); + + LogRuntimeTrace( + "window-close", + "AbortUnregisteredWindow end windowId='" + std::string(window.GetWindowId()) + + "' hostAfter=" + DescribeHostWindows(m_hostRuntime.GetWindows())); +} + +void EditorWindowLifecycleCoordinator::ShutdownAllWindows() { + std::vector closeTargets = {}; + closeTargets.reserve(m_hostRuntime.GetWindows().size()); + for (const std::unique_ptr& window : m_hostRuntime.GetWindows()) { + if (window != nullptr) { + closeTargets.push_back(window.get()); + } + } + + for (EditorWindow* closeTarget : closeTargets) { + if (closeTarget != nullptr) { + ExecuteCloseRequest(*closeTarget); + } + } + + ReapDestroyedWindows(); +} + +void EditorWindowLifecycleCoordinator::ReapDestroyedWindows() { + auto& windows = m_hostRuntime.GetWindows(); + for (auto it = windows.begin(); it != windows.end();) { + EditorWindow* const window = it->get(); + if (window == nullptr || window->GetHwnd() != nullptr) { + ++it; + continue; + } + + if (m_hostRuntime.m_pendingCreateWindow == window) { + m_hostRuntime.m_pendingCreateWindow = nullptr; + } + + LogRuntimeTrace( + "window-close", + "ReapDestroyedWindows erase windowId='" + std::string(window->GetWindowId()) + + "' hostBefore=" + DescribeHostWindows(windows)); + it = windows.erase(it); + LogRuntimeTrace( + "window-close", + "ReapDestroyedWindows erase end hostAfter=" + DescribeHostWindows(windows)); + } +} + +void EditorWindowLifecycleCoordinator::ShutdownRuntimeIfNeeded(EditorWindow& window) { + if (window.IsRenderReady()) { + window.Shutdown(); + } +} + +void EditorWindowLifecycleCoordinator::EraseWindow(EditorWindow& window) { + auto& windows = m_hostRuntime.GetWindows(); + const auto it = std::find_if( + windows.begin(), + windows.end(), + [&window](const std::unique_ptr& candidate) { + return candidate.get() == &window; + }); + if (it == windows.end()) { + return; + } + + if (m_hostRuntime.m_pendingCreateWindow == &window) { + m_hostRuntime.m_pendingCreateWindow = nullptr; + } + + windows.erase(it); +} + +void EditorWindowLifecycleCoordinator::LogRuntimeTrace( + std::string_view channel, + std::string_view message) const { + m_hostRuntime.LogRuntimeTrace(channel, message); +} + +} // namespace XCEngine::UI::Editor::App diff --git a/new_editor/app/Platform/Win32/WindowManager/EditorWindowLifecycleCoordinator.h b/new_editor/app/Platform/Win32/WindowManager/EditorWindowLifecycleCoordinator.h new file mode 100644 index 00000000..972f9da2 --- /dev/null +++ b/new_editor/app/Platform/Win32/WindowManager/EditorWindowLifecycleCoordinator.h @@ -0,0 +1,34 @@ +#pragma once + +#include + +namespace XCEngine::UI::Editor::App { + +class EditorWindow; +class EditorWindowHostRuntime; +class EditorWindowWorkspaceCoordinator; + +class EditorWindowLifecycleCoordinator final { +public: + EditorWindowLifecycleCoordinator( + EditorWindowHostRuntime& hostRuntime, + EditorWindowWorkspaceCoordinator& workspaceCoordinator); + ~EditorWindowLifecycleCoordinator(); + + void PostCloseRequest(EditorWindow& window); + void ExecuteCloseRequest(EditorWindow& window); + void HandleNativeWindowDestroyed(EditorWindow& window); + void AbortUnregisteredWindow(EditorWindow& window); + void ShutdownAllWindows(); + void ReapDestroyedWindows(); + +private: + void ShutdownRuntimeIfNeeded(EditorWindow& window); + void EraseWindow(EditorWindow& window); + void LogRuntimeTrace(std::string_view channel, std::string_view message) const; + + EditorWindowHostRuntime& m_hostRuntime; + EditorWindowWorkspaceCoordinator& m_workspaceCoordinator; +}; + +} // namespace XCEngine::UI::Editor::App diff --git a/new_editor/app/Platform/Win32/WindowManager/EditorWindowManager.cpp b/new_editor/app/Platform/Win32/WindowManager/EditorWindowManager.cpp index 950a6b7e..e370162c 100644 --- a/new_editor/app/Platform/Win32/WindowManager/EditorWindowManager.cpp +++ b/new_editor/app/Platform/Win32/WindowManager/EditorWindowManager.cpp @@ -2,6 +2,7 @@ #include "Platform/Win32/EditorWindow.h" #include "Platform/Win32/WindowManager/EditorWindowHostRuntime.h" +#include "Platform/Win32/WindowManager/EditorWindowLifecycleCoordinator.h" #include "Platform/Win32/WindowManager/EditorWindowMessageDispatcher.h" #include "Platform/Win32/WindowManager/EditorWindowWorkspaceCoordinator.h" @@ -19,6 +20,11 @@ EditorWindowManager::EditorWindowManager( editorContext)) { m_workspaceCoordinator = std::make_unique(*m_hostRuntime); + m_lifecycleCoordinator = std::make_unique( + *m_hostRuntime, + *m_workspaceCoordinator); + m_hostRuntime->BindLifecycleCoordinator(*m_lifecycleCoordinator); + m_workspaceCoordinator->BindLifecycleCoordinator(*m_lifecycleCoordinator); } EditorWindowManager::~EditorWindowManager() = default; @@ -40,7 +46,7 @@ void EditorWindowManager::HandlePendingNativeWindowCreated(HWND hwnd) { void EditorWindowManager::Shutdown() { m_workspaceCoordinator->EndGlobalTabDragSession(); - m_hostRuntime->Shutdown(); + m_lifecycleCoordinator->ShutdownAllWindows(); } bool EditorWindowManager::TryDispatchWindowMessage( @@ -61,6 +67,7 @@ bool EditorWindowManager::TryDispatchWindowMessage( return EditorWindowMessageDispatcher::TryDispatch( hwnd, *m_hostRuntime, + *m_lifecycleCoordinator, *m_workspaceCoordinator, *window, message, @@ -98,7 +105,7 @@ bool EditorWindowManager::HasWindows() const { } void EditorWindowManager::DestroyClosedWindows() { - m_hostRuntime->DestroyClosedWindows(); + m_lifecycleCoordinator->ReapDestroyedWindows(); } void EditorWindowManager::RenderAllWindows() { diff --git a/new_editor/app/Platform/Win32/WindowManager/EditorWindowMessageDispatcher.cpp b/new_editor/app/Platform/Win32/WindowManager/EditorWindowMessageDispatcher.cpp index ded08fab..6157279f 100644 --- a/new_editor/app/Platform/Win32/WindowManager/EditorWindowMessageDispatcher.cpp +++ b/new_editor/app/Platform/Win32/WindowManager/EditorWindowMessageDispatcher.cpp @@ -5,6 +5,7 @@ #include "Platform/Win32/EditorWindow.h" #include "Platform/Win32/EditorWindowPointerCapture.h" #include "Platform/Win32/WindowManager/EditorWindowHostRuntime.h" +#include "Platform/Win32/WindowManager/EditorWindowLifecycleCoordinator.h" #include "Platform/Win32/WindowManager/EditorWindowWorkspaceCoordinator.h" #include @@ -55,6 +56,7 @@ std::string DescribeHostWindows(const EditorWindowHostRuntime& hostRuntime) { struct EditorWindowMessageDispatcher::DispatchContext { HWND hwnd = nullptr; EditorWindowHostRuntime& hostRuntime; + EditorWindowLifecycleCoordinator& lifecycleCoordinator; EditorWindowWorkspaceCoordinator& workspaceCoordinator; EditorWindow& window; }; @@ -403,18 +405,7 @@ bool EditorWindowMessageDispatcher::TryDispatchWindowLifecycleMessage( outResult = 0; return true; case WM_CLOSE: - context.hostRuntime.LogRuntimeTrace( - "window-close", - "WM_CLOSE windowId='" + std::string(context.window.GetWindowId()) + - "' hwnd=" + DescribeHwnd(context.hwnd) + - " localPrimary=" + (context.window.IsPrimary() ? "1" : "0") + - " closingBefore=" + (context.window.IsClosing() ? "1" : "0") + - " workspace=" + context.workspaceCoordinator.DescribeWindowSet() + - " host=" + DescribeHostWindows(context.hostRuntime)); - if (!context.window.IsClosing()) { - context.window.MarkClosing(); - } - DestroyWindow(context.hwnd); + context.lifecycleCoordinator.ExecuteCloseRequest(context.window); outResult = 0; return true; case WM_PAINT: @@ -425,30 +416,7 @@ bool EditorWindowMessageDispatcher::TryDispatchWindowLifecycleMessage( outResult = 1; return true; case WM_DESTROY: - if (context.workspaceCoordinator.OwnsActiveGlobalTabDrag(context.window.GetWindowId())) { - context.workspaceCoordinator.EndGlobalTabDragSession(); - } - { - const bool destroyedPrimary = - context.workspaceCoordinator.IsPrimaryWindowId(context.window.GetWindowId()); - context.hostRuntime.LogRuntimeTrace( - "window-close", - "WM_DESTROY begin windowId='" + std::string(context.window.GetWindowId()) + - "' hwnd=" + DescribeHwnd(context.hwnd) + - " destroyedPrimary=" + (destroyedPrimary ? "1" : "0") + - " localPrimary=" + (context.window.IsPrimary() ? "1" : "0") + - " workspaceBefore=" + context.workspaceCoordinator.DescribeWindowSet() + - " hostBefore=" + DescribeHostWindows(context.hostRuntime)); - context.workspaceCoordinator.HandleWindowDestroyed( - context.window.GetWindowId(), - destroyedPrimary); - context.hostRuntime.HandleDestroyedWindow(context.window, destroyedPrimary); - context.hostRuntime.LogRuntimeTrace( - "window-close", - "WM_DESTROY end windowId='" + std::string(context.window.GetWindowId()) + - "' workspaceAfter=" + context.workspaceCoordinator.DescribeWindowSet() + - " hostAfter=" + DescribeHostWindows(context.hostRuntime)); - } + context.lifecycleCoordinator.HandleNativeWindowDestroyed(context.window); outResult = 0; return true; default: @@ -519,6 +487,7 @@ bool EditorWindowMessageDispatcher::TryDispatchWindowChromeMessage( bool EditorWindowMessageDispatcher::TryDispatch( HWND hwnd, EditorWindowHostRuntime& hostRuntime, + EditorWindowLifecycleCoordinator& lifecycleCoordinator, EditorWindowWorkspaceCoordinator& workspaceCoordinator, EditorWindow& window, UINT message, @@ -528,6 +497,7 @@ bool EditorWindowMessageDispatcher::TryDispatch( const DispatchContext context = { .hwnd = hwnd, .hostRuntime = hostRuntime, + .lifecycleCoordinator = lifecycleCoordinator, .workspaceCoordinator = workspaceCoordinator, .window = window, }; diff --git a/new_editor/app/Platform/Win32/WindowManager/EditorWindowMessageDispatcher.h b/new_editor/app/Platform/Win32/WindowManager/EditorWindowMessageDispatcher.h index 6f01a87f..895115b4 100644 --- a/new_editor/app/Platform/Win32/WindowManager/EditorWindowMessageDispatcher.h +++ b/new_editor/app/Platform/Win32/WindowManager/EditorWindowMessageDispatcher.h @@ -13,6 +13,7 @@ class EditorWindow; namespace XCEngine::UI::Editor::App { class EditorWindowHostRuntime; +class EditorWindowLifecycleCoordinator; class EditorWindowWorkspaceCoordinator; class EditorWindowMessageDispatcher final { @@ -20,6 +21,7 @@ public: static bool TryDispatch( HWND hwnd, EditorWindowHostRuntime& hostRuntime, + EditorWindowLifecycleCoordinator& lifecycleCoordinator, EditorWindowWorkspaceCoordinator& workspaceCoordinator, EditorWindow& window, UINT message, diff --git a/new_editor/app/Platform/Win32/WindowManager/EditorWindowWorkspaceCoordinator.cpp b/new_editor/app/Platform/Win32/WindowManager/EditorWindowWorkspaceCoordinator.cpp index 5618e88e..5c2b1e4e 100644 --- a/new_editor/app/Platform/Win32/WindowManager/EditorWindowWorkspaceCoordinator.cpp +++ b/new_editor/app/Platform/Win32/WindowManager/EditorWindowWorkspaceCoordinator.cpp @@ -3,6 +3,7 @@ #include "Composition/EditorContext.h" #include "Platform/Win32/EditorWindow.h" #include "Platform/Win32/WindowManager/EditorWindowHostRuntime.h" +#include "Platform/Win32/WindowManager/EditorWindowLifecycleCoordinator.h" #include #include @@ -87,6 +88,11 @@ EditorWindowWorkspaceCoordinator::EditorWindowWorkspaceCoordinator( EditorWindowWorkspaceCoordinator::~EditorWindowWorkspaceCoordinator() = default; +void EditorWindowWorkspaceCoordinator::BindLifecycleCoordinator( + EditorWindowLifecycleCoordinator& lifecycleCoordinator) { + m_lifecycleCoordinator = &lifecycleCoordinator; +} + void EditorWindowWorkspaceCoordinator::RegisterExistingWindow(EditorWindow& window) { std::string error = {}; if (!m_workspaceStore.RegisterWindowProjection( @@ -137,7 +143,7 @@ std::string EditorWindowWorkspaceCoordinator::DescribeWindowSet() const { return DescribeWindowSetState(m_workspaceStore.GetWindowSet()); } -void EditorWindowWorkspaceCoordinator::HandleWindowDestroyed( +void EditorWindowWorkspaceCoordinator::RemoveWindowProjection( std::string_view windowId, bool primary) { LogRuntimeTrace( @@ -249,27 +255,12 @@ bool EditorWindowWorkspaceCoordinator::SynchronizeWindowsFromWindowSet( }; const auto destroyAndEraseWindowById = [this](std::string_view windowId) { - auto& windows = m_hostRuntime.GetWindows(); - const auto it = std::find_if( - windows.begin(), - windows.end(), - [windowId](const std::unique_ptr& candidate) { - return candidate != nullptr && candidate->GetWindowId() == windowId; - }); - if (it == windows.end() || *it == nullptr) { + EditorWindow* const window = m_hostRuntime.FindWindow(windowId); + if (window == nullptr || m_lifecycleCoordinator == nullptr) { return false; } - EditorWindow& window = *it->get(); - const HWND hwnd = window.GetHwnd(); - window.ForceReleasePointerCapture(); - - window.Shutdown(); - if (hwnd != nullptr && IsWindow(hwnd)) { - DestroyWindow(hwnd); - } - window.MarkDestroyed(); - windows.erase(it); + m_lifecycleCoordinator->AbortUnregisteredWindow(*window); return true; }; @@ -357,8 +348,9 @@ bool EditorWindowWorkspaceCoordinator::SynchronizeWindowsFromWindowSet( windowIdsInSet.end(), window->GetWindowId()) != windowIdsInSet.end(); if (!existsInWindowSet) { - window->MarkClosing(); - PostMessageW(window->GetHwnd(), WM_CLOSE, 0, 0); + if (m_lifecycleCoordinator != nullptr) { + m_lifecycleCoordinator->PostCloseRequest(*window); + } } } diff --git a/new_editor/app/Platform/Win32/WindowManager/EditorWindowWorkspaceCoordinator.h b/new_editor/app/Platform/Win32/WindowManager/EditorWindowWorkspaceCoordinator.h index 412ec264..303a2367 100644 --- a/new_editor/app/Platform/Win32/WindowManager/EditorWindowWorkspaceCoordinator.h +++ b/new_editor/app/Platform/Win32/WindowManager/EditorWindowWorkspaceCoordinator.h @@ -16,17 +16,19 @@ namespace XCEngine::UI::Editor::App { class EditorWindow; class EditorWindowHostRuntime; +class EditorWindowLifecycleCoordinator; class EditorWindowWorkspaceCoordinator final { public: explicit EditorWindowWorkspaceCoordinator(EditorWindowHostRuntime& hostRuntime); ~EditorWindowWorkspaceCoordinator(); + void BindLifecycleCoordinator(EditorWindowLifecycleCoordinator& lifecycleCoordinator); void RegisterExistingWindow(EditorWindow& window); void CommitWindowProjection(EditorWindow& window); bool IsPrimaryWindowId(std::string_view windowId) const; std::string DescribeWindowSet() const; - void HandleWindowDestroyed(std::string_view windowId, bool primary); + void RemoveWindowProjection(std::string_view windowId, bool primary); bool IsGlobalTabDragActive() const; bool OwnsActiveGlobalTabDrag(std::string_view windowId) const; @@ -103,6 +105,7 @@ private: void LogRuntimeTrace(std::string_view channel, std::string_view message) const; EditorWindowHostRuntime& m_hostRuntime; + EditorWindowLifecycleCoordinator* m_lifecycleCoordinator = nullptr; EditorWindowWorkspaceStore m_workspaceStore; GlobalTabDragSession m_globalTabDragSession = {}; };