ROOT CAUSE. mPresentParams.BackBufferWidth/Height were assigned ONLY in the
fullscreen branch (L4VIDEO.cpp:3430-3434); windowed they stayed 0, which tells
D3D9 to derive the backbuffer from the device window's client area at
CreateDevice. Fine at startup -- but the device-lost recovery path saves and
restores mPresentParams around Reset(), so it faithfully preserved those ZEROS
and Reset re-derived the backbuffer from whatever the client area was at THAT
moment, while gBTCockpitCanvasW/H still described the startup canvas.
The cockpit layout is computed in backbuffer space and clicks are mapped
client -> canvas (L4VB16.cpp BTCockpitMouseDown), so after that divergence panels
are drawn for one geometry and clicks are mapped in another: buttons drift off
their artwork, and at a large enough mismatch nothing is clickable at all -- which
is #50 (SAURON: 'none of my MFDs clickable' while other players' worked).
It needs BOTH a resize/maximise AND a device loss (alt-tab, Steam overlay,
monitor sleep, UAC, RDP, driver hiccup), in that order. That is why it hits some
players and never the operator, who does not resize the cockpit window -- and it
matches the report exactly: the buttons 'become' misaligned rather than starting
that way.
FIX
* windowed: record the client rect into BackBufferWidth/Height at CreateDevice.
That is exactly what D3D would have derived, so startup behaviour is
unchanged, but the save/restore now preserves a REAL size and Reset can never
pick a different one. Deliberately NOT screenWidth/screenHeight -- those are
the app's -res values (default 800x600) while the cockpit window is sized
independently, so pinning to them would shrink the backbuffer.
* BTVerifyCockpitCanvasAfterReset(): called at both device-lost recovery sites;
compares the real backbuffer against the canvas globals, and if they ever
disagree it says so and re-syncs instead of drifting silently.
VERIFIED: solo cockpit run unchanged -- '[cockpit] view 900x440 canvas 1452x999',
BT_SHOT still 1452x999, Heat panel renders correctly, no mismatch warning.
NOTE: reverted an earlier scripted edit of this file that had corrupted an
unrelated line -- L4VIDEO.cpp is CRLF and a Python join('\n') introduced a bare
LF inside a string literal. Use the edit tool on this file, not line surgery.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0166KTsC7ADm7VXEi1HF1jNg