Detailed changes
@@ -108,7 +108,9 @@
"ctrl-'": "editor::ToggleHunkDiff",
"ctrl-\"": "editor::ExpandAllHunkDiffs",
"ctrl-i": "editor::ShowSignatureHelp",
- "alt-g b": "editor::ToggleGitBlame"
+ "alt-g b": "editor::ToggleGitBlame",
+ "menu": "editor::OpenContextMenu",
+ "shift-f10": "editor::OpenContextMenu"
}
},
{
@@ -296,6 +296,7 @@ gpui::actions!(
NewlineBelow,
NextInlineCompletion,
NextScreen,
+ OpenContextMenu,
OpenExcerpts,
OpenExcerptsSplit,
OpenProposedChangesEditor,
@@ -13075,6 +13075,12 @@ impl Editor {
cx.write_to_clipboard(ClipboardItem::new_string(lines));
}
+ pub fn open_context_menu(&mut self, _: &OpenContextMenu, cx: &mut ViewContext<Self>) {
+ self.request_autoscroll(Autoscroll::newest(), cx);
+ let position = self.selections.newest_display(cx).start;
+ mouse_context_menu::deploy_context_menu(self, None, position, cx);
+ }
+
pub fn inlay_hint_cache(&self) -> &InlayHintCache {
&self.inlay_hint_cache
}
@@ -13296,6 +13302,23 @@ impl Editor {
.get(&type_id)
.and_then(|item| item.to_any().downcast_ref::<T>())
}
+
+ fn character_size(&self, cx: &mut ViewContext<Self>) -> gpui::Point<Pixels> {
+ let text_layout_details = self.text_layout_details(cx);
+ let style = &text_layout_details.editor_style;
+ let font_id = cx.text_system().resolve_font(&style.text.font());
+ let font_size = style.text.font_size.to_pixels(cx.rem_size());
+ let line_height = style.text.line_height_in_pixels(cx.rem_size());
+
+ let em_width = cx
+ .text_system()
+ .typographic_bounds(font_id, font_size, 'm')
+ .unwrap()
+ .size
+ .width;
+
+ gpui::Point::new(em_width, line_height)
+ }
}
fn char_len_with_expanded_tabs(offset: usize, text: &str, tab_size: NonZeroU32) -> usize {
@@ -14725,17 +14748,10 @@ impl ViewInputHandler for Editor {
cx: &mut ViewContext<Self>,
) -> Option<gpui::Bounds<Pixels>> {
let text_layout_details = self.text_layout_details(cx);
- let style = &text_layout_details.editor_style;
- let font_id = cx.text_system().resolve_font(&style.text.font());
- let font_size = style.text.font_size.to_pixels(cx.rem_size());
- let line_height = style.text.line_height_in_pixels(cx.rem_size());
-
- let em_width = cx
- .text_system()
- .typographic_bounds(font_id, font_size, 'm')
- .unwrap()
- .size
- .width;
+ let gpui::Point {
+ x: em_width,
+ y: line_height,
+ } = self.character_size(cx);
let snapshot = self.snapshot(cx);
let scroll_position = snapshot.scroll_position();
@@ -169,6 +169,7 @@ impl EditorElement {
crate::rust_analyzer_ext::apply_related_actions(view, cx);
crate::clangd_ext::apply_related_actions(view, cx);
+ register_action(view, cx, Editor::open_context_menu);
register_action(view, cx, Editor::move_left);
register_action(view, cx, Editor::move_right);
register_action(view, cx, Editor::move_down);
@@ -595,7 +596,7 @@ impl EditorElement {
position_map.point_for_position(text_hitbox.bounds, event.position);
mouse_context_menu::deploy_context_menu(
editor,
- event.position,
+ Some(event.position),
point_for_position.previous_valid,
cx,
);
@@ -2730,6 +2731,7 @@ impl EditorElement {
&self,
editor_snapshot: &EditorSnapshot,
visible_range: Range<DisplayRow>,
+ content_origin: gpui::Point<Pixels>,
cx: &mut WindowContext,
) -> Option<AnyElement> {
let position = self.editor.update(cx, |editor, cx| {
@@ -2747,16 +2749,11 @@ impl EditorElement {
let mouse_context_menu = editor.mouse_context_menu.as_ref()?;
let (source_display_point, position) = match mouse_context_menu.position {
MenuPosition::PinnedToScreen(point) => (None, point),
- MenuPosition::PinnedToEditor {
- source,
- offset_x,
- offset_y,
- } => {
+ MenuPosition::PinnedToEditor { source, offset } => {
let source_display_point = source.to_display_point(editor_snapshot);
- let mut source_point = editor.to_pixel_point(source, editor_snapshot, cx)?;
- source_point.x += offset_x;
- source_point.y += offset_y;
- (Some(source_display_point), source_point)
+ let source_point = editor.to_pixel_point(source, editor_snapshot, cx)?;
+ let position = content_origin + source_point + offset;
+ (Some(source_display_point), position)
}
};
@@ -4325,8 +4322,8 @@ fn deploy_blame_entry_context_menu(
});
editor.update(cx, move |editor, cx| {
- editor.mouse_context_menu = Some(MouseContextMenu::pinned_to_screen(
- position,
+ editor.mouse_context_menu = Some(MouseContextMenu::new(
+ MenuPosition::PinnedToScreen(position),
context_menu,
cx,
));
@@ -5578,8 +5575,12 @@ impl Element for EditorElement {
);
}
- let mouse_context_menu =
- self.layout_mouse_context_menu(&snapshot, start_row..end_row, cx);
+ let mouse_context_menu = self.layout_mouse_context_menu(
+ &snapshot,
+ start_row..end_row,
+ content_origin,
+ cx,
+ );
cx.with_element_namespace("crease_toggles", |cx| {
self.prepaint_crease_toggles(
@@ -20,8 +20,7 @@ pub enum MenuPosition {
/// Disappears when the position is no longer visible.
PinnedToEditor {
source: multi_buffer::Anchor,
- offset_x: Pixels,
- offset_y: Pixels,
+ offset: Point<Pixels>,
},
}
@@ -48,36 +47,22 @@ impl MouseContextMenu {
context_menu: View<ui::ContextMenu>,
cx: &mut ViewContext<Editor>,
) -> Option<Self> {
- let context_menu_focus = context_menu.focus_handle(cx);
- cx.focus(&context_menu_focus);
-
- let _subscription = cx.subscribe(
- &context_menu,
- move |editor, _, _event: &DismissEvent, cx| {
- editor.mouse_context_menu.take();
- if context_menu_focus.contains_focused(cx) {
- editor.focus(cx);
- }
- },
- );
-
let editor_snapshot = editor.snapshot(cx);
- let source_point = editor.to_pixel_point(source, &editor_snapshot, cx)?;
- let offset = position - source_point;
-
- Some(Self {
- position: MenuPosition::PinnedToEditor {
- source,
- offset_x: offset.x,
- offset_y: offset.y,
- },
- context_menu,
- _subscription,
- })
+ let content_origin = editor.last_bounds?.origin
+ + Point {
+ x: editor.gutter_dimensions.width,
+ y: Pixels(0.0),
+ };
+ let source_position = editor.to_pixel_point(source, &editor_snapshot, cx)?;
+ let menu_position = MenuPosition::PinnedToEditor {
+ source,
+ offset: position - (source_position + content_origin),
+ };
+ return Some(MouseContextMenu::new(menu_position, context_menu, cx));
}
- pub(crate) fn pinned_to_screen(
- position: Point<Pixels>,
+ pub(crate) fn new(
+ position: MenuPosition,
context_menu: View<ui::ContextMenu>,
cx: &mut ViewContext<Editor>,
) -> Self {
@@ -95,7 +80,7 @@ impl MouseContextMenu {
);
Self {
- position: MenuPosition::PinnedToScreen(position),
+ position,
context_menu,
_subscription,
}
@@ -119,7 +104,7 @@ fn display_ranges<'a>(
pub fn deploy_context_menu(
editor: &mut Editor,
- position: Point<Pixels>,
+ position: Option<Point<Pixels>>,
point: DisplayPoint,
cx: &mut ViewContext<Editor>,
) {
@@ -213,8 +198,18 @@ pub fn deploy_context_menu(
})
};
- editor.mouse_context_menu =
- MouseContextMenu::pinned_to_editor(editor, source_anchor, position, context_menu, cx);
+ editor.mouse_context_menu = match position {
+ Some(position) => {
+ MouseContextMenu::pinned_to_editor(editor, source_anchor, position, context_menu, cx)
+ }
+ None => {
+ let menu_position = MenuPosition::PinnedToEditor {
+ source: source_anchor,
+ offset: editor.character_size(cx),
+ };
+ Some(MouseContextMenu::new(menu_position, context_menu, cx))
+ }
+ };
cx.notify();
}
@@ -248,7 +243,9 @@ mod tests {
}
"});
cx.editor(|editor, _app| assert!(editor.mouse_context_menu.is_none()));
- cx.update_editor(|editor, cx| deploy_context_menu(editor, Default::default(), point, cx));
+ cx.update_editor(|editor, cx| {
+ deploy_context_menu(editor, Some(Default::default()), point, cx)
+ });
cx.assert_editor_state(indoc! {"
fn test() {