editor: refactor workspace window synchronization

This commit is contained in:
2026-04-26 11:17:57 +08:00
parent 4fcaac81d6
commit 57fe2cfd3b
17 changed files with 99 additions and 301 deletions

View File

@@ -11,6 +11,16 @@ namespace XCEngine::UI::Editor::App {
namespace {
UIEditorWindowWorkspaceState BuildWindowStateFromController(
std::string_view windowId,
const UIEditorWorkspaceController& workspaceController) {
UIEditorWindowWorkspaceState windowState = {};
windowState.windowId = std::string(windowId);
windowState.workspace = workspaceController.GetWorkspace();
windowState.session = workspaceController.GetSession();
return windowState;
}
EditorWindowContentCursorKind ToContentCursorKind(ProjectPanel::CursorKind cursorKind) {
switch (cursorKind) {
case ProjectPanel::CursorKind::ResizeEW:
@@ -35,12 +45,8 @@ EditorWindowContentCursorKind ToContentCursorKind(
}
EditorWorkspaceWindowProjection BuildWorkspaceProjectionFromController(
const UIEditorWorkspaceController& workspaceController,
std::string_view windowId) {
const UIEditorWorkspaceController& workspaceController) {
EditorWorkspaceWindowProjection projection = {};
projection.windowState.windowId = std::string(windowId);
projection.windowState.workspace = workspaceController.GetWorkspace();
projection.windowState.session = workspaceController.GetSession();
projection.minimumOuterSize = ResolveUIEditorDetachedWorkspaceMinimumOuterSize(
workspaceController);
projection.useDetachedTitleBarTabStrip = HasUIEditorSingleVisibleRootTab(workspaceController);
@@ -56,9 +62,8 @@ EditorWorkspaceWindowContentController::EditorWorkspaceWindowContentController(
UIEditorWorkspaceController workspaceController,
EditorWindowSystem& windowSystem)
: m_windowId(std::move(windowId)),
m_workspaceController(std::move(workspaceController)),
m_windowSystem(windowSystem) {
RefreshProjectionFromWorkspaceController();
RefreshProjectionFromWorkspaceController(workspaceController);
}
EditorWorkspaceWindowContentController::~EditorWorkspaceWindowContentController() = default;
@@ -103,11 +108,6 @@ EditorWorkspaceWindowContentController::TryGetTitleBarBinding() const {
return this;
}
const UIEditorWorkspaceController*
EditorWorkspaceWindowContentController::TryGetWorkspaceController() const {
return &m_workspaceController;
}
const EditorWorkspaceWindowProjection*
EditorWorkspaceWindowContentController::TryGetWorkspaceProjection() const {
return &m_projection;
@@ -115,43 +115,39 @@ EditorWorkspaceWindowContentController::TryGetWorkspaceProjection() const {
void EditorWorkspaceWindowContentController::RefreshWorkspaceProjection(
EditorWorkspaceWindowProjection projection) {
projection.windowState.windowId = m_windowId;
const auto currentSnapshot = BuildUIEditorWorkspaceLayoutSnapshot(
m_workspaceController.GetWorkspace(),
m_workspaceController.GetSession());
const auto nextSnapshot = BuildUIEditorWorkspaceLayoutSnapshot(
projection.windowState.workspace,
projection.windowState.session);
if (!AreUIEditorWorkspaceLayoutSnapshotsEquivalent(currentSnapshot, nextSnapshot)) {
m_workspaceController = UIEditorWorkspaceController(
m_workspaceController.GetPanelRegistry(),
projection.windowState.workspace,
projection.windowState.session);
}
m_projection = std::move(projection);
}
void EditorWorkspaceWindowContentController::RefreshProjectionFromWorkspaceController(bool primary) {
bool EditorWorkspaceWindowContentController::TryBuildAuthoritativeWorkspaceController(
UIEditorWorkspaceController& outController) const {
const UIEditorWindowWorkspaceState* windowState =
m_windowSystem.FindWindowState(m_windowId);
if (windowState == nullptr) {
return false;
}
outController = BuildWorkspaceControllerForWindowState(
m_windowSystem.GetPanelRegistry(),
*windowState);
return true;
}
void EditorWorkspaceWindowContentController::RefreshProjectionFromWorkspaceController(
const UIEditorWorkspaceController& workspaceController,
bool primary) {
const std::wstring preservedWindowTitle = m_projection.windowTitle;
m_projection = BuildWorkspaceProjectionFromController(m_workspaceController, m_windowId);
m_projection = BuildWorkspaceProjectionFromController(workspaceController);
if (!primary) {
m_projection.windowTitle = ResolveEditorWindowPresentationTitle(
std::wstring_view{},
m_workspaceController.GetPanelRegistry(),
m_projection.windowState,
workspaceController.GetPanelRegistry(),
BuildWindowStateFromController(m_windowId, workspaceController),
false);
} else if (!preservedWindowTitle.empty()) {
m_projection.windowTitle = preservedWindowTitle;
}
}
void EditorWorkspaceWindowContentController::RestoreWorkspaceControllerFromProjection() {
m_workspaceController = UIEditorWorkspaceController(
m_workspaceController.GetPanelRegistry(),
m_projection.windowState.workspace,
m_projection.windowState.session);
}
void EditorWorkspaceWindowContentController::Initialize(
const EditorWindowContentInitializationContext& context) {
m_shellRuntime.Initialize(context.repoRoot, context.textureHost, context.textMeasurer);
@@ -173,12 +169,21 @@ void EditorWorkspaceWindowContentController::SetViewportSurfacePresentationEnabl
EditorWindowFrameTransferRequests EditorWorkspaceWindowContentController::UpdateAndAppend(
const EditorWindowContentFrameContext& context,
::XCEngine::UI::UIDrawData& drawData) {
UIEditorWorkspaceController workspaceController = {};
if (!TryBuildAuthoritativeWorkspaceController(workspaceController)) {
AppendUIEditorRuntimeTrace(
"window",
"workspace frame skipped: authoritative state missing for window '" +
m_windowId + "'");
return {};
}
const auto beforeSnapshot = BuildUIEditorWorkspaceLayoutSnapshot(
m_workspaceController.GetWorkspace(),
m_workspaceController.GetSession());
workspaceController.GetWorkspace(),
workspaceController.GetSession());
EditorWindowFrameTransferRequests transferRequests = m_frameOrchestrator.UpdateAndAppend(
context.editorContext,
m_workspaceController,
workspaceController,
m_shellRuntime,
context.bounds,
context.inputEvents,
@@ -189,21 +194,20 @@ EditorWindowFrameTransferRequests EditorWorkspaceWindowContentController::Update
context.useDetachedTitleBarTabStrip,
drawData);
const auto afterSnapshot = BuildUIEditorWorkspaceLayoutSnapshot(
m_workspaceController.GetWorkspace(),
m_workspaceController.GetSession());
workspaceController.GetWorkspace(),
workspaceController.GetSession());
if (!AreUIEditorWorkspaceLayoutSnapshotsEquivalent(beforeSnapshot, afterSnapshot)) {
std::string error = {};
if (!m_windowSystem.CommitLiveWindowMutation(
m_windowId,
m_workspaceController,
workspaceController,
error)) {
AppendUIEditorRuntimeTrace(
"window",
"workspace direct commit rejected for window '" +
m_windowId + "': " + error);
RestoreWorkspaceControllerFromProjection();
} else {
RefreshProjectionFromWorkspaceController(context.primary);
RefreshProjectionFromWorkspaceController(workspaceController, context.primary);
}
}
return transferRequests;