From 01429d72cdd1a962ca19544f1aa4798cf8b774a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Sat, 11 Oct 2025 07:57:37 +0200 Subject: [PATCH] Levitate `cursor` in `scrollable` Fixes #3074 --- widget/src/scrollable.rs | 56 +++++++++++++++++------------------ widget/src/slider.rs | 10 ++++--- widget/src/vertical_slider.rs | 7 ++--- 3 files changed, 36 insertions(+), 37 deletions(-) diff --git a/widget/src/scrollable.rs b/widget/src/scrollable.rs index 75fd249c..8c146543 100644 --- a/widget/src/scrollable.rs +++ b/widget/src/scrollable.rs @@ -762,7 +762,7 @@ where ), ) } - _ => mouse::Cursor::Unavailable, + _ => cursor.levitate(), }; let had_input_method = shell.input_method().is_enabled(); @@ -1178,35 +1178,33 @@ where let (mouse_over_y_scrollbar, mouse_over_x_scrollbar) = scrollbars.is_mouse_over(cursor); - if (mouse_over_x_scrollbar || mouse_over_y_scrollbar) - || state.scrollers_grabbed() - { - mouse::Interaction::None - } else { - let translation = - state.translation(self.direction, bounds, content_bounds); - - let cursor = match cursor_over_scrollable { - Some(cursor_position) - if !(mouse_over_x_scrollbar || mouse_over_y_scrollbar) => - { - mouse::Cursor::Available(cursor_position + translation) - } - _ => mouse::Cursor::Unavailable, - }; - - self.content.as_widget().mouse_interaction( - &tree.children[0], - content_layout, - cursor, - &Rectangle { - y: bounds.y + translation.y, - x: bounds.x + translation.x, - ..bounds - }, - renderer, - ) + if state.scrollers_grabbed() { + return mouse::Interaction::None; } + + let translation = + state.translation(self.direction, bounds, content_bounds); + + let cursor = match cursor_over_scrollable { + Some(cursor_position) + if !(mouse_over_x_scrollbar || mouse_over_y_scrollbar) => + { + mouse::Cursor::Available(cursor_position + translation) + } + _ => cursor.levitate(), + }; + + self.content.as_widget().mouse_interaction( + &tree.children[0], + content_layout, + cursor, + &Rectangle { + y: bounds.y + translation.y, + x: bounds.x + translation.x, + ..bounds + }, + renderer, + ) } fn overlay<'b>( diff --git a/widget/src/slider.rs b/widget/src/slider.rs index 887d5a40..8aa697cd 100644 --- a/widget/src/slider.rs +++ b/widget/src/slider.rs @@ -363,7 +363,11 @@ where Event::Mouse(mouse::Event::CursorMoved { .. }) | Event::Touch(touch::Event::FingerMoved { .. }) => { if state.is_dragging { - let _ = cursor.position().and_then(locate).map(change); + let _ = cursor + .land() + .position() + .and_then(locate) + .map(change); shell.capture_event(); } @@ -527,12 +531,10 @@ where _renderer: &Renderer, ) -> mouse::Interaction { let state = tree.state.downcast_ref::(); - let bounds = layout.bounds(); - let is_mouse_over = cursor.is_over(bounds); if state.is_dragging { mouse::Interaction::Grabbing - } else if is_mouse_over { + } else if cursor.is_over(layout.bounds()) { mouse::Interaction::Grab } else { mouse::Interaction::default() diff --git a/widget/src/vertical_slider.rs b/widget/src/vertical_slider.rs index d7532d18..d14941cd 100644 --- a/widget/src/vertical_slider.rs +++ b/widget/src/vertical_slider.rs @@ -365,7 +365,8 @@ where Event::Mouse(mouse::Event::CursorMoved { .. }) | Event::Touch(touch::Event::FingerMoved { .. }) => { if is_dragging { - let _ = cursor.position().and_then(locate).map(change); + let _ = + cursor.land().position().and_then(locate).map(change); shell.capture_event(); } @@ -522,12 +523,10 @@ where _renderer: &Renderer, ) -> mouse::Interaction { let state = tree.state.downcast_ref::(); - let bounds = layout.bounds(); - let is_mouse_over = cursor.is_over(bounds); if state.is_dragging { mouse::Interaction::Grabbing - } else if is_mouse_over { + } else if cursor.is_over(layout.bounds()) { mouse::Interaction::Grab } else { mouse::Interaction::default()