fix(shell-native): collapsed-sidebar canvas input uses canvas_region

Stop-hook fix: native over_canvas + apply_wheel + apply_click
LayerPanel hit-test all hardcoded LAYER_PANEL_WIDTH for the canvas
left edge. When the sidebar was collapsed, paint moved the canvas
left to x=0 but input still treated x∈[0,240) as 'over the LayerPanel'
— so clicks in that strip resolved to LayerPanel hits (against
nothing), wheel zoom anchored off-screen to the left of the cursor,
and pan-drag refused to start in that strip.

over_canvas now derives both x and y bounds from canvas_region;
apply_wheel uses canvas_region for the cursor offset; apply_click
short-circuits when sidebar is closed (LayerPanel isn't painted)
and lets the empty-canvas branch clear selection + start pan-drag.
This commit is contained in:
Kayshen-X 2026-05-10 17:26:20 +08:00
parent 0954629626
commit 1d2dd789a9

View file

@ -171,18 +171,13 @@ impl WidgetHostNative {
/// Hit-test which screen region the cursor is over. Used by
/// the wheel + drag handlers so wheel-zoom + Hand-pan only
/// fire when the cursor is over the canvas (not over a panel).
/// Uses `canvas_region` so it stays in sync with paint when
/// the sidebar is collapsed (codex Step 6 stop-hook fix:
/// "native collapsed-sidebar canvas input still uses the old
/// left offset").
fn over_canvas(&self, x: f32, y: f32, viewport_w: f32, viewport_h: f32) -> bool {
let canvas_left = LAYER_PANEL_WIDTH;
let has_property = self.document.selected_node().is_some();
let canvas_right = if has_property {
viewport_w - PROPERTY_PANEL_WIDTH
} else {
viewport_w
};
x >= canvas_left
&& x <= canvas_right
&& y >= TOP_BAR_HEIGHT
&& y <= viewport_h
let (cx0, cy0, cw, ch) = self.canvas_region(viewport_w, viewport_h);
x >= cx0 && x <= cx0 + cw && y >= cy0 && y <= cy0 + ch
}
/// Apply a wheel event — zoom centered at `(x, y)` when over
@ -198,8 +193,11 @@ impl WidgetHostNative {
if !self.over_canvas(x, y, viewport_width, viewport_height) {
return false;
}
let canvas_left = LAYER_PANEL_WIDTH;
let cursor = Point2D::new(x - canvas_left, y - TOP_BAR_HEIGHT);
// Cursor in canvas-local coords — use canvas_region's
// dynamic left edge so cursor-centered zoom stays anchored
// when the sidebar is collapsed.
let (cx0, cy0, _cw, _ch) = self.canvas_region(viewport_width, viewport_height);
let cursor = Point2D::new(x - cx0, y - cy0);
self.document.viewport.zoom_at(cursor, delta_y);
true
}
@ -568,6 +566,13 @@ impl WidgetHostNative {
openpencil_shell_core::widgets::ToolbarHit::Action(_) => return false,
}
}
// LayerPanel hits only land when the sidebar is open —
// when collapsed the panel isn't painted (codex stop-hook
// fix: native collapsed-sidebar input was still resolving
// canvas clicks to the LayerPanel rect underneath).
if !self.document.ui.sidebar_open {
return was_focused;
}
let layer_rect = Rect {
origin: Point2D::new(0.0, TOP_BAR_HEIGHT),
size: Point2D::new(