Fix stale hover latch on drag release, tooltip anchor, border off-by-one; pin gutter golden test, drop DPI framing
This commit is contained in:
@@ -242,3 +242,8 @@ slider couldn't. Two pure modules split the forward (draw) and inverse (edit) ma
|
||||
Channel-mode (D-E) bus-renegotiation design and the earlier Preserve-onset-latency
|
||||
framing in the S16 guardrails. Root `CLAUDE.md` is the current source of truth
|
||||
for both — do not reintroduce either superseded design.
|
||||
- **`keyboard_strip`'s width-uniformity guarantee is client-pixel only.** Its test sweep
|
||||
covers client-pixel widths (including multiples standing in for larger client areas);
|
||||
nothing in the instrument implements `IPlugViewContentScaleSupport`, so host-side DPI
|
||||
scaling of the plugin window — which would resample the uniform integer key widths at the
|
||||
physical-pixel level — is unverified.
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
// keyboard_strip.h — piano-keyboard geometry for the editor's root strip: per-class key
|
||||
// rects, hit-test, the root marker, and the note name a hovered key reports.
|
||||
//
|
||||
// Same-class keys are one integer width by construction. An arbitrary band width is not
|
||||
// divisible by the 75 white keys, so the residue lands in symmetric end margins — uniform
|
||||
// key widths and gap-free edge-to-edge tiling cannot both hold, and uniformity wins.
|
||||
// See src/core/instrument/CLAUDE.md for the uniform-width-vs-edge-to-edge-tiling tradeoff.
|
||||
|
||||
#pragma once
|
||||
|
||||
@@ -21,7 +19,8 @@ inline constexpr int kStripKeyCount = 128;
|
||||
inline constexpr int kStripWhiteKeyCount = 75;
|
||||
|
||||
struct StripLayout {
|
||||
Rect band; // the surface handed in, edge to edge
|
||||
Rect band; // the surface handed in, edge to edge (no src/ consumer; kept as the tests'
|
||||
// reference bound instead of recomputing Rect::ltrb(0, 0, w, h) at each call site)
|
||||
Rect keys; // the tiled key area, kStripWhiteKeyCount * whiteWidth, centred in band
|
||||
int whiteWidth = 0;
|
||||
int blackWidth = 0;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "core/instrument/ui/sample_bands.h" // kPad / kTitleHeight / kChromeRowHeight
|
||||
#include "core/instrument/ui/sample_bands.h" // kPad
|
||||
|
||||
namespace reasampler::instrument::ui {
|
||||
|
||||
|
||||
@@ -79,6 +79,11 @@ void ReaSamplerEditor::onMouseUp(int x, int y) {
|
||||
drag_ = DragKind::kNone;
|
||||
dragParamId_ = -1;
|
||||
curvePointIndex_ = -1;
|
||||
// hover_ is deliberately not re-resolved during a drag (see resolveHover's caller), so it
|
||||
// still names wherever the drag started. Re-resolve now against the release position, for
|
||||
// every drag kind — otherwise the next paint latches a stale hover (wrong note name/tooltip,
|
||||
// wrong control outline) until the next WM_MOUSEMOVE.
|
||||
resolveHover(x, y);
|
||||
// A scrollbar drag is transient UI (no parameter change), and the processor-side knobs
|
||||
// (the preview-velocity -2 sentinel, voice count, master gain) are per-instance settings
|
||||
// that don't reload the instrument. Master gain is an atomic the audio thread reads
|
||||
|
||||
@@ -75,7 +75,6 @@ bool ReaSamplerEditor::mouseDownChrome(const FaceLayout& fl, int x, int y) {
|
||||
const StripLayout sl = layoutStrip(cr.rootStrip.width, cr.rootStrip.height);
|
||||
if (keyAtPoint(sl, x - cr.rootStrip.x, y - cr.rootStrip.y) >= 0) {
|
||||
drag_ = DragKind::kRootMarker;
|
||||
dragStartX_ = x;
|
||||
dragStartParams_ = params_;
|
||||
onMouseMove(x, y);
|
||||
return true;
|
||||
|
||||
@@ -205,13 +205,16 @@ void ReaSamplerEditor::paintChromeTooltip(LICE_IBitmap* bmp, const FaceLayout& f
|
||||
|
||||
const std::string label = noteName(hover_.index);
|
||||
const int textW = static_cast<int>(label.size()) * kTooltipCharPx;
|
||||
const TooltipBox tb = computeTooltip(area.x + key.x, area.y + key.y, key.width, key.height,
|
||||
// Anchor y/h to the whole strip row, not the hovered key: a black key (18px) is shorter
|
||||
// than a white key (30px), and anchoring to the key rect placed the chip 12px higher for
|
||||
// black keys — landing on the keyboard's bottom edge and, near the root, on the badge.
|
||||
const TooltipBox tb = computeTooltip(area.x + key.x, area.y, key.width, area.height,
|
||||
textW, kTooltipTextH, w, h, TooltipSpec{});
|
||||
if (tb.empty()) return;
|
||||
|
||||
const Rect box = Rect::ltrb(tb.x, tb.y, tb.x + tb.width, tb.y + tb.height);
|
||||
fillSurface(bmp, toKitBox(box), Role::BgCell, InteractionState::Hover);
|
||||
LICE_DrawRect(bmp, box.x, box.y, box.width, box.height,
|
||||
LICE_DrawRect(bmp, box.x, box.y, box.width - 1, box.height - 1,
|
||||
toLice(roleColor(Role::LineHairline)), 1.0f, 0);
|
||||
kitTextCentered(bmp, box, label.c_str(), Font::Label, Role::TextPrimary);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user