fix(instrument): stop Ctrl-before-click stealing a waveform mark grab from a coincident node

Ctrl held before mouse-down forced the node/toggle win over a smaller cap or
column regardless of area; now it defers to the ordinary smallest-area
arbitration like a plain click. Also amends product docs, VERIFICATION.md, and
adds sparse-material/narrow-overlay test fixtures.
This commit is contained in:
2026-08-03 16:07:49 -04:00
parent b7b7e88195
commit f91054276b
10 changed files with 117 additions and 15 deletions
+8
View File
@@ -311,3 +311,11 @@ against a performance budget — they are there because `VoiceEngine::applyLiveT
"channel identity derives from `app_version` accessors, no scattered `#ifdef`s" —
`INLINE_UID` needs literal brace-init tokens, so it can't route through a runtime
string accessor.
- **Ctrl held during a waveform marker drag defeats the zero-crossing snap outright**
(`editor_input_waveform.cpp`'s `dragWaveform`, reading `dragModifiers().ctrl` — the same
"get out of the way, I want exactness" role Ctrl plays as the knobs' fine drag). It is
undiscoverable by design — no cursor cue, no label — so this note is its only home; the
radius itself (`core/instrument/ui/waveform_view`'s `snapToZeroCrossing`) is documented there,
not here. `resolveWaveformClaim` (`core/instrument/ui/spline_edit`) is the reason Ctrl held
BEFORE mouse-down still reaches the mark rather than stealing a coincident envelope-node grab
or hard/smooth toggle.
@@ -286,10 +286,11 @@ void ReaSamplerEditor::dragWaveform(const FaceLayout& fl, int x, int y) {
// where the mark was dropped. Pure over the cached mono frames — no host types, no file I/O.
// The crossfade handle is exempt: it sets a fade LENGTH, and the whole point of the fade is
// that its edges need no zero crossing. Ctrl defeats the snap outright, the same "get out of
// the way, I want exactness" role it plays as the knobs' fine drag.
// the way, I want exactness" role it plays as the knobs' fine drag. `[verify — DAW]` this
// `GetKeyState` read has no test target — nothing in CI observes the defeat actually landing.
const std::vector<AudioSample>& pcm = monoPcmFor(selectedId_);
if (!pcm.empty() && waveMarker_ != WaveMarker::kCrossfade && !dragModifiers().ctrl) {
newFrame = snapToZeroCrossing(pcm.data(), static_cast<std::int64_t>(pcm.size()), newFrame,
newFrame = snapToZeroCrossing(pcm.data(), frames, newFrame,
zeroCrossingSnapFrames(overlay, frames));
}