diff --git a/crates/op-host-native/src/widget_host/scroll.rs b/crates/op-host-native/src/widget_host/scroll.rs index 37e5dff7b..3610a60ca 100644 --- a/crates/op-host-native/src/widget_host/scroll.rs +++ b/crates/op-host-native/src/widget_host/scroll.rs @@ -254,6 +254,15 @@ impl WidgetHostNative { viewport_width: f32, viewport_height: f32, ) -> bool { + // Floating VariablesPanel owns the wheel over its rect — run this + // BEFORE `over_topmost_panel`, which also lists the variables panel + // and would otherwise swallow the event WITHOUT scrolling (its rows + // never advanced because the topmost-panel guard returned first). + // `try_scroll_variables_panel` swallows the wheel when over the + // panel, so the "don't zoom the canvas beneath" guarantee holds. + if self.try_scroll_variables_panel(x, y, delta_y, viewport_width, viewport_height) { + return true; + } // Any top-most floating panel (Design-MD / Component-Browser) // owns the wheel before lower layers — a scroll over them // never reaches the modal / Git panel / canvas. @@ -288,10 +297,6 @@ impl WidgetHostNative { if self.try_scroll_chat_checklist(x, y, delta_y, viewport_width, viewport_height) { return true; } - // Floating VariablesPanel owns the wheel over its rect. - if self.try_scroll_variables_panel(x, y, delta_y, viewport_width, viewport_height) { - return true; - } // Agent-settings modal owns wheel. if self.editor_state.editor_ui.agent_settings_open { use op_editor_ui::widgets::agent_settings_panel::AgentSettingsPanel; diff --git a/crates/op-host-native/src/widget_host/variables_panel_tests.rs b/crates/op-host-native/src/widget_host/variables_panel_tests.rs index 5628a3645..c34eb3fca 100644 --- a/crates/op-host-native/src/widget_host/variables_panel_tests.rs +++ b/crates/op-host-native/src/widget_host/variables_panel_tests.rs @@ -528,6 +528,7 @@ fn variables_panel_preset_button_toggles_menu() { host.editor_state_mut().editor_ui.variables_panel_open = true; let rect = host.variables_panel_rect(VIEWPORT_W, VIEWPORT_H).unwrap(); + // Press the preset button (in the header, ~22 px down) — opens the menu. assert!(host.apply_press( rect.origin.x + 82.0, rect.origin.y + 22.0, @@ -536,9 +537,13 @@ fn variables_panel_preset_button_toggles_menu() { )); assert!(host.editor_state().editor_ui.variables_preset_menu_open); + // Press the SAME button again — toggles the menu closed. (A press at + // +58 would land in the open dropdown's SaveCurrent row, which focuses + // the name input and intentionally keeps the popover open — see + // `anchor_press_does_not_double_toggle` for the canonical toggle path.) assert!(host.apply_press( rect.origin.x + 82.0, - rect.origin.y + 58.0, + rect.origin.y + 22.0, VIEWPORT_W, VIEWPORT_H ));