diff --git a/editor/AGENTS.md b/editor/AGENTS.md index bacd846c..34dcefb5 100644 --- a/editor/AGENTS.md +++ b/editor/AGENTS.md @@ -16,8 +16,8 @@ The important production targets are: synchronization planner, and presentation projection under `XCEditor/Windowing`. - `XCUIEditorAppWindowing`: app-internal static library for the current - host contracts, content controllers, coordinators, frame transfer flow, and - window manager. + host contracts, content controllers, coordinators, frame transfer flow, + runtime controllers, and window manager. - `XCUIEditorApp`: concrete editor executable. Its output name is `XCEngine`. Do not invent target boundaries that are not present in `editor/CMakeLists.txt`. @@ -43,10 +43,11 @@ Use these ownership boundaries when changing code: host runtime, native platform, and rendering details. - `editor/app/Composition`, `Commands`, `Features`, `Project`, `Scene`, `State`, `System`, `UtilityWindows`: editor product semantics. -- `editor/app/Windowing/Content`, `Coordinator`, `Frame`, `Host`: platform - neutral app window orchestration. +- `editor/app/Windowing/Content`, `Coordinator`, `Frame`, `Host`, `Runtime`: + app window orchestration, content ownership, frame driving, frame transfer, + and per-window runtime state. - `editor/app/Platform/Win32`: native window, message dispatch, input, - lifecycle, chrome, and concrete host runtime. + lifecycle, chrome, HWND ownership, and native host adapter behavior. - `editor/app/Rendering`: editor rendering host and D3D12 integration. The semantic dependency direction should remain: @@ -76,12 +77,35 @@ EditorContext::BuildWorkspaceController() -> EditorWindowSystem::BootstrapPrimaryWindow(...) -> EditorWindowManager::CreateWorkspaceWindow(...) -> EditorWindowContentFactory::CreateWorkspaceContentController(...) - -> EditorWindowHostRuntime::CreateHostWindow(...) + -> EditorWindowRuntimeController(EditorContext, contentController) + -> EditorWindowHostRuntime::CreateHostWindow(runtimeController, ...) ``` Keep authoritative window bootstrap in `EditorWindowSystem`; do not move it back into the Win32 host. +## Frame Runtime Ownership + +`EditorWindowManager` owns steady-state frame iteration and the immediate-frame +callbacks used by native paint, resize, maximize/restore, and chrome actions. +The Win32 host may request a frame through `EditorWindowHostCoordinator`, but it +must not own the editor frame loop or fetch `EditorContext`. + +`EditorWindowRuntimeController` lives under `editor/app/Windowing/Runtime`. +App windowing creates it from `EditorContext` plus a workspace or utility +content controller, then passes it to the native host. The Win32 host stores and +calls the runtime controller, but it does not create content controllers and it +does not receive `EditorContext`. + +The host contract direction is: + +```text +EditorWindowManager / coordinators + -> create EditorWindowRuntimeController + -> EditorWindowHostRuntime::CreateHostWindow(runtimeController, ...) + -> Win32 EditorWindow owns HWND and delegates frame work to the runtime +``` + ## Window Authority Model `EditorWindowSystem` owns the authoritative `UIEditorWindowWorkspaceSet` through @@ -147,8 +171,9 @@ content controllers. - Workspace windows use `EditorWorkspaceWindowContentController`. - Utility windows use `EditorUtilityWindowContentController`. - App windowing creates content through `EditorWindowContentFactory`. -- The concrete host validates `EditorWindowContentCapabilities` when a native - host window is created. +- App windowing wraps content in `EditorWindowRuntimeController`. +- The concrete host validates `EditorWindowContentCapabilities` through the + runtime controller when a native host window is created. Utility windows are descriptor driven through `EditorUtilityWindowDescriptor`, `EditorUtilityWindowRegistry`, and `CreateEditorUtilityWindowPanel(...)`. @@ -169,13 +194,17 @@ logic. generic window authority, synchronization, validation, and presentation projection. - Use `editor/app/Windowing` for app-specific window runtime semantics, - content, frame transfer, host contracts, and coordinators. + content, frame transfer, host contracts, runtime controllers, and + coordinators. - Use `editor/app/Platform/Win32` only for native host behavior and message - integration. -- Do not let `editor/app/Windowing` include `Platform/Win32` or D3D12 concrete - host headers. + integration. Win32 code may request frames through the host coordinator; it + must not own the editor frame loop or expose `EditorContext`. +- Do not let `editor/app/Windowing` include `Platform/Win32` headers. +- Keep concrete rendering details inside `editor/app/Windowing/Runtime` or + `editor/app/Rendering`; do not spread D3D12 host types into content, + coordinator, frame-transfer, or public host-contract headers. - Do not let Win32 host code create workspace or utility content directly. - It should receive content through the app-windowing host contract. + It should receive an `EditorWindowRuntimeController` created by app windowing. - Use direct authoritative workspace binding for ordinary in-window workspace mutations. - Use synchronization plans for operations that create, close, replace, or @@ -187,9 +216,10 @@ logic. The highest-value windowing boundary has been hardened: `XCUIEditorLib` now owns the reusable window authority, synchronization planner, workspace store, and presentation projection under `XCEditor/Windowing`. `XCUIEditorAppWindowing` -owns the app-internal content controller factory, coordinators, frame transfer -flow, host contracts, and manager. The Win32 host is the concrete native -adapter and creates native host windows from content supplied by app windowing. +owns the app-internal content controller factory, runtime controllers, +coordinators, frame transfer flow, host contracts, and manager. The Win32 host +is the concrete native adapter and creates native host windows from runtime +controllers supplied by app windowing. The framework/app compile boundary is also enforced. `XCUIEditorLib` does not receive `editor/app` includes, and `XCUIEditorApp` does not directly compile @@ -197,11 +227,19 @@ the shared framework sources. When framework UI code needs app-provided data such as loaded icons, expose a framework-owned interface and adapt it in app composition code. -The main remaining debt is promotion discipline around the app runtime surface. +The main windowing debt that was previously in the Win32 host has been cut: +frame iteration, immediate frame driving, content-controller construction, and +`EditorContext` ownership now live in app windowing. `EditorWindowHostCoordinator` +does not expose `GetEditorContext()`, and the native host receives an +`EditorWindowRuntimeController` rather than raw workspace/utility content. + +The remaining promotion debt is the app runtime surface itself. `XCUIEditorAppWindowing` is still app-internal and may depend on app semantics -such as `EditorContext`, `EditorShellRuntime`, utility window descriptors, and -product-specific content. Do not promote host interfaces, frame transfer, or -content controllers to `XCEditor` until they are generic enough to expose. +such as `EditorContext`, `EditorShellRuntime`, utility window descriptors, +product-specific content, and the current D3D12 window render loop. Do not +promote host interfaces, frame transfer, runtime controllers, or content +controllers to `XCEditor` until they are generic enough to expose. Do not move +frame ownership back into `editor/app/Platform/Win32`. ## Validation @@ -245,6 +283,8 @@ Start with these files for editor/windowing work: - `editor/app/Windowing/Content/EditorWorkspaceWindowContentController.*` - `editor/app/Windowing/Frame/EditorWindowFrameOrchestrator.*` - `editor/app/Windowing/Frame/EditorWindowTransferRequests.h` +- `editor/app/Windowing/Runtime/EditorWindowRuntimeController.*` +- `editor/app/Windowing/Runtime/EditorWindowScreenshotController.*` - `editor/app/Windowing/Coordinator/EditorWindowWorkspaceCoordinator.*` - `editor/app/Windowing/Coordinator/EditorUtilityWindowCoordinator.*` - `editor/app/Windowing/EditorWindowManager.*` @@ -253,22 +293,22 @@ Start with these files for editor/windowing work: - `editor/app/Platform/Win32/Windowing/EditorWindowMessageDispatcher.*` - `tests/UI/Editor/smoke/CMakeLists.txt` -## 前面几刀 +## Recent Cuts -- 最近一刀封死 framework -> app 的反向依赖:`UIEditorShellCompose` - 不再认识 `App::BuiltInIcons`,改由 `UIEditorShellIconResolver` 抽象取图标, - app 在 `EditorShellDrawComposer` 里用 adapter 连接 `BuiltInIcons`。 -- 同一刀收紧构建边界:`XCUIEditorLib` 不再拥有 `editor/app` include, - `XCUIEditorApp` 不再直接编译 `${XCUI_EDITOR_SHARED_SOURCES}`,也不再把 - `editor/src` 加进 include;app 通过 `XCUIEditorLib` 消费 framework。 -- 前一刀把窗口权威核心切到 framework:`EditorWindowSystem`、同步计划/规划器、 - workspace store 和 presentation projection 位于 `editor/include/XCEditor/Windowing` - 与 `editor/src/Windowing`。 -- `editor/app/Windowing` 保留 app-specific 的 content controllers、coordinators、 - frame transfer、host contracts 和 `EditorWindowManager`;Win32 host 仍只做 - native adapter。 -- 未提升到 `XCEditor` 的内容包括 `EditorContext`、`EditorShellRuntime`、utility - descriptors/panels、host interfaces、content controllers、coordinators、 - frame transfer 和 Win32/D3D12 host。 -- 默认验证也收口:只构建 `XCUIEditorApp` 相关 smoke 目标并跑 12 秒 smoke; - 需要专项覆盖时再单独运行 windowing/unit targets。 +- The framework-to-app icon dependency is sealed: `UIEditorShellCompose` uses + the framework-owned `UIEditorShellIconResolver`, and the app adapts + `BuiltInIcons` in `EditorShellDrawComposer`. +- The framework/app compile boundary is sealed: `XCUIEditorLib` does not receive + `editor/app` includes, `XCUIEditorApp` does not directly compile + `${XCUI_EDITOR_SHARED_SOURCES}`, and the app consumes framework code through + `XCUIEditorLib`. +- The reusable window authority core lives in the framework: + `EditorWindowSystem`, synchronization planning, workspace store, and + presentation projection are under `editor/include/XCEditor/Windowing` and + `editor/src/Windowing`. +- App windowing owns the runtime cut: content controllers, + `EditorWindowRuntimeController`, frame driving, frame transfer, host + contracts, and `EditorWindowManager` are under `editor/app/Windowing`; Win32 + remains the native adapter and no longer exposes `EditorContext`. +- Default validation remains the editor app build plus the 12-second smoke run; + run broader windowing/unit targets only for targeted coverage. diff --git a/editor/app/Windowing/Coordinator/EditorUtilityWindowCoordinator.cpp b/editor/app/Windowing/Coordinator/EditorUtilityWindowCoordinator.cpp index 54afe2cf..f2312617 100644 --- a/editor/app/Windowing/Coordinator/EditorUtilityWindowCoordinator.cpp +++ b/editor/app/Windowing/Coordinator/EditorUtilityWindowCoordinator.cpp @@ -7,6 +7,7 @@ #include "Windowing/Runtime/EditorWindowRuntimeController.h" #include +#include namespace XCEngine::UI::Editor::App { diff --git a/editor/app/Windowing/Coordinator/EditorWindowWorkspaceCoordinator.cpp b/editor/app/Windowing/Coordinator/EditorWindowWorkspaceCoordinator.cpp index 6128ca84..08dc4a63 100644 --- a/editor/app/Windowing/Coordinator/EditorWindowWorkspaceCoordinator.cpp +++ b/editor/app/Windowing/Coordinator/EditorWindowWorkspaceCoordinator.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include diff --git a/editor/app/Windowing/EditorWindowManager.cpp b/editor/app/Windowing/EditorWindowManager.cpp index 95562f5a..32fc86e1 100644 --- a/editor/app/Windowing/EditorWindowManager.cpp +++ b/editor/app/Windowing/EditorWindowManager.cpp @@ -9,6 +9,7 @@ #include +#include #include #include diff --git a/editor/app/Windowing/Runtime/EditorWindowRuntimeController.cpp b/editor/app/Windowing/Runtime/EditorWindowRuntimeController.cpp index 35992765..3468ca36 100644 --- a/editor/app/Windowing/Runtime/EditorWindowRuntimeController.cpp +++ b/editor/app/Windowing/Runtime/EditorWindowRuntimeController.cpp @@ -15,6 +15,8 @@ #include #include +#include + namespace XCEngine::UI::Editor::App { using App::LoadEmbeddedPngTexture; @@ -122,10 +124,11 @@ const ::XCEngine::UI::UITextureHandle& EditorWindowRuntimeController::GetTitleBa } bool EditorWindowRuntimeController::Initialize( - HWND hwnd, + void* nativeWindowHandle, const std::filesystem::path& repoRoot, const std::filesystem::path& captureRoot, bool autoCaptureOnStartup) { + HWND hwnd = static_cast(nativeWindowHandle); if (hwnd == nullptr) { LogRuntimeTrace("app", "window initialize skipped: hwnd is null"); return false; @@ -247,7 +250,7 @@ void EditorWindowRuntimeController::ResetInteractionState() { ResetFrameTiming(); } -bool EditorWindowRuntimeController::ApplyResize(UINT width, UINT height) { +bool EditorWindowRuntimeController::ApplyResize(std::uint32_t width, std::uint32_t height) { if (!m_ready || width == 0u || height == 0u) { return false; } diff --git a/editor/app/Windowing/Runtime/EditorWindowRuntimeController.h b/editor/app/Windowing/Runtime/EditorWindowRuntimeController.h index 962bd8d3..437f5367 100644 --- a/editor/app/Windowing/Runtime/EditorWindowRuntimeController.h +++ b/editor/app/Windowing/Runtime/EditorWindowRuntimeController.h @@ -15,9 +15,8 @@ #include -#include - #include +#include #include #include #include @@ -66,13 +65,13 @@ public: const ::XCEngine::UI::UITextureHandle& GetTitleBarLogoIcon() const; bool Initialize( - HWND hwnd, + void* nativeWindowHandle, const std::filesystem::path& repoRoot, const std::filesystem::path& captureRoot, bool autoCaptureOnStartup); void Shutdown(); void ResetInteractionState(); - bool ApplyResize(UINT width, UINT height); + bool ApplyResize(std::uint32_t width, std::uint32_t height); void PrepareEditorContext(); bool IsEditorContextValid() const;