refactor(new_editor): centralize window lifecycle ownership

This commit is contained in:
2026-04-22 14:47:48 +08:00
parent b44f5ca9fc
commit 4372c1ce7b
12 changed files with 337 additions and 156 deletions

View File

@@ -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

View File

@@ -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;

View File

@@ -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<EditorWindowHostRuntime> m_hostRuntime = {};
std::unique_ptr<EditorWindowLifecycleCoordinator> m_lifecycleCoordinator = {};
std::unique_ptr<EditorWindowWorkspaceCoordinator> m_workspaceCoordinator = {};
};

View File

@@ -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 <XCEditor/Foundation/UIEditorRuntimeTrace.h>
@@ -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<EditorWindow*>(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<EditorWindow>& 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<EditorWindow>& 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;

View File

@@ -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<std::unique_ptr<EditorWindow>> m_windows = {};
EditorWindow* m_pendingCreateWindow = nullptr;
EditorWindowLifecycleCoordinator* m_lifecycleCoordinator = nullptr;
};
} // namespace XCEngine::UI::Editor::App

View File

@@ -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 <algorithm>
#include <cstdint>
#include <sstream>
#include <vector>
namespace XCEngine::UI::Editor::App {
namespace {
std::string DescribeHwnd(HWND hwnd) {
std::ostringstream stream = {};
stream << "0x" << std::hex << std::uppercase
<< reinterpret_cast<std::uintptr_t>(hwnd);
return stream.str();
}
std::string DescribeHostWindows(
const std::vector<std::unique_ptr<EditorWindow>>& windows) {
std::ostringstream stream = {};
stream << "count=" << windows.size() << " [";
bool first = true;
for (const std::unique_ptr<EditorWindow>& window : windows) {
if (!first) {
stream << ", ";
}
first = false;
if (window == nullptr) {
stream << "<null>";
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<EditorWindow*> closeTargets = {};
closeTargets.reserve(m_hostRuntime.GetWindows().size());
for (const std::unique_ptr<EditorWindow>& 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<EditorWindow*> closeTargets = {};
closeTargets.reserve(m_hostRuntime.GetWindows().size());
for (const std::unique_ptr<EditorWindow>& 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<EditorWindow>& 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

View File

@@ -0,0 +1,34 @@
#pragma once
#include <string_view>
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

View File

@@ -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<EditorWindowWorkspaceCoordinator>(*m_hostRuntime);
m_lifecycleCoordinator = std::make_unique<EditorWindowLifecycleCoordinator>(
*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() {

View File

@@ -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 <cstdint>
@@ -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,
};

View File

@@ -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,

View File

@@ -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 <XCEditor/Docking/UIEditorDockHostTransfer.h>
#include <XCEditor/Workspace/UIEditorWindowWorkspaceController.h>
@@ -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<EditorWindow>& 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);
}
}
}

View File

@@ -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 = {};
};