Properly calculate y offsets for multi buffer context menus (#15594)

Kirill Bulatov and Max Brunsfeld created

Follow-up of https://github.com/zed-industries/zed/pull/14727

Release Notes:

- Fixed multi buffer context menus not showing properly

Co-authored-by: Max Brunsfeld <max@zed.dev>

Change summary

crates/editor/src/editor.rs             | 29 ++++++--------------------
crates/editor/src/mouse_context_menu.rs | 10 +++++++++
2 files changed, 17 insertions(+), 22 deletions(-)

Detailed changes

crates/editor/src/editor.rs 🔗

@@ -11824,24 +11824,8 @@ impl Editor {
         editor_snapshot: &EditorSnapshot,
         cx: &mut ViewContext<Self>,
     ) -> Option<gpui::Point<Pixels>> {
-        let text_layout_details = self.text_layout_details(cx);
-        let line_height = text_layout_details
-            .editor_style
-            .text
-            .line_height_in_pixels(cx.rem_size());
         let source_point = source.to_display_point(editor_snapshot);
-        let first_visible_line = text_layout_details
-            .scroll_anchor
-            .anchor
-            .to_display_point(editor_snapshot);
-        if first_visible_line > source_point {
-            return None;
-        }
-        let source_x = editor_snapshot.x_for_display_point(source_point, &text_layout_details);
-        let source_y = line_height
-            * ((source_point.row() - first_visible_line.row()).0 as f32
-                - text_layout_details.scroll_anchor.offset.y);
-        Some(gpui::Point::new(source_x, source_y))
+        self.display_to_pixel_point(source_point, editor_snapshot, cx)
     }
 
     pub fn display_to_pixel_point(
@@ -11852,15 +11836,16 @@ impl Editor {
     ) -> Option<gpui::Point<Pixels>> {
         let line_height = self.style()?.text.line_height_in_pixels(cx.rem_size());
         let text_layout_details = self.text_layout_details(cx);
-        let first_visible_line = text_layout_details
+        let scroll_top = text_layout_details
             .scroll_anchor
-            .anchor
-            .to_display_point(editor_snapshot);
-        if first_visible_line > source {
+            .scroll_position(editor_snapshot)
+            .y;
+
+        if source.row().as_f32() < scroll_top.floor() {
             return None;
         }
         let source_x = editor_snapshot.x_for_display_point(source, &text_layout_details);
-        let source_y = line_height * (source.row() - first_visible_line.row()).0 as f32;
+        let source_y = line_height * (source.row().as_f32() - scroll_top);
         Some(gpui::Point::new(source_x, source_y))
     }
 }

crates/editor/src/mouse_context_menu.rs 🔗

@@ -10,6 +10,7 @@ use gpui::prelude::FluentBuilder;
 use gpui::{DismissEvent, Pixels, Point, Subscription, View, ViewContext};
 use workspace::OpenInTerminal;
 
+#[derive(Debug)]
 pub enum MenuPosition {
     /// When the editor is scrolled, the context menu stays on the exact
     /// same position on the screen, never disappearing.
@@ -29,6 +30,15 @@ pub struct MouseContextMenu {
     _subscription: Subscription,
 }
 
+impl std::fmt::Debug for MouseContextMenu {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        f.debug_struct("MouseContextMenu")
+            .field("position", &self.position)
+            .field("context_menu", &self.context_menu)
+            .finish()
+    }
+}
+
 impl MouseContextMenu {
     pub(crate) fn pinned_to_editor(
         editor: &mut Editor,