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

When the ScrollBar is set to Visibility::AlwaysVisible, scrolling is always possible & contains pointer #4412

Closed
wants to merge 18 commits into from
Closed
29 changes: 17 additions & 12 deletions crates/egui/src/containers/scroll_area.rs
Original file line number Diff line number Diff line change
Expand Up @@ -871,7 +871,13 @@ impl Prepared {

let max_offset = content_size - inner_rect.size();
let is_hovering_outer_rect = ui.rect_contains_pointer(outer_rect);
if scrolling_enabled && is_hovering_outer_rect {

if scrolling_enabled
&& (is_hovering_outer_rect
|| scroll_bar_visibility == ScrollBarVisibility::AlwaysVisible)
{
ui.ctx().create_scroll_delta(inner_rect);

let always_scroll_enabled_direction = ui.style().always_scroll_the_only_direction
&& scroll_enabled[0] != scroll_enabled[1];
for d in 0..2 {
Expand All @@ -890,20 +896,19 @@ impl Prepared {

if scrolling_up || scrolling_down {
state.offset[d] -= scroll_delta;

// Clear scroll delta so no parent scroll will use it:
ui.ctx().input_mut(|input| {
if always_scroll_enabled_direction {
input.smooth_scroll_delta[0] = 0.0;
input.smooth_scroll_delta[1] = 0.0;
} else {
input.smooth_scroll_delta[d] = 0.0;
}
});

state.scroll_stuck_to_end[d] = false;
state.offset_target[d] = None;
}

// Clear scroll delta so no parent scroll will use it:
ui.ctx().input_mut(|input| {
if always_scroll_enabled_direction {
input.smooth_scroll_delta[0] = 0.0;
input.smooth_scroll_delta[1] = 0.0;
} else {
input.smooth_scroll_delta[d] = 0.0;
}
});
}
}
}
Expand Down
11 changes: 11 additions & 0 deletions crates/egui/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1079,6 +1079,17 @@ impl Context {
.map_or(false, |response| response.contains_pointer)
}

/// Create scroll delta
///
/// See [`InputState`], [`ScrollArea`]
pub(crate) fn create_scroll_delta(&self, inner_rect: Rect) {
self.input_mut(|input| {
let pointer_position = input.pointer.interact_pos().unwrap_or_default();
let is_contains_pointer = inner_rect.contains(pointer_position);
input.create_scroll_delta(false, is_contains_pointer);
});
}

/// Do all interaction for an existing widget, without (re-)registering it.
fn get_response(&self, widget_rect: WidgetRect) -> Response {
let WidgetRect {
Expand Down
37 changes: 35 additions & 2 deletions crates/egui/src/input_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ impl InputState {
}
}

{
if unprocessed_scroll_delta_for_zoom != 0.0 {
// Smooth scroll-to-zoom:
if unprocessed_scroll_delta_for_zoom.abs() < 1.0 {
smooth_scroll_delta_for_zoom += unprocessed_scroll_delta_for_zoom;
Expand All @@ -321,7 +321,7 @@ impl InputState {
unprocessed_scroll_delta,
unprocessed_scroll_delta_for_zoom,
raw_scroll_delta,
smooth_scroll_delta,
smooth_scroll_delta: self.smooth_scroll_delta,
zoom_factor_delta,
screen_rect,
pixels_per_point,
Expand All @@ -338,6 +338,39 @@ impl InputState {
}
}

pub fn create_scroll_delta(&mut self, is_begin_frame: bool, is_contains_pointer: bool) {
if !is_begin_frame && !is_contains_pointer {
return;
}

if !is_begin_frame && is_contains_pointer {
self.unprocessed_scroll_delta += self.raw_scroll_delta;
self.raw_scroll_delta = Vec2::ZERO;
}

if self.unprocessed_scroll_delta != Vec2::ZERO {
let dt = self.stable_dt.at_most(0.1);
let t = crate::emath::exponential_smooth_factor(0.90, 0.1, dt);

for d in 0..2 {
if self.unprocessed_scroll_delta[d].abs() < 1.0 {
self.smooth_scroll_delta[d] += self.unprocessed_scroll_delta[d];
self.unprocessed_scroll_delta[d] = 0.0;
} else {
let smooth_delta = t * self.unprocessed_scroll_delta[d];
let direct_delta = self.unprocessed_scroll_delta[d];
// Smooth: smooth_delta > 0.0, Direct: smooth_delta < 0.0
let applied = match smooth_delta < 0.0 {
true => smooth_delta.min(direct_delta),
false => smooth_delta.max(direct_delta),
};
self.smooth_scroll_delta[d] += applied;
self.unprocessed_scroll_delta[d] -= applied;
}
}
}
}

/// Info about the active viewport
#[inline]
pub fn viewport(&self) -> &ViewportInfo {
Expand Down
Loading