refactor(new_editor/app): reorganize host structure and add smoke test

This commit is contained in:
2026-04-15 08:24:06 +08:00
parent 3617b4840b
commit 9e5954cf0a
235 changed files with 11157 additions and 10028 deletions

View File

@@ -0,0 +1,245 @@
#include "EditorWindowManager.h"
#include "State/EditorContext.h"
#include "Bootstrap/EditorResources.h"
#include "EditorWindow.h"
#include <XCEditor/Foundation/UIEditorRuntimeTrace.h>
#include <algorithm>
namespace XCEngine::UI::Editor::App {
EditorWindowManager::EditorWindowManager(
EditorWindowHostConfig hostConfig,
std::filesystem::path repoRoot,
EditorContext& editorContext)
: m_hostConfig(hostConfig),
m_repoRoot(std::move(repoRoot)),
m_editorContext(editorContext) {}
EditorWindowManager::~EditorWindowManager() = default;
EditorWindow* EditorWindowManager::CreateEditorWindow(
UIEditorWorkspaceController workspaceController,
const CreateParams& params) {
auto windowPtr = std::make_unique<EditorWindow>(
params.windowId,
params.title.empty() ? std::wstring(L"XCEngine Editor") : params.title,
params.primary,
std::move(workspaceController));
EditorWindow* const rawWindow = windowPtr.get();
m_windows.push_back(std::move(windowPtr));
const auto eraseRawWindow = [this, rawWindow]() {
const auto it = std::find_if(
m_windows.begin(),
m_windows.end(),
[rawWindow](const std::unique_ptr<EditorWindow>& candidate) {
return candidate.get() == rawWindow;
});
if (it != m_windows.end()) {
m_windows.erase(it);
}
};
m_pendingCreateWindow = rawWindow;
const HWND hwnd = CreateWindowExW(
WS_EX_APPWINDOW,
m_hostConfig.windowClassName,
rawWindow->GetTitle().c_str(),
m_hostConfig.windowStyle,
params.initialX,
params.initialY,
params.initialWidth,
params.initialHeight,
nullptr,
nullptr,
m_hostConfig.hInstance,
m_hostConfig.windowUserData);
m_pendingCreateWindow = nullptr;
if (hwnd == nullptr) {
eraseRawWindow();
return nullptr;
}
if (!rawWindow->HasHwnd()) {
rawWindow->AttachHwnd(hwnd);
}
auto failWindowInitialization = [&](std::string_view message) {
LogRuntimeTrace("window", std::string(message));
DestroyEditorWindow(*rawWindow);
eraseRawWindow();
return static_cast<EditorWindow*>(nullptr);
};
const HICON bigIcon = static_cast<HICON>(
LoadImageW(
m_hostConfig.hInstance,
MAKEINTRESOURCEW(IDI_APP_ICON),
IMAGE_ICON,
0,
0,
LR_DEFAULTSIZE));
const HICON smallIcon = static_cast<HICON>(
LoadImageW(
m_hostConfig.hInstance,
MAKEINTRESOURCEW(IDI_APP_ICON_SMALL),
IMAGE_ICON,
GetSystemMetrics(SM_CXSMICON),
GetSystemMetrics(SM_CYSMICON),
LR_DEFAULTCOLOR));
if (bigIcon != nullptr) {
SendMessageW(hwnd, WM_SETICON, ICON_BIG, reinterpret_cast<LPARAM>(bigIcon));
}
if (smallIcon != nullptr) {
SendMessageW(hwnd, WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>(smallIcon));
}
if (!rawWindow->Initialize(
m_repoRoot,
m_editorContext,
m_editorContext.GetShellAsset().captureRootPath,
params.autoCaptureOnStartup)) {
return failWindowInitialization("managed window initialization failed");
}
ShowWindow(hwnd, params.showCommand);
UpdateWindow(hwnd);
return rawWindow;
}
void EditorWindowManager::HandlePendingNativeWindowCreated(HWND hwnd) {
if (m_pendingCreateWindow != nullptr && !m_pendingCreateWindow->HasHwnd()) {
m_pendingCreateWindow->AttachHwnd(hwnd);
}
}
void EditorWindowManager::Shutdown() {
for (const std::unique_ptr<EditorWindow>& window : m_windows) {
if (window != nullptr) {
DestroyEditorWindow(*window);
}
}
m_windows.clear();
m_pendingCreateWindow = nullptr;
m_globalTabDragSession = {};
}
EditorWindow* EditorWindowManager::FindWindow(HWND hwnd) {
if (hwnd == nullptr) {
return nullptr;
}
for (const std::unique_ptr<EditorWindow>& window : m_windows) {
if (window != nullptr && window->GetHwnd() == hwnd) {
return window.get();
}
}
return nullptr;
}
const EditorWindow* EditorWindowManager::FindWindow(HWND hwnd) const {
return const_cast<EditorWindowManager*>(this)->FindWindow(hwnd);
}
EditorWindow* EditorWindowManager::FindWindow(std::string_view windowId) {
if (windowId.empty()) {
return nullptr;
}
for (const std::unique_ptr<EditorWindow>& window : m_windows) {
if (window != nullptr && window->GetWindowId() == windowId) {
return window.get();
}
}
return nullptr;
}
const EditorWindow* EditorWindowManager::FindWindow(std::string_view windowId) const {
return const_cast<EditorWindowManager*>(this)->FindWindow(windowId);
}
EditorWindow* EditorWindowManager::FindPrimaryWindow() {
for (const std::unique_ptr<EditorWindow>& window : m_windows) {
if (window != nullptr && window->IsPrimary()) {
return window.get();
}
}
return nullptr;
}
const EditorWindow* EditorWindowManager::FindPrimaryWindow() const {
return const_cast<EditorWindowManager*>(this)->FindPrimaryWindow();
}
bool EditorWindowManager::HasWindows() const {
return !m_windows.empty();
}
void EditorWindowManager::DestroyEditorWindow(EditorWindow& window) {
const HWND hwnd = window.GetHwnd();
if (GetCapture() == hwnd) {
ReleaseCapture();
}
window.Shutdown();
if (hwnd != nullptr && IsWindow(hwnd)) {
DestroyWindow(hwnd);
}
window.MarkDestroyed();
}
void EditorWindowManager::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;
}
window->Shutdown();
it = m_windows.erase(it);
}
}
void EditorWindowManager::RenderAllWindows() {
for (const std::unique_ptr<EditorWindow>& window : m_windows) {
if (window == nullptr || window->GetHwnd() == nullptr) {
continue;
}
window->RenderFrame(m_editorContext, IsGlobalTabDragActive());
}
}
void EditorWindowManager::HandleDestroyedWindow(HWND hwnd) {
if (EditorWindow* window = FindWindow(hwnd); window != nullptr) {
window->MarkDestroyed();
if (window->IsPrimary()) {
for (const std::unique_ptr<EditorWindow>& otherWindow : m_windows) {
if (otherWindow != nullptr &&
otherWindow.get() != window &&
otherWindow->GetHwnd() != nullptr) {
PostMessageW(otherWindow->GetHwnd(), WM_CLOSE, 0, 0);
}
}
}
}
}
void EditorWindowManager::LogRuntimeTrace(
std::string_view channel,
std::string_view message) const {
AppendUIEditorRuntimeTrace(channel, message);
}
} // namespace XCEngine::UI::Editor::App