diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index 2696cb406e..c733d51356 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -12,8 +12,8 @@ use crate::{ use buffer_diff::{BufferDiff, DiffHunkSecondaryStatus, DiffHunkStatus, DiffHunkStatusKind}; use futures::StreamExt; use gpui::{ - BackgroundExecutor, SemanticVersion, TestAppContext, UpdateGlobal, VisualTestContext, - WindowBounds, WindowOptions, div, + BackgroundExecutor, DismissEvent, SemanticVersion, TestAppContext, UpdateGlobal, + VisualTestContext, WindowBounds, WindowOptions, div, }; use indoc::indoc; use language::{ @@ -19549,6 +19549,64 @@ println!("5"); }); } +#[gpui::test] +async fn test_hide_mouse_context_menu_on_modal_opened(cx: &mut TestAppContext) { + struct EmptyModalView { + focus_handle: gpui::FocusHandle, + } + impl EventEmitter for EmptyModalView {} + impl Render for EmptyModalView { + fn render(&mut self, _: &mut Window, _: &mut Context<'_, Self>) -> impl IntoElement { + div() + } + } + impl Focusable for EmptyModalView { + fn focus_handle(&self, _cx: &App) -> gpui::FocusHandle { + self.focus_handle.clone() + } + } + impl workspace::ModalView for EmptyModalView {} + fn new_empty_modal_view(cx: &App) -> EmptyModalView { + EmptyModalView { + focus_handle: cx.focus_handle(), + } + } + + init_test(cx, |_| {}); + + let fs = FakeFs::new(cx.executor()); + let project = Project::test(fs, [], cx).await; + let workspace = cx.add_window(|window, cx| Workspace::test_new(project.clone(), window, cx)); + let buffer = cx.update(|cx| MultiBuffer::build_simple("hello world!", cx)); + let cx = &mut VisualTestContext::from_window(*workspace.deref(), cx); + let editor = cx.new_window_entity(|window, cx| { + Editor::new( + EditorMode::full(), + buffer, + Some(project.clone()), + window, + cx, + ) + }); + workspace + .update(cx, |workspace, window, cx| { + workspace.add_item_to_active_pane(Box::new(editor.clone()), None, true, window, cx); + }) + .unwrap(); + editor.update_in(cx, |editor, window, cx| { + editor.open_context_menu(&OpenContextMenu, window, cx); + assert!(editor.mouse_context_menu.is_some()); + }); + workspace + .update(cx, |workspace, window, cx| { + workspace.toggle_modal(window, cx, |_, cx| new_empty_modal_view(cx)); + }) + .unwrap(); + cx.read(|cx| { + assert!(editor.read(cx).mouse_context_menu.is_none()); + }); +} + fn empty_range(row: usize, column: usize) -> Range { let point = DisplayPoint::new(DisplayRow(row as u32), column as u32); point..point diff --git a/crates/editor/src/items.rs b/crates/editor/src/items.rs index 3d493db8ce..b41b35bb5e 100644 --- a/crates/editor/src/items.rs +++ b/crates/editor/src/items.rs @@ -928,9 +928,17 @@ impl Item for Editor { &mut self, workspace: &mut Workspace, _window: &mut Window, - _: &mut Context, + cx: &mut Context, ) { self.workspace = Some((workspace.weak_handle(), workspace.database_id())); + if let Some(workspace) = &workspace.weak_handle().upgrade() { + cx.subscribe(&workspace, |editor, _, event: &workspace::Event, _cx| { + if matches!(event, workspace::Event::ModalOpened) { + editor.mouse_context_menu.take(); + } + }) + .detach(); + } } fn to_item_events(event: &EditorEvent, mut f: impl FnMut(ItemEvent)) { diff --git a/crates/workspace/src/modal_layer.rs b/crates/workspace/src/modal_layer.rs index 660945676c..7e92c7b8e9 100644 --- a/crates/workspace/src/modal_layer.rs +++ b/crates/workspace/src/modal_layer.rs @@ -1,6 +1,6 @@ use gpui::{ - AnyView, DismissEvent, Entity, FocusHandle, Focusable as _, ManagedView, MouseButton, - Subscription, + AnyView, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable as _, ManagedView, + MouseButton, Subscription, }; use ui::prelude::*; @@ -56,6 +56,10 @@ pub struct ModalLayer { dismiss_on_focus_lost: bool, } +pub(crate) struct ModalOpenedEvent; + +impl EventEmitter for ModalLayer {} + impl Default for ModalLayer { fn default() -> Self { Self::new() @@ -84,6 +88,7 @@ impl ModalLayer { } let new_modal = cx.new(|cx| build_view(window, cx)); self.show_modal(new_modal, window, cx); + cx.emit(ModalOpenedEvent); } fn show_modal(&mut self, new_modal: Entity, window: &mut Window, cx: &mut Context) diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index f65104b78f..9ef35a69a4 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -781,6 +781,7 @@ pub enum Event { language: &'static str, }, ZoomChanged, + ModalOpened, } #[derive(Debug)] @@ -1051,6 +1052,13 @@ impl Workspace { cx.emit(Event::WorkspaceCreated(weak_handle.clone())); let modal_layer = cx.new(|_| ModalLayer::new()); let toast_layer = cx.new(|_| ToastLayer::new()); + cx.subscribe( + &modal_layer, + |_, _, _: &modal_layer::ModalOpenedEvent, cx| { + cx.emit(Event::ModalOpened); + }, + ) + .detach(); let bottom_dock_layout = WorkspaceSettings::get_global(cx).bottom_dock_layout; let left_dock = Dock::new(DockPosition::Left, modal_layer.clone(), window, cx);