# Retail shared main-panel geometry — pseudocode **Date:** 2026-07-17 **Symptom:** moving Inventory and then opening Character/Skills or Magic opens the new panel at its own stale saved position instead of the position just used. ## Retail oracle Named Sept-2013 retail symbols: - `gmPanelUI::SetupChildren @ 0x004BC9E0` - `gmPanelUI::RecvNotice_SetPanelVisibility @ 0x004BC6F0` - `gmPanelUI::PostInit @ 0x004BD010` - `gmPanelUI::ResizeTo @ 0x004BC6E0` Verbatim `acclient.h` ownership: ```text gmPanelUI : UIElement_Field SmartArray m_childrenInfoArray UIElement* m_currentlyShownPanel UIElement* m_previouslyShownPanel UIElement* m_pPanelPagesFrame bool m_bStretchMode PanelChildInfo UIElement* child uint panelID ``` `SetupChildren` resolves each known panel element recursively, stores the child pointer together with its property-`0x10000029` panel ID, and initially hides every child. It does not create independent top-level windows. ## Retail behavior ```text SetPanelVisibility(panelId, show): requested = find m_childrenInfoArray entry by panelId if requested is missing: return if show: if requested.child == m_currentlyShownPanel: requested.child.SetVisible(true) parent.SetVisible(true) return previous = m_currentlyShownPanel m_currentlyShownPanel = requested.child if previous is visible: if requested restores previous and previous does not: m_previouslyShownPanel = previous else: m_previouslyShownPanel = null send SetPanelVisibility(previous.panelID, false) requested.child.SetVisible(true) parent.SetVisible(true) return if requested.child == m_currentlyShownPanel: requested.child.SetVisible(false) if m_previouslyShownPanel exists: send SetPanelVisibility(previous.panelID, true) m_previouslyShownPanel = null else: m_currentlyShownPanel = null parent.SetVisible(false) return requested.child.SetVisible(false) ``` The decisive geometry fact is structural: Inventory, Character Information, Character/Skills, Magic, Effects, and the other detail pages are children of one `gmPanelUI`. The switch changes child visibility; there is no child move, resize, or per-panel top-level rectangle. Moving or resizing the parent therefore changes the one rectangle subsequently used by every child. ## Resize follow-up The production end-of-retail LayoutDesc supplies the missing geometry oracle: ```text LayoutDesc 0x2100006E gmPanelUI host 0x100005FE 310 x 372 content parent 0x10000180 300 x 362, anchored on all edges Character Information 0x10000183 panel 3, 300 x 362 Helpful Effects 0x10000184 panel 4, 300 x 362 Harmful Effects 0x10000185 panel 5, 300 x 362 Inventory child 0x1000018B panel 7, 300 x 362 Character/Skills child 0x1000018E panel 11, 300 x 362 Magic child 0x10000190 panel 13, 300 x 362 top-center 0x1000065C Type 2 Dragbar, cursor 0x06006119 bottom-center 0x10000660 Type 9 Resizebar, cursor 0x06005E66 ``` Every primary child therefore participates in the shared host's vertical resize; Magic is not a fixed-height exception. Named `gmPanelUI::ResizeTo @ 0x004BC6E0` delegates directly to `UIElement::ResizeTo @ 0x00463C30`, whose only size limits are effective DAT properties `0x3C..0x3F`. There is no retail 760-pixel Character limit and no maximum captured from the host's original screen position. acdream retains independent wrappers under IA-12, so the faithful adaptation is to give each registered child wrapper the same bottom-only vertical resize policy, leave its maximum unbounded by an authored substitute, and calculate the available desktop extent from its current position during the resize. The viewport remains the physical limit; an old static maximum must not become a smaller limit after the shared panel moves. ## acdream port shape acdream imports these child LayoutDesc roots independently, so each currently has its own retained wrapper. `RetailPanelUiController` already ports retail's one-active-child and restore-previous lifecycle. Complete that logical-parent ownership by adding one canonical rectangle for all registered main-panel children, including Character Information `3`, Helpful/Harmful `4`/`5`, Inventory `7`, Character/Skills `11`, and Magic `13`: ```text on registered child frame moved or resized: canonicalGeometry = frame left, top, width, height apply canonicalGeometry to every hidden sibling before showing a registered child: if canonicalGeometry exists: apply canonicalGeometry to requested child frame else: canonicalGeometry = requested child frame geometry before hiding the active child: capture its current geometry as canonicalGeometry ``` The controller owns this synchronization and subscribes to typed `RetailWindowHandle.Moved` and `Resized` events. Toolbar, indicator, and keyboard commands, restore-previous effects, persistence restore, and direct window dragging all therefore pass through the same owner. Each wrapper retains its own imported content tree, but its outer rectangle and bottom-only resize contract mirror the shared retail host. ACE contains no client UI implementation, and the in-tree WorldBuilder reference contains no `gmPanelUI` port, so neither supplies a competing behavioral interpretation. The named retail client and verbatim header are the oracle for this UI ownership rule.