Merge pull request #2438 from Koranir/on-scroll-patch

Notify `scrollable::Viewport` changes
This commit is contained in:
Héctor Ramón 2024-09-10 22:48:08 +02:00 committed by GitHub
commit 7bffab72b7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -12,6 +12,7 @@ use crate::core::touch;
use crate::core::widget; use crate::core::widget;
use crate::core::widget::operation::{self, Operation}; use crate::core::widget::operation::{self, Operation};
use crate::core::widget::tree::{self, Tree}; use crate::core::widget::tree::{self, Tree};
use crate::core::window;
use crate::core::{ use crate::core::{
self, Background, Clipboard, Color, Element, Layout, Length, Padding, self, Background, Clipboard, Color, Element, Layout, Length, Padding,
Pixels, Point, Rectangle, Shell, Size, Theme, Vector, Widget, Pixels, Point, Rectangle, Shell, Size, Theme, Vector, Widget,
@ -526,7 +527,7 @@ where
content_bounds, content_bounds,
); );
let _ = notify_on_scroll( let _ = notify_scroll(
state, state,
&self.on_scroll, &self.on_scroll,
bounds, bounds,
@ -564,7 +565,7 @@ where
state.y_scroller_grabbed_at = Some(scroller_grabbed_at); state.y_scroller_grabbed_at = Some(scroller_grabbed_at);
let _ = notify_on_scroll( let _ = notify_scroll(
state, state,
&self.on_scroll, &self.on_scroll,
bounds, bounds,
@ -597,7 +598,7 @@ where
content_bounds, content_bounds,
); );
let _ = notify_on_scroll( let _ = notify_scroll(
state, state,
&self.on_scroll, &self.on_scroll,
bounds, bounds,
@ -635,7 +636,7 @@ where
state.x_scroller_grabbed_at = Some(scroller_grabbed_at); state.x_scroller_grabbed_at = Some(scroller_grabbed_at);
let _ = notify_on_scroll( let _ = notify_scroll(
state, state,
&self.on_scroll, &self.on_scroll,
bounds, bounds,
@ -759,7 +760,7 @@ where
content_bounds, content_bounds,
); );
if notify_on_scroll( if notify_scroll(
state, state,
&self.on_scroll, &self.on_scroll,
bounds, bounds,
@ -807,7 +808,7 @@ where
Some(cursor_position); Some(cursor_position);
// TODO: bubble up touch movements if not consumed. // TODO: bubble up touch movements if not consumed.
let _ = notify_on_scroll( let _ = notify_scroll(
state, state,
&self.on_scroll, &self.on_scroll,
bounds, bounds,
@ -821,6 +822,17 @@ where
event::Status::Captured event::Status::Captured
} }
Event::Window(window::Event::RedrawRequested(_)) => {
let _ = notify_viewport(
state,
&self.on_scroll,
bounds,
content_bounds,
shell,
);
event::Status::Ignored
}
_ => event::Status::Ignored, _ => event::Status::Ignored,
} }
} }
@ -1153,8 +1165,23 @@ pub fn scroll_by<T>(id: Id, offset: AbsoluteOffset) -> Task<T> {
))) )))
} }
/// Returns [`true`] if the viewport actually changed. fn notify_scroll<Message>(
fn notify_on_scroll<Message>( state: &mut State,
on_scroll: &Option<Box<dyn Fn(Viewport) -> Message + '_>>,
bounds: Rectangle,
content_bounds: Rectangle,
shell: &mut Shell<'_, Message>,
) -> bool {
if notify_viewport(state, on_scroll, bounds, content_bounds, shell) {
state.last_scrolled = Some(Instant::now());
true
} else {
false
}
}
fn notify_viewport<Message>(
state: &mut State, state: &mut State,
on_scroll: &Option<Box<dyn Fn(Viewport) -> Message + '_>>, on_scroll: &Option<Box<dyn Fn(Viewport) -> Message + '_>>,
bounds: Rectangle, bounds: Rectangle,
@ -1167,6 +1194,11 @@ fn notify_on_scroll<Message>(
return false; return false;
} }
let Some(on_scroll) = on_scroll else {
state.last_notified = None;
return false;
};
let viewport = Viewport { let viewport = Viewport {
offset_x: state.offset_x, offset_x: state.offset_x,
offset_y: state.offset_y, offset_y: state.offset_y,
@ -1186,7 +1218,9 @@ fn notify_on_scroll<Message>(
(a - b).abs() <= f32::EPSILON || (a.is_nan() && b.is_nan()) (a - b).abs() <= f32::EPSILON || (a.is_nan() && b.is_nan())
}; };
if unchanged(last_relative_offset.x, current_relative_offset.x) if last_notified.bounds == bounds
&& last_notified.content_bounds == content_bounds
&& unchanged(last_relative_offset.x, current_relative_offset.x)
&& unchanged(last_relative_offset.y, current_relative_offset.y) && unchanged(last_relative_offset.y, current_relative_offset.y)
&& unchanged(last_absolute_offset.x, current_absolute_offset.x) && unchanged(last_absolute_offset.x, current_absolute_offset.x)
&& unchanged(last_absolute_offset.y, current_absolute_offset.y) && unchanged(last_absolute_offset.y, current_absolute_offset.y)
@ -1195,12 +1229,8 @@ fn notify_on_scroll<Message>(
} }
} }
if let Some(on_scroll) = on_scroll { shell.publish(on_scroll(viewport));
shell.publish(on_scroll(viewport));
}
state.last_notified = Some(viewport); state.last_notified = Some(viewport);
state.last_scrolled = Some(Instant::now());
true true
} }