Files
XCEngine/editor/app/Windowing/EditorWindowManager.cpp

323 lines
10 KiB
C++
Raw Normal View History

2026-04-27 19:16:08 +08:00
#include "EditorWindowManager.h"
2026-04-25 16:46:01 +08:00
2026-04-27 19:16:08 +08:00
#include "Content/EditorWindowContentController.h"
#include "Content/EditorWindowContentFactory.h"
#include "Coordinator/EditorWindowLifecycleCoordinator.h"
#include "Coordinator/EditorUtilityWindowCoordinator.h"
#include "Coordinator/EditorWindowWorkspaceCoordinator.h"
#include "EditorWindowInstance.h"
#include "Runtime/EditorWindowRuntimeController.h"
2026-04-25 16:46:01 +08:00
2026-04-27 22:21:40 +08:00
#include "EditorWindowRenderRuntime.h"
2026-04-26 19:21:38 +08:00
2026-04-26 13:44:19 +08:00
#include <XCEditor/Workspace/UIEditorWindowWorkspaceModel.h>
2026-04-25 19:25:49 +08:00
2026-04-26 17:49:30 +08:00
#include <memory>
#include <algorithm>
2026-04-25 16:46:01 +08:00
#include <utility>
#include <vector>
2026-04-25 16:46:01 +08:00
namespace XCEngine::UI::Editor::App {
EditorWindowManager::EditorWindowManager(
EditorContext& editorContext,
2026-04-26 13:44:19 +08:00
EditorWindowSystem& windowSystem,
2026-04-26 19:21:38 +08:00
Rendering::Host::EditorWindowRenderRuntimeFactory& renderRuntimeFactory,
2026-04-27 13:40:26 +08:00
EditorWindowHostRuntimeServices& hostRuntime,
EditorWorkspacePanelRuntimeSetFactory workspacePanelFactory,
EditorUtilityWindowPanelFactory utilityPanelFactory)
2026-04-26 13:44:19 +08:00
: m_editorContext(editorContext)
2026-04-26 19:21:38 +08:00
, m_renderRuntimeFactory(renderRuntimeFactory)
2026-04-26 13:44:19 +08:00
, m_hostRuntime(hostRuntime) {
2026-04-27 13:40:26 +08:00
m_contentFactory = CreateDefaultEditorWindowContentFactory(
windowSystem,
std::move(workspacePanelFactory),
std::move(utilityPanelFactory));
2026-04-25 16:46:01 +08:00
m_workspaceCoordinator =
2026-04-26 16:01:07 +08:00
std::make_unique<EditorWindowWorkspaceCoordinator>(
m_editorContext,
2026-04-26 16:01:07 +08:00
m_hostRuntime,
*this,
2026-04-26 16:01:07 +08:00
windowSystem,
2026-04-26 19:21:38 +08:00
m_renderRuntimeFactory,
2026-04-26 16:01:07 +08:00
*m_contentFactory);
2026-04-25 16:46:01 +08:00
m_utilityCoordinator =
2026-04-26 16:01:07 +08:00
std::make_unique<EditorUtilityWindowCoordinator>(
m_editorContext,
2026-04-26 16:01:07 +08:00
m_hostRuntime,
*this,
2026-04-26 19:21:38 +08:00
m_renderRuntimeFactory,
2026-04-26 16:01:07 +08:00
*m_contentFactory);
2026-04-25 16:46:01 +08:00
m_lifecycleCoordinator = std::make_unique<EditorWindowLifecycleCoordinator>(
2026-04-26 13:44:19 +08:00
m_hostRuntime,
2026-04-25 16:46:01 +08:00
*m_workspaceCoordinator);
2026-04-26 13:44:19 +08:00
m_hostRuntime.BindHostCoordinator(*this);
2026-04-25 16:46:01 +08:00
m_workspaceCoordinator->BindLifecycleCoordinator(*m_lifecycleCoordinator);
m_utilityCoordinator->BindLifecycleCoordinator(*m_lifecycleCoordinator);
}
EditorWindowManager::~EditorWindowManager() = default;
EditorHostWindow* EditorWindowManager::CreateWorkspaceWindow(
2026-04-26 13:44:19 +08:00
const UIEditorWindowWorkspaceState& windowState,
const EditorWindowCreateParams& params) {
2026-04-26 16:01:07 +08:00
if (m_contentFactory == nullptr) {
return nullptr;
}
if (windowState.windowId.empty()) {
return nullptr;
}
if (!params.windowId.empty() && windowState.windowId != params.windowId) {
return nullptr;
}
auto windowInstance = CreateEditorWindowInstance(
params.windowId,
params.title,
params.category,
params.chromePolicy,
params.primary,
std::make_unique<EditorWindowRuntimeController>(
m_editorContext,
m_contentFactory->CreateWorkspaceContentController(windowState),
m_renderRuntimeFactory.CreateWindowRenderRuntime()));
EditorHostWindow* const window = windowInstance.get();
if (!m_hostRuntime.CreateHostWindow(*window, params)) {
return nullptr;
}
m_windows.push_back(std::move(windowInstance));
2026-04-25 19:25:49 +08:00
if (window != nullptr) {
m_workspaceCoordinator->RegisterExistingWindow(*window);
}
return window;
}
EditorHostWindow* EditorWindowManager::CreateUtilityWindow(
2026-04-25 19:25:49 +08:00
const EditorUtilityWindowDescriptor& descriptor,
const EditorWindowCreateParams& params) {
2026-04-26 16:01:07 +08:00
if (m_contentFactory == nullptr) {
return nullptr;
}
auto windowInstance = CreateEditorWindowInstance(
params.windowId,
params.title,
params.category,
params.chromePolicy,
params.primary,
std::make_unique<EditorWindowRuntimeController>(
m_editorContext,
m_contentFactory->CreateUtilityContentController(descriptor),
m_renderRuntimeFactory.CreateWindowRenderRuntime()));
EditorHostWindow* const window = windowInstance.get();
if (!m_hostRuntime.CreateHostWindow(*window, params)) {
return nullptr;
}
m_windows.push_back(std::move(windowInstance));
2026-04-25 19:25:49 +08:00
if (window != nullptr) {
m_workspaceCoordinator->RegisterExistingWindow(*window);
}
return window;
}
2026-04-25 16:46:01 +08:00
void EditorWindowManager::Shutdown() {
m_workspaceCoordinator->EndGlobalTabDragSession();
m_lifecycleCoordinator->ShutdownAllWindows();
ReapDestroyedWindows();
m_windows.clear();
2026-04-25 16:46:01 +08:00
}
bool EditorWindowManager::RequestPrimaryWindowClose() {
2026-04-26 13:44:19 +08:00
if (m_lifecycleCoordinator == nullptr) {
return false;
}
for (const std::unique_ptr<EditorWindowInstance>& window : m_windows) {
2026-04-26 13:44:19 +08:00
if (window == nullptr || !window->IsPrimary()) {
continue;
}
m_lifecycleCoordinator->PostCloseRequest(*window);
return true;
}
2026-04-26 13:44:19 +08:00
return false;
}
2026-04-26 13:44:19 +08:00
bool EditorWindowManager::HasWindows() const {
return !m_windows.empty();
2026-04-26 13:44:19 +08:00
}
2026-04-25 16:46:01 +08:00
2026-04-26 13:44:19 +08:00
void EditorWindowManager::DestroyClosedWindows() {
ReapDestroyedWindows();
2026-04-26 13:44:19 +08:00
}
2026-04-25 16:46:01 +08:00
2026-04-26 13:44:19 +08:00
void EditorWindowManager::RenderAllWindows() {
struct WindowFrameTransferBatch {
EditorHostWindow* sourceWindow = nullptr;
EditorWindowFrameTransferRequests requests = {};
};
std::vector<WindowFrameTransferBatch> transferBatches = {};
std::vector<EditorHostWindow*> windows = {};
windows.reserve(m_windows.size());
for (const std::unique_ptr<EditorWindowInstance>& window : m_windows) {
if (window != nullptr) {
windows.push_back(window.get());
}
}
transferBatches.reserve(windows.size());
for (EditorHostWindow* window : windows) {
if (window == nullptr ||
!window->HasLiveHostWindow() ||
window->GetLifecycleState() != EditorWindowLifecycleState::Running) {
continue;
}
if (window->ConsumeSkipNextSteadyStateFrame()) {
RefreshWindowPresentation(*window);
continue;
}
EditorWindowFrameTransferRequests transferRequests = DriveWindowFrame(*window);
RefreshWindowPresentation(*window);
if (!transferRequests.HasPendingRequests()) {
continue;
}
transferBatches.push_back(WindowFrameTransferBatch{
window,
std::move(transferRequests),
});
}
for (WindowFrameTransferBatch& batch : transferBatches) {
if (batch.sourceWindow == nullptr ||
!batch.sourceWindow->HasLiveHostWindow() ||
batch.sourceWindow->GetLifecycleState() != EditorWindowLifecycleState::Running) {
continue;
}
DispatchWindowFrameTransferRequests(
*batch.sourceWindow,
batch.requests);
}
2026-04-25 16:46:01 +08:00
}
bool EditorWindowManager::InitializeHostWindow(
EditorHostWindow& window,
const EditorHostWindowRuntimeInitializationParams& params) {
return window.InitializeRuntime(params);
2026-04-25 16:46:01 +08:00
}
EditorWindowFrameTransferRequests EditorWindowManager::DriveWindowFrame(
EditorHostWindow& window) {
return DriveWindowFrameInternal(window, false);
}
EditorWindowFrameTransferRequests EditorWindowManager::DriveImmediateWindowFrame(
EditorHostWindow& window) {
return DriveWindowFrameInternal(window, true);
}
EditorWindowFrameTransferRequests EditorWindowManager::DriveWindowFrameInternal(
EditorHostWindow& window,
bool requestSkipNextSteadyStateFrame) {
if (!window.IsRenderReady() ||
!window.HasLiveHostWindow() ||
window.GetLifecycleState() != EditorWindowLifecycleState::Running) {
return {};
}
EditorWindowFrameTransferRequests transferRequests =
window.RenderHostFrame(IsGlobalTabDragActive());
window.ValidateHostFrame();
if (requestSkipNextSteadyStateFrame) {
window.RequestSkipNextSteadyStateFrame();
}
return transferRequests;
2026-04-25 16:46:01 +08:00
}
2026-04-26 13:44:19 +08:00
bool EditorWindowManager::IsGlobalTabDragActive() const {
return m_workspaceCoordinator != nullptr &&
m_workspaceCoordinator->IsGlobalTabDragActive();
2026-04-25 16:46:01 +08:00
}
2026-04-26 13:44:19 +08:00
bool EditorWindowManager::OwnsActiveGlobalTabDrag(std::string_view windowId) const {
return m_workspaceCoordinator != nullptr &&
m_workspaceCoordinator->OwnsActiveGlobalTabDrag(windowId);
2026-04-25 16:46:01 +08:00
}
2026-04-26 13:44:19 +08:00
bool EditorWindowManager::HandleGlobalTabDragPointerMove(EditorHostWindow& window) {
return m_workspaceCoordinator != nullptr &&
m_workspaceCoordinator->HandleGlobalTabDragPointerMove(window);
2026-04-25 16:46:01 +08:00
}
2026-04-26 13:44:19 +08:00
bool EditorWindowManager::HandleGlobalTabDragPointerButtonUp(EditorHostWindow& window) {
return m_workspaceCoordinator != nullptr &&
m_workspaceCoordinator->HandleGlobalTabDragPointerButtonUp(window);
2026-04-25 16:46:01 +08:00
}
2026-04-26 13:44:19 +08:00
void EditorWindowManager::EndGlobalTabDragSession() {
if (m_workspaceCoordinator != nullptr) {
m_workspaceCoordinator->EndGlobalTabDragSession();
}
2026-04-25 16:46:01 +08:00
}
2026-04-26 13:44:19 +08:00
void EditorWindowManager::RefreshWindowPresentation(EditorHostWindow& window) {
if (m_workspaceCoordinator != nullptr) {
m_workspaceCoordinator->RefreshWindowPresentation(window);
}
2026-04-25 16:46:01 +08:00
}
2026-04-26 13:44:19 +08:00
void EditorWindowManager::DispatchWindowFrameTransferRequests(
EditorHostWindow& sourceWindow,
const EditorWindowFrameTransferRequests& transferRequests) {
if (m_workspaceCoordinator != nullptr) {
m_workspaceCoordinator->HandleWindowFrameTransferRequests(
sourceWindow,
transferRequests);
}
if (m_utilityCoordinator != nullptr) {
m_utilityCoordinator->HandleWindowFrameTransferRequests(
sourceWindow,
transferRequests);
}
}
void EditorWindowManager::ExecuteCloseRequest(EditorHostWindow& window) {
if (m_lifecycleCoordinator != nullptr) {
m_lifecycleCoordinator->ExecuteCloseRequest(window);
}
}
void EditorWindowManager::HandleNativeWindowDestroyed(EditorHostWindow& window) {
if (m_lifecycleCoordinator != nullptr) {
m_lifecycleCoordinator->HandleNativeWindowDestroyed(window);
}
}
void EditorWindowManager::AbortUnregisteredWindow(EditorHostWindow& window) {
if (m_lifecycleCoordinator != nullptr) {
m_lifecycleCoordinator->AbortUnregisteredWindow(window);
}
}
void EditorWindowManager::ReapDestroyedWindows() {
if (m_lifecycleCoordinator != nullptr) {
m_lifecycleCoordinator->ReapDestroyedWindows();
}
m_windows.erase(
std::remove_if(
m_windows.begin(),
m_windows.end(),
[](const std::unique_ptr<EditorWindowInstance>& window) {
return window == nullptr || window->IsDestroyed();
}),
m_windows.end());
2026-04-25 16:46:01 +08:00
}
} // namespace XCEngine::UI::Editor::App