Clear go-to-def link when deactivating the window

Max Brunsfeld created

Change summary

crates/editor/src/items.rs                 |  8 +++++
crates/editor/src/link_go_to_definition.rs | 31 ++++++++++++++++++++++-
crates/workspace/src/workspace.rs          | 29 ++++++++++++++-------
3 files changed, 55 insertions(+), 13 deletions(-)

Detailed changes

crates/editor/src/items.rs 🔗

@@ -1,5 +1,6 @@
 use crate::{
-    Anchor, Autoscroll, Editor, Event, ExcerptId, MultiBuffer, NavigationData, ToPoint as _,
+    link_go_to_definition::hide_link_definition, Anchor, Autoscroll, Editor, Event, ExcerptId,
+    MultiBuffer, NavigationData, ToPoint as _,
 };
 use anyhow::{anyhow, Result};
 use futures::FutureExt;
@@ -376,6 +377,11 @@ impl Item for Editor {
         self.push_to_nav_history(selection.head(), None, cx);
     }
 
+    fn workspace_deactivated(&mut self, cx: &mut ViewContext<Self>) {
+        hide_link_definition(self, cx);
+        self.link_go_to_definition_state.last_mouse_location = None;
+    }
+
     fn is_dirty(&self, cx: &AppContext) -> bool {
         self.buffer().read(cx).read(cx).is_dirty()
     }
@@ -52,7 +52,7 @@ pub fn init(cx: &mut MutableAppContext) {
     cx.add_action(go_to_fetched_type_definition);
 }
 
-#[derive(Default)]
+#[derive(Debug, Default)]
 pub struct LinkGoToDefinitionState {
     pub last_mouse_location: Option<Anchor>,
     pub symbol_range: Option<Range<Anchor>>,
@@ -706,7 +706,34 @@ mod tests {
             fn do_work() { «test»(); }
         "});
 
-        // Moving within symbol range doesn't re-request
+        // Deactivating the window dismisses the highlight
+        cx.update_workspace(|workspace, cx| {
+            workspace.on_window_activation_changed(false, cx);
+        });
+        cx.assert_editor_text_highlights::<LinkGoToDefinitionState>(indoc! {"
+            fn test() { do_work(); }
+            fn do_work() { test(); }
+        "});
+
+        // Moving the mouse restores the highlights.
+        cx.update_editor(|editor, cx| {
+            update_go_to_definition_link(
+                editor,
+                &UpdateGoToDefinitionLink {
+                    point: Some(hover_point),
+                    cmd_held: true,
+                    shift_held: false,
+                },
+                cx,
+            );
+        });
+        cx.foreground().run_until_parked();
+        cx.assert_editor_text_highlights::<LinkGoToDefinitionState>(indoc! {"
+            fn test() { do_work(); }
+            fn do_work() { «test»(); }
+        "});
+
+        // Moving again within the same symbol range doesn't re-request
         let hover_point = cx.display_point(indoc! {"
             fn test() { do_work(); }
             fn do_work() { tesˇt(); }

crates/workspace/src/workspace.rs 🔗

@@ -261,6 +261,7 @@ pub struct AppState {
 
 pub trait Item: View {
     fn deactivated(&mut self, _: &mut ViewContext<Self>) {}
+    fn workspace_deactivated(&mut self, _: &mut ViewContext<Self>) {}
     fn navigate(&mut self, _: Box<dyn Any>, _: &mut ViewContext<Self>) -> bool {
         false
     }
@@ -433,6 +434,7 @@ pub trait ItemHandle: 'static + fmt::Debug {
         cx: &mut ViewContext<Workspace>,
     );
     fn deactivated(&self, cx: &mut MutableAppContext);
+    fn workspace_deactivated(&self, cx: &mut MutableAppContext);
     fn navigate(&self, data: Box<dyn Any>, cx: &mut MutableAppContext) -> bool;
     fn id(&self) -> usize;
     fn to_any(&self) -> AnyViewHandle;
@@ -629,6 +631,10 @@ impl<T: Item> ItemHandle for ViewHandle<T> {
         self.update(cx, |this, cx| this.deactivated(cx));
     }
 
+    fn workspace_deactivated(&self, cx: &mut MutableAppContext) {
+        self.update(cx, |this, cx| this.workspace_deactivated(cx));
+    }
+
     fn navigate(&self, data: Box<dyn Any>, cx: &mut MutableAppContext) -> bool {
         self.update(cx, |this, cx| this.navigate(data, cx))
     }
@@ -2383,18 +2389,21 @@ impl Workspace {
         None
     }
 
-    fn on_window_activation_changed(&mut self, active: bool, cx: &mut ViewContext<Self>) {
-        if !active
-            && matches!(
-                cx.global::<Settings>().autosave,
-                Autosave::OnWindowChange | Autosave::OnFocusChange
-            )
-        {
+    pub fn on_window_activation_changed(&mut self, active: bool, cx: &mut ViewContext<Self>) {
+        if !active {
             for pane in &self.panes {
                 pane.update(cx, |pane, cx| {
-                    for item in pane.items() {
-                        Pane::autosave_item(item.as_ref(), self.project.clone(), cx)
-                            .detach_and_log_err(cx);
+                    if let Some(item) = pane.active_item() {
+                        item.workspace_deactivated(cx);
+                    }
+                    if matches!(
+                        cx.global::<Settings>().autosave,
+                        Autosave::OnWindowChange | Autosave::OnFocusChange
+                    ) {
+                        for item in pane.items() {
+                            Pane::autosave_item(item.as_ref(), self.project.clone(), cx)
+                                .detach_and_log_err(cx);
+                        }
                     }
                 });
             }