From e7afbbd725053007a4d90a053916616bbb79b618 Mon Sep 17 00:00:00 2001 From: Ben Kunkle Date: Thu, 17 Apr 2025 12:38:12 -0400 Subject: [PATCH] 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 --- crates/editor/src/editor.rs | 1 + crates/editor/src/mouse_context_menu.rs | 43 +++++++++++++++++++++---- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 26e6c645fca3a9b1290c3471b2d83f9721f56ed0..4e8b6e1e45dbae3bb9e97a2a929dd16f65f626f1 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -1787,6 +1787,7 @@ impl Editor { cx: &mut Context, ) { self.mouse_context_menu = Some(MouseContextMenu::new( + self, crate::mouse_context_menu::MenuPosition::PinnedToScreen(position), context_menu, None, diff --git a/crates/editor/src/mouse_context_menu.rs b/crates/editor/src/mouse_context_menu.rs index 404d282c916d2c88e48116e81173855850a3d07b..e7453f59bd0f382fec395ef214848cb94d37a138 100644 --- a/crates/editor/src/mouse_context_menu.rs +++ b/crates/editor/src/mouse_context_menu.rs @@ -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, pub(crate) code_action: Option, - _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, code_action: Option, @@ -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,