makepad/widgets/families/maps
Kevin Boos 888ca924bf
Scroll: keep each gesture with the scroller it began on, and let nested scrollers share a drag (#1317)
* StackNavigation: add `push_without_animation()` to show a view right away

Pushing a view always slid it in, so an app couldn't restore a screen it was already showing
in another layout (e.g., after switching from a wide layout to a narrow one) without animating it.
* `push_view()` takes an `Animate`; with `Animate::No`, the view is shown at rest right away
  and the outgoing view is released, leaving no transition in progress
* It redraws the view being replaced first, since a never-drawn view can't trigger a redraw itself

* Scroll: nested scroll views keep their scrolls, and a gesture stays with its scroller

Scrolling inside a nested scroll view also scrolled its ancestors: PortalList never marked a
scroll handled, and a ScrollBar at its limit passed scrolls and momentum up.
* The innermost view that can scroll on an axis owns that axis, even at its limits, so
  nothing around it moves, momentum included; a view whose content fits passes scrolls on
* Ownership is decided when a gesture starts (a trackpad `Began`, or a wheel after a 500 ms
  pause, as in Chromium) and kept for the gesture, so content moving under a still pointer
  can't capture it; moving the pointer off a wheel's owner after 100 ms at rest frees it,
  as in Firefox
* Each axis has its own owner, and an owner that disappears frees only its axis
* Scrollables ask `cx.is_scroll_owner()`; containers wrap their children's dispatch in
  `begin_scroll_container()`/`end_scroll_container()` so a list that fits defers to them
* An open DropDown, DropDown2 or ComboBox keeps scrolls from what's under it, and a scroller
  partly clipped by a modal still takes its own
* Touch drags go to the inner scroller too: StackNavigation's swipe-back and ExpandablePanel
  yield to it, and TabBar, Chart and Map pans claim their drags
* Remote `/m?k=scroll&phase=` sends trackpad phases and `/m?k=touch` drives a touch;
  makepad_test gains `scroll_at`, touch drags and drags that rest before letting go

* Examples: scroll_containment, UI tests for nested scrolling

Lists, scroll views, a multiline TextInput, a code block beside a horizontal strip, a
DropDown2, a StackNavigation, an ExpandablePanel and a Modal nested in each other, with UI
tests that drive wheels, trackpad gestures with momentum and touch drags over them.

* Turtle: `Base::Unused` under a growing parent, and `turtle_visible_y_range`

A `Fit{max: Unused}` view inside a Fit parent skipped past it and read the space left in some
turtle further up, so a body under a pinned header couldn't size to what's left of its parent.
* `Base::Unused` of a Fit parent with a max is that max minus what the parent has used
* `Cx2d::turtle_visible_y_range()` gives what the clips around a turtle can show, stopping at
  a turtle that can still move what it holds (a positioned list item, or a row or column that
  aligns its children on y)

* Scroll: nested scrollers share a drag, and a shared gesture keeps to the way it started

A View's drag scroll never saw a press a child had captured, so dragging on something that only
scrolls sideways (like code in a page) could never scroll the page.
* Drag scrollers hold the presses they get, and a scroller around them can join a press only they
  hold (along an axis they didn't take); their holds don't lock the mouse against each other
* A drag or trackpad gesture two scrollers share keeps to the axis it started along, or goes both
  ways (each owning its axis) if it started diagonally; PortalList and TouchGesture honor it too
* A second finger no longer restarts a drag, a claimed press still stops a fling, and
  `set_scroll_pos` stops any motion in progress

* CodeEditor: touch drags scroll, and a Fit editor draws every line in view

A touch drag always selected text, and a Fit editor with no max only drew its first 10,000px.
* With drag scrolling on, a touch drag scrolls and a tap places the cursor; a mouse press that
  selects claims its drag, so nothing scrolls under the selection
* A Fit editor with no max is as tall as its text, and draws only the lines the clips around it show

* Examples: scroll_containment code modal, and touch drags that turn

A modal like Robrix's event source one (a pinned title over a page holding code that only scrolls
sideways) plus a scroller drawn over it, with UI tests for touch, mouse, trackpad and wheel input,
and for drags that start out diagonally or turn.
* makepad_test gains `touch_drag_through_and_hold`, for a finger that turns

* Scroll: a new scroll at a nested scroller's limit goes on to the one around it

A scroll over a nested scroller resting at its limit never reached the scroller around it, so a page
couldn't be scrolled from over a list or code block it holds. Browsers hand such a scroll on, while a
gesture still stays with the scroller it began on.
* A new wheel or trackpad gesture goes to the innermost scroller under the pointer that can move its
  way, or to the innermost one if nothing around it can (to rubber-band and count travel)
* A trackpad gesture picks its scrollers when it first moves, since its `Began` can carry no delta
* `contain_scroll` on a `ScrollBar`, `PortalList` or `TextInput` keeps even a new scroll at its
  limit, like CSS `overscroll-behavior: contain`
2026-10-21 16:01:19 +02:00
..
src Scroll: keep each gesture with the scroller it began on, and let nested scrollers share a drag (#1317) 2026-10-21 16:01:19 +02:00
Cargo.toml draw, widgets: the library is makepad-widgets-core plus a crate per widget family, eighty new widgets and the storybook, relief-lit skeuomorphic surfaces, the feedback panel, keyboard focus and tooltips clear of the cursor 2026-09-26 20:10:50 +02:00