Skip to content

refactor(vfo): m_meterMenuOpen as meter-selector open-state source of truth (#3773)#3775

Merged
ten9876 merged 1 commit into
mainfrom
fix/metermenu-open-source-of-truth
Jun 23, 2026
Merged

refactor(vfo): m_meterMenuOpen as meter-selector open-state source of truth (#3773)#3775
ten9876 merged 1 commit into
mainfrom
fix/metermenu-open-source-of-truth

Conversation

@ten9876

@ten9876 ten9876 commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator

Summary

Closes #3773. Consistency follow-up to #3771.

#3771 introduced m_meterMenuOpen as the explicit open-state for the SmartMTR meter selector and switched the paintEvent underline onto it (the child m_meterMenuRow->isVisible() reads false while the flag is hidden and rasterized into a GPU sprite). This retires the two remaining m_meterMenuRow->isVisible() reads of the same logical open-state:

Both are live-flag interaction paths, so isVisible() was accurate there and there is no behavior change — this just makes m_meterMenuOpen the single source of truth so the two reads can't ever disagree with the flag the way paintEvent did.

The null-guard dropped at the tab path is safe: setMeterMenuOpen() early-returns on a null m_meterMenuRow, and m_meterMenuOpen is only set true after that guard, so a true value implies the row exists.

Test plan

  • Local build passes (cmake --build build --target AetherSDR)
  • Existing tests pass (CI)
  • Manual: meter-strip click toggles the selector; opening a tab still closes it; underline unaffected

🤖 Generated with Claude Code

…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>
@ten9876 ten9876 requested a review from a team as a code owner June 23, 2026 13:38
@ten9876 ten9876 merged commit e92cfb8 into main Jun 23, 2026
5 checks passed
@ten9876 ten9876 deleted the fix/metermenu-open-source-of-truth branch June 23, 2026 13:56
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>
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.

VfoWidget: make m_meterMenuOpen the single source of truth for the meter-selector open-state

1 participant