Fix canvas rect

This commit is contained in:
2026-09-09 21:28:49 +02:00
parent f35e5c82e5
commit a64a5327e7
+66 -6
View File
@@ -580,19 +580,19 @@ impl CanvasView {
// *canvas*, and egui clips interaction rectangles to it, so the clip
// has to be corrected before anything in the layer is interacted with:
// otherwise the background stops responding as soon as the view is
// panned away from where it started.
// panned away from where it started. The correction is the visible
// area and not a pixel more: the layer paints above the panels, so a
// background reaching past the central panel would sit on top of the
// inspector and swallow the clicks meant for its widgets.
let visible = self.to_global.inverse() * outer;
let background_rect = visible.expand(visible.width().max(visible.height()));
scene.set_clip_rect(background_rect);
scene.set_clip_rect(visible);
let background = scene.interact(
background_rect,
visible,
scene.id().with("background"),
Sense::click_and_drag(),
);
self.handle_pan_and_zoom(&scene, &background);
let visible = self.to_global.inverse() * outer;
scene.set_clip_rect(visible);
ui.ctx().set_transform_layer(layer, self.to_global);
if self.show_grid {
@@ -1694,6 +1694,40 @@ mod tests {
.drop_without_applying_deltas();
}
/// Like `pass`, but with a panel on the right the way the app puts the
/// inspector there. Reports whether the widget filling that panel was
/// clicked.
fn pass_beside_a_panel(
ctx: &egui::Context,
view: &mut CanvasView,
doc: &mut Document,
screen: Rect,
events: Vec<egui::Event>,
) -> bool {
let palette = Palette::dark();
let input = egui::RawInput {
screen_rect: Some(screen),
events,
..Default::default()
};
let mut clicked = false;
ctx.run_ui(input, |ui| {
egui::Panel::right("inspector")
.default_size(300.0)
.show(ui, |ui| {
let size = ui.available_size();
clicked = ui.add_sized(size, egui::Button::new("A control")).clicked();
});
egui::CentralPanel::default()
.frame(egui::Frame::NONE)
.show(ui, |ui| {
view.show(ui, doc, &palette);
});
})
.drop_without_applying_deltas();
clicked
}
fn click(at: Pos2) -> egui::Event {
egui::Event::PointerButton {
pos: at,
@@ -1771,6 +1805,32 @@ mod tests {
);
}
#[test]
fn a_click_in_the_inspector_stays_in_the_inspector() {
let ctx = egui::Context::default();
let mut doc = Document::new();
doc.canvas = canvas_with_two_nodes();
let mut view = CanvasView::new();
view.selection.set_node("a");
let screen = Rect::from_min_size(Pos2::ZERO, vec2(1200.0, 900.0));
let at = pos2(1050.0, 450.0);
let mut hit = false;
for events in [
vec![egui::Event::PointerMoved(at)],
vec![click(at)],
vec![release(at)],
] {
hit |= pass_beside_a_panel(&ctx, &mut view, &mut doc, screen, events);
}
assert!(hit, "the widget in the panel never saw the click");
assert!(
view.selection.has_node("a"),
"the canvas took a click that belonged to the panel"
);
}
fn canvas_with_two_nodes() -> Canvas {
let mut canvas = Canvas::default();
canvas.nodes.push(Node::new(