From adc50469ff0c938415c4995ce8ed7fb761021a68 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Sun, 6 Aug 2023 12:45:31 -0600 Subject: [PATCH] WIP --- Cargo.lock | 39 ++- Cargo.toml | 1 + crates/collab/src/tests/integration_tests.rs | 4 +- .../src/incoming_call_notification.rs | 2 +- .../src/project_shared_notification.rs | 2 +- crates/command_palette/src/command_palette.rs | 2 +- crates/diagnostics/src/diagnostics.rs | 4 +- crates/editor/src/editor_tests.rs | 2 +- .../src/test/editor_lsp_test_context.rs | 2 +- crates/editor/src/test/editor_test_context.rs | 2 +- crates/file_finder/src/file_finder.rs | 22 +- crates/gpui/Cargo.toml | 1 + crates/gpui/src/app.rs | 264 +++++++++--------- crates/gpui/src/app/test_app_context.rs | 33 ++- crates/gpui/src/app/window.rs | 21 +- crates/project_panel/src/project_panel.rs | 8 +- crates/project_symbols/src/project_symbols.rs | 2 +- crates/search/src/buffer_search.rs | 10 +- crates/search/src/project_search.rs | 4 +- crates/workspace/src/workspace.rs | 161 +++++------ crates/zed/src/zed.rs | 20 +- 21 files changed, 329 insertions(+), 277 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fbf4e750c6..6cd36252d1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1649,6 +1649,12 @@ dependencies = [ "theme", ] +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + [[package]] name = "copilot" version = "0.1.0" @@ -2133,6 +2139,19 @@ dependencies = [ "serde", ] +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version 0.4.0", + "syn 1.0.109", +] + [[package]] name = "dhat" version = "0.3.2" @@ -3096,6 +3115,7 @@ dependencies = [ "core-graphics", "core-text", "ctor", + "derive_more", "dhat", "env_logger 0.9.3", "etagere", @@ -5106,7 +5126,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39fe46acc5503595e5949c17b818714d26fdf9b4920eacf3b2947f0199f4a6ff" dependencies = [ - "rustc_version", + "rustc_version 0.3.3", ] [[package]] @@ -6276,7 +6296,16 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" dependencies = [ - "semver", + "semver 0.11.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver 1.0.18", ] [[package]] @@ -6716,6 +6745,12 @@ dependencies = [ "semver-parser", ] +[[package]] +name = "semver" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" + [[package]] name = "semver-parser" version = "0.10.2" diff --git a/Cargo.toml b/Cargo.toml index 6e79c6b657..1938e832e9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -79,6 +79,7 @@ resolver = "2" anyhow = { version = "1.0.57" } async-trait = { version = "0.1" } ctor = { version = "0.1" } +derive_more = { version = "0.99.17" } env_logger = { version = "0.9" } futures = { version = "0.3" } globset = { version = "0.4" } diff --git a/crates/collab/src/tests/integration_tests.rs b/crates/collab/src/tests/integration_tests.rs index 037f97f71a..1a8e6d938d 100644 --- a/crates/collab/src/tests/integration_tests.rs +++ b/crates/collab/src/tests/integration_tests.rs @@ -3446,7 +3446,7 @@ async fn test_newline_above_or_below_does_not_move_guest_cursor( let editor_a = window_a.add_view(cx_a, |cx| Editor::for_buffer(buffer_a, Some(project_a), cx)); let mut editor_cx_a = EditorTestContext { cx: cx_a, - window_id: window_a.window_id(), + window_id: window_a.id(), editor: editor_a, }; @@ -3459,7 +3459,7 @@ async fn test_newline_above_or_below_does_not_move_guest_cursor( let editor_b = window_b.add_view(cx_b, |cx| Editor::for_buffer(buffer_b, Some(project_b), cx)); let mut editor_cx_b = EditorTestContext { cx: cx_b, - window_id: window_b.window_id(), + window_id: window_b.id(), editor: editor_b, }; diff --git a/crates/collab_ui/src/incoming_call_notification.rs b/crates/collab_ui/src/incoming_call_notification.rs index 770f5d5795..a9c5e697a5 100644 --- a/crates/collab_ui/src/incoming_call_notification.rs +++ b/crates/collab_ui/src/incoming_call_notification.rs @@ -49,7 +49,7 @@ pub fn init(app_state: &Arc, cx: &mut AppContext) { |_| IncomingCallNotification::new(incoming_call.clone(), app_state.clone()), ); - notification_windows.push(window.window_id()); + notification_windows.push(window.id()); } } } diff --git a/crates/collab_ui/src/project_shared_notification.rs b/crates/collab_ui/src/project_shared_notification.rs index 5be7e33bf3..03ab91623b 100644 --- a/crates/collab_ui/src/project_shared_notification.rs +++ b/crates/collab_ui/src/project_shared_notification.rs @@ -52,7 +52,7 @@ pub fn init(app_state: &Arc, cx: &mut AppContext) { notification_windows .entry(*project_id) .or_insert(Vec::new()) - .push(window.window_id()); + .push(window.id()); } } room::Event::RemoteProjectUnshared { project_id } => { diff --git a/crates/command_palette/src/command_palette.rs b/crates/command_palette/src/command_palette.rs index 935358c2a1..7d4b4126b7 100644 --- a/crates/command_palette/src/command_palette.rs +++ b/crates/command_palette/src/command_palette.rs @@ -297,7 +297,7 @@ mod tests { let project = Project::test(app_state.fs.clone(), [], cx).await; let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); let workspace = window.root(cx); - let window_id = window.window_id(); + let window_id = window.id(); let editor = cx.add_view(window_id, |cx| { let mut editor = Editor::single_line(None, cx); editor.set_text("abc", cx); diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index f2db0a7763..2444465be6 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -857,7 +857,7 @@ mod tests { let project = Project::test(fs.clone(), ["/test".as_ref()], cx).await; let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); let workspace = window.root(cx); - let window_id = window.window_id(); + let window_id = window.id(); // Create some diagnostics project.update(cx, |project, cx| { @@ -1252,7 +1252,7 @@ mod tests { let project = Project::test(fs.clone(), ["/test".as_ref()], cx).await; let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); let workspace = window.root(cx); - let window_id = window.window_id(); + let window_id = window.id(); let view = cx.add_view(window_id, |cx| { ProjectDiagnosticsEditor::new(project.clone(), workspace.downgrade(), cx) diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index e8913505ca..a114cd437b 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -525,7 +525,7 @@ async fn test_navigation_history(cx: &mut TestAppContext) { let project = Project::test(fs, [], cx).await; let window = cx.add_window(|cx| Workspace::test_new(project, cx)); let workspace = window.root(cx); - let window_id = window.window_id(); + let window_id = window.id(); let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone()); cx.add_view(window_id, |cx| { let buffer = MultiBuffer::build_simple(&sample_text(300, 5, 'a'), cx); diff --git a/crates/editor/src/test/editor_lsp_test_context.rs b/crates/editor/src/test/editor_lsp_test_context.rs index d25ca7bb88..f53115f224 100644 --- a/crates/editor/src/test/editor_lsp_test_context.rs +++ b/crates/editor/src/test/editor_lsp_test_context.rs @@ -99,7 +99,7 @@ impl<'a> EditorLspTestContext<'a> { Self { cx: EditorTestContext { cx, - window_id: window.window_id(), + window_id: window.id(), editor, }, lsp, diff --git a/crates/editor/src/test/editor_test_context.rs b/crates/editor/src/test/editor_test_context.rs index ac519764fd..c7ea1b4f38 100644 --- a/crates/editor/src/test/editor_test_context.rs +++ b/crates/editor/src/test/editor_test_context.rs @@ -39,7 +39,7 @@ impl<'a> EditorTestContext<'a> { let editor = window.root(cx); Self { cx, - window_id: window.window_id(), + window_id: window.id(), editor, } } diff --git a/crates/file_finder/src/file_finder.rs b/crates/file_finder/src/file_finder.rs index 84a45b083e..12bf324262 100644 --- a/crates/file_finder/src/file_finder.rs +++ b/crates/file_finder/src/file_finder.rs @@ -619,7 +619,7 @@ mod tests { let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await; let window = cx.add_window(|cx| Workspace::test_new(project, cx)); let workspace = window.root(cx); - cx.dispatch_action(window.window_id(), Toggle); + cx.dispatch_action(window.id(), Toggle); let finder = cx.read(|cx| workspace.read(cx).modal::().unwrap()); finder @@ -632,8 +632,8 @@ mod tests { }); let active_pane = cx.read(|cx| workspace.read(cx).active_pane().clone()); - cx.dispatch_action(window.window_id(), SelectNext); - cx.dispatch_action(window.window_id(), Confirm); + cx.dispatch_action(window.id(), SelectNext); + cx.dispatch_action(window.id(), Confirm); active_pane .condition(cx, |pane, _| pane.active_item().is_some()) .await; @@ -674,7 +674,7 @@ mod tests { let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await; let window = cx.add_window(|cx| Workspace::test_new(project, cx)); let workspace = window.root(cx); - cx.dispatch_action(window.window_id(), Toggle); + cx.dispatch_action(window.id(), Toggle); let finder = cx.read(|cx| workspace.read(cx).modal::().unwrap()); let file_query = &first_file_name[..3]; @@ -706,8 +706,8 @@ mod tests { }); let active_pane = cx.read(|cx| workspace.read(cx).active_pane().clone()); - cx.dispatch_action(window.window_id(), SelectNext); - cx.dispatch_action(window.window_id(), Confirm); + cx.dispatch_action(window.id(), SelectNext); + cx.dispatch_action(window.id(), Confirm); active_pane .condition(cx, |pane, _| pane.active_item().is_some()) .await; @@ -758,7 +758,7 @@ mod tests { let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await; let window = cx.add_window(|cx| Workspace::test_new(project, cx)); let workspace = window.root(cx); - cx.dispatch_action(window.window_id(), Toggle); + cx.dispatch_action(window.id(), Toggle); let finder = cx.read(|cx| workspace.read(cx).modal::().unwrap()); let file_query = &first_file_name[..3]; @@ -790,8 +790,8 @@ mod tests { }); let active_pane = cx.read(|cx| workspace.read(cx).active_pane().clone()); - cx.dispatch_action(window.window_id(), SelectNext); - cx.dispatch_action(window.window_id(), Confirm); + cx.dispatch_action(window.id(), SelectNext); + cx.dispatch_action(window.id(), Confirm); active_pane .condition(cx, |pane, _| pane.active_item().is_some()) .await; @@ -1168,7 +1168,7 @@ mod tests { let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await; let window = cx.add_window(|cx| Workspace::test_new(project, cx)); let workspace = window.root(cx); - let window_id = window.window_id(); + let window_id = window.id(); let worktree_id = cx.read(|cx| { let worktrees = workspace.read(cx).worktrees(cx).collect::>(); assert_eq!(worktrees.len(), 1); @@ -1376,7 +1376,7 @@ mod tests { let window = cx.add_window(|cx| Workspace::test_new(project, cx)); let workspace = window.root(cx); - let window_id = window.window_id(); + let window_id = window.id(); let worktree_id = cx.read(|cx| { let worktrees = workspace.read(cx).worktrees(cx).collect::>(); assert_eq!(worktrees.len(), 1,); diff --git a/crates/gpui/Cargo.toml b/crates/gpui/Cargo.toml index 31b7db008d..5bd7d03184 100644 --- a/crates/gpui/Cargo.toml +++ b/crates/gpui/Cargo.toml @@ -22,6 +22,7 @@ sqlez = { path = "../sqlez" } async-task = "4.0.3" backtrace = { version = "0.3", optional = true } ctor.workspace = true +derive_more.workspace = true dhat = { version = "0.3", optional = true } env_logger = { version = "0.9", optional = true } etagere = "0.2" diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index 62d7d1d48a..f967f13403 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -23,6 +23,7 @@ use std::{ }; use anyhow::{anyhow, Context, Result}; +use derive_more::Deref; use parking_lot::Mutex; use postage::oneshot; use smallvec::SmallVec; @@ -132,11 +133,13 @@ pub trait BorrowAppContext { pub trait BorrowWindowContext { type Result; - fn read_window_with(&self, window_id: usize, f: F) -> Self::Result + fn read_window_with(&self, window_handle: H, f: F) -> Self::Result where + H: Into, F: FnOnce(&WindowContext) -> T; - fn update_window(&mut self, window_id: usize, f: F) -> Self::Result + fn update_window(&mut self, window_handle: H, f: F) -> Self::Result where + H: Into, F: FnOnce(&mut WindowContext) -> T; } @@ -300,13 +303,13 @@ impl App { result } - fn update_window T>( - &mut self, - window_id: usize, - callback: F, - ) -> Option { + fn update_window(&mut self, handle: H, callback: F) -> Option + where + H: Into, + F: FnOnce(&mut WindowContext) -> T, + { let mut state = self.0.borrow_mut(); - let result = state.update_window(window_id, callback); + let result = state.update_window(handle, callback); state.pending_notifications.clear(); result } @@ -333,6 +336,10 @@ impl AsyncAppContext { self.0.borrow_mut().update(callback) } + pub fn windows(&self) -> Vec { + self.0.borrow().windows().collect() + } + pub fn read_window T>( &self, window_id: usize, @@ -343,10 +350,10 @@ impl AsyncAppContext { pub fn update_window T>( &mut self, - window_id: usize, + handle: AnyWindowHandle, callback: F, ) -> Option { - self.0.borrow_mut().update_window(window_id, callback) + self.0.borrow_mut().update_window(handle, callback) } pub fn debug_elements(&self, window_id: usize) -> Option { @@ -359,14 +366,14 @@ impl AsyncAppContext { pub fn dispatch_action( &mut self, - window_id: usize, + window: impl Into, view_id: usize, action: &dyn Action, ) -> Result<()> { self.0 .borrow_mut() - .update_window(window_id, |window| { - window.dispatch_action(Some(view_id), action); + .update_window(window, |cx| { + cx.dispatch_action(Some(view_id), action); }) .ok_or_else(|| anyhow!("window not found")) } @@ -380,22 +387,6 @@ impl AsyncAppContext { .unwrap_or_default() } - pub fn has_window(&self, window_id: usize) -> bool { - self.read(|cx| cx.windows.contains_key(&window_id)) - } - - pub fn window_is_active(&self, window_id: usize) -> bool { - self.read(|cx| cx.windows.get(&window_id).map_or(false, |w| w.is_active)) - } - - pub fn root_view(&self, window_id: usize) -> Option { - self.read(|cx| cx.windows.get(&window_id).map(|w| w.root_view().clone())) - } - - pub fn window_ids(&self) -> Vec { - self.read(|cx| cx.windows.keys().copied().collect()) - } - pub fn add_model(&mut self, build_model: F) -> ModelHandle where T: Entity, @@ -501,7 +492,7 @@ pub struct AppContext { models: HashMap>, views: HashMap<(usize, usize), Box>, views_metadata: HashMap<(usize, usize), ViewMetadata>, - windows: HashMap, + windows: HashMap, globals: HashMap>, element_states: HashMap>, background: Arc, @@ -818,22 +809,6 @@ impl AppContext { Some(callback(&window_context)) } - pub fn update_window T>( - &mut self, - window_id: usize, - callback: F, - ) -> Option { - self.update(|app_context| { - let mut window = app_context.windows.remove(&window_id)?; - let mut window_context = WindowContext::mutable(app_context, &mut window, window_id); - let result = callback(&mut window_context); - if !window_context.removed { - app_context.windows.insert(window_id, window); - } - Some(result) - }) - } - pub fn update_active_window T>( &mut self, callback: F, @@ -1331,43 +1306,40 @@ impl AppContext { F: FnOnce(&mut ViewContext) -> V, { self.update(|this| { - let window_id = post_inc(&mut this.next_id); + let window = WindowHandle::::new(post_inc(&mut this.next_id)); let platform_window = this.platform - .open_window(window_id, window_options, this.foreground.clone()); - let window = this.build_window(window_id, platform_window, build_root_view); - this.windows.insert(window_id, window); - WindowHandle::new(window_id) + .open_window(window, window_options, this.foreground.clone()); + let window = this.build_window(window, platform_window, build_root_view); + this.windows.insert(window.into(), window); + window }) } - pub fn add_status_bar_item(&mut self, build_root_view: F) -> (usize, ViewHandle) + pub fn add_status_bar_item(&mut self, build_root_view: F) -> WindowHandle where V: View, F: FnOnce(&mut ViewContext) -> V, { self.update(|this| { - let window_id = post_inc(&mut this.next_id); - let platform_window = this.platform.add_status_item(window_id); - let window = this.build_window(window_id, platform_window, build_root_view); - let root_view = window.root_view().clone().downcast::().unwrap(); + let handle = WindowHandle::::new(post_inc(&mut this.next_id)); + let platform_window = this.platform.add_status_item(handle.id()); + let window = this.build_window(handle, platform_window, build_root_view); - this.windows.insert(window_id, window); - this.update_window(window_id, |cx| { - root_view.update(cx, |view, cx| view.focus_in(cx.handle().into_any(), cx)) - }); - - (window_id, root_view) + this.windows.insert(handle.into(), window); + handle.update_root(this, |view, cx| view.focus_in(cx.handle().into_any(), cx)); + handle }) } - pub fn build_window( + pub fn build_window( &mut self, - window_id: usize, + handle: H, mut platform_window: Box, build_root_view: F, ) -> Window where + H: Into, V: View, F: FnOnce(&mut ViewContext) -> V, { @@ -1375,7 +1347,7 @@ impl AppContext { let mut app = self.upgrade(); platform_window.on_event(Box::new(move |event| { - app.update_window(window_id, |cx| { + app.update_window(handle, |cx| { if let Event::KeyDown(KeyDownEvent { keystroke, .. }) = &event { if cx.dispatch_keystroke(keystroke) { return true; @@ -1391,35 +1363,35 @@ impl AppContext { { let mut app = self.upgrade(); platform_window.on_active_status_change(Box::new(move |is_active| { - app.update(|cx| cx.window_changed_active_status(window_id, is_active)) + app.update(|cx| cx.window_changed_active_status(handle, is_active)) })); } { let mut app = self.upgrade(); platform_window.on_resize(Box::new(move || { - app.update(|cx| cx.window_was_resized(window_id)) + app.update(|cx| cx.window_was_resized(handle)) })); } { let mut app = self.upgrade(); platform_window.on_moved(Box::new(move || { - app.update(|cx| cx.window_was_moved(window_id)) + app.update(|cx| cx.window_was_moved(handle)) })); } { let mut app = self.upgrade(); platform_window.on_fullscreen(Box::new(move |is_fullscreen| { - app.update(|cx| cx.window_was_fullscreen_changed(window_id, is_fullscreen)) + app.update(|cx| cx.window_was_fullscreen_changed(handle, is_fullscreen)) })); } { let mut app = self.upgrade(); platform_window.on_close(Box::new(move || { - app.update(|cx| cx.update_window(window_id, |cx| cx.remove_window())); + app.update(|cx| cx.update_window(handle, |cx| cx.remove_window())); })); } @@ -1431,27 +1403,20 @@ impl AppContext { platform_window.set_input_handler(Box::new(WindowInputHandler { app: self.upgrade().0, - window_id, + window_id: handle, })); - let mut window = Window::new(window_id, platform_window, self, build_root_view); - let mut cx = WindowContext::mutable(self, &mut window, window_id); + let mut window = Window::new(handle, platform_window, self, build_root_view); + let mut cx = WindowContext::mutable(self, &mut window, handle); cx.layout(false).expect("initial layout should not error"); let scene = cx.paint().expect("initial paint should not error"); window.platform_window.present_scene(scene); window } - pub(crate) fn replace_root_view( - &mut self, - window_id: usize, - build_root_view: F, - ) -> Option> - where - V: View, - F: FnOnce(&mut ViewContext) -> V, - { - self.update_window(window_id, |cx| cx.replace_root_view(build_root_view)) + pub fn windows(&self) -> impl Iterator { + todo!(); + None.into_iter() } pub fn read_view(&self, handle: &ViewHandle) -> &T { @@ -2192,11 +2157,20 @@ impl BorrowWindowContext for AppContext { AppContext::read_window(self, window_id, f) } - fn update_window(&mut self, window_id: usize, f: F) -> Self::Result + fn update_window(&mut self, window: usize, f: F) -> Self::Result where F: FnOnce(&mut WindowContext) -> T, { - AppContext::update_window(self, window_id, f) + self.update(|app_context| { + let mut window = app_context.windows.remove(&window_handle)?; + let mut window_context = + WindowContext::mutable(app_context, &mut window, window_handle); + let result = callback(&mut window_context); + if !window_context.removed { + app_context.windows.insert(window_handle, window); + } + Some(result) + }) } } @@ -3862,44 +3836,28 @@ impl Clone for WeakModelHandle { impl Copy for WeakModelHandle {} +#[derive(Deref, Copy, Clone)] pub struct WindowHandle { - window_id: usize, + #[deref] + any_handle: AnyWindowHandle, root_view_type: PhantomData, } -#[allow(dead_code)] impl WindowHandle { fn new(window_id: usize) -> Self { WindowHandle { - window_id, + any_handle: AnyWindowHandle { + window_id, + root_view_type: TypeId::of::(), + }, root_view_type: PhantomData, } } - pub fn window_id(&self) -> usize { - self.window_id - } - pub fn root(&self, cx: &C) -> C::Result> { self.read_with(cx, |cx| cx.root_view().clone().downcast().unwrap()) } - pub fn read_with(&self, cx: &C, read: F) -> C::Result - where - C: BorrowWindowContext, - F: FnOnce(&WindowContext) -> R, - { - cx.read_window_with(self.window_id(), |cx| read(cx)) - } - - pub fn update(&self, cx: &mut C, update: F) -> C::Result - where - C: BorrowWindowContext, - F: FnOnce(&mut WindowContext) -> R, - { - cx.update_window(self.window_id(), update) - } - pub fn read_root_with(&self, cx: &C, read: F) -> C::Result where C: BorrowWindowContext, @@ -3918,7 +3876,7 @@ impl WindowHandle { C: BorrowWindowContext, F: FnOnce(&mut V, &mut ViewContext) -> R, { - cx.update_window(self.window_id, |cx| { + cx.update_window(*self, |cx| { cx.root_view() .clone() .downcast::() @@ -3927,6 +3885,53 @@ impl WindowHandle { }) } + pub fn replace_root(&self, cx: &mut C, build_root: F) -> C::Result> + where + C: BorrowWindowContext, + F: FnOnce(&mut ViewContext) -> V, + { + cx.update_window(self.into_any(), |cx| { + let root_view = self.add_view(cx, |cx| build_root(cx)); + cx.window.root_view = Some(root_view.clone().into_any()); + cx.window.focused_view_id = Some(root_view.id()); + root_view + }) + } +} + +impl Into for WindowHandle { + fn into(self) -> AnyWindowHandle { + self.any_handle + } +} + +#[derive(Copy, Clone, Eq, PartialEq, Hash)] +pub struct AnyWindowHandle { + window_id: usize, + root_view_type: TypeId, +} + +impl AnyWindowHandle { + pub fn id(&self) -> usize { + self.window_id + } + + pub fn read_with(&self, cx: &C, read: F) -> C::Result + where + C: BorrowWindowContext, + F: FnOnce(&WindowContext) -> R, + { + cx.read_window_with(self.window_id, |cx| read(cx)) + } + + pub fn update(&self, cx: &mut C, update: F) -> C::Result + where + C: BorrowWindowContext, + F: FnOnce(&mut WindowContext) -> R, + { + cx.update_window(self.window_id, update) + } + pub fn add_view(&self, cx: &mut C, build_view: F) -> C::Result> where C: BorrowWindowContext, @@ -3936,21 +3941,16 @@ impl WindowHandle { self.update(cx, |cx| cx.add_view(build_view)) } - pub(crate) fn replace_root_view( - &self, - cx: &mut C, - build_root_view: F, - ) -> C::Result> - where - C: BorrowWindowContext, - F: FnOnce(&mut ViewContext) -> V, - { - cx.update_window(self.window_id, |cx| { - let root_view = self.add_view(cx, |cx| build_root_view(cx)); - cx.window.root_view = Some(root_view.clone().into_any()); - cx.window.focused_view_id = Some(root_view.id()); - root_view - }) + pub fn root_is(&self) -> bool { + self.root_view_type == TypeId::of::() + } + + pub fn is_active(&self, cx: &C) -> C::Result { + self.read_with(cx, |cx| cx.window.is_active) + } + + pub fn remove(&self, cx: &mut C) -> C::Result<()> { + self.update(cx, |cx| cx.remove_window()) } } @@ -5390,7 +5390,7 @@ mod tests { TestView { events: Vec::new() } }); - assert_eq!(window.read_root_with(cx, |view, _| assert_eq!(view.events, ["before notify"]))); + window.read_root_with(cx, |view, _| assert_eq!(view.events, ["before notify"])); } #[crate::test(self)] @@ -6227,7 +6227,7 @@ mod tests { // Check that global actions do not have a binding, even if a binding does exist in another view assert_eq!( - &available_actions(window.window_id(), view_1.id(), cx), + &available_actions(window.id(), view_1.id(), cx), &[ ("test::Action1", vec![Keystroke::parse("a").unwrap()]), ("test::GlobalAction", vec![]) @@ -6236,7 +6236,7 @@ mod tests { // Check that view 1 actions and bindings are available even when called from view 2 assert_eq!( - &available_actions(window.window_id(), view_2.id(), cx), + &available_actions(window.id(), view_2.id(), cx), &[ ("test::Action1", vec![Keystroke::parse("a").unwrap()]), ("test::Action2", vec![Keystroke::parse("b").unwrap()]), @@ -6299,7 +6299,7 @@ mod tests { ]); }); - let actions = cx.available_actions(window.window_id(), view.id()); + let actions = cx.available_actions(window.id(), view.id()); assert_eq!( actions[0].1.as_any().downcast_ref::(), Some(&ActionWithArg { arg: false }) @@ -6585,25 +6585,25 @@ mod tests { [("window 2", false), ("window 3", true)] ); - cx.simulate_window_activation(Some(window_2.window_id())); + cx.simulate_window_activation(Some(window_2.id())); assert_eq!( mem::take(&mut *events.borrow_mut()), [("window 3", false), ("window 2", true)] ); - cx.simulate_window_activation(Some(window_1.window_id())); + cx.simulate_window_activation(Some(window_1.id())); assert_eq!( mem::take(&mut *events.borrow_mut()), [("window 2", false), ("window 1", true)] ); - cx.simulate_window_activation(Some(window_3.window_id())); + cx.simulate_window_activation(Some(window_3.id())); assert_eq!( mem::take(&mut *events.borrow_mut()), [("window 1", false), ("window 3", true)] ); - cx.simulate_window_activation(Some(window_3.window_id())); + cx.simulate_window_activation(Some(window_3.id())); assert_eq!(mem::take(&mut *events.borrow_mut()), []); } diff --git a/crates/gpui/src/app/test_app_context.rs b/crates/gpui/src/app/test_app_context.rs index 3b574eb03e..5b005d7d6f 100644 --- a/crates/gpui/src/app/test_app_context.rs +++ b/crates/gpui/src/app/test_app_context.rs @@ -4,9 +4,9 @@ use crate::{ keymap_matcher::{Binding, Keystroke}, platform, platform::{Event, InputHandler, KeyDownEvent, Platform}, - Action, AppContext, BorrowAppContext, BorrowWindowContext, Entity, FontCache, Handle, - ModelContext, ModelHandle, Subscription, Task, View, ViewContext, ViewHandle, WeakHandle, - WindowContext, WindowHandle, + Action, AnyWindowHandle, AppContext, BorrowAppContext, BorrowWindowContext, Entity, FontCache, + Handle, ModelContext, ModelHandle, Subscription, Task, View, ViewContext, ViewHandle, + WeakHandle, WindowContext, WindowHandle, }; use collections::BTreeMap; use futures::Future; @@ -124,6 +124,13 @@ impl TestAppContext { } } + pub fn window(&self, window_id: usize) -> Option> { + self.cx + .borrow() + .read_window(window_id, |cx| cx.window()) + .flatten() + } + pub fn read_window T>( &self, window_id: usize, @@ -157,9 +164,9 @@ impl TestAppContext { .cx .borrow_mut() .add_window(Default::default(), build_root_view); - self.simulate_window_activation(Some(window.window_id())); + self.simulate_window_activation(Some(window.id())); - WindowHandle::new(window.window_id()) + WindowHandle::new(window.id()) } pub fn add_view(&mut self, window_id: usize, build_view: F) -> ViewHandle @@ -191,10 +198,14 @@ impl TestAppContext { self.cx.borrow_mut().subscribe_global(callback) } - pub fn window_ids(&self) -> Vec { - self.cx.borrow().windows.keys().copied().collect() + pub fn windows(&self) -> impl Iterator { + self.cx.borrow().windows() } + // pub fn window_ids(&self) -> Vec { + // self.cx.borrow().windows.keys().copied().collect() + // } + pub fn remove_all_windows(&mut self) { self.update(|cx| cx.windows.clear()); } @@ -311,15 +322,15 @@ impl TestAppContext { pub fn simulate_window_activation(&self, to_activate: Option) { self.cx.borrow_mut().update(|cx| { - let other_window_ids = cx + let other_windows = cx .windows .keys() - .filter(|window_id| Some(**window_id) != to_activate) + .filter(|window| Some(window.id()) != to_activate) .copied() .collect::>(); - for window_id in other_window_ids { - cx.window_changed_active_status(window_id, false) + for window in other_windows { + cx.window_changed_active_status(window.id(), false) } if let Some(to_activate) = to_activate { diff --git a/crates/gpui/src/app/window.rs b/crates/gpui/src/app/window.rs index 20992bfbaa..cc8468edbd 100644 --- a/crates/gpui/src/app/window.rs +++ b/crates/gpui/src/app/window.rs @@ -196,6 +196,16 @@ impl<'a> WindowContext<'a> { self.window_id } + pub fn window(&self) -> Option> { + self.window.root_view.as_ref().and_then(|root_view| { + if root_view.is::() { + Some(WindowHandle::new(self.window_id)) + } else { + None + } + }) + } + pub fn app_context(&mut self) -> &mut AppContext { &mut self.app_context } @@ -1157,17 +1167,6 @@ impl<'a> WindowContext<'a> { self.window.platform_window.prompt(level, msg, answers) } - pub(crate) fn replace_root_view(&mut self, build_root_view: F) -> WindowHandle - where - V: View, - F: FnOnce(&mut ViewContext) -> V, - { - let root_view = self.add_view(|cx| build_root_view(cx)); - self.window.focused_view_id = Some(root_view.id()); - self.window.root_view = Some(root_view.into_any()); - WindowHandle::new(self.window_id) - } - pub fn add_view(&mut self, build_view: F) -> ViewHandle where T: View, diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index 80847f9f4b..021ea2d3bc 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -1872,7 +1872,7 @@ mod tests { let project = Project::test(fs.clone(), ["/root1".as_ref(), "/root2".as_ref()], cx).await; let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); let workspace = window.root(cx); - let window_id = window.window_id(); + let window_id = window.id(); let panel = workspace.update(cx, |workspace, cx| ProjectPanel::new(workspace, cx)); select_path(&panel, "root1", cx); @@ -2225,7 +2225,7 @@ mod tests { let project = Project::test(fs.clone(), ["/root1".as_ref(), "/root2".as_ref()], cx).await; let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); let workspace = window.root(cx); - let window_id = window.window_id(); + let window_id = window.id(); let panel = workspace.update(cx, |workspace, cx| ProjectPanel::new(workspace, cx)); select_path(&panel, "root1", cx); @@ -2402,7 +2402,7 @@ mod tests { let project = Project::test(fs.clone(), ["/src".as_ref()], cx).await; let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); let workspace = window.root(cx); - let window_id = window.window_id(); + let window_id = window.id(); let panel = workspace.update(cx, |workspace, cx| ProjectPanel::new(workspace, cx)); toggle_expand_dir(&panel, "src/test", cx); @@ -2493,7 +2493,7 @@ mod tests { let project = Project::test(fs.clone(), ["/src".as_ref()], cx).await; let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); let workspace = window.root(cx); - let window_id = window.window_id(); + let window_id = window.id(); let panel = workspace.update(cx, |workspace, cx| ProjectPanel::new(workspace, cx)); select_path(&panel, "src/", cx); diff --git a/crates/project_symbols/src/project_symbols.rs b/crates/project_symbols/src/project_symbols.rs index 4bd186fc98..8471f3a3a7 100644 --- a/crates/project_symbols/src/project_symbols.rs +++ b/crates/project_symbols/src/project_symbols.rs @@ -328,7 +328,7 @@ mod tests { let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); let workspace = window.root(cx); - let window_id = window.window_id(); + let window_id = window.id(); // Create the project symbols view. let symbols = cx.add_view(window_id, |cx| { diff --git a/crates/search/src/buffer_search.rs b/crates/search/src/buffer_search.rs index 265e4f0206..1e635432bd 100644 --- a/crates/search/src/buffer_search.rs +++ b/crates/search/src/buffer_search.rs @@ -851,11 +851,11 @@ mod tests { }); let window = cx.add_window(|_| EmptyView); - let editor = cx.add_view(window.window_id(), |cx| { + let editor = cx.add_view(window.id(), |cx| { Editor::for_buffer(buffer.clone(), None, cx) }); - let search_bar = cx.add_view(window.window_id(), |cx| { + let search_bar = cx.add_view(window.id(), |cx| { let mut search_bar = BufferSearchBar::new(cx); search_bar.set_active_pane_item(Some(&editor), cx); search_bar.show(cx); @@ -1232,7 +1232,7 @@ mod tests { ); let buffer = cx.add_model(|cx| Buffer::new(0, buffer_text, cx)); let window = cx.add_window(|_| EmptyView); - let window_id = window.window_id(); + let window_id = window.id(); let editor = cx.add_view(window_id, |cx| Editor::for_buffer(buffer.clone(), None, cx)); @@ -1421,11 +1421,11 @@ mod tests { let buffer = cx.add_model(|cx| Buffer::new(0, buffer_text, cx)); let window = cx.add_window(|_| EmptyView); - let editor = cx.add_view(window.window_id(), |cx| { + let editor = cx.add_view(window.id(), |cx| { Editor::for_buffer(buffer.clone(), None, cx) }); - let search_bar = cx.add_view(window.window_id(), |cx| { + let search_bar = cx.add_view(window.id(), |cx| { let mut search_bar = BufferSearchBar::new(cx); search_bar.set_active_pane_item(Some(&editor), cx); search_bar.show(cx); diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index febd564050..0db66b4e37 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -1568,7 +1568,7 @@ pub mod tests { let project = Project::test(fs.clone(), ["/dir".as_ref()], cx).await; let window = cx.add_window(|cx| Workspace::test_new(project, cx)); let workspace = window.root(cx); - let window_id = window.window_id(); + let window_id = window.id(); let active_item = cx.read(|cx| { workspace @@ -1874,7 +1874,7 @@ pub mod tests { let project = Project::test(fs.clone(), ["/dir".as_ref()], cx).await; let window = cx.add_window(|cx| Workspace::test_new(project, cx)); let workspace = window.root(cx); - let window_id = window.window_id(); + let window_id = window.id(); workspace.update(cx, |workspace, cx| { ProjectSearchView::deploy(workspace, &workspace::NewSearch, cx) }); diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 09e4c4c219..37fab1ee46 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -37,7 +37,7 @@ use gpui::{ }, AnyModelHandle, AnyViewHandle, AnyWeakViewHandle, AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle, SizeConstraint, Subscription, Task, View, ViewContext, ViewHandle, - WeakViewHandle, WindowContext, + WeakViewHandle, WindowContext, WindowHandle, }; use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ProjectItem}; use itertools::Itertools; @@ -749,7 +749,7 @@ impl Workspace { fn new_local( abs_paths: Vec, app_state: Arc, - requesting_window_id: Option, + requesting_window: Option>, cx: &mut AppContext, ) -> Task<( WeakViewHandle, @@ -793,55 +793,60 @@ impl Workspace { DB.next_id().await.unwrap_or(0) }; - let window = requesting_window_id.and_then(|window_id| { - cx.update(|cx| { - cx.replace_root_view(window_id, |cx| { - Workspace::new(workspace_id, project_handle.clone(), app_state.clone(), cx) - }) - }) - }); - let window = window.unwrap_or_else(|| { - let window_bounds_override = window_bounds_env_override(&cx); - let (bounds, display) = if let Some(bounds) = window_bounds_override { - (Some(bounds), None) - } else { - serialized_workspace - .as_ref() - .and_then(|serialized_workspace| { - let display = serialized_workspace.display?; - let mut bounds = serialized_workspace.bounds?; + let window = if let Some(window) = requesting_window { + window.replace_root(&mut cx, |cx| { + Workspace::new(workspace_id, project_handle.clone(), app_state.clone(), cx) + }); + window + } else { + { + let window_bounds_override = window_bounds_env_override(&cx); + let (bounds, display) = if let Some(bounds) = window_bounds_override { + (Some(bounds), None) + } else { + serialized_workspace + .as_ref() + .and_then(|serialized_workspace| { + let display = serialized_workspace.display?; + let mut bounds = serialized_workspace.bounds?; - // Stored bounds are relative to the containing display. - // So convert back to global coordinates if that screen still exists - if let WindowBounds::Fixed(mut window_bounds) = bounds { - if let Some(screen) = cx.platform().screen_by_id(display) { - let screen_bounds = screen.bounds(); - window_bounds.set_origin_x( - window_bounds.origin_x() + screen_bounds.origin_x(), - ); - window_bounds.set_origin_y( - window_bounds.origin_y() + screen_bounds.origin_y(), - ); - bounds = WindowBounds::Fixed(window_bounds); - } else { - // Screen no longer exists. Return none here. - return None; + // Stored bounds are relative to the containing display. + // So convert back to global coordinates if that screen still exists + if let WindowBounds::Fixed(mut window_bounds) = bounds { + if let Some(screen) = cx.platform().screen_by_id(display) { + let screen_bounds = screen.bounds(); + window_bounds.set_origin_x( + window_bounds.origin_x() + screen_bounds.origin_x(), + ); + window_bounds.set_origin_y( + window_bounds.origin_y() + screen_bounds.origin_y(), + ); + bounds = WindowBounds::Fixed(window_bounds); + } else { + // Screen no longer exists. Return none here. + return None; + } } - } - Some((bounds, display)) - }) - .unzip() - }; + Some((bounds, display)) + }) + .unzip() + }; - // Use the serialized workspace to construct the new window - cx.add_window( - (app_state.build_window_options)(bounds, display, cx.platform().as_ref()), - |cx| { - Workspace::new(workspace_id, project_handle.clone(), app_state.clone(), cx) - }, - ) - }); + // Use the serialized workspace to construct the new window + cx.add_window( + (app_state.build_window_options)(bounds, display, cx.platform().as_ref()), + |cx| { + Workspace::new( + workspace_id, + project_handle.clone(), + app_state.clone(), + cx, + ) + }, + ) + } + }; // We haven't yielded the main thread since obtaining the window handle, // so the window exists. @@ -1227,14 +1232,14 @@ impl Workspace { pub fn close_global(_: &CloseWindow, cx: &mut AppContext) { cx.spawn(|mut cx| async move { - let id = cx - .window_ids() + let window = cx + .windows() .into_iter() - .find(|&id| cx.window_is_active(id)); - if let Some(id) = id { + .find(|window| window.is_active(&cx).unwrap_or(false)); + if let Some(window) = window { //This can only get called when the window's project connection has been lost //so we don't need to prompt the user for anything and instead just close the window - cx.remove_window(id); + window.remove(&mut cx); } }) .detach(); @@ -1265,9 +1270,9 @@ impl Workspace { cx.spawn(|this, mut cx| async move { let workspace_count = cx - .window_ids() + .windows() .into_iter() - .filter_map(|window_id| cx.root_view(window_id)?.clone().downcast::()) + .filter(|window| window.root_is::()) .count(); if let Some(active_call) = active_call { @@ -1385,7 +1390,7 @@ impl Workspace { paths: Vec, cx: &mut ViewContext, ) -> Task> { - let window_id = cx.window_id(); + let window = cx.window::(); let is_remote = self.project.read(cx).is_remote(); let has_worktree = self.project.read(cx).worktrees(cx).next().is_some(); let has_dirty_items = self.items(cx).any(|item| item.is_dirty(cx)); @@ -1397,15 +1402,15 @@ impl Workspace { let app_state = self.app_state.clone(); cx.spawn(|_, mut cx| async move { - let window_id_to_replace = if let Some(close_task) = close_task { + let window_to_replace = if let Some(close_task) = close_task { if !close_task.await? { return Ok(()); } - Some(window_id) + window } else { None }; - cx.update(|cx| open_paths(&paths, &app_state, window_id_to_replace, cx)) + cx.update(|cx| open_paths(&paths, &app_state, window_to_replace, cx)) .await?; Ok(()) }) @@ -3851,7 +3856,7 @@ pub async fn last_opened_workspace_paths() -> Option { pub fn open_paths( abs_paths: &[PathBuf], app_state: &Arc, - requesting_window_id: Option, + requesting_window: Option>, cx: &mut AppContext, ) -> Task< Result<( @@ -3879,7 +3884,7 @@ pub fn open_paths( } else { Ok(cx .update(|cx| { - Workspace::new_local(abs_paths, app_state.clone(), requesting_window_id, cx) + Workspace::new_local(abs_paths, app_state.clone(), requesting_window, cx) }) .await) } @@ -4196,14 +4201,14 @@ mod tests { ); }); assert_eq!( - cx.current_window_title(window.window_id()).as_deref(), + cx.current_window_title(window.id()).as_deref(), Some("one.txt — root1") ); // Add a second item to a non-empty pane workspace.update(cx, |workspace, cx| workspace.add_item(Box::new(item2), cx)); assert_eq!( - cx.current_window_title(window.window_id()).as_deref(), + cx.current_window_title(window.id()).as_deref(), Some("two.txt — root1") ); project.read_with(cx, |project, cx| { @@ -4222,7 +4227,7 @@ mod tests { .await .unwrap(); assert_eq!( - cx.current_window_title(window.window_id()).as_deref(), + cx.current_window_title(window.id()).as_deref(), Some("one.txt — root1") ); project.read_with(cx, |project, cx| { @@ -4242,14 +4247,14 @@ mod tests { .await .unwrap(); assert_eq!( - cx.current_window_title(window.window_id()).as_deref(), + cx.current_window_title(window.id()).as_deref(), Some("one.txt — root1, root2") ); // Remove a project folder project.update(cx, |project, cx| project.remove_worktree(worktree_id, cx)); assert_eq!( - cx.current_window_title(window.window_id()).as_deref(), + cx.current_window_title(window.id()).as_deref(), Some("one.txt — root2") ); } @@ -4285,9 +4290,9 @@ mod tests { }); let task = workspace.update(cx, |w, cx| w.prepare_to_close(false, cx)); cx.foreground().run_until_parked(); - cx.simulate_prompt_answer(window.window_id(), 2 /* cancel */); + cx.simulate_prompt_answer(window.id(), 2 /* cancel */); cx.foreground().run_until_parked(); - assert!(!cx.has_pending_prompt(window.window_id())); + assert!(!cx.has_pending_prompt(window.id())); assert!(!task.await.unwrap()); } @@ -4346,10 +4351,10 @@ mod tests { assert_eq!(pane.items_len(), 4); assert_eq!(pane.active_item().unwrap().id(), item1.id()); }); - assert!(cx.has_pending_prompt(window.window_id())); + assert!(cx.has_pending_prompt(window.id())); // Confirm saving item 1. - cx.simulate_prompt_answer(window.window_id(), 0); + cx.simulate_prompt_answer(window.id(), 0); cx.foreground().run_until_parked(); // Item 1 is saved. There's a prompt to save item 3. @@ -4360,10 +4365,10 @@ mod tests { assert_eq!(pane.items_len(), 3); assert_eq!(pane.active_item().unwrap().id(), item3.id()); }); - assert!(cx.has_pending_prompt(window.window_id())); + assert!(cx.has_pending_prompt(window.id())); // Cancel saving item 3. - cx.simulate_prompt_answer(window.window_id(), 1); + cx.simulate_prompt_answer(window.id(), 1); cx.foreground().run_until_parked(); // Item 3 is reloaded. There's a prompt to save item 4. @@ -4374,10 +4379,10 @@ mod tests { assert_eq!(pane.items_len(), 2); assert_eq!(pane.active_item().unwrap().id(), item4.id()); }); - assert!(cx.has_pending_prompt(window.window_id())); + assert!(cx.has_pending_prompt(window.id())); // Confirm saving item 4. - cx.simulate_prompt_answer(window.window_id(), 0); + cx.simulate_prompt_answer(window.id(), 0); cx.foreground().run_until_parked(); // There's a prompt for a path for item 4. @@ -4480,7 +4485,7 @@ mod tests { &[ProjectEntryId::from_proto(0)] ); }); - cx.simulate_prompt_answer(window.window_id(), 0); + cx.simulate_prompt_answer(window.id(), 0); cx.foreground().run_until_parked(); left_pane.read_with(cx, |pane, cx| { @@ -4489,7 +4494,7 @@ mod tests { &[ProjectEntryId::from_proto(2)] ); }); - cx.simulate_prompt_answer(window.window_id(), 0); + cx.simulate_prompt_answer(window.id(), 0); cx.foreground().run_until_parked(); close.await.unwrap(); @@ -4549,7 +4554,7 @@ mod tests { item.read_with(cx, |item, _| assert_eq!(item.save_count, 2)); // Deactivating the window still saves the file. - cx.simulate_window_activation(Some(window.window_id())); + cx.simulate_window_activation(Some(window.id())); item.update(cx, |item, cx| { cx.focus_self(); item.is_dirty = true; @@ -4591,7 +4596,7 @@ mod tests { pane.update(cx, |pane, cx| pane.close_items(cx, move |id| id == item_id)) .await .unwrap(); - assert!(!cx.has_pending_prompt(window.window_id())); + assert!(!cx.has_pending_prompt(window.id())); item.read_with(cx, |item, _| assert_eq!(item.save_count, 5)); // Add the item again, ensuring autosave is prevented if the underlying file has been deleted. @@ -4612,7 +4617,7 @@ mod tests { let _close_items = pane.update(cx, |pane, cx| pane.close_items(cx, move |id| id == item_id)); deterministic.run_until_parked(); - assert!(cx.has_pending_prompt(window.window_id())); + assert!(cx.has_pending_prompt(window.id())); item.read_with(cx, |item, _| assert_eq!(item.save_count, 5)); } diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 46fcc014a1..a8a287fb4e 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -813,11 +813,12 @@ mod tests { // Replace existing windows let window_id = cx.window_ids()[0]; + let window = cx.read_window(window_id, |cx| cx.window()).flatten(); cx.update(|cx| { open_paths( &[PathBuf::from("/root/c"), PathBuf::from("/root/d")], &app_state, - Some(window_id), + window, cx, ) }) @@ -982,9 +983,8 @@ mod tests { .await; let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await; - let workspace = cx - .add_window(|cx| Workspace::test_new(project, cx)) - .root(cx); + let window = cx.add_window(|cx| Workspace::test_new(project, cx)); + let workspace = window.root(cx); let entries = cx.read(|cx| workspace.file_project_paths(cx)); let file1 = entries[0].clone(); @@ -1298,7 +1298,7 @@ mod tests { let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await; let window = cx.add_window(|cx| Workspace::test_new(project, cx)); let workspace = window.root(cx); - let window_id = window.window_id(); + let window_id = window.id(); // Open a file within an existing worktree. workspace @@ -1341,7 +1341,7 @@ mod tests { project.update(cx, |project, _| project.languages().add(rust_lang())); let window = cx.add_window(|cx| Workspace::test_new(project, cx)); let workspace = window.root(cx); - let window_id = window.window_id(); + let window_id = window.id(); let worktree = cx.read(|cx| workspace.read(cx).worktrees(cx).next().unwrap()); // Create a new untitled buffer @@ -1436,7 +1436,7 @@ mod tests { project.update(cx, |project, _| project.languages().add(rust_lang())); let window = cx.add_window(|cx| Workspace::test_new(project, cx)); let workspace = window.root(cx); - let window_id = window.window_id(); + let window_id = window.id(); // Create a new untitled buffer cx.dispatch_action(window_id, NewFile); @@ -1489,7 +1489,7 @@ mod tests { let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await; let window = cx.add_window(|cx| Workspace::test_new(project, cx)); let workspace = window.root(cx); - let window_id = window.window_id(); + let window_id = window.id(); let entries = cx.read(|cx| workspace.file_project_paths(cx)); let file1 = entries[0].clone(); @@ -2087,7 +2087,7 @@ mod tests { cx.foreground().run_until_parked(); let window = cx.add_window(|_| TestView); - let window_id = window.window_id(); + let window_id = window.id(); // Test loading the keymap base at all assert_key_bindings_for( @@ -2258,7 +2258,7 @@ mod tests { cx.foreground().run_until_parked(); let window = cx.add_window(|_| TestView); - let window_id = window.window_id(); + let window_id = window.id(); // Test loading the keymap base at all assert_key_bindings_for(