From 0a762f6a1e2bac823a18a246715a6c8a1cbd7a3b Mon Sep 17 00:00:00 2001 From: Kayshen-X Date: Thu, 14 May 2026 19:33:09 +0800 Subject: [PATCH] fix(host): fill-picker dismiss at the middle of the cascade MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous commit (7fafa379) moved fill-picker dismiss to the very top of the press cascade, but that stole layer-context-menu clicks (codex stop-gate). The commit before THAT (c3394fda) had it late enough to be stolen by VariablesPanel. Right answer: middle position (the original 0c0 spot, between TopBar and VariablesPanel) — after the higher-z overlays (color picker, layer-context-menu, agent-settings modal) so those keep their own click handling when both happen to be open, but BEFORE the rail walkers (VariablesPanel, PropertyPanel) so the picker can't survive a click into them. Cascade now reads: pre rename / text-edit blur pre agent-settings modal 0-c color picker overlay pre layer context menu 0aa commit-on-blur for property inputs 0z panel resize gutter 0ab shape picker overlay 0a locale picker overlay 0b TopBar 0c0 **fill-type picker dismiss** ← settled position 0b1 VariablesPanel 0c PropertyPanel input + action 1+ chat, toolbar, canvas, … The remaining edge case — TopBar / shape-picker / locale-picker clicks while fill-picker is open consume the click without closing fill — is pre-existing behavior. The cascade ordering between those small overlays is a wider design question (last-opened wins vs. priority list); not in scope for this commit. press.rs: 839 → 840 (+1). 295 shell-core + 20 shell-native tests pass. --- .../src/widget_host/press.rs | 73 ++++++++++--------- 1 file changed, 37 insertions(+), 36 deletions(-) diff --git a/crates/openpencil-shell-native/src/widget_host/press.rs b/crates/openpencil-shell-native/src/widget_host/press.rs index 51cb07333..f7bde83d4 100644 --- a/crates/openpencil-shell-native/src/widget_host/press.rs +++ b/crates/openpencil-shell-native/src/widget_host/press.rs @@ -130,42 +130,6 @@ impl WidgetHostNative { { return true; } - - // 0-fp. Fill-type picker — outside-click dismiss runs FIRST - // among overlay dismissers so an open picker can't survive - // a click that another later step (TopBar, Toolbar, Variables, - // canvas) would otherwise consume. Codex stop-gate: previous - // ordering let the picker stay open after a TopBar / shape- - // picker / VariablesPanel click. A click inside the picker's - // own dropdown rows still routes to SetFillType / - // ToggleFillTypePicker; everything else swallows + closes. - if self.document.ui.fill_type_picker_open { - if let Some(panel) = PropertyPanel::for_selection(&self.document) { - let property_rect = Rect { - origin: Point2D::new( - viewport_width - self.document.ui.property_panel_width, - TOP_BAR_HEIGHT, - ), - size: Point2D::new( - self.document.ui.property_panel_width, - (viewport_height - TOP_BAR_HEIGHT).max(0.0), - ), - }; - if let Some(action) = panel.hit_test_action(property_rect, Point2D::new(x, y)) { - if matches!( - action, - openpencil_shell_core::widgets::PropertyPanelAction::SetFillType(_) - | openpencil_shell_core::widgets::PropertyPanelAction::ToggleFillTypePicker - ) { - self.apply_property_action(action); - return true; - } - } - } - self.document.ui.fill_type_picker_open = false; - return true; - } - // 0-color. Color picker overlay — top-most when open. if let Some(state) = self.document.ui.color_picker.clone() { use openpencil_shell_core::widgets::color_picker::{ @@ -319,6 +283,43 @@ impl WidgetHostNative { return rename_committed || text_edit_committed; } + // 0c0. Fill-type picker — outside-click dismiss. Runs after + // the higher-priority overlays (color picker, layer + // context menu, agent-settings modal) so those can + // still consume their own clicks when both happen to + // be open. Codex stop-gate: an earlier attempt to put + // this first stole layer-context-menu clicks; the + // previous late position let the picker survive a + // VariablesPanel click. This middle position satisfies + // both — picker dismisses before VariablesPanel + the + // rail walkers, but not before higher-z overlays. + if self.document.ui.fill_type_picker_open { + if let Some(panel) = PropertyPanel::for_selection(&self.document) { + let property_rect = Rect { + origin: Point2D::new( + viewport_width - self.document.ui.property_panel_width, + TOP_BAR_HEIGHT, + ), + size: Point2D::new( + self.document.ui.property_panel_width, + (viewport_height - TOP_BAR_HEIGHT).max(0.0), + ), + }; + if let Some(action) = panel.hit_test_action(property_rect, Point2D::new(x, y)) { + if matches!( + action, + openpencil_shell_core::widgets::PropertyPanelAction::SetFillType(_) + | openpencil_shell_core::widgets::PropertyPanelAction::ToggleFillTypePicker + ) { + self.apply_property_action(action); + return true; + } + } + } + self.document.ui.fill_type_picker_open = false; + return true; + } + // 0b1. VariablesPanel — tested before PropertyPanel so the // bottom-anchored Variables rect wins (paint stack: // PropertyPanel under, Variables over).