Improve state handling

This commit is contained in:
MrSubidubi 2025-08-25 23:39:07 +02:00
parent b4223d318f
commit c0891800dc

View file

@ -618,15 +618,12 @@ impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> ScrollbarState<S, T> {
&self.scroll_handle &self.scroll_handle
} }
fn set_offset(&mut self, offset: Point<Pixels>, window: &mut Window, cx: &mut Context<Self>) { fn set_offset(&mut self, offset: Point<Pixels>, cx: &mut Context<Self>) {
if self.scroll_handle.offset() != offset { if self.scroll_handle.offset() != offset {
self.scroll_handle.set_offset(offset); self.scroll_handle.set_offset(offset);
self.notify_parent(cx); self.notify_parent(cx);
cx.notify(); cx.notify();
} }
// We always want to show scrollbars in cases where the offset is updated.
self.show_scrollbars(window, cx);
} }
fn is_dragging(&self) -> bool { fn is_dragging(&self) -> bool {
@ -667,7 +664,7 @@ impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> ScrollbarState<S, T> {
fn set_thumb_state(&mut self, state: ThumbState, window: &mut Window, cx: &mut Context<Self>) { fn set_thumb_state(&mut self, state: ThumbState, window: &mut Window, cx: &mut Context<Self>) {
if self.thumb_state != state { if self.thumb_state != state {
if matches!(state, ThumbState::Inactive) { if state == ThumbState::Inactive {
self.schedule_auto_hide(window, cx); self.schedule_auto_hide(window, cx);
} else { } else {
self.show_scrollbars(window, cx); self.show_scrollbars(window, cx);
@ -916,6 +913,12 @@ impl ScrollbarLayout {
} }
} }
impl PartialEq for ScrollbarLayout {
fn eq(&self, other: &Self) -> bool {
self.axis == other.axis && self.thumb_bounds == other.thumb_bounds
}
}
#[derive(Clone)] #[derive(Clone)]
pub struct ScrollbarPrepaintState { pub struct ScrollbarPrepaintState {
parent_bounds: Bounds<Pixels>, parent_bounds: Bounds<Pixels>,
@ -940,6 +943,12 @@ impl ScrollbarPrepaintState {
} }
} }
impl PartialEq for ScrollbarPrepaintState {
fn eq(&self, other: &Self) -> bool {
self.thumbs == other.thumbs
}
}
impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> Element for ScrollbarElement<S, T> { impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> Element for ScrollbarElement<S, T> {
type RequestLayoutState = (); type RequestLayoutState = ();
type PrepaintState = Option<ScrollbarPrepaintState>; type PrepaintState = Option<ScrollbarPrepaintState>;
@ -978,7 +987,8 @@ impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> Element for ScrollbarEl
window: &mut Window, window: &mut Window,
cx: &mut App, cx: &mut App,
) -> Self::PrepaintState { ) -> Self::PrepaintState {
self.state let prepaint_state = self
.state
.read(cx) .read(cx)
.disabled() .disabled()
.not() .not()
@ -1056,7 +1066,16 @@ impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> Element for ScrollbarEl
}) })
.collect() .collect()
}, },
}) });
if prepaint_state
.as_ref()
.is_some_and(|state| Some(state) != self.state.read(cx).last_prepaint_state.as_ref())
{
self.state
.update(cx, |state, cx| state.show_scrollbars(window, cx));
}
prepaint_state
} }
fn paint( fn paint(
@ -1158,7 +1177,6 @@ impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> Element for ScrollbarEl
); );
state.set_offset( state.set_offset(
scroll_handle.offset().apply_along(*axis, |_| click_offset), scroll_handle.offset().apply_along(*axis, |_| click_offset),
window,
cx, cx,
); );
}; };
@ -1200,9 +1218,7 @@ impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> Element for ScrollbarEl
let new_offset = let new_offset =
scroll_handle.offset().apply_along(axis, |_| drag_offset); scroll_handle.offset().apply_along(axis, |_| drag_offset);
state.update(cx, |state, cx| { state.update(cx, |state, cx| state.set_offset(new_offset, cx));
state.set_offset(new_offset, window, cx)
});
cx.stop_propagation(); cx.stop_propagation();
} }
} }
@ -1218,7 +1234,7 @@ impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> Element for ScrollbarEl
cx.stop_propagation(); cx.stop_propagation();
} }
ParentHovered::No(state_changed) if state_changed => { ParentHovered::No(state_changed) if state_changed => {
state.schedule_auto_hide(window, cx); state.set_thumb_state(ThumbState::Inactive, window, cx);
} }
_ => {} _ => {}
} }