From eadd7b8e8193d19ae394a73dd7b84452d5311761 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Fri, 28 Nov 2025 06:29:25 +0100 Subject: [PATCH] Smooth out auto-scrolling speed scaling in `scrollable` --- examples/gallery/src/main.rs | 4 ++- widget/src/scrollable.rs | 48 ++++++++++++++++++++++-------------- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/examples/gallery/src/main.rs b/examples/gallery/src/main.rs index f6ed0077..198cdc27 100644 --- a/examples/gallery/src/main.rs +++ b/examples/gallery/src/main.rs @@ -275,7 +275,9 @@ impl Gallery { .height(grid::aspect_ratio(Preview::WIDTH, Preview::HEIGHT)) .spacing(10); - let content = container(scrollable(gallery).spacing(10)).padding(10); + let content = + container(scrollable(gallery).spacing(10).auto_scroll(true)) + .padding(10); let viewer = self.viewer.view(self.now); stack![content, viewer].into() diff --git a/widget/src/scrollable.rs b/widget/src/scrollable.rs index 62871600..2610cb45 100644 --- a/widget/src/scrollable.rs +++ b/widget/src/scrollable.rs @@ -579,7 +579,7 @@ where _viewport: &Rectangle, ) { const AUTOSCROLL_DEADZONE: f32 = 20.0; - const AUTOSCROLL_SPEED: f32 = 10.0; + const AUTOSCROLL_SMOOTHNESS: f32 = 1.5; let state = tree.state.downcast_mut::(); let bounds = layout.bounds(); @@ -764,6 +764,21 @@ where } } + if matches!(state.interaction, Interaction::AutoScrolling { .. }) + && matches!( + event, + Event::Mouse( + mouse::Event::ButtonPressed(_) + | mouse::Event::WheelScrolled { .. } + ) | Event::Touch(_) + | Event::Keyboard(_) + ) + { + state.interaction = Interaction::None; + shell.capture_event(); + return; + } + if state.last_scrolled.is_none() || !matches!( event, @@ -820,20 +835,6 @@ where return; } - if matches!(state.interaction, Interaction::AutoScrolling { .. }) - && matches!( - event, - Event::Mouse( - mouse::Event::ButtonPressed(_) - | mouse::Event::WheelScrolled { .. } - ) | Event::Touch(_) - | Event::Keyboard(_) - ) - { - state.interaction = Interaction::None; - return; - } - if shell.is_event_captured() { return; } @@ -1025,13 +1026,22 @@ where Duration::ZERO }; - let scroll_factor = - time_delta.as_secs_f32() * AUTOSCROLL_SPEED; + let scroll_factor = time_delta.as_secs_f32(); state.scroll( self.direction.align(Vector::new( - delta.x * scroll_factor, - delta.y * scroll_factor, + delta.x.signum() + * delta + .x + .abs() + .powf(AUTOSCROLL_SMOOTHNESS) + * scroll_factor, + delta.y.signum() + * delta + .y + .abs() + .powf(AUTOSCROLL_SMOOTHNESS) + * scroll_factor, )), bounds, content_bounds,