diff --git a/crates/ui/src/components/context_menu.rs b/crates/ui/src/components/context_menu.rs index 3736a2e320..3eedf11bc1 100644 --- a/crates/ui/src/components/context_menu.rs +++ b/crates/ui/src/components/context_menu.rs @@ -233,6 +233,11 @@ pub struct ContextMenu { submenu_trigger_bounds: Rc>>>, submenu_trigger_mouse_down: bool, ignore_blur_until: Option, + /// When set to true, the next on_focus_in callback will not automatically + /// select an item. This prevents a visual flash where a submenu close in + /// on_hover(false) returns focus to the main menu and on_focus_in + /// re-selects the first item before the next on_hover(true) clears it. + suppress_focus_selection: bool, } #[derive(Copy, Clone, PartialEq, Eq)] @@ -303,9 +308,10 @@ impl ContextMenu { // menus we prefer the currently-checked item. We only do this when // nothing is selected yet so we don't override an existing selection. cx.on_focus_in(&focus_handle, window, |this, window, cx| { - if this.selected_index.is_none() { + if this.selected_index.is_none() && !this.suppress_focus_selection { this.select_toggled_or_first(window, cx); } + this.suppress_focus_selection = false; }) .detach(); @@ -333,6 +339,7 @@ impl ContextMenu { submenu_trigger_bounds: Rc::new(Cell::new(None)), submenu_trigger_mouse_down: false, ignore_blur_until: None, + suppress_focus_selection: false, }, window, cx, @@ -419,6 +426,7 @@ impl ContextMenu { submenu_trigger_bounds: Rc::new(Cell::new(None)), submenu_trigger_mouse_down: false, ignore_blur_until: None, + suppress_focus_selection: false, }, window, cx, @@ -488,6 +496,7 @@ impl ContextMenu { submenu_trigger_bounds: Rc::new(Cell::new(None)), submenu_trigger_mouse_down: false, ignore_blur_until: None, + suppress_focus_selection: false, }, window, cx, @@ -1324,6 +1333,7 @@ impl ContextMenu { submenu_trigger_bounds: Rc::new(Cell::new(None)), submenu_trigger_mouse_down: false, ignore_blur_until: None, + suppress_focus_selection: false, }; menu = (builder)(menu, window, cx); @@ -1649,6 +1659,7 @@ impl ContextMenu { if *hovered { this.clear_selected(); + this.suppress_focus_selection = true; window.focus(&this.focus_handle.clone(), cx); this.hover_target = HoverTarget::MainMenu; this.submenu_safety_threshold_x = Some(mouse_pos.x - px(50.0)); @@ -1686,6 +1697,7 @@ impl ContextMenu { { this.close_submenu(false, cx); this.clear_selected(); + this.suppress_focus_selection = true; window.focus(&this.focus_handle.clone(), cx); cx.notify(); } @@ -1973,6 +1985,7 @@ impl ContextMenu { item.on_hover(cx.listener(move |this, hovered, window, cx| { if *hovered { this.clear_selected(); + this.suppress_focus_selection = true; window.focus(&this.focus_handle.clone(), cx); if let SubmenuState::Open(open_submenu) = &this.submenu_state {