git_ui: Fix tooltip overlaying context menu in git blame (#42764)

Mustaque Ahmed and Finn Evers created

Closes #26949


## Summary

1. Split editor references to avoid borrow conflicts in event handlers
2. Check
[has_mouse_context_menu()](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html)
state directly in tooltip conditional instead of caching stale value
3. Restructured context menu deployment to ensure proper sequencing:
hide popover → build menu → deploy menu → notify for re-render

**Screen recording**



https://github.com/user-attachments/assets/8a00f882-1c54-47b0-9211-4f28f8deb867



Release Notes:

- Fixed an issue where the context menu in the Git Blame view would be
frequently overlapped by the commit information tooltip.

---------

Co-authored-by: Finn Evers <finn.evers@outlook.de>

Change summary

crates/editor/src/editor.rs   |  6 +++++-
crates/git_ui/src/blame_ui.rs | 27 +++++++++++++++++----------
2 files changed, 22 insertions(+), 11 deletions(-)

Detailed changes

crates/editor/src/editor.rs 🔗

@@ -6920,7 +6920,11 @@ impl Editor {
         }
     }
 
-    fn hide_blame_popover(&mut self, ignore_timeout: bool, cx: &mut Context<Self>) -> bool {
+    pub fn has_mouse_context_menu(&self) -> bool {
+        self.mouse_context_menu.is_some()
+    }
+
+    pub fn hide_blame_popover(&mut self, ignore_timeout: bool, cx: &mut Context<Self>) -> bool {
         self.inline_blame_popover_show_task.take();
         if let Some(state) = &mut self.inline_blame_popover {
             let hide_task = cx.spawn(async move |editor, cx| {

crates/git_ui/src/blame_ui.rs 🔗

@@ -55,6 +55,7 @@ impl BlameRenderer for GitBlameRenderer {
         } else {
             None
         };
+
         Some(
             div()
                 .mr_2()
@@ -80,7 +81,10 @@ impl BlameRenderer for GitBlameRenderer {
                         .on_mouse_down(MouseButton::Right, {
                             let blame_entry = blame_entry.clone();
                             let details = details.clone();
+                            let editor = editor.clone();
                             move |event, window, cx| {
+                                cx.stop_propagation();
+
                                 deploy_blame_entry_context_menu(
                                     &blame_entry,
                                     details.as_ref(),
@@ -107,17 +111,19 @@ impl BlameRenderer for GitBlameRenderer {
                                 )
                             }
                         })
-                        .hoverable_tooltip(move |_window, cx| {
-                            cx.new(|cx| {
-                                CommitTooltip::blame_entry(
-                                    &blame_entry,
-                                    details.clone(),
-                                    repository.clone(),
-                                    workspace.clone(),
-                                    cx,
-                                )
+                        .when(!editor.read(cx).has_mouse_context_menu(), |el| {
+                            el.hoverable_tooltip(move |_window, cx| {
+                                cx.new(|cx| {
+                                    CommitTooltip::blame_entry(
+                                        &blame_entry,
+                                        details.clone(),
+                                        repository.clone(),
+                                        workspace.clone(),
+                                        cx,
+                                    )
+                                })
+                                .into()
                             })
-                            .into()
                         }),
                 )
                 .into_any(),
@@ -396,6 +402,7 @@ fn deploy_blame_entry_context_menu(
     });
 
     editor.update(cx, move |editor, cx| {
+        editor.hide_blame_popover(false, cx);
         editor.deploy_mouse_context_menu(position, context_menu, window, cx);
         cx.notify();
     });