From a3e2e2b4a9d9d07b04e1479b4ed70aed188864c8 Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Sun, 26 Apr 2026 23:49:25 +0800 Subject: [PATCH] Seal editor host content binding boundary --- editor/AGENTS.md | 42 +++++++--- .../Chrome/EditorWindowChromeController.cpp | 2 +- .../Platform/Win32/Windowing/EditorWindow.cpp | 2 +- .../EditorWindowMessageDispatcher.cpp | 2 +- .../Content/EditorWindowContentController.h | 59 +------------- editor/app/Windowing/EditorWindowInstance.cpp | 2 +- .../Host/EditorWindowContentBindings.h | 77 +++++++++++++++++++ 7 files changed, 115 insertions(+), 71 deletions(-) create mode 100644 editor/app/Windowing/Host/EditorWindowContentBindings.h diff --git a/editor/AGENTS.md b/editor/AGENTS.md index 551c2d59..f603b141 100644 --- a/editor/AGENTS.md +++ b/editor/AGENTS.md @@ -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`. diff --git a/editor/app/Platform/Win32/Chrome/EditorWindowChromeController.cpp b/editor/app/Platform/Win32/Chrome/EditorWindowChromeController.cpp index ca526344..76744e6f 100644 --- a/editor/app/Platform/Win32/Chrome/EditorWindowChromeController.cpp +++ b/editor/app/Platform/Win32/Chrome/EditorWindowChromeController.cpp @@ -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 diff --git a/editor/app/Platform/Win32/Windowing/EditorWindow.cpp b/editor/app/Platform/Win32/Windowing/EditorWindow.cpp index 0d83ee01..b448ae42 100644 --- a/editor/app/Platform/Win32/Windowing/EditorWindow.cpp +++ b/editor/app/Platform/Win32/Windowing/EditorWindow.cpp @@ -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 #include #include diff --git a/editor/app/Platform/Win32/Windowing/EditorWindowMessageDispatcher.cpp b/editor/app/Platform/Win32/Windowing/EditorWindowMessageDispatcher.cpp index 99703834..027aacab 100644 --- a/editor/app/Platform/Win32/Windowing/EditorWindowMessageDispatcher.cpp +++ b/editor/app/Platform/Win32/Windowing/EditorWindowMessageDispatcher.cpp @@ -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 diff --git a/editor/app/Windowing/Content/EditorWindowContentController.h b/editor/app/Windowing/Content/EditorWindowContentController.h index 4882e4d1..71fdebe9 100644 --- a/editor/app/Windowing/Content/EditorWindowContentController.h +++ b/editor/app/Windowing/Content/EditorWindowContentController.h @@ -1,12 +1,10 @@ #pragma once #include "Windowing/Frame/EditorWindowTransferRequests.h" +#include "Windowing/Host/EditorWindowContentBindings.h" -#include #include -#include -#include #include #include #include @@ -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; diff --git a/editor/app/Windowing/EditorWindowInstance.cpp b/editor/app/Windowing/EditorWindowInstance.cpp index 4170f8c2..ce83b38c 100644 --- a/editor/app/Windowing/EditorWindowInstance.cpp +++ b/editor/app/Windowing/EditorWindowInstance.cpp @@ -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 diff --git a/editor/app/Windowing/Host/EditorWindowContentBindings.h b/editor/app/Windowing/Host/EditorWindowContentBindings.h new file mode 100644 index 00000000..d172f1f9 --- /dev/null +++ b/editor/app/Windowing/Host/EditorWindowContentBindings.h @@ -0,0 +1,77 @@ +#pragma once + +#include +#include + +#include +#include +#include + +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