Hang the auto-crop off the slider's commit, not off the pointer passing over

The straighten auto-crop worked once and then stopped. It was keyed on
`PlainSlider::drag-changed`, whose name is a lie inherited from what it
forwards: `SliderTrack` defines `engaged` as `has-hover || claimed`, and
it has to — a `Flickable` withholds the press for 100ms, so hover is the
only signal that arrives in time to stand the scrolling ancestor down.
That is the right definition for the job it was written for and the wrong
one for this.

Keyed on hover, the correction fires when the pointer first crosses the
track — before anything has been dragged — and then does not fire again
for as long as the pointer stays on it, however many times the angle is
changed. Which is exactly what "it only works once" looks like.

`SliderTrack` already publishes the signal this wants. `committed` fires
on release, once per gesture, after the final `changed`, and its doc
comment says so in as many words. It was simply not forwarded through
`PlainSlider`, so it now is, and the geometry panel's callback is a
`committed(float)` rather than a `drag-changed(bool)`.

The angle needs no re-applying here: the track emits its last `changed`
before it commits, so the value is already in the graph by the time this
runs. What is left is the correction that has to happen exactly once.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-29 13:49:21 +02:00
co-authored by Claude Opus 5
parent 2c8768ac29
commit c38df01bf7
4 changed files with 45 additions and 23 deletions
+12 -4
View File
@@ -2707,13 +2707,21 @@ pub fn run(paths: Vec<PathBuf>) -> Result<()> {
// Only on release, and only on release. Doing it per frame ratchets
// the crop down through every angle the slider passed through rather
// than the one it stopped at; see `auto_crop_to_angle`.
//
// Hung off the track's `committed`, not off `engaged-changed`. The
// latter is *hover* — it has to be, because a `Flickable` withholds
// the press — so a correction keyed on it fires when the pointer first
// crosses the track, whether or not anything was dragged, and then
// never fires again for as long as the pointer stays on it. Which
// reads, exactly, as an auto-crop that works once.
let weak = window.as_weak();
let session = session.clone();
let redraw = redraw.clone();
window.on_straighten_drag_changed(move |dragging| {
if dragging {
return;
}
window.on_straighten_committed(move |_degrees| {
// The angle itself is already applied: `SliderTrack` emits its
// last `changed` before it commits, so `on_straighten_changed` has
// run with this very value. What is left is the correction that
// has to happen exactly once.
let Some(w) = weak.upgrade() else { return };
if let Some(s) = session.borrow_mut().as_mut() {
s.auto_crop_to_angle();