From 33433b89244dee10c7b238813e62b5ee2f306a0c Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 15 Oct 2026 18:15:51 +0000 Subject: [PATCH] fix(dock): keep an auto-hiding panel out while its colour popup is open The Layer Manager's colour dropdown draws as an overlay, which the docked edge's mouse area reads as the pointer leaving. The auto-hide timer then collapsed the panel and the dropdown with it, so no colour could be picked. Defer the hide while a pallet colour dropdown or the Select Color window is open. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_014ihuqzxdUhd9UbioPn5MGu --- src/app/dock/tests.rs | 24 ++++++++++++++++++++++++ src/app/dock/update.rs | 20 ++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/src/app/dock/tests.rs b/src/app/dock/tests.rs index eeda37b0e..4276df96b 100644 --- a/src/app/dock/tests.rs +++ b/src/app/dock/tests.rs @@ -393,6 +393,30 @@ fn dock_hover_reveals_groups_only_on_an_auto_hiding_edge() { assert!(app.dock_edge_expanded(DockSide::Left)); } +#[test] +fn dock_auto_hide_waits_for_an_open_layer_color_dropdown() { + use crate::ui::dock::{DockGroup, DockMsg, PanelId}; + let mut app = dock_app(); + app.dock.left.push(DockGroup::single(PanelId::Layers)); + let _ = app.on_dock(DockMsg::AutoCollapseToggle(PanelId::Layers)); + let _ = app.on_dock(DockMsg::Hover(PanelId::Layers)); + let _ = app.on_dock(DockMsg::HoverSettled(app.dock_hover_gen)); + assert_eq!(app.dock_peek, Some(PanelId::Layers)); + // Opening a row's colour swatch, then moving onto its dropdown, reads + // as the pointer leaving the edge: the panel must stay out. + let _ = app.update(Message::LayerColorPickerToggle("0".to_string())); + assert!(app.tabs[app.active_tab].layers.color_picker_row.is_some()); + let _ = app.on_dock(DockMsg::HoverExit); + let _ = app.on_dock(DockMsg::HoverSettled(app.dock_hover_gen)); + assert_eq!(app.dock_peek, Some(PanelId::Layers)); + let _ = app.on_dock(DockMsg::HoverSettled(app.dock_hover_gen)); + assert_eq!(app.dock_peek, Some(PanelId::Layers)); + // Once the dropdown closes with the pointer still away, it hides. + let _ = app.update(Message::LayerColorPickerToggle("0".to_string())); + let _ = app.on_dock(DockMsg::HoverSettled(app.dock_hover_gen)); + assert_eq!(app.dock_peek, None); +} + #[test] fn dock_float_resize_grows_the_panel() { use crate::ui::dock::{DockMsg, FloatPanel, PanelId}; diff --git a/src/app/dock/update.rs b/src/app/dock/update.rs index e77857c45..514ab2f50 100644 --- a/src/app/dock/update.rs +++ b/src/app/dock/update.rs @@ -207,6 +207,15 @@ impl OpenCADStudio { Some(HoverPending::Hide) if self.dock_peek.is_some_and(|id| self.dock.auto_hides(id)) => { + // A dropdown or the colour window opened from the + // panel draws as an overlay, which the edge's + // mouse area reads as the pointer leaving. Keep + // the panel out until it closes, so a pick can + // still land; then hide unless the pointer is + // back (its re-entry cancels this). + if self.dock_popup_open() { + return self.dock_hover_arm(HoverPending::Hide); + } self.dock_peek = None; } _ => {} @@ -412,6 +421,17 @@ impl OpenCADStudio { }) } + /// Whether a popup a pallet opened is showing: a colour dropdown in the + /// Layer Manager or Properties, or the Select Color window. + fn dock_popup_open(&self) -> bool { + let tab = &self.tabs[self.active_tab]; + tab.layers.color_picker_row.is_some() + || tab.properties.color_picker_open + || tab.properties.bg_color_picker_open + || tab.properties.open_color_field.is_some() + || self.color_picker.is_some() + } + /// Drop any pending delayed reveal / hide. fn dock_hover_cancel(&mut self) { self.dock_hover_gen = self.dock_hover_gen.wrapping_add(1);