Hide editor hover on mouse move out & always notify when hiding hover

Julia and Antonio Scandurra created

Co-Authored-By: Antonio Scandurra <me@as-cii.com>

Change summary

crates/editor/src/editor.rs        | 10 +++++-----
crates/editor/src/element.rs       | 10 +++++++---
crates/editor/src/hover_popover.rs | 16 ++++++++++++----
crates/editor/src/scroll.rs        |  8 ++++----
4 files changed, 28 insertions(+), 16 deletions(-)

Detailed changes

crates/editor/src/editor.rs 🔗

@@ -44,7 +44,7 @@ use gpui::{
     ViewContext, ViewHandle, WeakViewHandle,
 };
 use highlight_matching_bracket::refresh_matching_bracket_highlights;
-use hover_popover::{hide_hover, HoverState};
+use hover_popover::{hide_hover, HideHover, HoverState};
 pub use items::MAX_TAB_TITLE_LEN;
 use itertools::Itertools;
 pub use language::{char_kind, CharKind};
@@ -1319,7 +1319,7 @@ impl Editor {
                 }
             }
 
-            hide_hover(self, cx);
+            hide_hover(self, &HideHover, cx);
 
             if old_cursor_position.to_display_point(&display_map).row()
                 != new_cursor_position.to_display_point(&display_map).row()
@@ -1694,7 +1694,7 @@ impl Editor {
             return;
         }
 
-        if hide_hover(self, cx) {
+        if hide_hover(self, &HideHover, cx) {
             return;
         }
 
@@ -6174,7 +6174,7 @@ impl View for Editor {
             cx.defer(move |cx| {
                 if let Some(editor) = handle.upgrade(cx) {
                     editor.update(cx, |editor, cx| {
-                        hide_hover(editor, cx);
+                        hide_hover(editor, &HideHover, cx);
                         hide_link_definition(editor, cx);
                     })
                 }
@@ -6223,7 +6223,7 @@ impl View for Editor {
         self.buffer
             .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
         self.hide_context_menu(cx);
-        hide_hover(self, cx);
+        hide_hover(self, &HideHover, cx);
         cx.emit(Event::Blurred);
         cx.notify();
     }

crates/editor/src/element.rs 🔗

@@ -7,7 +7,7 @@ use crate::{
     display_map::{BlockStyle, DisplaySnapshot, TransformBlock},
     git::{diff_hunk_to_display, DisplayDiffHunk},
     hover_popover::{
-        HoverAt, HOVER_POPOVER_GAP, MIN_POPOVER_CHARACTER_WIDTH, MIN_POPOVER_LINE_HEIGHT,
+        HideHover, HoverAt, HOVER_POPOVER_GAP, MIN_POPOVER_CHARACTER_WIDTH, MIN_POPOVER_LINE_HEIGHT,
     },
     link_go_to_definition::{
         GoToFetchedDefinition, GoToFetchedTypeDefinition, UpdateGoToDefinitionLink,
@@ -114,6 +114,7 @@ impl EditorElement {
     fn attach_mouse_handlers(
         view: &WeakViewHandle<Editor>,
         position_map: &Arc<PositionMap>,
+        has_popovers: bool,
         visible_bounds: RectF,
         text_bounds: RectF,
         gutter_bounds: RectF,
@@ -190,8 +191,10 @@ impl EditorElement {
                         }
                     }
                 })
-                .on_move_out(|e, cx| {
-                    println!("on move out");
+                .on_move_out(move |_, cx| {
+                    if has_popovers {
+                        cx.dispatch_action(HideHover);
+                    }
                 })
                 .on_scroll({
                     let position_map = position_map.clone();
@@ -1873,6 +1876,7 @@ impl Element for EditorElement {
         Self::attach_mouse_handlers(
             &self.view,
             &layout.position_map,
+            layout.hover_popovers.is_some(),
             visible_bounds,
             text_bounds,
             gutter_bounds,

crates/editor/src/hover_popover.rs 🔗

@@ -29,12 +29,16 @@ pub struct HoverAt {
     pub point: Option<DisplayPoint>,
 }
 
+#[derive(Copy, Clone, PartialEq)]
+pub struct HideHover;
+
 actions!(editor, [Hover]);
-impl_internal_actions!(editor, [HoverAt]);
+impl_internal_actions!(editor, [HoverAt, HideHover]);
 
 pub fn init(cx: &mut MutableAppContext) {
     cx.add_action(hover);
     cx.add_action(hover_at);
+    cx.add_action(hide_hover);
 }
 
 /// Bindable action which uses the most recent selection head to trigger a hover
@@ -50,7 +54,7 @@ pub fn hover_at(editor: &mut Editor, action: &HoverAt, cx: &mut ViewContext<Edit
         if let Some(point) = action.point {
             show_hover(editor, point, false, cx);
         } else {
-            hide_hover(editor, cx);
+            hide_hover(editor, &HideHover, cx);
         }
     }
 }
@@ -58,7 +62,7 @@ pub fn hover_at(editor: &mut Editor, action: &HoverAt, cx: &mut ViewContext<Edit
 /// Hides the type information popup.
 /// Triggered by the `Hover` action when the cursor is not over a symbol or when the
 /// selections changed.
-pub fn hide_hover(editor: &mut Editor, cx: &mut ViewContext<Editor>) -> bool {
+pub fn hide_hover(editor: &mut Editor, _: &HideHover, cx: &mut ViewContext<Editor>) -> bool {
     let did_hide = editor.hover_state.info_popover.take().is_some()
         | editor.hover_state.diagnostic_popover.take().is_some();
 
@@ -67,6 +71,10 @@ pub fn hide_hover(editor: &mut Editor, cx: &mut ViewContext<Editor>) -> bool {
 
     editor.clear_background_highlights::<HoverState>(cx);
 
+    if did_hide {
+        cx.notify();
+    }
+
     did_hide
 }
 
@@ -121,7 +129,7 @@ fn show_hover(
                 // Hover triggered from same location as last time. Don't show again.
                 return;
             } else {
-                hide_hover(editor, cx);
+                hide_hover(editor, &HideHover, cx);
             }
         }
     }

crates/editor/src/scroll.rs 🔗

@@ -17,7 +17,7 @@ use workspace::WorkspaceId;
 
 use crate::{
     display_map::{DisplaySnapshot, ToDisplayPoint},
-    hover_popover::hide_hover,
+    hover_popover::{hide_hover, HideHover},
     persistence::DB,
     Anchor, DisplayPoint, Editor, EditorMode, Event, MultiBufferSnapshot, ToPoint,
 };
@@ -307,7 +307,7 @@ impl Editor {
     ) {
         let map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 
-        hide_hover(self, cx);
+        hide_hover(self, &HideHover, cx);
         self.scroll_manager.set_scroll_position(
             scroll_position,
             &map,
@@ -323,7 +323,7 @@ impl Editor {
     }
 
     pub fn set_scroll_anchor(&mut self, scroll_anchor: ScrollAnchor, cx: &mut ViewContext<Self>) {
-        hide_hover(self, cx);
+        hide_hover(self, &HideHover, cx);
         let top_row = scroll_anchor
             .top_anchor
             .to_point(&self.buffer().read(cx).snapshot(cx))
@@ -337,7 +337,7 @@ impl Editor {
         scroll_anchor: ScrollAnchor,
         cx: &mut ViewContext<Self>,
     ) {
-        hide_hover(self, cx);
+        hide_hover(self, &HideHover, cx);
         let top_row = scroll_anchor
             .top_anchor
             .to_point(&self.buffer().read(cx).snapshot(cx))