refactor(vfo): m_meterMenuOpen as meter-selector open-state source of truth (#3773)#3775
Merged
Merged
Conversation
…ource of truth #3771 introduced m_meterMenuOpen as an explicit open-state flag and switched the paintEvent underline onto it, because m_meterMenuRow->isVisible() reads false while the flag is hidden and rasterized into a GPU sprite. Two other reads of the row's isVisible() for the same logical open-state remained: - the meter-strip click-to-toggle - the open-a-tab-closes-the-selector mutual exclusion Both are live-flag interaction paths, so isVisible() is accurate there today and there was no misbehavior — but routing them through m_meterMenuOpen makes the flag the single source of truth and removes the latent inconsistency. No behavior change. The dropped m_meterMenuRow null-guard at the tab path is safe: setMeterMenuOpen() early-returns on a null row, and m_meterMenuOpen is only set true after that guard, so a true value implies the row exists. Closes #3773. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This was referenced Jun 25, 2026
ten9876
added a commit
that referenced
this pull request
Jun 26, 2026
…ve (#3777) (#3806) ## Summary **Strategy B** of the GPU-flag reversion plan (attached to #3777) — the **full excision** that #3803 (the one-line default-flip) was the reversible precursor to. VFO slice flags are now **unconditionally live child widgets**; the off-screen-sprite + live-on-hover machinery is removed entirely, fixing the #3777 idle-flag blur and the Diversity-mode RX-antenna regression at the source. **Net −582 lines** across `SpectrumWidget.{cpp,h}` and `VfoWidget.{cpp,h}`. ## Relationship to #3803 These are **alternatives — merge one, not both.** #3803 flips the default but keeps the sprite path behind `AETHER_GPU_FLAGS=1` (reversible, for measurement). This PR deletes the machinery (no env opt-in remains). Recommended sequence: validate live-flag behavior + the 4-panadapter re-profile via #3803 first; if the group commits to it, merge **this** as the clean removal and close #3803. ## Removed (all sprite-path) - SpectrumWidget: `m_gpuFlagMode` + the env gate, `m_flagRefreshTimer` + lambda, `grabFlagSprites`/`releaseFlagSprite`, `setLiveFlag`/`updateLiveFlag`, `updateFlagRefreshTimer`/`attachFlagTimerWindowWatcher` + `m_flagTimerFilteredWindow`, `FlagSprite` + `m_flagSprites`/`m_flagDrawOrder`/`m_flagQuadVbo`/`m_flagSampler`/`kMaxFlagSprites`, the `renderGpuFrame` sprite draw-order/texture/quad blocks, and the QRhi flag-resource init/teardown. - VfoWidget: `setButtonsOccluded` + `m_occludeRestore`/`m_buttonsOccluded`. ## Kept intact (verified) - **`repositionVfoFlags()`** — the *shared* positioner that calls `updatePosition()` on every flag; only its trailing GPU-mode hide-block was removed. Still called each frame from `renderGpuFrame`, so live flags position correctly. This was the key correctness invariant. - The whole **GPU panadapter** path (`AETHER_GPU_SPECTRUM`: FFT/waterfall/overlay) — untouched. - The **SmartMTR** render-mode-agnostic fixes from #3771/#3773/#3775. - `event()`/`eventFilter()` non-flag logic (`setMouseTracking`, Mac QRhi teardown in `prepareForTopLevelChange`) preserved. ## Trade-off (unchanged from #3803) Re-introduces the #3617 main-thread composite cost #3695 removed (**~0.82 vs 0.45 cores, +0.37 ≈ +45% main-thread**). Separate from and likely additive to #3797. ## Test plan - [x] Builds clean (`cmake --build build --target AetherSDR`); zero dangling references to removed symbols - [ ] Idle VFO-flag text crisp; no hover-pop (Windows) - [ ] Diversity-mode RX-antenna selection works - [ ] Flags position/move correctly with 1, 2, and N panadapters; split-partner side-locking intact (repositionVfoFlags path) - [ ] Dragging a flag: no audio crackle / re-raster crash (#3695's original concern) - [ ] 4-panadapter main-thread CPU re-profile (the decision gate) - [ ] a11y linter clean; SmartMTR meter renders correctly Refs #3777, #3617. Supersedes #3803. Plan: see the #3777 comment. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #3773. Consistency follow-up to #3771.
#3771 introduced
m_meterMenuOpenas the explicit open-state for the SmartMTR meter selector and switched thepaintEventunderline onto it (the childm_meterMenuRow->isVisible()reads false while the flag is hidden and rasterized into a GPU sprite). This retires the two remainingm_meterMenuRow->isVisible()reads of the same logical open-state:setMeterMenuOpen(!m_meterMenuOpen)if (m_meterMenuOpen)Both are live-flag interaction paths, so
isVisible()was accurate there and there is no behavior change — this just makesm_meterMenuOpenthe single source of truth so the two reads can't ever disagree with the flag the waypaintEventdid.The null-guard dropped at the tab path is safe:
setMeterMenuOpen()early-returns on a nullm_meterMenuRow, andm_meterMenuOpenis only set true after that guard, so a true value implies the row exists.Test plan
cmake --build build --target AetherSDR)🤖 Generated with Claude Code