From 52db5223c7475260b22366784915f2ba5b55eeb9 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 367763e9dc38cb20b388684e3773f9959ab921a7..09a3fa7ec1cd6f86aad713f86007adc4d91c6bad 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -1718,6 +1718,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,