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

scroll_with_delta doesn't work #2783

Open
marcin-serwin opened this issue Mar 4, 2023 · 1 comment · May be fixed by #4303, #4332, #4348, #4412 or #4182
Open

scroll_with_delta doesn't work #2783

marcin-serwin opened this issue Mar 4, 2023 · 1 comment · May be fixed by #4303, #4332, #4348, #4412 or #4182
Labels
bug Something is broken

Comments

@marcin-serwin
Copy link

Describe the bug

scroll_with_delta doesn't seem to work.

To Reproduce

Steps to reproduce the behavior:

  1. Create an app with eframe.
  2. Copy the scroll_with_delta example from documentation.
  3. Click Scroll down button.
  4. See that nothing happens.
use eframe::egui::{self, Vec2};

fn main() -> Result<(), eframe::Error> {
    eframe::run_native(
        "My egui App",
        eframe::NativeOptions::default(),
        Box::new(|_cc| Box::new(MyApp {})),
    )
}

struct MyApp {}

impl eframe::App for MyApp {
    fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
        egui::CentralPanel::default().show(ctx, |ui| {
            let mut scroll_delta = Vec2::ZERO;
            if ui.button("Scroll down").clicked() {
                scroll_delta.y -= 64.0; // move content up
            }
            egui::ScrollArea::vertical().show(ui, |ui| {
                ui.scroll_with_delta(scroll_delta);
                for i in 0..1000 {
                    ui.label(format!("Item {}", i));
                }
            });
        });
    }
}

Expected behavior

Content scrolls down.

Screenshots

untitled.webm

Desktop (please complete the following information):

  • OS: GNU/Linux
@marcin-serwin marcin-serwin added the bug Something is broken label Mar 4, 2023
@YgorSouza
Copy link
Contributor

YgorSouza commented Mar 4, 2023

It looks like this is the code that handles the scroll_delta:

if scrolling_enabled && ui.rect_contains_pointer(outer_rect) {
for d in 0..2 {
if has_bar[d] {
let scroll_delta = ui.ctx().frame_state(|fs| fs.scroll_delta);
let scrolling_up = state.offset[d] > 0.0 && scroll_delta[d] > 0.0;
let scrolling_down = state.offset[d] < max_offset[d] && scroll_delta[d] < 0.0;
if scrolling_up || scrolling_down {
state.offset[d] -= scroll_delta[d];
// Clear scroll delta so no parent scroll will use it.
ui.ctx().frame_state_mut(|fs| fs.scroll_delta[d] = 0.0);
state.scroll_stuck_to_end[d] = false;
}
}
}
}

It only takes the delta into account if the pointer is inside the scroll area, so the example will never work, since you have to click a button that is outside the area. If I remove this condition, it works as intended. I don't know why it is written this way, and both the code above and the scroll_with_delta method are untouched for almost a year. I also tested with the commit that originally introduced the method (676ff04), and it didn't work there either. If there is no other reason for the && ui.rect_contains_pointer(outer_rect) condition, I supposed it could just be removed and the method will be fixed. But I'll wait to see if anyone has anything to say about it, and do some tests to see if it breaks anything else.

I suspect that since the scroll_delta is set in the Context, and is therefore global to the whole UI, the idea is that if there is more than one scroll area, the one that is hovered by the mouse would be the one to use the delta. But I guess if you set it from within the show() method of the scroll area that you want to manipulate, that will not be a problem. But I'm not sure I fully understand how this is supposed to work.

Edit: actually, the && ui.rect_contains_pointer(outer_rect) is needed because this scroll_delta value is also set by the scrolling events. If we remove it, scrolling with the mouse wheel is going to affect the first scroll area that is drawn on that frame, regardless of where the pointer is. So that is not an option. I guess we have to separate the two functionalities somehow, so that the input-based scroll uses the pointer position to determine which scroll area is concerned, but the programmatic scroll affects the next scroll area to be drawn after the scroll_with_delta call.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment