diff --git a/crates/ui-egui/src/canvas.rs b/crates/ui-egui/src/canvas.rs index 6d3b98f64..7f2856f48 100644 --- a/crates/ui-egui/src/canvas.rs +++ b/crates/ui-egui/src/canvas.rs @@ -354,9 +354,12 @@ fn canvas_input(app: &mut VectorcraftApp, ui: &Ui, resp: &egui::Response, rect: handle_input(app, ui, resp, rect); // `hover_doc` is the document point under the pointer in the view `handle_input` left. The // wheel, a pan, a Rotate View drag, the Zoom tool and a Presentation Mode click move the view - // there. + // there. A dialog, floating panel or menu over the canvas hides it (Object Highlighting + // showed through them: #4518), unless a drag that began on the canvas goes on there. let moved = Xf::new(rect, app.view().unwrap_or(&View::default())); - app.hover_doc = ui.input(|i| i.pointer.hover_pos()).filter(|p| rect.contains(*p)).map(|p| moved.to_doc(p)); + let dragging = ui.data(|d| d.get_temp::(drag_id()).is_some()); + app.hover_doc = + ui.input(|i| i.pointer.hover_pos()).filter(|p| rect.contains(*p) && (dragging || drag::on_canvas(ui, resp, *p))).map(|p| moved.to_doc(p)); } } diff --git a/crates/ui-egui/src/canvas/tests.rs b/crates/ui-egui/src/canvas/tests.rs index 7b2ddba66..4616338c1 100644 --- a/crates/ui-egui/src/canvas/tests.rs +++ b/crates/ui-egui/src/canvas/tests.rs @@ -7328,6 +7328,28 @@ fn distance_guides_follow_what_lies_under_a_still_pointer() { assert_eq!(gap_label(&run(&mut app, vec![])), None, "another document"); } +/// #4518: a floating panel or a modal dialog over the canvas hides the pointer from it, so Object +/// Highlighting, the rulers and the Info panel don't follow a pointer that is over the dialog. +#[test] +fn a_panel_or_dialog_over_the_canvas_hides_the_pointer_from_it() { + let (mut app, ctx, _, over, _) = distance_scene(true); + let run = |app: &mut VectorcraftApp, events, cover| distance_frame_covered(app, &ctx, events, cover); + run(&mut app, vec![egui::Event::PointerMoved(over)], None); + run(&mut app, vec![], None); + assert!(app.hover_doc.is_some(), "over the canvas"); + for cover in [Cover::Panel(egui::Rect::from_center_size(over, vec2(120.0, 120.0))), Cover::Dialog] { + // A new window takes a sizing pass before it covers anything, as in the test above. + for _ in 0..3 { + run(&mut app, vec![], Some(cover)); + } + assert_eq!(app.hover_doc, None, "under it"); + for _ in 0..3 { + run(&mut app, vec![], None); + } + assert!(app.hover_doc.is_some(), "back once it closes"); + } +} + /// The 800 × 600 window [`frame`] draws the canvas in. const WINDOW: egui::Rect = egui::Rect { min: Pos2::ZERO, max: Pos2 { x: 800.0, y: 600.0 } };