[ux] Restore keyboard shortcut use after slider nudges#1952
[ux] Restore keyboard shortcut use after slider nudges#1952ten9876 merged 1 commit intoten9876:mainfrom
Conversation
There was a problem hiding this comment.
Thanks for tackling this, @jensenpat — the "stuck slider" behavior is a real papercut for operators, and the lease-based approach is a solid design choice over the permanent suppression.
I read through the full diff and compared against main. The implementation is clean and well-scoped (only MainWindow.cpp / .h, no scope creep). A few observations:
Looks good
- Lease pattern is sound. The
beginSliderShortcutLease→renewSliderShortcutLease→releaseSliderShortcutLeaselifecycle is clear. UsingQPointerform_sliderShortcutLeaseis the right call — safely handles slider destruction mid-lease. - Mouse-drag safety.
isSliderDown()check in bothrenewSliderShortcutLease(stops the timer) andreleaseSliderShortcutLease(defers the clear) correctly prevents yanking focus during an active drag. Nice detail. - PageUp/Down and Home/End handling. The old code only intercepted arrow keys. Adding these makes the slider feel complete before the lease expires.
- No convention violations. Uses
AppSettingspattern (notQSettings),QPointerfor RAII-safe weak reference,constexprfor the timeout constant. Files changed match stated scope.
Questions / potential issues
-
Double disable on focus change. When a slider is clicked, the
eventFilterfiresbeginSliderShortcutLease(viaMouseButtonPress), which callssetShortcutsEnabled(false). Then thefocusChangedsignal fires for the same slider and callsbeginSliderShortcutLeaseagain, which callssetShortcutsEnabled(false)a second time. This is idempotent and harmless, but the timer restart inrenewSliderShortcutLeasemeans the 2-second clock resets from the focus event rather than the click — which is actually fine since they're nearly simultaneous. Just flagging that the double-entry is intentional/benign. -
s_sliderShortcutLeaseActivestatic vs. member. The lease state is tracked in both a file-statics_sliderShortcutLeaseActive(forshortcutInputCaptured()) and the memberm_sliderShortcutLeasepointer. This works because there's only ever oneMainWindow, but it's worth a brief comment noting the static is needed becauseshortcutInputCaptured()is a free function called from theshortcutGuardcallback. (Not blocking — just a readability note.) -
Keyboard-only focus. If a user Tabs into a slider (no mouse click), the
focusChangedpath callsbeginSliderShortcutLease, which starts the timer. After 2 seconds of idle,releaseSliderShortcutLease(true)callsslider->clearFocus(). This means Tab-focused sliders lose focus after 2s even if the user hasn't interacted with them yet. In practice this may be fine for this app (operators rarely Tab to sliders), but worth considering whether theclearFocusshould only happen if there was an actual key nudge. A simple guard likem_sliderHadKeyNudgewould do it. -
Thread safety note. All paths run on the GUI thread (event filter, focus signal, QTimer), so the static flag is safe. No issue here, just confirming.
Overall this is a well-considered improvement. The core approach is correct and the edge cases are handled. Item 3 above is the only thing I'd suggest addressing before merge — the Tab-focus scenario could surprise users who use keyboard navigation. The rest is ready.
Reviewed by AetherClaude
Summary
Root Cause
Applet and sidebar sliders previously disabled all operating QShortcuts whenever a QAbstractSlider had keyboard focus. A clicked slider can remain the focus widget indefinitely, so tuning shortcuts such as Left Arrow and Right Arrow stayed suppressed until the user manually clicked somewhere else.
User Impact
Operators can still click volume, AGC, AF, or similar sliders and make a few keyboard nudges. After a brief idle period, keyboard control returns to normal tuning behavior without an extra click, preventing the session from feeling stuck after any applet-slider adjustment.
Implementation Notes
Validation
👨🏼💻 Generated with OpenAI Codex (GPT-5.5 Pro 4/23) and tested by @jensenpat