Problem: dragging a clip edge in the Timeline previewed the raw pointer
delta, so the edge kept growing past the end of the clip's media (or into
the neighbouring clip) and only jumped back when the button came up and
`timeline.trim` clamped it (#653, point 2 of #374).
Fix: `commands::trim_delta` computes, without editing, the delta
`timeline.trim` would apply (the same clamp across linked partners, now
shared by both), and the Timeline's trim drag shows that delta.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
While an edge was dragged, the Timeline drew the clip at its new length
from the untrimmed item, so draw_waveform spread the clip's whole source
range over the shorter (or longer) box: the waveform squeezed and the
sound under the pointer moved, which made it hard to trim to where the
music starts (#374, item 13). Trim and roll previews now draw from the
item the edit will leave, so every timeline time still covered shows the
same media and the waveform is cut off at the moving edge. Video
thumbnails show the new first frame the same way. Rate Stretch, which
really fits the same media into a new length, still squeezes.
The item update is factored out of trim and ripple_trim_group into
filmcraft_edit::move_edge, which the preview uses too, so preview and
edit agree for speed-changed, reversed and frame-held clips.
Rendered mid-drag against the released result, the music clip's
waveform matched in 15% of pixel columns before and 100% after.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
data_mut() and drag_delta() both take egui's non-reentrant context
write-lock; calling the second inside the first froze the app on the
first frame of a drag in the Trim Monitor. The delta is now read
before the lock is taken, and a regression test drags through the
real Trim Monitor.
Caption blocks chose move / trim in / trim out where egui recognised the drag, about 9 px in
from a press 2 px inside the edge and past the 5 px edge zone, so they moved instead of
trimming. They now decide at the press origin and measure the drag from it. UI test that
failed before.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Hovering a clip edge draws the edit-point bracket at half strength on the edge a press would
grab: red for a ripple; yellow for a trim, roll, rate stretch or remix; on both sides of the
cut for a roll. It follows the tool and the modifiers, from the same grab_at as the press.
The bracket drawing is shared with the selected edit points (trim_monitor::paint_bracket).
An ignored test renders the four cases at a demo cut to PNGs for review:
cargo test -p filmcraft-ui-egui --test timeline_trim_ui -- --ignored hover_bracket_screenshots
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Pressing a clip edge and dragging inward selected and moved the clip: the press was hit-tested
only once egui recognised a drag, 6 pt later, by when the pointer had left the 7 px edge zone.
And at a cut the left clip's Out edge claimed both sides, so the right clip's In edge could not
be grabbed.
What a press grabs is now worked out on the frame the button goes down (timeline_hit::grab_at,
shared by the cursor, the press and ui.timeline.hit) and acted on by both the click and the
drag. Inside a clip beats outside it, so the side of a cut picks the clip; zero-width clips
have no edges. Trims, rolls, rate stretches and remixes move by how far the pointer moved since
the press, and a moved clip stays under the point it was grabbed by. ui.timeline.hit takes
`modifiers` and reports `kind`, the trim a press would start.
Unit tests for the zones and tools; headless UI tests that drag a pixel or a few per frame at
60 fps (before: the clip moved, the wrong clip was trimmed, a wobbly click selected the clip, a
moved clip lagged).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>