315 lines
14 KiB
Markdown
315 lines
14 KiB
Markdown
# XCUI Editor Agent Guide
|
|
|
|
This file documents the current editor architecture for agents working under
|
|
`editor/`. It describes the code that exists in this checkout, not a desired
|
|
future shape.
|
|
|
|
If this file conflicts with the current code, `editor/CMakeLists.txt`, or the
|
|
real directory tree, trust the code and update this file in the same change.
|
|
|
|
## Build Shape
|
|
|
|
The important production targets are:
|
|
|
|
- `XCUIEditorLib`: reusable XCEditor framework code from `editor/src` and
|
|
`editor/include/XCEditor`, including the reusable window authority,
|
|
synchronization planner, and presentation projection under
|
|
`XCEditor/Windowing`.
|
|
- `XCUIEditorAppWindowing`: app-internal static library for the current
|
|
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`.
|
|
Names such as `XCUIEditorAppCore`, `XCUIEditorAppLib`, and `XCUIEditorHost`
|
|
are not current production library boundaries in this checkout.
|
|
|
|
There is now a narrow public `editor/include/XCEditor/Windowing` layer for the
|
|
generic window authority model, synchronization plan/planner, and presentation
|
|
projection. App-specific window orchestration remains under
|
|
`editor/app/Windowing`, and the concrete Win32 host remains under
|
|
`editor/app/Platform/Win32`.
|
|
|
|
## Layering
|
|
|
|
Use these ownership boundaries when changing code:
|
|
|
|
- `editor/include/XCEditor` and `editor/src`: reusable editor framework.
|
|
Keep this layer independent from app state, Win32, D3D12 host code, and
|
|
`App::*` types.
|
|
- `editor/include/XCEditor/Windowing` and `editor/src/Windowing`: reusable
|
|
window authority, validation, synchronization planning, commit, and
|
|
presentation projection. Keep this layer generic and free of app content,
|
|
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`, `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, HWND ownership, and native host adapter behavior.
|
|
- `editor/app/Rendering`: editor rendering host and D3D12 integration.
|
|
|
|
The semantic dependency direction should remain:
|
|
|
|
```text
|
|
XCEditor framework
|
|
<- editor app semantics
|
|
<- app windowing runtime
|
|
<- Win32 host / rendering host
|
|
```
|
|
|
|
## Startup Flow
|
|
|
|
The application starts through:
|
|
|
|
```text
|
|
app/main.cpp
|
|
-> RunXCUIEditorApp
|
|
-> Application::Run
|
|
-> Application::Initialize
|
|
```
|
|
|
|
The primary workspace window is initialized through:
|
|
|
|
```text
|
|
EditorContext::BuildWorkspaceController()
|
|
-> EditorWindowSystem::BootstrapPrimaryWindow(...)
|
|
-> EditorWindowManager::CreateWorkspaceWindow(...)
|
|
-> EditorWindowContentFactory::CreateWorkspaceContentController(...)
|
|
-> 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
|
|
`EditorWindowWorkspaceStore`.
|
|
|
|
Normal per-frame workspace edits now use direct writes into that authoritative
|
|
state:
|
|
|
|
```text
|
|
EditorWorkspaceWindowContentController::UpdateAndAppend(...)
|
|
-> EditorWindowSystem::TryBuildLiveWindowWorkspaceController(windowId, ...)
|
|
-> UIEditorWorkspaceController::BindToState(...)
|
|
-> workspace operations mutate the bound authoritative workspace/session
|
|
```
|
|
|
|
The old normal path is obsolete:
|
|
|
|
```text
|
|
snapshot diff
|
|
-> workspaceMutation frame request
|
|
-> coordinator
|
|
-> synchronization plan
|
|
-> commit
|
|
```
|
|
|
|
Do not reintroduce `workspaceMutation` as the steady-state route for ordinary
|
|
layout, tab, visibility, or active-panel edits inside an existing workspace
|
|
window.
|
|
|
|
Cross-window create, update, close, and destroyed-window reconciliation still
|
|
use the planner/coordinator flow:
|
|
|
|
```text
|
|
target UIEditorWindowWorkspaceSet
|
|
-> EditorWindowSystem::BuildPlanForWindowSet(...)
|
|
-> EditorWindowWorkspaceCoordinator::ApplySynchronizationPlan(...)
|
|
-> EditorWindowSystem::CommitSynchronizationPlan(...)
|
|
```
|
|
|
|
`EditorWindowWorkspaceCoordinator::RefreshWindowPresentation(...)` refreshes
|
|
each workspace window projection from authoritative state. Presentation should
|
|
follow authority; it should not become a second source of truth.
|
|
|
|
## Frame Transfer Requests
|
|
|
|
`EditorWindowFrameTransferRequests` is only for host-side or cross-window side
|
|
effects that cannot be represented as direct in-window workspace edits.
|
|
|
|
Current request fields are:
|
|
|
|
- `workspace.beginGlobalTabDrag`
|
|
- `workspace.detachPanel`
|
|
- `utility.openUtilityWindow`
|
|
|
|
There is no `workspace.workspaceMutation` field in the current frame transfer
|
|
contract. Treat any doc, comment, or test name that says otherwise as stale.
|
|
|
|
## Window Categories
|
|
|
|
Workspace and utility windows share the native host path but use distinct
|
|
content controllers.
|
|
|
|
- Workspace windows use `EditorWorkspaceWindowContentController`.
|
|
- Utility windows use `EditorUtilityWindowContentController`.
|
|
- App windowing creates content through `EditorWindowContentFactory`.
|
|
- 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(...)`.
|
|
Register new utility windows there rather than hard-coding them in Win32 host
|
|
logic.
|
|
|
|
## Modification Rules
|
|
|
|
- First decide whether the change belongs to XCEditor framework, app semantics,
|
|
app windowing, Win32 host, or rendering host.
|
|
- Keep public framework headers free of `App::*`, Win32, and D3D12 host types.
|
|
- Do not add `editor/app` as an include directory for `XCUIEditorLib`.
|
|
App-only services must cross into framework code through framework-owned
|
|
interfaces and app-side adapters.
|
|
- Do not compile `${XCUI_EDITOR_SHARED_SOURCES}` directly into `XCUIEditorApp`;
|
|
the executable should consume shared framework code through `XCUIEditorLib`.
|
|
- Use `editor/include/XCEditor/Windowing` and `editor/src/Windowing` for
|
|
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.
|
|
- Use `editor/app/Platform/Win32` only for native host behavior and message
|
|
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 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
|
|
reconcile workspace windows.
|
|
- Use frame transfer requests only for host-side or cross-window effects.
|
|
|
|
## Current Architecture Debt
|
|
|
|
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, 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
|
|
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 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,
|
|
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
|
|
|
|
Default editor validation is only the app build plus the 12-second smoke run:
|
|
|
|
```powershell
|
|
cmake --build build --config Debug --target editor_ui_smoke_targets
|
|
build\tests\UI\Editor\smoke\Debug\editor_ui_smoke_runner.exe build\editor\Debug\XCEngine.exe
|
|
```
|
|
|
|
Do not run `editor_windowing_phase1_tests`, `editor_ui_tests`, or broader test
|
|
targets by default. Run them only when the user explicitly asks for them or a
|
|
separate targeted change makes them necessary.
|
|
|
|
The runner sets `XCUIEDITOR_SMOKE_TEST_DURATION_SECONDS=12`, waits for the
|
|
editor to launch, lets the app auto-exit, and treats a clean editor exit as
|
|
success.
|
|
|
|
## Recommended Reading
|
|
|
|
Start with these files for editor/windowing work:
|
|
|
|
- `editor/CMakeLists.txt`
|
|
- `editor/app/Bootstrap/Application.*`
|
|
- `editor/app/Composition/EditorContext.*`
|
|
- `editor/app/Composition/EditorShellRuntime.*`
|
|
- `editor/include/XCEditor/Workspace/UIEditorWorkspaceController.h`
|
|
- `editor/src/Workspace/UIEditorWorkspaceController.cpp`
|
|
- `editor/include/XCEditor/Windowing/System/EditorWindowSystem.h`
|
|
- `editor/include/XCEditor/Windowing/System/EditorWindowSynchronizationPlan.h`
|
|
- `editor/include/XCEditor/Windowing/System/EditorWindowSynchronizationPlanner.h`
|
|
- `editor/include/XCEditor/Windowing/Presentation/EditorWorkspaceWindowProjection.h`
|
|
- `editor/include/XCEditor/Windowing/Presentation/EditorWindowPresentationPolicy.h`
|
|
- `editor/src/Windowing/System/EditorWindowSystem.cpp`
|
|
- `editor/src/Windowing/System/EditorWindowWorkspaceStore.*`
|
|
- `editor/src/Windowing/System/EditorWindowSynchronizationPlanner.cpp`
|
|
- `editor/src/Windowing/Presentation/EditorWindowPresentationPolicy.cpp`
|
|
- `editor/app/Windowing/Host/EditorWindowHostInterfaces.h`
|
|
- `editor/app/Windowing/Content/EditorWindowContentController.h`
|
|
- `editor/app/Windowing/Content/EditorWindowContentFactory.*`
|
|
- `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.*`
|
|
- `editor/app/Platform/Win32/Windowing/EditorWindow.*`
|
|
- `editor/app/Platform/Win32/Windowing/EditorWindowHostRuntime.*`
|
|
- `editor/app/Platform/Win32/Windowing/EditorWindowMessageDispatcher.*`
|
|
- `tests/UI/Editor/smoke/CMakeLists.txt`
|
|
|
|
## Recent Cuts
|
|
|
|
- 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.
|