Files
plotter/adapters
Martino Ferrari 9aff06acee fix(glfw): route a drag by the row it began in, and drop stale hover state
`controller_at()` routed every pointer event by the row the pixel was in,
ignoring the row a drag started in, so a press on one figure row followed by a
motion and release in another delivered the motion and release to a controller
whose `mode_ == None`. The owning controller kept `mode_`, `drag_region_`,
`drag_cursor_` and `drag_fixed_x_` set for ever: `publish_hot()` kept publishing
the grabbed handle, `grabbed_region()` reported a drag that had ended, and a
later gesture re-entering the row resumed the stale edit from the old anchor.

`feed_pointer_event()` now owns the routing: a press captures the row it landed
in and every motion and the release until the button comes up go to that row
(`pointer_target()`), cleared on release and when another figure is set. The
GLFW callbacks build the event and call it, so a windowless host or a test can
drive the routing too.

Two neighbours in the same seam:

* `sync_figure_crosshair()` called the four-argument overload unconditionally,
  so a documented vertical-only crosshair (`horizontal == false`) was promoted
  to a full cross at the stored y == 0, clamped to the axes edge and made
  permanent; the change detection also keyed on x alone, missing a y-only move
  to another row at the same x (two rows showing one horizontal line, spec 17).
  It now consults `crosshair().horizontal` and compares the hovered row's y.
* Only the row under the pointer republished its hot handles, so a row the
  pointer left kept drawing a hovered marker or bound as if it were still
  under the pointer, and answered `hovered_region()`/`grabbed_cursor()` for
  it. The run loop clears every other row's handles, keeping the captured
  row while a drag owns the button, and reads the frame's one layout once
  instead of recomputing every row five times.

Test: a press on row A's region, a motion into row B, a release in row B
asserts no controller keeps a drag mode, nothing reports a grabbed handle, and
a later press-and-motion that re-enters row A does not resume the old edit.
2026-09-28 22:36:30 +02:00
..