The last four arms --- `CursorMoved`, `MouseInput` twice, `MouseWheel`
--- move to `apply_cursor_moved` / `apply_left_button` /
`apply_right_press` / `apply_wheel`. `window_event` is now 33 lines
against 655: one `route_event` call and one arm per route. The seam is
complete.
THE BUTTON DISCRIMINATION WAS THE FIND. It lived in the shape and order
of two overlapping `MouseInput` arms --- left in either state, right in
the pressed state only --- with everything else falling through a
wildcard several hundred lines below. The asymmetry is real and
deliberate (a context menu opens on the press; its release means
nothing), but it was an artefact of arm order rather than a stated
decision. `PointerRoute` names all four cases and both witnesses and
mutations now bear on them.
`UnusedButton` follows the keyboard family's `Release`: a middle /
back / forward / other button, and a right-button release, are CLAIMED
BY THE POINTER FAMILY AND DROPPED rather than left unrouted. Same
behaviour as the wildcard they used to reach, and Stage 1b's B4
(middle-click PRIMARY paste on Linux) lands on exactly this route.
The wheel delta is carried RAW. Converting it to lines needs the code
line height, which is `State`'s to know, so the router must not try ---
and the witness drives both `LineDelta` and `PixelDelta` to pin that.
All four bodies verified as the original arm bodies rustfmt-normalised,
by re-running rustfmt on the pre-move text at the new indent level and
diffing. `apply_cursor_moved` additionally renames `position.x`/`.y` to
`x`/`y`, 6 and 9 occurrences, counted.
Evidence --- 13 rows, 6 further mutations:
M12 right button claimed in both states -> the right-button row
M13 left button claimed only on press -> the left-button row
M14 CursorMoved axes swapped -> the cursor row (+ transcript)
M15 unused button falls through -> unused + right rows (+ transcript)
M16 harness records outbound only -> the transcript row ALONE
M17 wheel delta zeroed -> the wheel row ALONE
P3 RE-DEMONSTRATED AGAINST THE FINAL SHAPE, AND AGAINST THE WHOLE
SUITE. Replacing `window_event`'s entire body with `let _ =
(event_loop, event);` --- a GUI that responds to no input at all ---
leaves ALL 256 `pmacs-gpu` tests green, not merely the 13 routing rows.
That is the accepted structural exception measured rather than
asserted: no headless test anywhere in this crate observes the
delegation, because `ActiveEventLoop` cannot exist outside a live event
loop.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016bqGA6s9tTUFzYpbeW3tai