Skip to content

Fix panadapter layout/floating persistence + macOS GPU lifecycle (rfoust/#2780)#2786

Merged
ten9876 merged 1 commit into
mainfrom
auto/fix-panadapter-restore
May 17, 2026
Merged

Fix panadapter layout/floating persistence + macOS GPU lifecycle (rfoust/#2780)#2786
ten9876 merged 1 commit into
mainfrom
auto/fix-panadapter-restore

Conversation

@ten9876

@ten9876 ten9876 commented May 17, 2026

Copy link
Copy Markdown
Collaborator

Summary

Cherry-pick of @rfoust's panadapter persistence and macOS GPU lifecycle work from PR #2780, applied cleanly onto current main with the stale-snapshot reverts left out.

Why a cherry-pick rather than merge of #2780

PR #2780 was based on commit `a0512d99` (PR #2772 merge), and its single Codex-generated commit included stale-snapshot content for files outside the intended scope. Squash-merging #2780 as-is would have silently reverted two recently-landed PRs:

Verified by three-way merge dry run: post-merge state showed `class RadioSetupDialog : public QDialog` (pre-#2772) and 5 occurrences of `lcAetherAx25Shim` (pre-#2770).

The actual panadapter work in PR #2780 is real and valuable, so this PR extracts it onto a fresh branch from current main and skips the unintentional reverts.

What's in this PR (= the intended scope of #2780)

Cherry-picked verbatim from #2780:

File Change
`src/gui/MainWindow.{cpp,h}` Persist/restore PanadapterLayout + FloatingPanIds; expand layout count handling from 4 to 8 pans; preserve unseen floating IDs across reconnect
`src/gui/PanadapterStack.{cpp,h}` Sensible-fallback docked-splitter layouts when some pans are floating or saved layout count mismatches
`src/gui/SpectrumWidget.{cpp,h}` macOS QRhiWidget lifecycle: `WindowAboutToChangeInternal` before reparent; QRhi resource release during shutdown while parent backing stores are valid; guarded late callbacks; auto FFT floor relock after geometry/ypixels changes
`src/core/PanadapterStream.cpp` Defensive dBm-range clamping (-180 floor, ≥10 dB span); FFT decode clamps pixel input and dbm output to range
`src/models/RadioModel.cpp` Use actual FFT pane height for radio `ypixels` rather than total widget height

Net: +548 / -215 across 8 files.

What was NOT cherry-picked (stale-snapshot reverts)

File Reason
`CMakeLists.txt` -7 lines reverting #2770's test-target linkage I added to fix the link error
`src/core/tnc/AetherAx25LibmodemShim.cpp` Robbie's content has local `Q_LOGGING_CATEGORY(lcAetherAx25Shim, ...)` — pre-#2770. Main has the consolidated `lcAx25` from LogManager
`src/gui/Ax25HfPacketDecodeDialog.cpp` Same pattern — `lcAetherAx25Dialog` local, pre-#2770
`src/gui/RadioSetupDialog.{cpp,h}` Robbie's diff was 100% pure revert of #2772 — no new content, no panadapter-related additions. Confirmed by inspecting the full `git diff a0512d9..e72d7e4 -- RadioSetupDialog.cpp` output

Attribution

Commit author is set to Robbie Foust so his contribution shows in `git log` and the contributor stats. PR #2780 is being reset to Draft (not closed) so Robbie has a clean reference point + can update with fresh work if he wants.

Test plan

  • Local build clean (402/402 link, only pre-existing warnings)
  • Three-way merge dry-run against current main: clean
  • Manual on Linux: multi-pan layout, detached panadapter, restart, confirm layout + detached state restore
  • Manual on macOS GPU build: two detached panadapter windows, Cmd-Q, restart, confirm both restore without the QRhi cleanup callback crash
  • Manual: detach/redock panadapter and confirm auto FFT floor relocks

Cross-references

🤖 Generated with Claude Code

Cherry-picked from #2780 onto current main.  PR #2780's branch was based
at a0512d9 (#2772) and its Codex-generated commit included stale-snapshot
content for files outside the intended scope — silently reverting #2770
(aether.ax25 Q_LOGGING_CATEGORY consolidation) and #2772 (RadioSetupDialog
PersistentDialog migration) when squash-merged.  This commit takes only
the panadapter / macOS GPU work from the original PR.

Original PR description follows:

Fix panadapter layout/floating persistence, FFT sizing after layout
changes, and the macOS GPU panadapter reparent/shutdown crash path.

* Persist PanadapterLayout and restore it after restart when the
  restored pan count matches.
* Avoid overwriting the saved PanadapterLayout when the app temporarily
  falls back after pan removal or radio resource limits.
* Expand panadapter layout count/default handling from 4 to 8 pans so
  5-8 pan saved layouts restore correctly and fallback layouts choose
  the right shape.
* Persist FloatingPanIds and restore detached panadapters after restart.
* Preserve saved floating IDs for pans not seen in the current run so
  unavailable/restored-later pans do not lose detached state.
* Choose sensible docked splitter layouts when some pans are floating
  or the saved layout count does not match the docked count.
* Use the actual FFT pane height for radio ypixels instead of total
  widget height.
* Reacquire auto FFT floor lock after geometry/ypixels changes so
  detach/redock does not reuse a stale floor baseline.

macOS GPU crash fix — QRhiWidget lifecycle crash during panadapter
float/dock/rearrange/shutdown on macOS GPU builds:

* Send WindowAboutToChangeInternal before top-level reparenting so Qt
  unregisters the widget from the old backing-store QRhi.
* Release QRhi resources and destroy the native child window during
  shutdown while parent backing stores are still valid.
* Avoid sending the same backing-store notification again during the
  delayed post-reparent GPU refresh; the refresh now only recreates the
  GPU surface for the new native view.
* Explicitly prepare/destroy panadapter UI before MainWindow teardown.
* Guard late pan-stream and S-History callbacks during shutdown.

Files cherry-picked: MainWindow.{cpp,h}, PanadapterStack.{cpp,h},
SpectrumWidget.{cpp,h}, PanadapterStream.cpp, RadioModel.cpp.

Files deliberately NOT cherry-picked (stale-snapshot reverts of recent
landed PRs):
  - CMakeLists.txt (revert of #2770 + #2774 + #2779 test-target wiring)
  - src/core/tnc/AetherAx25LibmodemShim.cpp (revert of #2770)
  - src/gui/Ax25HfPacketDecodeDialog.cpp (revert of #2770)
  - src/gui/RadioSetupDialog.{cpp,h} (revert of #2772 — diff was 100%
    pure revert, no new content from this PR)

Co-Authored-By: Robbie Foust <rfoust@duke.edu>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@ten9876 ten9876 requested a review from jensenpat as a code owner May 17, 2026 03:00
@ten9876 ten9876 enabled auto-merge (squash) May 17, 2026 03:00
@ten9876 ten9876 merged commit ad9a315 into main May 17, 2026
5 checks passed
@ten9876 ten9876 deleted the auto/fix-panadapter-restore branch May 17, 2026 03:28
@ten9876 ten9876 mentioned this pull request May 17, 2026
aethersdr-agent Bot added a commit that referenced this pull request May 17, 2026
…ersistent (#2781). Principle III.

Settings → FlexControl, Settings → USB Cables, and the XVTR overlay button each
called `new RadioSetupDialog(...)` directly, bypassing the m_persistentDialogs
registry that PR #2772 (RadioSetupDialog → PersistentDialog migration) set up.
Symptoms: clicking any two entries opens two windows, frameless toggle skips
the shortcut-opened dialog, and "first opener wins" signal wiring diverges.

This pass routes all four entry points (primary Radio Setup, FlexControl, USB
Cables, XVTR overlay) through showOrRaisePersistent + selectTab, and factors
the txBandSettingsRequested / serialSettingsChanged / sliceLetterDisplayModeChanged
/ QDialog::finished wiring into a single private helper wireRadioSetupDialogSignals
so a fresh construction picks up the full handler set regardless of which menu
clicked first.  The dialog now lives in m_persistentDialogs unconditionally, so
the special-case qobject_cast in setFramelessWindow is removed — the
persistentDialogs loop below already handles it.

Also re-asserts the primary Radio Setup entry's #2772 migration that #2786
silently reverted during a panadapter-layout merge.

Blast radius (codegraph impact on MainWindow::buildMenuBar, max_depth=3):
risk_score=0.7297, 18 high_risk affected (top: MainWindow::MainWindow,
AppSettings::instance, AppSettings::value).  The score reflects buildMenuBar's
breadth across the menu surface; the actual edit is four lambda bodies plus a
helper, none of which alter buildMenuBar's caller-facing contract.  No new
test-target link dependencies (wireRadioSetupDialogSignals is private to
MainWindow.cpp, RadioSetupDialog.h was already #included).
ten9876 pushed a commit that referenced this pull request May 17, 2026
## Summary

Fix spectrum display jumps around dBm range changes.

- Rebase a few incoming FFT frames after dBm scale release so stale
radio-encoded frames do not briefly snap the trace back to the old
display location.
- Apply the same protection to vertical span / scale adjustments, not
just moving the top dBm reference.
- Split manual dBm-range echo handling from auto FFT floor echo handling
so auto-floor can keep its local smooth animation running while waiting
for the radio echo.
- Avoid applying an older auto-floor echo if the local animation has
already moved past it; reissue the current local range instead.

## Cause

The likely regression came from the later dBm stabilization work in PR
#2786 / #2780. That path made the stream decoder switch to the requested
dBm range immediately while the radio could still send several FFT
frames encoded against the old range. It also caused auto-floor movement
to pause behind the pending echo guard, which made the smooth motion
appear as steps.

## Test Plan

- [x] git diff --check
- [x] cmake --build build --parallel 8
- [ ] Manual: drag dBm reference line and release; confirm no snap-back
- [ ] Manual: Ctrl-drag vertical dBm span/scale and release; confirm no
snap-back
- [ ] Manual: enable/open panadapter with auto FFT floor adjustment;
confirm movement is smooth instead of stepping

Build passes. Existing warnings remain unrelated.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants