Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: Scroll doesn't work or is inaccurate in ScrollArea #5307

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 22 additions & 10 deletions crates/egui/src/containers/scroll_area.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ pub struct State {
/// If set, quickly but smoothly scroll to this target offset.
offset_target: [Option<ScrollingToTarget>; 2],

/// The offset value when the `offset_target` is set.
offset_target_start: [Option<f32>; 2],

/// Were the scroll bars visible last frame?
show_scroll: Vec2b,

Expand Down Expand Up @@ -52,6 +55,7 @@ impl Default for State {
Self {
offset: Vec2::ZERO,
offset_target: Default::default(),
offset_target_start: Default::default(),
show_scroll: Vec2b::FALSE,
content_is_too_large: Vec2b::FALSE,
scroll_bar_interaction: Vec2b::FALSE,
Expand Down Expand Up @@ -825,22 +829,25 @@ impl Prepared {

let content_size = content_ui.min_size();

let scroll_delta = content_ui
.ctx()
.pass_state_mut(|state| std::mem::take(&mut state.scroll_delta));

for d in 0..2 {
// PassState::scroll_delta is inverted from the way we apply the delta, so we need to negate it.
let mut delta = -scroll_delta.0[d];
let mut animation = scroll_delta.1;

// We always take both scroll targets regardless of which scroll axes are enabled. This
// is to avoid them leaking to other scroll areas.
let scroll_target = content_ui
.ctx()
.pass_state_mut(|state| state.scroll_target[d].take());

if scroll_enabled[d] {
let (scroll_delta_0, scroll_delta_1) = content_ui.ctx().pass_state_mut(|state| {
(
std::mem::take(&mut state.scroll_delta.0[d]),
std::mem::take(&mut state.scroll_delta.1),
)
});

// PassState::scroll_delta is inverted from the way we apply the delta, so we need to negate it.
let mut delta = -scroll_delta_0;
let mut animation = scroll_delta_1;

if let Some(target) = scroll_target {
let pass_state::ScrollTarget {
range,
Expand Down Expand Up @@ -883,10 +890,14 @@ impl Prepared {

if !animated {
state.offset[d] = target_offset;
} else if let Some(animation) = &mut state.offset_target[d] {
} else if let Some(scroll_to_target) = &mut state.offset_target[d] {
// For instance: the user is continuously calling `ui.scroll_to_cursor`,
// so we don't want to reset the animation, but perhaps update the target:
animation.target_offset = target_offset;
if let Some(offset_target_start) = state.offset_target_start[d].take() {
let new_target_offset = offset_target_start + delta;
scroll_to_target.target_offset +=
scroll_to_target.target_offset - new_target_offset;
}
} else {
// The further we scroll, the more time we take.
let now = ui.input(|i| i.time);
Expand All @@ -896,6 +907,7 @@ impl Prepared {
animation_time_span: (now, now + animation_duration as f64),
target_offset,
});
state.offset_target_start[d] = Some(state.offset[d]);
}
ui.ctx().request_repaint();
}
Expand Down
Loading