@@ -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<DismissEvent> 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<DisplayPoint> {
let point = DisplayPoint::new(DisplayRow(row as u32), column as u32);
point..point
@@ -928,9 +928,17 @@ impl Item for Editor {
&mut self,
workspace: &mut Workspace,
_window: &mut Window,
- _: &mut Context<Self>,
+ cx: &mut Context<Self>,
) {
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)) {
@@ -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<ModalOpenedEvent> 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<V>(&mut self, new_modal: Entity<V>, window: &mut Window, cx: &mut Context<Self>)
@@ -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);