diff --git a/crates/ui-egui/src/canvas.rs b/crates/ui-egui/src/canvas.rs index 1d14b60c..818a9f5f 100644 --- a/crates/ui-egui/src/canvas.rs +++ b/crates/ui-egui/src/canvas.rs @@ -142,6 +142,15 @@ pub fn show(app: &mut SlideApp, ui: &mut Ui) { let avail = ui.available_rect_before_wrap(); app.canvas_rect = Some(avail); let Some(st) = app.session.active() else { return }; + // The leftover fraction of a wheel line belongs to one presentation. Drop it whenever another + // one is drawn here, hovered or not, so switching away and back starts from zero. + let carry_id = ui.id().with("wheel_carry"); + let doc_uid = st.uid; + ui.data_mut(|d| { + if d.get_temp::<(u64, f32)>(carry_id).is_none_or(|(uid, _)| uid != doc_uid) { + d.insert_temp(carry_id, (doc_uid, 0.0_f32)); + } + }); if st.doc.slides.is_empty() && st.selection.target == Target::Slides { let resp = ui.allocate_rect(avail, Sense::click()); ui.painter().text(avail.center(), Align2::CENTER_CENTER, "Click to add first slide", theme::font(22.0), t.text_dim); @@ -177,13 +186,7 @@ pub fn show(app: &mut SlideApp, ui: &mut Ui) { if overflow != egui::Vec2::ZERO { offset -= wheel; } else if !app.anim_preview_active() && app.session.tool.marquee.is_none() && !app.session.tool.dragging() { - // The leftover fraction belongs to one presentation: another one starts from zero. - let carry_id = ui.id().with("wheel_carry"); - let (carry_doc, mut carry): (Option, f32) = ui.data_mut(|d| d.get_temp(carry_id).unwrap_or_default()); - let doc_uid = app.session.active().map(|d| d.uid); - if carry_doc != doc_uid { - carry = 0.0; - } + let (_, mut carry): (u64, f32) = ui.data_mut(|d| d.get_temp(carry_id).unwrap_or_default()); let wheel_step = app.session.active().and_then(|d| { let current = d.selection.slide; ui.input(|i| wheel_slide_target(&i.events, current, d.doc.slides.len(), &mut carry)).map(|target| (current, target)) diff --git a/crates/ui-egui/src/lib.rs b/crates/ui-egui/src/lib.rs index b7759cc8..c898465c 100644 --- a/crates/ui-egui/src/lib.rs +++ b/crates/ui-egui/src/lib.rs @@ -3393,6 +3393,7 @@ mod tests { mouse_wheel(&mut h, &[-0.75]); assert_eq!(slide_at(h.state()), 0); + let a = h.state().session.active_index().unwrap(); h.state_mut().run("file.new", json!({})).unwrap(); h.state_mut().run("slide.new", json!({})).unwrap(); h.state_mut().run("slide.go", json!({"index": 0})).unwrap(); @@ -3402,6 +3403,23 @@ mod tests { assert_eq!(slide_at(h.state()), 0, "a quarter line in the new presentation does not turn the page"); mouse_wheel(&mut h, &[-0.75]); assert_eq!(slide_at(h.state()), 1, "a whole line in the new presentation does"); + + // Back in the first one, leave 0.75 of a line, then switch away and back with the pointer + // off the canvas (on the tabs): the canvas never sees a hover in the other presentation. + let b = h.state().session.active_index().unwrap(); + h.state_mut().session.set_active(a); + h.state_mut().ui.zoom = Some(0.4); + h.run_steps(2); + mouse_wheel(&mut h, &[-0.75]); + assert_eq!(slide_at(h.state()), 0); + h.input_mut().events.push(egui::Event::PointerMoved(egui::pos2(-10.0, -10.0))); + h.run_steps(1); + h.state_mut().session.set_active(b); + h.run_steps(2); + h.state_mut().session.set_active(a); + h.run_steps(2); + mouse_wheel(&mut h, &[-0.25]); + assert_eq!(slide_at(h.state()), 0, "switching away without a hover still drops the fraction"); } #[test]