Seal editor host content binding boundary

This commit is contained in:
2026-04-26 23:49:25 +08:00
parent 6c6daf7ebe
commit a3e2e2b4a9
7 changed files with 115 additions and 71 deletions

View File

@@ -51,9 +51,10 @@ Use these ownership boundaries when changing code:
- `editor/app/Composition`, `Commands`, `Features`, `Project`, `Scene`,
`State`, `System`, `UtilityWindows`: editor product semantics.
- `editor/app/Windowing/Content`, `Coordinator`, `Frame`, `Host`, `Runtime`:
app window orchestration, content ownership, frame driving, frame transfer,
and per-window runtime state. Keep this layer backend-neutral; it may depend
on `editor/app/Rendering/Host` contracts, but not concrete render backends.
app window orchestration, content ownership, host-facing content binding
contracts, frame driving, frame transfer, and per-window runtime state. Keep
this layer backend-neutral; it may depend on `editor/app/Rendering/Host`
contracts, but not concrete render backends.
- `editor/app/Platform/Win32`: native window, message dispatch, input,
lifecycle, chrome, HWND ownership, Win32 diagnostics, concrete native render
surface adapters, and native host adapter behavior.
@@ -148,6 +149,13 @@ normal frame data such as HWND, render size, DPI, pending input, cursor point,
workspace bounds, title-bar mode, or cursor application. Extend the
snapshot/command structs when the frame contract needs new data.
Host-visible content binding interfaces live under
`editor/app/Windowing/Host`, not `editor/app/Windowing/Content`. The native
host may consume small binding contracts such as
`EditorWindowInputFeedbackBinding`, `EditorWindowTitleBarBinding`, and
`EditorWindowDockHostBinding`; it must not include the content-controller
header or couple to concrete workspace/utility content controllers.
## Window Authority Model
`EditorWindowSystem` owns the authoritative `UIEditorWindowWorkspaceSet` through
@@ -247,8 +255,8 @@ logic. Utility descriptors may express native host semantics such as
generic window authority, synchronization, validation, and presentation
projection.
- Use `editor/app/Windowing` for app-specific window runtime semantics,
content, frame transfer, host contracts, runtime controllers, and
coordinators.
content, frame transfer, host contracts, host-visible content binding
interfaces, runtime controllers, and coordinators.
- Use `editor/app/Rendering/Host` for renderer-facing contracts that app
windowing or app content may consume, including
`EditorWindowRenderRuntimeFactory`.
@@ -276,6 +284,10 @@ logic. Utility descriptors may express native host semantics such as
- Do not let Win32 host code create workspace or utility content directly.
It should receive an app-owned `EditorHostWindow`/`EditorWindowInstance`
created by app windowing, not an `EditorWindowRuntimeController`.
- Do not let `editor/app/Platform/Win32` include
`Windowing/Content/EditorWindowContentController.h`. Host-visible content
state must cross through `Windowing/Host/EditorWindowContentBindings.h` and
`Windowing/Host/EditorWindowHostInterfaces.h`.
- Keep `EditorWindowNativePeer` frame/runtime communication data-shaped:
use `EditorNativeWindowRuntimeSurface`, `EditorNativeWindowFrameSnapshot`,
`EditorNativeWindowFrameCommands`, and small metrics snapshots instead of
@@ -352,6 +364,12 @@ platform-neutral, and Win32 exception/DbgHelp stack capture lives under
native shell intent with semantic host policy values rather than Win32 style
bits; the Win32 host maps those semantics to `WS_*` constants.
The host/content binding cut has also been made: host-visible content binding
contracts live in `editor/app/Windowing/Host/EditorWindowContentBindings.h`.
`editor/app/Windowing/Content/EditorWindowContentController.h` owns concrete
content-controller contracts, while the Win32 native host consumes only the
small host binding interfaces exposed from `Windowing/Host`.
The remaining promotion debt is the app runtime surface and host contract
vocabulary itself.
`editor/app/Windowing` is still app-internal and may depend on app semantics
@@ -373,10 +391,12 @@ improvement should be boundary guardrails, such as checks that keep
frame getters; keep app semantics free of Win32 `WS_*` constants; keep
`editor/include/XCEditor` and `editor/src` free of Win32 diagnostics and
exception types; and keep `editor/app/Platform/Win32` free of `Rendering/D3D12`
and `Windowing/Runtime/EditorWindowRuntimeController.h`. Consider another
structural source-directory cut only when there is concrete pressure, such as
another native host, another render backend, or headless editor/window tests;
do not satisfy that pressure by adding another production static library.
and `Windowing/Runtime/EditorWindowRuntimeController.h`; keep
`editor/app/Platform/Win32` free of
`Windowing/Content/EditorWindowContentController.h`. Consider another structural
source-directory cut only when there is concrete pressure, such as another
native host, another render backend, or headless editor/window tests; do not
satisfy that pressure by adding another production static library.
## Validation
@@ -414,6 +434,7 @@ Start with these files for editor/windowing work:
- `editor/src/Windowing/System/EditorWindowWorkspaceStore.*`
- `editor/src/Windowing/System/EditorWindowSynchronizationPlanner.cpp`
- `editor/src/Windowing/Presentation/EditorWindowPresentationPolicy.cpp`
- `editor/app/Windowing/Host/EditorWindowContentBindings.h`
- `editor/app/Windowing/Host/EditorWindowHostInterfaces.h`
- `editor/app/Windowing/Content/EditorWindowContentController.h`
- `editor/app/Windowing/Content/EditorWindowContentFactory.*`
@@ -477,6 +498,9 @@ Start with these files for editor/windowing work:
stack capture lives under `editor/app/Platform/Win32/Diagnostics`; utility
window descriptors use semantic native host policies instead of `WS_*`
constants.
- The host/content binding cut is sealed: native host-visible content binding
contracts live under `editor/app/Windowing/Host`, and Win32 code consumes
`EditorWindowContentBindings.h` instead of the content-controller contract.
- The production target shape is sealed: `XCUIEditorLib` is the only editor
static library, and all app-side source directories compile into
`XCUIEditorApp`.

View File

@@ -2,7 +2,7 @@
#include "Platform/Win32/Windowing/EditorWindow.h"
#include "Platform/Win32/Windowing/EditorWindowSupport.h"
#include "Windowing/Content/EditorWindowContentController.h"
#include "Windowing/Host/EditorWindowContentBindings.h"
#include "Windowing/Host/EditorWindowHostCoordinator.h"
#include <XCEditor/Foundation/UIEditorTheme.h>

View File

@@ -5,7 +5,7 @@
#include "Platform/Win32/Windowing/EditorWindowSupport.h"
#include "Platform/Win32/Windowing/Win32EditorWindowRenderRuntimeSurface.h"
#include "Platform/Win32/Runtime/EditorWindowInputController.h"
#include "Windowing/Content/EditorWindowContentController.h"
#include "Windowing/Host/EditorWindowContentBindings.h"
#include <XCEditor/Docking/UIEditorDockHostTransfer.h>
#include <XCEditor/Foundation/UIEditorRuntimeTrace.h>
#include <XCEditor/Shell/UIEditorShellInteraction.h>

View File

@@ -5,7 +5,7 @@
#include "Platform/Win32/Runtime/EditorWindowInputController.h"
#include "Platform/Win32/Windowing/EditorWindow.h"
#include "Platform/Win32/Windowing/EditorWindowPointerCapture.h"
#include "Windowing/Content/EditorWindowContentController.h"
#include "Windowing/Host/EditorWindowContentBindings.h"
#include "Windowing/Host/EditorWindowHostCoordinator.h"
#include <cstdint>

View File

@@ -1,12 +1,10 @@
#pragma once
#include "Windowing/Frame/EditorWindowTransferRequests.h"
#include "Windowing/Host/EditorWindowContentBindings.h"
#include <XCEditor/Docking/UIEditorDockHostTransfer.h>
#include <XCEditor/Foundation/UIEditorTextMeasurement.h>
#include <XCEditor/Windowing/Presentation/EditorWorkspaceWindowProjection.h>
#include <cstdint>
#include <filesystem>
#include <optional>
#include <string>
@@ -35,10 +33,6 @@ namespace XCEngine::UI::Editor {
struct UIEditorShellInteractionFrame;
struct UIEditorShellInteractionState;
namespace Widgets {
struct UIEditorDockHostDropPreviewState;
}
} // namespace XCEngine::UI::Editor
namespace XCEngine::UI::Editor::Rendering::Host {
@@ -52,12 +46,6 @@ namespace XCEngine::UI::Editor::App {
class EditorContext;
enum class EditorWindowContentCursorKind : std::uint8_t {
Arrow = 0,
ResizeEW,
ResizeNS,
};
struct EditorWindowContentCapabilities {
bool workspace = false;
bool dockHost = false;
@@ -67,51 +55,6 @@ struct EditorWindowContentCapabilities {
bool utilityPanel = false;
};
class EditorWindowWorkspaceBinding {
public:
virtual ~EditorWindowWorkspaceBinding() = default;
virtual const EditorWorkspaceWindowProjection* TryGetWorkspaceProjection() const = 0;
virtual void RefreshWorkspaceProjection(EditorWorkspaceWindowProjection projection) = 0;
};
class EditorWindowDockHostBinding {
public:
virtual ~EditorWindowDockHostBinding() = default;
virtual void SetExternalDockHostDropPreview(
const Widgets::UIEditorDockHostDropPreviewState& preview) = 0;
virtual void ClearExternalDockHostDropPreview() = 0;
virtual bool TryResolveDockTabDragHotspot(
std::string_view nodeId,
std::string_view panelId,
const ::XCEngine::UI::UIPoint& point,
::XCEngine::UI::UIPoint& outHotspot) const = 0;
virtual UIEditorDockHostTabDropTarget ResolveDockTabDropTarget(
const ::XCEngine::UI::UIPoint& point) const = 0;
};
class EditorWindowInputFeedbackBinding {
public:
virtual ~EditorWindowInputFeedbackBinding() = default;
virtual bool HasHostedContentCapture() const = 0;
virtual bool HasShellInteractiveCapture() const = 0;
virtual bool HasInteractiveCapture() const = 0;
virtual EditorWindowContentCursorKind GetHostedContentCursorKind() const = 0;
virtual EditorWindowContentCursorKind GetDockCursorKind() const = 0;
};
class EditorWindowTitleBarBinding {
public:
virtual ~EditorWindowTitleBarBinding() = default;
virtual bool ShouldUseDetachedTitleBarTabStrip() const = 0;
virtual std::string ResolveTabStripTitleText(std::string_view fallbackTitle) const = 0;
virtual std::string ResolveDetachedWindowTitleText(
std::string_view fallbackWindowTitle) const = 0;
};
struct EditorWindowContentInitializationContext {
const std::filesystem::path& repoRoot;
EditorContext& editorContext;

View File

@@ -1,7 +1,7 @@
#include "Windowing/EditorWindowInstance.h"
#include "Support/StringEncoding.h"
#include "Windowing/Content/EditorWindowContentController.h"
#include "Windowing/Host/EditorWindowContentBindings.h"
#include "Windowing/Runtime/EditorWindowRuntimeController.h"
#include <XCEditor/Docking/UIEditorDockHostTransfer.h>

View File

@@ -0,0 +1,77 @@
#pragma once
#include <XCEditor/Docking/UIEditorDockHostTransfer.h>
#include <XCEditor/Windowing/Presentation/EditorWorkspaceWindowProjection.h>
#include <cstdint>
#include <string>
#include <string_view>
namespace XCEngine::UI {
struct UIPoint;
} // namespace XCEngine::UI
namespace XCEngine::UI::Editor {
namespace Widgets {
struct UIEditorDockHostDropPreviewState;
}
} // namespace XCEngine::UI::Editor
namespace XCEngine::UI::Editor::App {
enum class EditorWindowContentCursorKind : std::uint8_t {
Arrow = 0,
ResizeEW,
ResizeNS,
};
class EditorWindowWorkspaceBinding {
public:
virtual ~EditorWindowWorkspaceBinding() = default;
virtual const EditorWorkspaceWindowProjection* TryGetWorkspaceProjection() const = 0;
virtual void RefreshWorkspaceProjection(EditorWorkspaceWindowProjection projection) = 0;
};
class EditorWindowDockHostBinding {
public:
virtual ~EditorWindowDockHostBinding() = default;
virtual void SetExternalDockHostDropPreview(
const Widgets::UIEditorDockHostDropPreviewState& preview) = 0;
virtual void ClearExternalDockHostDropPreview() = 0;
virtual bool TryResolveDockTabDragHotspot(
std::string_view nodeId,
std::string_view panelId,
const ::XCEngine::UI::UIPoint& point,
::XCEngine::UI::UIPoint& outHotspot) const = 0;
virtual UIEditorDockHostTabDropTarget ResolveDockTabDropTarget(
const ::XCEngine::UI::UIPoint& point) const = 0;
};
class EditorWindowInputFeedbackBinding {
public:
virtual ~EditorWindowInputFeedbackBinding() = default;
virtual bool HasHostedContentCapture() const = 0;
virtual bool HasShellInteractiveCapture() const = 0;
virtual bool HasInteractiveCapture() const = 0;
virtual EditorWindowContentCursorKind GetHostedContentCursorKind() const = 0;
virtual EditorWindowContentCursorKind GetDockCursorKind() const = 0;
};
class EditorWindowTitleBarBinding {
public:
virtual ~EditorWindowTitleBarBinding() = default;
virtual bool ShouldUseDetachedTitleBarTabStrip() const = 0;
virtual std::string ResolveTabStripTitleText(std::string_view fallbackTitle) const = 0;
virtual std::string ResolveDetachedWindowTitleText(
std::string_view fallbackWindowTitle) const = 0;
};
} // namespace XCEngine::UI::Editor::App