Repro
Render two GraphView widgets simultaneously (e.g. side-by-side egui::SidePanels) with default SettingsNavigation (zoom + pan enabled). Hold Ctrl and scroll the wheel anywhere on the screen — including outside either
graph. Both graphs zoom in lockstep at the same rate. The examples/multiple example in this repo reproduces the symptom directly.
Expected vs actual
- Expected: only the graph whose response rect contains the pointer should zoom.
- Actual: every visible
GraphView with zoom_and_pan_enabled = true zooms on every Ctrl+Wheel event, regardless of pointer position.
Cause
GraphView::handle_zoom (src/graph_view.rs, 0.30.0) reads ui.input(|i| i.zoom_delta()) whenever settings_navigation.zoom_and_pan_enabled is true, with no containment check on the passed &Response:
fn handle_zoom(&self, ui: &Ui, resp: &Response, ...) {
if !self.settings_navigation.zoom_and_pan_enabled { return; }
ui.input(|i| {
let delta = i.zoom_delta();
// ...
let local_center = i.pointer.hover_pos().map(|p| self.local_pos(resp, p));
// ...
self.zoom(&local_rect, step, local_center, meta);
});
}
resp is consulted only to compute the zoom centre, never to gate whether the delta applies. With multiple GraphViews sharing the same egui::Context, every visible graph reads the same global zoom delta on every
frame.
Proposed fix
Wrap the input read in a hover gate:
fn handle_zoom(...) {
if !self.settings_navigation.zoom_and_pan_enabled { return; }
if !resp.hovered() { return; }
ui.input(|i| { /* existing body unchanged */ });
}
resp.hovered() already accounts for layer ordering and pointer occlusion, which matches user expectation. Two-line patch; happy to send a PR if the approach looks right.
Workaround today
Set settings_navigation.zoom_and_pan_enabled = false on every graph except the primary. The early-return at the top of handle_zoom/handle_pan suppresses input on secondaries. Acceptable when secondaries are read-only;
awkward when users expect multiple independently navigable graphs.
Versions
egui_graphs 0.30.0.
Repro
Render two
GraphViewwidgets simultaneously (e.g. side-by-sideegui::SidePanels) with defaultSettingsNavigation(zoom + pan enabled). Hold Ctrl and scroll the wheel anywhere on the screen — including outside eithergraph. Both graphs zoom in lockstep at the same rate. The
examples/multipleexample in this repo reproduces the symptom directly.Expected vs actual
GraphViewwithzoom_and_pan_enabled = truezooms on every Ctrl+Wheel event, regardless of pointer position.Cause
GraphView::handle_zoom(src/graph_view.rs, 0.30.0) readsui.input(|i| i.zoom_delta())wheneversettings_navigation.zoom_and_pan_enabledis true, with no containment check on the passed&Response:respis consulted only to compute the zoom centre, never to gate whether the delta applies. With multipleGraphViews sharing the sameegui::Context, every visible graph reads the same global zoom delta on everyframe.
Proposed fix
Wrap the input read in a hover gate:
resp.hovered()already accounts for layer ordering and pointer occlusion, which matches user expectation. Two-line patch; happy to send a PR if the approach looks right.Workaround today
Set
settings_navigation.zoom_and_pan_enabled = falseon every graph except the primary. The early-return at the top ofhandle_zoom/handle_pansuppresses input on secondaries. Acceptable when secondaries are read-only;awkward when users expect multiple independently navigable graphs.
Versions
egui_graphs0.30.0.