editor: Dismiss mouse context menus on selections change (#28729)

Closes #ISSUE

Adds an extra subscription for mouse context menus (i.e. right click context menu) so that when selections change in the editor while the context menu is open (e.g. with vim motions), the context menu closes.

Release Notes:

- N/A
This commit is contained in:
Ben Kunkle 2025-04-17 12:38:12 -04:00 committed by GitHub
parent 133932ed74
commit e7afbbd725
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 38 additions and 6 deletions

View file

@ -2,7 +2,7 @@ use crate::{
ConfirmCodeAction, Copy, CopyAndTrim, CopyPermalinkToLine, Cut, DebuggerEvaluateSelectedText,
DisplayPoint, DisplaySnapshot, Editor, FindAllReferences, GoToDeclaration, GoToDefinition,
GoToImplementation, GoToTypeDefinition, Paste, Rename, RevealInFileManager, SelectMode,
ToDisplayPoint, ToggleCodeActions,
SelectionExt, ToDisplayPoint, ToggleCodeActions,
actions::{Format, FormatSelections},
code_context_menus::CodeActionContents,
selections_collection::SelectionsCollection,
@ -41,7 +41,8 @@ pub struct MouseContextMenu {
pub(crate) position: MenuPosition,
pub(crate) context_menu: Entity<ui::ContextMenu>,
pub(crate) code_action: Option<MouseCodeAction>,
_subscription: Subscription,
_dismiss_subscription: Subscription,
_cursor_move_subscription: Subscription,
}
enum CodeActionLoadState {
@ -80,6 +81,7 @@ impl MouseContextMenu {
offset: position - (source_position + content_origin),
};
return Some(MouseContextMenu::new(
editor,
menu_position,
context_menu,
code_action,
@ -89,6 +91,7 @@ impl MouseContextMenu {
}
pub(crate) fn new(
editor: &Editor,
position: MenuPosition,
context_menu: Entity<ui::ContextMenu>,
code_action: Option<MouseCodeAction>,
@ -98,14 +101,40 @@ impl MouseContextMenu {
let context_menu_focus = context_menu.focus_handle(cx);
window.focus(&context_menu_focus);
let _subscription = cx.subscribe_in(
&context_menu,
window,
let _dismiss_subscription = cx.subscribe_in(&context_menu, window, {
let context_menu_focus = context_menu_focus.clone();
move |editor, _, _event: &DismissEvent, window, cx| {
editor.mouse_context_menu.take();
if context_menu_focus.contains_focused(window, cx) {
window.focus(&editor.focus_handle(cx));
}
}
});
let selection_init = editor.selections.newest_anchor().clone();
let _cursor_move_subscription = cx.subscribe_in(
&cx.entity(),
window,
move |editor, _, event: &crate::EditorEvent, window, cx| {
let crate::EditorEvent::SelectionsChanged { local: true } = event else {
return;
};
let display_snapshot = &editor
.display_map
.update(cx, |display_map, cx| display_map.snapshot(cx));
let selection_init_range = selection_init.display_range(&display_snapshot);
let selection_now_range = editor
.selections
.newest_anchor()
.display_range(&display_snapshot);
if selection_now_range == selection_init_range {
return;
}
editor.mouse_context_menu.take();
if context_menu_focus.contains_focused(window, cx) {
window.focus(&editor.focus_handle(cx));
}
},
);
@ -113,7 +142,8 @@ impl MouseContextMenu {
position,
context_menu,
code_action,
_subscription,
_dismiss_subscription,
_cursor_move_subscription,
}
}
}
@ -423,6 +453,7 @@ fn set_context_menu(
offset: gpui::point(character_size.width, character_size.height),
};
Some(MouseContextMenu::new(
editor,
menu_position,
context_menu,
code_action,