274 lines
8.8 KiB
C++
274 lines
8.8 KiB
C++
#include "Windowing/EditorWindowManager.h"
|
|
|
|
#include "Windowing/Content/EditorWindowContentController.h"
|
|
#include "Windowing/Content/EditorWindowContentFactory.h"
|
|
#include "Windowing/Coordinator/EditorWindowLifecycleCoordinator.h"
|
|
#include "Windowing/Coordinator/EditorUtilityWindowCoordinator.h"
|
|
#include "Windowing/Coordinator/EditorWindowWorkspaceCoordinator.h"
|
|
#include "Windowing/Runtime/EditorWindowRuntimeController.h"
|
|
|
|
#include <XCEditor/Workspace/UIEditorWindowWorkspaceModel.h>
|
|
|
|
#include <memory>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
namespace XCEngine::UI::Editor::App {
|
|
|
|
EditorWindowManager::EditorWindowManager(
|
|
EditorContext& editorContext,
|
|
EditorWindowSystem& windowSystem,
|
|
EditorWindowHostRuntimeServices& hostRuntime)
|
|
: m_editorContext(editorContext)
|
|
, m_hostRuntime(hostRuntime) {
|
|
m_contentFactory = CreateDefaultEditorWindowContentFactory(windowSystem);
|
|
m_workspaceCoordinator =
|
|
std::make_unique<EditorWindowWorkspaceCoordinator>(
|
|
m_editorContext,
|
|
m_hostRuntime,
|
|
windowSystem,
|
|
*m_contentFactory);
|
|
m_utilityCoordinator =
|
|
std::make_unique<EditorUtilityWindowCoordinator>(
|
|
m_editorContext,
|
|
m_hostRuntime,
|
|
*m_contentFactory);
|
|
m_lifecycleCoordinator = std::make_unique<EditorWindowLifecycleCoordinator>(
|
|
m_hostRuntime,
|
|
*m_workspaceCoordinator);
|
|
m_hostRuntime.BindHostCoordinator(*this);
|
|
m_workspaceCoordinator->BindLifecycleCoordinator(*m_lifecycleCoordinator);
|
|
m_utilityCoordinator->BindLifecycleCoordinator(*m_lifecycleCoordinator);
|
|
}
|
|
|
|
EditorWindowManager::~EditorWindowManager() = default;
|
|
|
|
EditorHostWindow* EditorWindowManager::CreateWorkspaceWindow(
|
|
const UIEditorWindowWorkspaceState& windowState,
|
|
const EditorWindowCreateParams& params) {
|
|
if (m_contentFactory == nullptr) {
|
|
return nullptr;
|
|
}
|
|
if (windowState.windowId.empty()) {
|
|
return nullptr;
|
|
}
|
|
if (!params.windowId.empty() && windowState.windowId != params.windowId) {
|
|
return nullptr;
|
|
}
|
|
|
|
EditorHostWindow* const window = m_hostRuntime.CreateHostWindow(
|
|
std::make_unique<EditorWindowRuntimeController>(
|
|
m_editorContext,
|
|
m_contentFactory->CreateWorkspaceContentController(windowState),
|
|
m_hostRuntime.CreateWindowRenderRuntime()),
|
|
params);
|
|
if (window != nullptr) {
|
|
m_workspaceCoordinator->RegisterExistingWindow(*window);
|
|
}
|
|
return window;
|
|
}
|
|
|
|
EditorHostWindow* EditorWindowManager::CreateUtilityWindow(
|
|
const EditorUtilityWindowDescriptor& descriptor,
|
|
const EditorWindowCreateParams& params) {
|
|
if (m_contentFactory == nullptr) {
|
|
return nullptr;
|
|
}
|
|
|
|
EditorHostWindow* const window = m_hostRuntime.CreateHostWindow(
|
|
std::make_unique<EditorWindowRuntimeController>(
|
|
m_editorContext,
|
|
m_contentFactory->CreateUtilityContentController(descriptor),
|
|
m_hostRuntime.CreateWindowRenderRuntime()),
|
|
params);
|
|
if (window != nullptr) {
|
|
m_workspaceCoordinator->RegisterExistingWindow(*window);
|
|
}
|
|
return window;
|
|
}
|
|
|
|
void EditorWindowManager::Shutdown() {
|
|
m_workspaceCoordinator->EndGlobalTabDragSession();
|
|
m_lifecycleCoordinator->ShutdownAllWindows();
|
|
}
|
|
|
|
bool EditorWindowManager::RequestPrimaryWindowClose() {
|
|
if (m_lifecycleCoordinator == nullptr) {
|
|
return false;
|
|
}
|
|
|
|
for (EditorHostWindow* window : m_hostRuntime.GetWindows()) {
|
|
if (window == nullptr || !window->IsPrimary()) {
|
|
continue;
|
|
}
|
|
|
|
m_lifecycleCoordinator->PostCloseRequest(*window);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool EditorWindowManager::HasWindows() const {
|
|
return !m_hostRuntime.GetWindows().empty();
|
|
}
|
|
|
|
void EditorWindowManager::DestroyClosedWindows() {
|
|
m_lifecycleCoordinator->ReapDestroyedWindows();
|
|
}
|
|
|
|
void EditorWindowManager::RenderAllWindows() {
|
|
struct WindowFrameTransferBatch {
|
|
EditorHostWindow* sourceWindow = nullptr;
|
|
EditorWindowFrameTransferRequests requests = {};
|
|
};
|
|
|
|
std::vector<WindowFrameTransferBatch> transferBatches = {};
|
|
const std::vector<EditorHostWindow*> windows = m_hostRuntime.GetWindows();
|
|
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);
|
|
}
|
|
}
|
|
|
|
bool EditorWindowManager::InitializeHostWindow(
|
|
EditorHostWindow& window,
|
|
const EditorHostWindowRuntimeInitializationParams& params) {
|
|
return window.InitializeRuntime(params);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
bool EditorWindowManager::IsGlobalTabDragActive() const {
|
|
return m_workspaceCoordinator != nullptr &&
|
|
m_workspaceCoordinator->IsGlobalTabDragActive();
|
|
}
|
|
|
|
bool EditorWindowManager::OwnsActiveGlobalTabDrag(std::string_view windowId) const {
|
|
return m_workspaceCoordinator != nullptr &&
|
|
m_workspaceCoordinator->OwnsActiveGlobalTabDrag(windowId);
|
|
}
|
|
|
|
bool EditorWindowManager::HandleGlobalTabDragPointerMove(EditorHostWindow& window) {
|
|
return m_workspaceCoordinator != nullptr &&
|
|
m_workspaceCoordinator->HandleGlobalTabDragPointerMove(window);
|
|
}
|
|
|
|
bool EditorWindowManager::HandleGlobalTabDragPointerButtonUp(EditorHostWindow& window) {
|
|
return m_workspaceCoordinator != nullptr &&
|
|
m_workspaceCoordinator->HandleGlobalTabDragPointerButtonUp(window);
|
|
}
|
|
|
|
void EditorWindowManager::EndGlobalTabDragSession() {
|
|
if (m_workspaceCoordinator != nullptr) {
|
|
m_workspaceCoordinator->EndGlobalTabDragSession();
|
|
}
|
|
}
|
|
|
|
void EditorWindowManager::RefreshWindowPresentation(EditorHostWindow& window) {
|
|
if (m_workspaceCoordinator != nullptr) {
|
|
m_workspaceCoordinator->RefreshWindowPresentation(window);
|
|
}
|
|
}
|
|
|
|
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();
|
|
}
|
|
}
|
|
|
|
} // namespace XCEngine::UI::Editor::App
|