fix #390: retail display-change UI cascade — clamp + per-res reload
Decomp-first per the block's rule: the research doc
(docs/research/2026-08-13-retail-ui-display-change.md, committed here)
pulled retail's actual mechanism before any code. A display change runs
UIElementManager::RefreshEvent @0x0045C530 ->
UIElement::UpdateForParentSizeChange @0x00462640, which unconditionally
re-applies every floating window's own clamping MoveTo override
(x = max(0, min(x, parentW - selfW)) - top-left priority, oversized
windows pin to 0), then broadcasts global message 0xE whose sole
listener reloads the per-resolution auto layout. No proportional moves,
no resets; retail saves layouts only via @saveui.
Port: RetailWindowLayoutPersistence.ClampAllToScreen() is the cascade
clamp (no store I/O; _restoring suppresses the per-move save so a live
drag-resize cannot write settings.json per frame), and
RetailUiRuntime.Draw carries a two-step screen-size edge detector:
change frame -> clamp; first stable frame -> one
RestoreAll(saveBack:false) per-resolution reload (the 0xE analog; no
lazy save-back, matching retail's save-only-on-command). The login
restore path already used retail's exact clamp math (Apply) - the live
trigger was the missing half, which is precisely the stranding the user
reported.
Deliberate deviation, register AD-91: retail's gmFloatyChatUI windows
have NO clamp and can strand; the block's requirement ("UI windows must
stay reachable") clamps every registered window uniformly.
Tests: 5 new persistence facts (clamp/top-left-pin/no-move/no-save-on-
clamp/no-save-on-live-reload). App suite 4,967/3 skips. Gate script
section D3 filled in.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
8463d64311
commit
2153bee247
7 changed files with 620 additions and 10 deletions
|
|
@ -44,11 +44,28 @@ default) on first load.
|
|||
desktop's own mode — the deliberate replacement for retail's 800x600
|
||||
default; register row IA-22), and the dropdown shows it selected.
|
||||
|
||||
## §D3 — UI windows stay reachable on downscale (#390) — PENDING SLICE
|
||||
## §D3 — UI windows stay reachable on downscale (#390)
|
||||
|
||||
*(To be filled in when the retail reposition mechanism lands. The test
|
||||
shape will be: park panels near the right/bottom edges at 2560x1440, pick
|
||||
1280x720, and confirm every window is still reachable per retail's rule.)*
|
||||
Retail's rule, ported exactly: on a display change every floating window
|
||||
re-clamps to `x = max(0, min(x, screenW − windowW))` — top-left priority —
|
||||
and the per-resolution saved layout for the NEW size reloads (without
|
||||
saving anything until you save).
|
||||
|
||||
1. **At 2560x1440, drag several windows to the edges** — chat to the
|
||||
bottom-right corner, the Options panel far right, a floating chat too.
|
||||
2. **Pick 1280x720 in the Resolution dropdown.** Every window must end up
|
||||
fully inside the new screen — anything that was past the new bounds
|
||||
slides in flush with the edge; nothing needs a window-resize to fetch
|
||||
back. (This includes floating chat windows — retail actually strands
|
||||
those; we clamp them by the block's own requirement, register AD-91.)
|
||||
3. **Drag-resize the window edge smaller** (not via the dropdown). Windows
|
||||
must stay reachable continuously while you drag — the clamp runs live.
|
||||
4. **Per-resolution memory:** at 1280x720 move a window somewhere
|
||||
distinctive, pick 2560x1440, then pick 1280x720 again — the window
|
||||
returns to where 1280x720 last had it (each resolution keeps its own
|
||||
layout, like retail's per-resolution auto layouts — YOUR drags save
|
||||
immediately under the current resolution; the automatic clamp/reload on
|
||||
a resolution change never writes anything).
|
||||
|
||||
## §D4–§D6 — Fullscreen family (#377/#376/#388) — PENDING SLICES
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue