feat(fresh-ui): give the wheel an axis - #3032
Merged
Merged
Conversation
The scroll model has always been two-dimensional — a viewport's offset
and its maximum are both `Point`s, and `ViewportProps::scroll` is a
pair — but nothing could address the horizontal one: `Input::Wheel`
carried a bare scalar and `scroll_chain` only ever moved `y`. The axis
was implied by the geometry everywhere except where it could be driven.
- `Axis::{Vertical, Horizontal}`, carried on `Input::Wheel` and on the
`Event` a `Wheel` listener receives, so a widget that scrolls itself
can tell the two apart instead of guessing.
- `scroll_chain` moves and clamps the axis it was given.
- The wheel is one parameter (`Wheel { delta, axis }`) through
propagation rather than two, so the gestures that are not wheels pass
`Wheel::NONE` instead of a bare zero whose meaning had to be inferred.
What this does NOT do is make the built-in `Viewport` scroll sideways.
A viewport lays its child out under `Constraints::new(0, w, ..)`,
bounding it to the window's own width, so content never overflows
horizontally and that maximum stays zero: `Viewport` is a vertical
scroller by construction, and remains one. A horizontally scrollable
viewport is a separate feature, and nothing needs it yet — a host leaf
that scrolls its own content (an editor buffer) does that itself, and
only needs the axis to reach its handler intact.
`tests/pointer.rs` pins all three: the listener sees the axis, a
vertical wheel still moves only `y`, and a horizontal wheel over a
viewport correctly does nothing rather than scrolling the wrong way.
The golden tests are unchanged, so no rendered output moved.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ws2GtzEBQRFZMv8qF61Jzr
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Base of a two-PR stack. #3028 (the fresh-editor UI migration) is stacked on top of this.
Why
The scroll model has always been two-dimensional — a viewport's offset and its maximum are both
Points, andViewportProps::scrollis a pair — but nothing could address the horizontal one.Input::Wheelcarried a bare scalar andscroll_chainonly ever movedy. The axis was implied by the geometry everywhere except where it could be driven.This surfaced while writing the editor-side input adapter for the migration: translating a horizontal wheel had no target, so the adapter had to decline it and leave it on the legacy path. Rather than encode that gap as an editor workaround — which is the class of thing the migration exists to remove — it is closed here, in the library, before anything depends on it.
What changed
Axis::{Vertical, Horizontal}, carried onInput::Wheeland on theEventaWheellistener receives, so a widget that scrolls itself can tell the two apart instead of guessing.scroll_chainmoves and clamps the axis it was given.Wheel { delta, axis }) rather than two, so the gestures that are not wheels passWheel::NONEinstead of a bare0whose meaning had to be inferred at each call site.What this deliberately does not do
It does not make the built-in
Viewportscroll sideways. A viewport lays its child out underConstraints::new(0, w, ..), bounding it to the window's own width, so content can never overflow horizontally and that maximum stays zero —Viewportis a vertical scroller by construction, and remains one here.A horizontally scrollable viewport is a separate feature, and nothing needs it yet: a host leaf that scrolls its own content (an editor buffer) does that itself and only needs the axis to reach its handler intact.
a_viewport_has_no_horizontal_extent_to_scrollpins that boundary, so if someone later builds a horizontal viewport, the test says what changed.Verification
tests/pointer.rscovers all three cases: aWheellistener sees the axis; a vertical wheel still moves onlyy; a horizontal wheel over a viewport correctly does nothing rather than scrolling the wrong way.Full suite green — 150 tests, goldens included, so no rendered output moved. The crate still builds standalone with
unicode-widthas its only runtime dependency.Generated by Claude Code