#140 glass_layout.cfg lost every MFD line on a desktop teardown

Regression from d213c98 (the pod PadRIO/panel coupling fix).

BTGlassPanels_Destroy calls SaveLayout FIRST, unconditionally, before it
looks at whether any windows are left.  d213c98 added a SECOND caller
(~LBE4ControlsManager) alongside the existing one in ~PadRIO, so on the
desktop path both run: ~LBE4ControlsManager does `delete rioPointer`, which
fires ~PadRIO -> destroy #1 saves the live windows and zeroes gWinCount ->
destroy #2 then rewrites the whole file from an empty list.

Why only the MFDs vanished, which is the detail that identifies it: external
windows (plasma) already cached a last-known rect (gExtern[].haveLast) and
were written from the cache; the per-display glass windows had no cache and
were simply skipped once their HWND was gone.  Hence the reported signature,
"all the MFDs and secondary lines missing, but plasma was still there".

The pod was never affected -- no PadRIO there, so only one destroy, and it
runs BT_GLASS_LAYOUT=load off a frozen master regardless.

Two fixes, because the guard alone would leave the trap armed for the next
teardown-ordering change:
  1. glass windows get the same remembered-geometry cache the extern windows
     have, kept ACROSS teardown.  The file is now monotonic -- a save can
     update a line or add one, never drop one.
  2. the teardown save is guarded on there being windows to report.

Also corrects the comment at the L4CTRL call site, which claimed the second
call was "a no-op on the PadRIO path".  That claim is what made it look safe.

Verified (scratchpad/night13/layoutsave.sh -- the tester's round trip, not a
single launch, since the report was "saved fine, reset on relaunch"):
  run 1  one "saved 8 window position(s)" line (was two, the second wiping)
         cfg holds all 7 glass windows + plasma
  run 2  "restored 7 window position(s)", cfg byte-identical after the trip

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NCJQkvq6G2JNrpVbA75tVZ
This commit is contained in:
Joe DiPrima
2026-08-07 01:03:32 -05:00
co-authored by Claude Opus 5
parent 6a96fb6420
commit c04bec0a52
3 changed files with 146 additions and 14 deletions
+67
View File
@@ -0,0 +1,67 @@
#!/usr/bin/env bash
# =========================================================================
# #140 glass_layout.cfg save regression -- the FIELD composition.
#
# SAURON's report: "set my glass panels, saved and borders off ... relaunched
# and it reset again ... the glass_layout.cfg had all the MFDs and secondary
# lines missing, but plasma was still there".
#
# So the acceptance test is the full ROUND TRIP a tester does, not just a
# single launch:
# run 1 -- BT_GLASS_LAYOUT=save, panels come up, quit cleanly
# check -- the cfg must list every MFD + the radar, not just plasma
# run 2 -- relaunch; the panels must come back where they were
#
# The teardown is what mattered: BTGlassPanels_Destroy has TWO callers on the
# desktop path (~PadRIO, then ~LBE4ControlsManager), and it ran SaveLayout
# BEFORE checking whether any windows were left -- so the second pass rewrote
# the file from an empty list.
# =========================================================================
set -x
. /c/git/bt411/scratchpad/night6/bench_common.sh
cd /c/git/bt411/content || exit 1
taskkill //F //IM btl4.exe > /dev/null 2>&1
sleep 2
rm -f glass_layout.cfg ls_run1.log ls_run2.log
# ---- run 1: create the layout ------------------------------------------
( export BT_GLASS_PANELS=1 BT_GLASS_LAYOUT=save
bt_launch ls_run1.log ARENA1.EGG 0x03 )
sleep 55
bt_kill_ours
sleep 2
taskkill //F //IM btl4.exe > /dev/null 2>&1
sleep 3
echo "############ RUN 1 SAVE RESULT ############"
echo "--- every 'saved N window position(s)' line (the double-save shows here) ---"
grep -a "window position" ls_run1.log
echo
echo "--- glass_layout.cfg AFTER a clean quit ---"
if [ -f glass_layout.cfg ]; then cat glass_layout.cfg; else echo "!!! NO FILE WRITTEN"; fi
echo
echo "--- line census (comments excluded) ---"
echo -n "total entries : "; grep -acE "^[^#]+=" glass_layout.cfg 2>/dev/null
echo -n "MFD lines : "; grep -acE "^(Heat|Comm|Mfd|Eng|Weap|Sec)" glass_layout.cfg 2>/dev/null
echo -n "plasma line : "; grep -ac "Plasma" glass_layout.cfg 2>/dev/null
cp glass_layout.cfg /tmp/ls_after_run1.cfg 2>/dev/null
# ---- run 2: does it RESTORE? -------------------------------------------
( export BT_GLASS_PANELS=1 BT_GLASS_LAYOUT=save
bt_launch ls_run2.log ARENA1.EGG 0x03 )
sleep 55
bt_kill_ours
sleep 2
taskkill //F //IM btl4.exe > /dev/null 2>&1
sleep 3
echo "############ RUN 2 (RELAUNCH) ############"
echo "--- restore receipts ---"
grep -aE "restored|glass_layout|window position" ls_run2.log | head -12
echo
echo "--- cfg after run 2 -- must still hold every line ---"
cat glass_layout.cfg 2>/dev/null
echo
echo "--- DIFF run1 -> run2 (empty = layout survived the round trip) ---"
diff /tmp/ls_after_run1.cfg glass_layout.cfg && echo "IDENTICAL"