fix(new_editor): finalize synchronous resize presentation cleanup
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
# NewEditor Frame Resize Synchronous Presentation Root Fix Plan
|
||||
|
||||
Date: 2026-04-22
|
||||
Status: Completed Archive
|
||||
|
||||
## 1. Objective
|
||||
|
||||
Restore the original `new_editor` resize-time anti-deformation contract without adding fallback branches, duplicated resize paths, or new ownership confusion.
|
||||
|
||||
The fix must re-establish one clean rule:
|
||||
|
||||
1. when a host-side transition needs a new window size before the native window visibly adopts it, the window content must be rendered synchronously for that target size
|
||||
2. when Win32 enters paint / size / DPI lifecycle messages, the host must be able to drive a synchronous frame before returning control
|
||||
3. normal steady-state rendering must remain on the centralized frame driver path
|
||||
|
||||
## 2. Confirmed Root Cause
|
||||
|
||||
The regression was introduced by commit `b44f5ca9` (`refactor(new_editor): centralize win32 frame execution`).
|
||||
|
||||
That refactor removed the synchronous render step from the critical resize path:
|
||||
|
||||
1. `EditorWindowChromeController::HandleResizePointerMove(...)`
|
||||
2. `EditorWindowChromeController::ApplyPredictedWindowRectTransition(...)`
|
||||
3. `EditorWindowMessageDispatcher` handling of `WM_SIZE`, `WM_DPICHANGED`, `WM_EXITSIZEMOVE`, and `WM_PAINT`
|
||||
|
||||
and replaced it with deferred `RequestFrame(...)` bookkeeping.
|
||||
|
||||
That bookkeeping does not preserve the old contract because:
|
||||
|
||||
1. `RequestFrame(...)` only records a bitmask
|
||||
2. rendering now happens later from the app main loop
|
||||
3. the window can already be resized before the new frame is presented
|
||||
4. the old presented surface is therefore stretched by the platform / swap chain path
|
||||
|
||||
This means the actual regression is not the custom title bar itself. The regression is the loss of synchronous presentation ownership in the Win32 host lifecycle.
|
||||
|
||||
## 3. Red Lines
|
||||
|
||||
The implementation must not:
|
||||
|
||||
1. add a second resize algorithm beside the current borderless resize path
|
||||
2. add ad hoc `if (interactiveResize)` branches throughout unrelated rendering code
|
||||
3. keep a dead frame-request state machine that no longer owns rendering policy
|
||||
4. duplicate `RenderFrame(...)` orchestration in multiple modules
|
||||
5. touch workspace transfer / docking semantics unrelated to resize-time presentation
|
||||
|
||||
## 4. Target End State
|
||||
|
||||
After the fix:
|
||||
|
||||
1. `EditorWindowFrameDriver` remains the single general-purpose frame execution entry point
|
||||
2. synchronous Win32 lifecycle rendering uses that same driver wherever possible
|
||||
3. `WM_PAINT` remains a special case only because it requires `BeginPaint` / `EndPaint`
|
||||
4. borderless predicted transitions render the target-size frame synchronously before `SetWindowPos(...)`
|
||||
5. dead `RequestFrame(...)` / `EditorWindowFrameRequestReason` plumbing is removed if it no longer owns any real policy
|
||||
|
||||
## 5. Implementation Plan
|
||||
|
||||
### Phase A. Remove the dead deferred frame-request layer
|
||||
|
||||
Completed on 2026-04-22.
|
||||
|
||||
1. removed `EditorWindowFrameRequestReason`
|
||||
2. removed `EditorWindow::RequestFrame(...)`
|
||||
3. removed `EditorWindow::ConsumePendingFrameRequestReasons()`
|
||||
4. removed all call sites that only existed to defer rendering into the main loop
|
||||
|
||||
### Phase B. Rebuild one synchronous frame-execution helper path
|
||||
|
||||
Completed on 2026-04-22.
|
||||
|
||||
1. kept `EditorWindowFrameDriver::DriveFrame(...)` as the shared frame executor
|
||||
2. added a dispatcher-local helper that drives a frame immediately and forwards transfer requests to `EditorWindowWorkspaceCoordinator`
|
||||
3. restored that helper to `WM_SIZE`, `WM_DPICHANGED`, and `WM_EXITSIZEMOVE`
|
||||
|
||||
### Phase C. Restore paint-time synchronous rendering
|
||||
|
||||
Completed on 2026-04-22.
|
||||
|
||||
1. restored `WM_PAINT` to render synchronously inside the paint handling path
|
||||
2. kept the paint special case local to `BeginPaint` / `EndPaint`
|
||||
|
||||
### Phase D. Restore predicted-transition pre-presentation
|
||||
|
||||
Completed on 2026-04-22.
|
||||
|
||||
1. `HandleResizePointerMove(...)` once again renders the target-size frame synchronously before `SetWindowPos(...)`
|
||||
2. `ApplyPredictedWindowRectTransition(...)` does the same for maximize / restore style transitions
|
||||
3. this was restored on the original transition path without adding a second resize subsystem
|
||||
|
||||
### Phase E. Verify no unrelated ownership was widened
|
||||
|
||||
Completed on 2026-04-22.
|
||||
|
||||
1. workspace transfer / docking semantics were left untouched
|
||||
2. `EditorWindowHostRuntime::RenderAllWindows(...)` still owns steady-state frame pumping
|
||||
3. only Win32 host lifecycle and predicted transition code were changed
|
||||
|
||||
## 6. Validation Requirements
|
||||
|
||||
Validation completed on 2026-04-22:
|
||||
|
||||
1. `XCUIEditorApp` Debug build passed after the fix
|
||||
2. user verified the resize deformation regression was gone in actual runtime
|
||||
|
||||
Pending after this archive:
|
||||
|
||||
1. follow-up investigation for remaining resize jitter
|
||||
2. any later refinement should stay on the same host lifecycle boundary and must not reintroduce a deferred fake scheduling layer
|
||||
|
||||
## 7. Completion Criteria
|
||||
|
||||
This work was completed with the following outcomes:
|
||||
|
||||
1. the regression source introduced by `b44f5ca9` was structurally removed
|
||||
2. one clear synchronous presentation path was restored for resize-time lifecycle transitions
|
||||
3. the dead deferred request layer was removed
|
||||
4. the resulting code path remained a mainline host-lifecycle design instead of a post hoc fallback patch
|
||||
Reference in New Issue
Block a user