Detailed changes
@@ -495,8 +495,9 @@ impl TestClient {
// We use a workspace container so that we don't need to remove the window in order to
// drop the workspace and we can use a ViewHandle instead.
- let (window_id, container) = cx.add_window(|_| WorkspaceContainer { workspace: None });
- let workspace = cx.add_view(window_id, |cx| Workspace::test_new(project.clone(), cx));
+ let window = cx.add_window(|_| WorkspaceContainer { workspace: None });
+ let container = window.root(cx);
+ let workspace = window.add_view(cx, |cx| Workspace::test_new(project.clone(), cx));
container.update(cx, |container, cx| {
container.workspace = Some(workspace.downgrade());
cx.notify();
@@ -7,8 +7,7 @@ use client::{User, RECEIVE_TIMEOUT};
use collections::HashSet;
use editor::{
test::editor_test_context::EditorTestContext, ConfirmCodeAction, ConfirmCompletion,
- ConfirmRename, Editor, ExcerptRange, MultiBuffer, Redo, Rename, ToOffset, ToggleCodeActions,
- Undo,
+ ConfirmRename, Editor, ExcerptRange, MultiBuffer, Redo, Rename, ToggleCodeActions, Undo,
};
use fs::{repository::GitFileStatus, FakeFs, Fs as _, LineEnding, RemoveOptions};
use futures::StreamExt as _;
@@ -1208,7 +1207,7 @@ async fn test_share_project(
cx_c: &mut TestAppContext,
) {
deterministic.forbid_parking();
- let (window_b, _) = cx_b.add_window(|_| EmptyView);
+ let window_b = cx_b.add_window(|_| EmptyView);
let mut server = TestServer::start(&deterministic).await;
let client_a = server.create_client(cx_a, "user_a").await;
let client_b = server.create_client(cx_b, "user_b").await;
@@ -1316,7 +1315,7 @@ async fn test_share_project(
.await
.unwrap();
- let editor_b = cx_b.add_view(window_b, |cx| Editor::for_buffer(buffer_b, None, cx));
+ let editor_b = window_b.add_view(cx_b, |cx| Editor::for_buffer(buffer_b, None, cx));
// Client A sees client B's selection
deterministic.run_until_parked();
@@ -1499,8 +1498,8 @@ async fn test_host_disconnect(
deterministic.run_until_parked();
assert!(worktree_a.read_with(cx_a, |tree, _| tree.as_local().unwrap().is_shared()));
- let (window_id_b, workspace_b) =
- cx_b.add_window(|cx| Workspace::test_new(project_b.clone(), cx));
+ let window_b = cx_b.add_window(|cx| Workspace::test_new(project_b.clone(), cx));
+ let workspace_b = window_b.root(cx_b);
let editor_b = workspace_b
.update(cx_b, |workspace, cx| {
workspace.open_path((worktree_id, "b.txt"), None, true, cx)
@@ -1509,9 +1508,7 @@ async fn test_host_disconnect(
.unwrap()
.downcast::<Editor>()
.unwrap();
- assert!(cx_b
- .read_window(window_id_b, |cx| editor_b.is_focused(cx))
- .unwrap());
+ assert!(window_b.read_with(cx_b, |cx| editor_b.is_focused(cx)));
editor_b.update(cx_b, |editor, cx| editor.insert("X", cx));
assert!(cx_b.is_window_edited(workspace_b.window_id()));
@@ -1525,7 +1522,7 @@ async fn test_host_disconnect(
assert!(worktree_a.read_with(cx_a, |tree, _| !tree.as_local().unwrap().is_shared()));
// Ensure client B's edited state is reset and that the whole window is blurred.
- cx_b.read_window(window_id_b, |cx| {
+ window_b.read_with(cx_b, |cx| {
assert_eq!(cx.focused_view_id(), None);
});
assert!(!cx_b.is_window_edited(workspace_b.window_id()));
@@ -3445,13 +3442,11 @@ async fn test_newline_above_or_below_does_not_move_guest_cursor(
.update(cx_a, |p, cx| p.open_buffer((worktree_id, "a.txt"), cx))
.await
.unwrap();
- let (window_a, _) = cx_a.add_window(|_| EmptyView);
- let editor_a = cx_a.add_view(window_a, |cx| {
- Editor::for_buffer(buffer_a, Some(project_a), cx)
- });
+ let window_a = cx_a.add_window(|_| EmptyView);
+ 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_a.window_id(),
editor: editor_a,
};
@@ -3460,13 +3455,11 @@ async fn test_newline_above_or_below_does_not_move_guest_cursor(
.update(cx_b, |p, cx| p.open_buffer((worktree_id, "a.txt"), cx))
.await
.unwrap();
- let (window_b, _) = cx_b.add_window(|_| EmptyView);
- let editor_b = cx_b.add_view(window_b, |cx| {
- Editor::for_buffer(buffer_b, Some(project_b), cx)
- });
+ let window_b = cx_b.add_window(|_| EmptyView);
+ 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_b.window_id(),
editor: editor_b,
};
@@ -4205,8 +4198,8 @@ async fn test_collaborating_with_completion(
.update(cx_b, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx))
.await
.unwrap();
- let (window_b, _) = cx_b.add_window(|_| EmptyView);
- let editor_b = cx_b.add_view(window_b, |cx| {
+ let window_b = cx_b.add_window(|_| EmptyView);
+ let editor_b = window_b.add_view(cx_b, |cx| {
Editor::for_buffer(buffer_b.clone(), Some(project_b.clone()), cx)
});
@@ -5316,7 +5309,8 @@ async fn test_collaborating_with_code_actions(
// Join the project as client B.
let project_b = client_b.build_remote_project(project_id, cx_b).await;
- let (_window_b, workspace_b) = cx_b.add_window(|cx| Workspace::test_new(project_b.clone(), cx));
+ let window_b = cx_b.add_window(|cx| Workspace::test_new(project_b.clone(), cx));
+ let workspace_b = window_b.root(cx_b);
let editor_b = workspace_b
.update(cx_b, |workspace, cx| {
workspace.open_path((worktree_id, "main.rs"), None, true, cx)
@@ -5540,7 +5534,8 @@ async fn test_collaborating_with_renames(
.unwrap();
let project_b = client_b.build_remote_project(project_id, cx_b).await;
- let (_window_b, workspace_b) = cx_b.add_window(|cx| Workspace::test_new(project_b.clone(), cx));
+ let window_b = cx_b.add_window(|cx| Workspace::test_new(project_b.clone(), cx));
+ let workspace_b = window_b.root(cx_b);
let editor_b = workspace_b
.update(cx_b, |workspace, cx| {
workspace.open_path((worktree_id, "one.rs"), None, true, cx)
@@ -5571,6 +5566,7 @@ async fn test_collaborating_with_renames(
.unwrap();
prepare_rename.await.unwrap();
editor_b.update(cx_b, |editor, cx| {
+ use editor::ToOffset;
let rename = editor.pending_rename().unwrap();
let buffer = editor.buffer().read(cx).snapshot(cx);
assert_eq!(
@@ -7601,8 +7597,8 @@ async fn test_on_input_format_from_host_to_guest(
.update(cx_a, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx))
.await
.unwrap();
- let (window_a, _) = cx_a.add_window(|_| EmptyView);
- let editor_a = cx_a.add_view(window_a, |cx| {
+ let window_a = cx_a.add_window(|_| EmptyView);
+ let editor_a = window_a.add_view(cx_a, |cx| {
Editor::for_buffer(buffer_a, Some(project_a.clone()), cx)
});
@@ -7730,8 +7726,8 @@ async fn test_on_input_format_from_guest_to_host(
.update(cx_b, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx))
.await
.unwrap();
- let (window_b, _) = cx_b.add_window(|_| EmptyView);
- let editor_b = cx_b.add_view(window_b, |cx| {
+ let window_b = cx_b.add_window(|_| EmptyView);
+ let editor_b = window_b.add_view(cx_b, |cx| {
Editor::for_buffer(buffer_b, Some(project_b.clone()), cx)
});
@@ -31,7 +31,7 @@ pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
for screen in cx.platform().screens() {
let screen_bounds = screen.bounds();
- let (window_id, _) = cx.add_window(
+ let window = cx.add_window(
WindowOptions {
bounds: WindowBounds::Fixed(RectF::new(
screen_bounds.upper_right()
@@ -49,7 +49,7 @@ pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
|_| IncomingCallNotification::new(incoming_call.clone(), app_state.clone()),
);
- notification_windows.push(window_id);
+ notification_windows.push(window.window_id());
}
}
}
@@ -26,7 +26,7 @@ pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
for screen in cx.platform().screens() {
let screen_bounds = screen.bounds();
- let (window_id, _) = cx.add_window(
+ let window = cx.add_window(
WindowOptions {
bounds: WindowBounds::Fixed(RectF::new(
screen_bounds.upper_right() - vec2f(PADDING + window_size.x(), PADDING),
@@ -52,7 +52,7 @@ pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
notification_windows
.entry(*project_id)
.or_insert(Vec::new())
- .push(window_id);
+ .push(window.window_id());
}
}
room::Event::RemoteProjectUnshared { project_id } => {
@@ -295,7 +295,9 @@ mod tests {
let app_state = init_test(cx);
let project = Project::test(app_state.fs.clone(), [], cx).await;
- let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let workspace = window.root(cx);
+ let window_id = window.window_id();
let editor = cx.add_view(window_id, |cx| {
let mut editor = Editor::single_line(None, cx);
editor.set_text("abc", cx);
@@ -4,7 +4,7 @@ use gpui::{
geometry::rect::RectF,
platform::{WindowBounds, WindowKind, WindowOptions},
AnyElement, AnyViewHandle, AppContext, ClipboardItem, Element, Entity, View, ViewContext,
- ViewHandle,
+ WindowHandle,
};
use theme::ui::modal;
@@ -18,43 +18,43 @@ const COPILOT_SIGN_UP_URL: &'static str = "https://github.com/features/copilot";
pub fn init(cx: &mut AppContext) {
if let Some(copilot) = Copilot::global(cx) {
- let mut code_verification: Option<ViewHandle<CopilotCodeVerification>> = None;
+ let mut verification_window: Option<WindowHandle<CopilotCodeVerification>> = None;
cx.observe(&copilot, move |copilot, cx| {
let status = copilot.read(cx).status();
match &status {
crate::Status::SigningIn { prompt } => {
- if let Some(code_verification_handle) = code_verification.as_mut() {
- let window_id = code_verification_handle.window_id();
- let updated = cx.update_window(window_id, |cx| {
- code_verification_handle.update(cx, |code_verification, cx| {
- code_verification.set_status(status.clone(), cx)
- });
- cx.activate_window();
- });
- if updated.is_none() {
- code_verification = Some(create_copilot_auth_window(cx, &status));
+ if let Some(window) = verification_window.as_mut() {
+ let updated = window
+ .root(cx)
+ .map(|root| {
+ root.update(cx, |verification, cx| {
+ verification.set_status(status.clone(), cx);
+ cx.activate_window();
+ })
+ })
+ .is_some();
+ if !updated {
+ verification_window = Some(create_copilot_auth_window(cx, &status));
}
} else if let Some(_prompt) = prompt {
- code_verification = Some(create_copilot_auth_window(cx, &status));
+ verification_window = Some(create_copilot_auth_window(cx, &status));
}
}
Status::Authorized | Status::Unauthorized => {
- if let Some(code_verification) = code_verification.as_ref() {
- let window_id = code_verification.window_id();
- cx.update_window(window_id, |cx| {
- code_verification.update(cx, |code_verification, cx| {
- code_verification.set_status(status, cx)
+ if let Some(window) = verification_window.as_ref() {
+ if let Some(verification) = window.root(cx) {
+ verification.update(cx, |verification, cx| {
+ verification.set_status(status, cx);
+ cx.platform().activate(true);
+ cx.activate_window();
});
-
- cx.platform().activate(true);
- cx.activate_window();
- });
+ }
}
}
_ => {
- if let Some(code_verification) = code_verification.take() {
- cx.update_window(code_verification.window_id(), |cx| cx.remove_window());
+ if let Some(code_verification) = verification_window.take() {
+ code_verification.update(cx, |cx| cx.remove_window());
}
}
}
@@ -66,7 +66,7 @@ pub fn init(cx: &mut AppContext) {
fn create_copilot_auth_window(
cx: &mut AppContext,
status: &Status,
-) -> ViewHandle<CopilotCodeVerification> {
+) -> WindowHandle<CopilotCodeVerification> {
let window_size = theme::current(cx).copilot.modal.dimensions();
let window_options = WindowOptions {
bounds: WindowBounds::Fixed(RectF::new(Default::default(), window_size)),
@@ -78,10 +78,9 @@ fn create_copilot_auth_window(
is_movable: true,
screen: None,
};
- let (_, view) = cx.add_window(window_options, |_cx| {
+ cx.add_window(window_options, |_cx| {
CopilotCodeVerification::new(status.clone())
- });
- view
+ })
}
pub struct CopilotCodeVerification {
@@ -855,7 +855,9 @@ mod tests {
let language_server_id = LanguageServerId(0);
let project = Project::test(fs.clone(), ["/test".as_ref()], cx).await;
- let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let workspace = window.root(cx);
+ let window_id = window.window_id();
// Create some diagnostics
project.update(cx, |project, cx| {
@@ -1248,7 +1250,9 @@ mod tests {
let server_id_1 = LanguageServerId(100);
let server_id_2 = LanguageServerId(101);
let project = Project::test(fs.clone(), ["/test".as_ref()], cx).await;
- let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let workspace = window.root(cx);
+ let window_id = window.window_id();
let view = cx.add_view(window_id, |cx| {
ProjectDiagnosticsEditor::new(project.clone(), workspace.downgrade(), cx)
@@ -48,36 +48,40 @@ fn test_edit_events(cx: &mut TestAppContext) {
});
let events = Rc::new(RefCell::new(Vec::new()));
- let (_, editor1) = cx.add_window({
- let events = events.clone();
- |cx| {
- cx.subscribe(&cx.handle(), move |_, _, event, _| {
- if matches!(
- event,
- Event::Edited | Event::BufferEdited | Event::DirtyChanged
- ) {
- events.borrow_mut().push(("editor1", event.clone()));
- }
- })
- .detach();
- Editor::for_buffer(buffer.clone(), None, cx)
- }
- });
- let (_, editor2) = cx.add_window({
- let events = events.clone();
- |cx| {
- cx.subscribe(&cx.handle(), move |_, _, event, _| {
- if matches!(
- event,
- Event::Edited | Event::BufferEdited | Event::DirtyChanged
- ) {
- events.borrow_mut().push(("editor2", event.clone()));
- }
- })
- .detach();
- Editor::for_buffer(buffer.clone(), None, cx)
- }
- });
+ let editor1 = cx
+ .add_window({
+ let events = events.clone();
+ |cx| {
+ cx.subscribe(&cx.handle(), move |_, _, event, _| {
+ if matches!(
+ event,
+ Event::Edited | Event::BufferEdited | Event::DirtyChanged
+ ) {
+ events.borrow_mut().push(("editor1", event.clone()));
+ }
+ })
+ .detach();
+ Editor::for_buffer(buffer.clone(), None, cx)
+ }
+ })
+ .root(cx);
+ let editor2 = cx
+ .add_window({
+ let events = events.clone();
+ |cx| {
+ cx.subscribe(&cx.handle(), move |_, _, event, _| {
+ if matches!(
+ event,
+ Event::Edited | Event::BufferEdited | Event::DirtyChanged
+ ) {
+ events.borrow_mut().push(("editor2", event.clone()));
+ }
+ })
+ .detach();
+ Editor::for_buffer(buffer.clone(), None, cx)
+ }
+ })
+ .root(cx);
assert_eq!(mem::take(&mut *events.borrow_mut()), []);
// Mutating editor 1 will emit an `Edited` event only for that editor.
@@ -173,7 +177,9 @@ fn test_undo_redo_with_selection_restoration(cx: &mut TestAppContext) {
let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
let group_interval = buffer.read_with(cx, |buffer, _| buffer.transaction_group_interval());
let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
- let (_, editor) = cx.add_window(|cx| build_editor(buffer.clone(), cx));
+ let editor = cx
+ .add_window(|cx| build_editor(buffer.clone(), cx))
+ .root(cx);
editor.update(cx, |editor, cx| {
editor.start_transaction_at(now, cx);
@@ -343,10 +349,12 @@ fn test_ime_composition(cx: &mut TestAppContext) {
fn test_selection_with_mouse(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- let (_, editor) = cx.add_window(|cx| {
- let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\nddddddd\n", cx);
- build_editor(buffer, cx)
- });
+ let editor = cx
+ .add_window(|cx| {
+ let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\nddddddd\n", cx);
+ build_editor(buffer, cx)
+ })
+ .root(cx);
editor.update(cx, |view, cx| {
view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
});
@@ -410,10 +418,12 @@ fn test_selection_with_mouse(cx: &mut TestAppContext) {
fn test_canceling_pending_selection(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- let (_, view) = cx.add_window(|cx| {
- let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
- build_editor(buffer, cx)
- });
+ let view = cx
+ .add_window(|cx| {
+ let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
+ build_editor(buffer, cx)
+ })
+ .root(cx);
view.update(cx, |view, cx| {
view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
@@ -456,10 +466,12 @@ fn test_clone(cx: &mut TestAppContext) {
true,
);
- let (_, editor) = cx.add_window(|cx| {
- let buffer = MultiBuffer::build_simple(&text, cx);
- build_editor(buffer, cx)
- });
+ let editor = cx
+ .add_window(|cx| {
+ let buffer = MultiBuffer::build_simple(&text, cx);
+ build_editor(buffer, cx)
+ })
+ .root(cx);
editor.update(cx, |editor, cx| {
editor.change_selections(None, cx, |s| s.select_ranges(selection_ranges.clone()));
@@ -473,9 +485,11 @@ fn test_clone(cx: &mut TestAppContext) {
);
});
- let (_, cloned_editor) = editor.update(cx, |editor, cx| {
- cx.add_window(Default::default(), |cx| editor.clone(cx))
- });
+ let cloned_editor = editor
+ .update(cx, |editor, cx| {
+ cx.add_window(Default::default(), |cx| editor.clone(cx))
+ })
+ .root(cx);
let snapshot = editor.update(cx, |e, cx| e.snapshot(cx));
let cloned_snapshot = cloned_editor.update(cx, |e, cx| e.snapshot(cx));
@@ -509,7 +523,9 @@ async fn test_navigation_history(cx: &mut TestAppContext) {
let fs = FakeFs::new(cx.background());
let project = Project::test(fs, [], cx).await;
- let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project, cx));
+ let workspace = window.root(cx);
+ let window_id = window.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);
@@ -618,10 +634,12 @@ async fn test_navigation_history(cx: &mut TestAppContext) {
fn test_cancel(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- let (_, view) = cx.add_window(|cx| {
- let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
- build_editor(buffer, cx)
- });
+ let view = cx
+ .add_window(|cx| {
+ let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
+ build_editor(buffer, cx)
+ })
+ .root(cx);
view.update(cx, |view, cx| {
view.begin_selection(DisplayPoint::new(3, 4), false, 1, cx);
@@ -661,9 +679,10 @@ fn test_cancel(cx: &mut TestAppContext) {
fn test_fold_action(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- let (_, view) = cx.add_window(|cx| {
- let buffer = MultiBuffer::build_simple(
- &"
+ let view = cx
+ .add_window(|cx| {
+ let buffer = MultiBuffer::build_simple(
+ &"
impl Foo {
// Hello!
@@ -680,11 +699,12 @@ fn test_fold_action(cx: &mut TestAppContext) {
}
}
"
- .unindent(),
- cx,
- );
- build_editor(buffer.clone(), cx)
- });
+ .unindent(),
+ cx,
+ );
+ build_editor(buffer.clone(), cx)
+ })
+ .root(cx);
view.update(cx, |view, cx| {
view.change_selections(None, cx, |s| {
@@ -752,7 +772,9 @@ fn test_move_cursor(cx: &mut TestAppContext) {
init_test(cx, |_| {});
let buffer = cx.update(|cx| MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx));
- let (_, view) = cx.add_window(|cx| build_editor(buffer.clone(), cx));
+ let view = cx
+ .add_window(|cx| build_editor(buffer.clone(), cx))
+ .root(cx);
buffer.update(cx, |buffer, cx| {
buffer.edit(
@@ -827,10 +849,12 @@ fn test_move_cursor(cx: &mut TestAppContext) {
fn test_move_cursor_multibyte(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- let (_, view) = cx.add_window(|cx| {
- let buffer = MultiBuffer::build_simple("āāāāā\nabcde\nαβγΓε\n", cx);
- build_editor(buffer.clone(), cx)
- });
+ let view = cx
+ .add_window(|cx| {
+ let buffer = MultiBuffer::build_simple("āāāāā\nabcde\nαβγΓε\n", cx);
+ build_editor(buffer.clone(), cx)
+ })
+ .root(cx);
assert_eq!('ā'.len_utf8(), 3);
assert_eq!('α'.len_utf8(), 2);
@@ -932,10 +956,12 @@ fn test_move_cursor_multibyte(cx: &mut TestAppContext) {
fn test_move_cursor_different_line_lengths(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- let (_, view) = cx.add_window(|cx| {
- let buffer = MultiBuffer::build_simple("āāāāā\nabcd\nαβγ\nabcd\nāāāāā\n", cx);
- build_editor(buffer.clone(), cx)
- });
+ let view = cx
+ .add_window(|cx| {
+ let buffer = MultiBuffer::build_simple("āāāāā\nabcd\nαβγ\nabcd\nāāāāā\n", cx);
+ build_editor(buffer.clone(), cx)
+ })
+ .root(cx);
view.update(cx, |view, cx| {
view.change_selections(None, cx, |s| {
s.select_display_ranges([empty_range(0, "āāāāā".len())]);
@@ -982,10 +1008,12 @@ fn test_move_cursor_different_line_lengths(cx: &mut TestAppContext) {
fn test_beginning_end_of_line(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- let (_, view) = cx.add_window(|cx| {
- let buffer = MultiBuffer::build_simple("abc\n def", cx);
- build_editor(buffer, cx)
- });
+ let view = cx
+ .add_window(|cx| {
+ let buffer = MultiBuffer::build_simple("abc\n def", cx);
+ build_editor(buffer, cx)
+ })
+ .root(cx);
view.update(cx, |view, cx| {
view.change_selections(None, cx, |s| {
s.select_display_ranges([
@@ -1145,10 +1173,12 @@ fn test_beginning_end_of_line(cx: &mut TestAppContext) {
fn test_prev_next_word_boundary(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- let (_, view) = cx.add_window(|cx| {
- let buffer = MultiBuffer::build_simple("use std::str::{foo, bar}\n\n {baz.qux()}", cx);
- build_editor(buffer, cx)
- });
+ let view = cx
+ .add_window(|cx| {
+ let buffer = MultiBuffer::build_simple("use std::str::{foo, bar}\n\n {baz.qux()}", cx);
+ build_editor(buffer, cx)
+ })
+ .root(cx);
view.update(cx, |view, cx| {
view.change_selections(None, cx, |s| {
s.select_display_ranges([
@@ -1197,10 +1227,13 @@ fn test_prev_next_word_boundary(cx: &mut TestAppContext) {
fn test_prev_next_word_bounds_with_soft_wrap(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- let (_, view) = cx.add_window(|cx| {
- let buffer = MultiBuffer::build_simple("use one::{\n two::three::four::five\n};", cx);
- build_editor(buffer, cx)
- });
+ let view = cx
+ .add_window(|cx| {
+ let buffer =
+ MultiBuffer::build_simple("use one::{\n two::three::four::five\n};", cx);
+ build_editor(buffer, cx)
+ })
+ .root(cx);
view.update(cx, |view, cx| {
view.set_wrap_width(Some(140.), cx);
@@ -1530,10 +1563,12 @@ async fn test_delete_to_beginning_of_line(cx: &mut gpui::TestAppContext) {
fn test_delete_to_word_boundary(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- let (_, view) = cx.add_window(|cx| {
- let buffer = MultiBuffer::build_simple("one two three four", cx);
- build_editor(buffer.clone(), cx)
- });
+ let view = cx
+ .add_window(|cx| {
+ let buffer = MultiBuffer::build_simple("one two three four", cx);
+ build_editor(buffer.clone(), cx)
+ })
+ .root(cx);
view.update(cx, |view, cx| {
view.change_selections(None, cx, |s| {
@@ -1566,10 +1601,12 @@ fn test_delete_to_word_boundary(cx: &mut TestAppContext) {
fn test_newline(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- let (_, view) = cx.add_window(|cx| {
- let buffer = MultiBuffer::build_simple("aaaa\n bbbb\n", cx);
- build_editor(buffer.clone(), cx)
- });
+ let view = cx
+ .add_window(|cx| {
+ let buffer = MultiBuffer::build_simple("aaaa\n bbbb\n", cx);
+ build_editor(buffer.clone(), cx)
+ })
+ .root(cx);
view.update(cx, |view, cx| {
view.change_selections(None, cx, |s| {
@@ -1589,9 +1626,10 @@ fn test_newline(cx: &mut TestAppContext) {
fn test_newline_with_old_selections(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- let (_, editor) = cx.add_window(|cx| {
- let buffer = MultiBuffer::build_simple(
- "
+ let editor = cx
+ .add_window(|cx| {
+ let buffer = MultiBuffer::build_simple(
+ "
a
b(
X
@@ -1600,19 +1638,20 @@ fn test_newline_with_old_selections(cx: &mut TestAppContext) {
X
)
"
- .unindent()
- .as_str(),
- cx,
- );
- let mut editor = build_editor(buffer.clone(), cx);
- editor.change_selections(None, cx, |s| {
- s.select_ranges([
- Point::new(2, 4)..Point::new(2, 5),
- Point::new(5, 4)..Point::new(5, 5),
- ])
- });
- editor
- });
+ .unindent()
+ .as_str(),
+ cx,
+ );
+ let mut editor = build_editor(buffer.clone(), cx);
+ editor.change_selections(None, cx, |s| {
+ s.select_ranges([
+ Point::new(2, 4)..Point::new(2, 5),
+ Point::new(5, 4)..Point::new(5, 5),
+ ])
+ });
+ editor
+ })
+ .root(cx);
editor.update(cx, |editor, cx| {
// Edit the buffer directly, deleting ranges surrounding the editor's selections
@@ -1817,12 +1856,14 @@ async fn test_newline_comments(cx: &mut gpui::TestAppContext) {
fn test_insert_with_old_selections(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- let (_, editor) = cx.add_window(|cx| {
- let buffer = MultiBuffer::build_simple("a( X ), b( Y ), c( Z )", cx);
- let mut editor = build_editor(buffer.clone(), cx);
- editor.change_selections(None, cx, |s| s.select_ranges([3..4, 11..12, 19..20]));
- editor
- });
+ let editor = cx
+ .add_window(|cx| {
+ let buffer = MultiBuffer::build_simple("a( X ), b( Y ), c( Z )", cx);
+ let mut editor = build_editor(buffer.clone(), cx);
+ editor.change_selections(None, cx, |s| s.select_ranges([3..4, 11..12, 19..20]));
+ editor
+ })
+ .root(cx);
editor.update(cx, |editor, cx| {
// Edit the buffer directly, deleting ranges surrounding the editor's selections
@@ -2329,10 +2370,12 @@ async fn test_delete(cx: &mut gpui::TestAppContext) {
fn test_delete_line(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- let (_, view) = cx.add_window(|cx| {
- let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
- build_editor(buffer, cx)
- });
+ let view = cx
+ .add_window(|cx| {
+ let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
+ build_editor(buffer, cx)
+ })
+ .root(cx);
view.update(cx, |view, cx| {
view.change_selections(None, cx, |s| {
s.select_display_ranges([
@@ -2352,10 +2395,12 @@ fn test_delete_line(cx: &mut TestAppContext) {
);
});
- let (_, view) = cx.add_window(|cx| {
- let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
- build_editor(buffer, cx)
- });
+ let view = cx
+ .add_window(|cx| {
+ let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
+ build_editor(buffer, cx)
+ })
+ .root(cx);
view.update(cx, |view, cx| {
view.change_selections(None, cx, |s| {
s.select_display_ranges([DisplayPoint::new(2, 0)..DisplayPoint::new(0, 1)])
@@ -2654,10 +2699,12 @@ async fn test_manipulate_lines_with_multi_selection(cx: &mut TestAppContext) {
fn test_duplicate_line(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- let (_, view) = cx.add_window(|cx| {
- let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
- build_editor(buffer, cx)
- });
+ let view = cx
+ .add_window(|cx| {
+ let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
+ build_editor(buffer, cx)
+ })
+ .root(cx);
view.update(cx, |view, cx| {
view.change_selections(None, cx, |s| {
s.select_display_ranges([
@@ -2680,10 +2727,12 @@ fn test_duplicate_line(cx: &mut TestAppContext) {
);
});
- let (_, view) = cx.add_window(|cx| {
- let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
- build_editor(buffer, cx)
- });
+ let view = cx
+ .add_window(|cx| {
+ let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
+ build_editor(buffer, cx)
+ })
+ .root(cx);
view.update(cx, |view, cx| {
view.change_selections(None, cx, |s| {
s.select_display_ranges([
@@ -2707,10 +2756,12 @@ fn test_duplicate_line(cx: &mut TestAppContext) {
fn test_move_line_up_down(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- let (_, view) = cx.add_window(|cx| {
- let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
- build_editor(buffer, cx)
- });
+ let view = cx
+ .add_window(|cx| {
+ let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
+ build_editor(buffer, cx)
+ })
+ .root(cx);
view.update(cx, |view, cx| {
view.fold_ranges(
vec![
@@ -2806,10 +2857,12 @@ fn test_move_line_up_down(cx: &mut TestAppContext) {
fn test_move_line_up_down_with_blocks(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- let (_, editor) = cx.add_window(|cx| {
- let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
- build_editor(buffer, cx)
- });
+ let editor = cx
+ .add_window(|cx| {
+ let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
+ build_editor(buffer, cx)
+ })
+ .root(cx);
editor.update(cx, |editor, cx| {
let snapshot = editor.buffer.read(cx).snapshot(cx);
editor.insert_blocks(
@@ -2834,102 +2887,94 @@ fn test_move_line_up_down_with_blocks(cx: &mut TestAppContext) {
fn test_transpose(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- _ = cx
- .add_window(|cx| {
- let mut editor = build_editor(MultiBuffer::build_simple("abc", cx), cx);
+ _ = cx.add_window(|cx| {
+ let mut editor = build_editor(MultiBuffer::build_simple("abc", cx), cx);
- editor.change_selections(None, cx, |s| s.select_ranges([1..1]));
- editor.transpose(&Default::default(), cx);
- assert_eq!(editor.text(cx), "bac");
- assert_eq!(editor.selections.ranges(cx), [2..2]);
+ editor.change_selections(None, cx, |s| s.select_ranges([1..1]));
+ editor.transpose(&Default::default(), cx);
+ assert_eq!(editor.text(cx), "bac");
+ assert_eq!(editor.selections.ranges(cx), [2..2]);
- editor.transpose(&Default::default(), cx);
- assert_eq!(editor.text(cx), "bca");
- assert_eq!(editor.selections.ranges(cx), [3..3]);
+ editor.transpose(&Default::default(), cx);
+ assert_eq!(editor.text(cx), "bca");
+ assert_eq!(editor.selections.ranges(cx), [3..3]);
- editor.transpose(&Default::default(), cx);
- assert_eq!(editor.text(cx), "bac");
- assert_eq!(editor.selections.ranges(cx), [3..3]);
+ editor.transpose(&Default::default(), cx);
+ assert_eq!(editor.text(cx), "bac");
+ assert_eq!(editor.selections.ranges(cx), [3..3]);
- editor
- })
- .1;
+ editor
+ });
- _ = cx
- .add_window(|cx| {
- let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
+ _ = cx.add_window(|cx| {
+ let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
- editor.change_selections(None, cx, |s| s.select_ranges([3..3]));
- editor.transpose(&Default::default(), cx);
- assert_eq!(editor.text(cx), "acb\nde");
- assert_eq!(editor.selections.ranges(cx), [3..3]);
+ editor.change_selections(None, cx, |s| s.select_ranges([3..3]));
+ editor.transpose(&Default::default(), cx);
+ assert_eq!(editor.text(cx), "acb\nde");
+ assert_eq!(editor.selections.ranges(cx), [3..3]);
- editor.change_selections(None, cx, |s| s.select_ranges([4..4]));
- editor.transpose(&Default::default(), cx);
- assert_eq!(editor.text(cx), "acbd\ne");
- assert_eq!(editor.selections.ranges(cx), [5..5]);
+ editor.change_selections(None, cx, |s| s.select_ranges([4..4]));
+ editor.transpose(&Default::default(), cx);
+ assert_eq!(editor.text(cx), "acbd\ne");
+ assert_eq!(editor.selections.ranges(cx), [5..5]);
- editor.transpose(&Default::default(), cx);
- assert_eq!(editor.text(cx), "acbde\n");
- assert_eq!(editor.selections.ranges(cx), [6..6]);
+ editor.transpose(&Default::default(), cx);
+ assert_eq!(editor.text(cx), "acbde\n");
+ assert_eq!(editor.selections.ranges(cx), [6..6]);
- editor.transpose(&Default::default(), cx);
- assert_eq!(editor.text(cx), "acbd\ne");
- assert_eq!(editor.selections.ranges(cx), [6..6]);
+ editor.transpose(&Default::default(), cx);
+ assert_eq!(editor.text(cx), "acbd\ne");
+ assert_eq!(editor.selections.ranges(cx), [6..6]);
- editor
- })
- .1;
+ editor
+ });
- _ = cx
- .add_window(|cx| {
- let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
+ _ = cx.add_window(|cx| {
+ let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
- editor.change_selections(None, cx, |s| s.select_ranges([1..1, 2..2, 4..4]));
- editor.transpose(&Default::default(), cx);
- assert_eq!(editor.text(cx), "bacd\ne");
- assert_eq!(editor.selections.ranges(cx), [2..2, 3..3, 5..5]);
+ editor.change_selections(None, cx, |s| s.select_ranges([1..1, 2..2, 4..4]));
+ editor.transpose(&Default::default(), cx);
+ assert_eq!(editor.text(cx), "bacd\ne");
+ assert_eq!(editor.selections.ranges(cx), [2..2, 3..3, 5..5]);
- editor.transpose(&Default::default(), cx);
- assert_eq!(editor.text(cx), "bcade\n");
- assert_eq!(editor.selections.ranges(cx), [3..3, 4..4, 6..6]);
+ editor.transpose(&Default::default(), cx);
+ assert_eq!(editor.text(cx), "bcade\n");
+ assert_eq!(editor.selections.ranges(cx), [3..3, 4..4, 6..6]);
- editor.transpose(&Default::default(), cx);
- assert_eq!(editor.text(cx), "bcda\ne");
- assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
+ editor.transpose(&Default::default(), cx);
+ assert_eq!(editor.text(cx), "bcda\ne");
+ assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
- editor.transpose(&Default::default(), cx);
- assert_eq!(editor.text(cx), "bcade\n");
- assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
+ editor.transpose(&Default::default(), cx);
+ assert_eq!(editor.text(cx), "bcade\n");
+ assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
- editor.transpose(&Default::default(), cx);
- assert_eq!(editor.text(cx), "bcaed\n");
- assert_eq!(editor.selections.ranges(cx), [5..5, 6..6]);
+ editor.transpose(&Default::default(), cx);
+ assert_eq!(editor.text(cx), "bcaed\n");
+ assert_eq!(editor.selections.ranges(cx), [5..5, 6..6]);
- editor
- })
- .1;
+ editor
+ });
- _ = cx
- .add_window(|cx| {
- let mut editor = build_editor(MultiBuffer::build_simple("ššā", cx), cx);
+ _ = cx.add_window(|cx| {
+ let mut editor = build_editor(MultiBuffer::build_simple("ššā", cx), cx);
- editor.change_selections(None, cx, |s| s.select_ranges([4..4]));
- editor.transpose(&Default::default(), cx);
- assert_eq!(editor.text(cx), "ššā");
- assert_eq!(editor.selections.ranges(cx), [8..8]);
+ editor.change_selections(None, cx, |s| s.select_ranges([4..4]));
+ editor.transpose(&Default::default(), cx);
+ assert_eq!(editor.text(cx), "ššā");
+ assert_eq!(editor.selections.ranges(cx), [8..8]);
- editor.transpose(&Default::default(), cx);
- assert_eq!(editor.text(cx), "šāš");
- assert_eq!(editor.selections.ranges(cx), [11..11]);
+ editor.transpose(&Default::default(), cx);
+ assert_eq!(editor.text(cx), "šāš");
+ assert_eq!(editor.selections.ranges(cx), [11..11]);
- editor.transpose(&Default::default(), cx);
- assert_eq!(editor.text(cx), "ššā");
- assert_eq!(editor.selections.ranges(cx), [11..11]);
+ editor.transpose(&Default::default(), cx);
+ assert_eq!(editor.text(cx), "ššā");
+ assert_eq!(editor.selections.ranges(cx), [11..11]);
- editor
- })
- .1;
+ editor
+ });
}
#[gpui::test]
@@ -3132,10 +3177,12 @@ async fn test_paste_multiline(cx: &mut gpui::TestAppContext) {
fn test_select_all(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- let (_, view) = cx.add_window(|cx| {
- let buffer = MultiBuffer::build_simple("abc\nde\nfgh", cx);
- build_editor(buffer, cx)
- });
+ let view = cx
+ .add_window(|cx| {
+ let buffer = MultiBuffer::build_simple("abc\nde\nfgh", cx);
+ build_editor(buffer, cx)
+ })
+ .root(cx);
view.update(cx, |view, cx| {
view.select_all(&SelectAll, cx);
assert_eq!(
@@ -3149,10 +3196,12 @@ fn test_select_all(cx: &mut TestAppContext) {
fn test_select_line(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- let (_, view) = cx.add_window(|cx| {
- let buffer = MultiBuffer::build_simple(&sample_text(6, 5, 'a'), cx);
- build_editor(buffer, cx)
- });
+ let view = cx
+ .add_window(|cx| {
+ let buffer = MultiBuffer::build_simple(&sample_text(6, 5, 'a'), cx);
+ build_editor(buffer, cx)
+ })
+ .root(cx);
view.update(cx, |view, cx| {
view.change_selections(None, cx, |s| {
s.select_display_ranges([
@@ -3196,10 +3245,12 @@ fn test_select_line(cx: &mut TestAppContext) {
fn test_split_selection_into_lines(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- let (_, view) = cx.add_window(|cx| {
- let buffer = MultiBuffer::build_simple(&sample_text(9, 5, 'a'), cx);
- build_editor(buffer, cx)
- });
+ let view = cx
+ .add_window(|cx| {
+ let buffer = MultiBuffer::build_simple(&sample_text(9, 5, 'a'), cx);
+ build_editor(buffer, cx)
+ })
+ .root(cx);
view.update(cx, |view, cx| {
view.fold_ranges(
vec![
@@ -3267,10 +3318,12 @@ fn test_split_selection_into_lines(cx: &mut TestAppContext) {
fn test_add_selection_above_below(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- let (_, view) = cx.add_window(|cx| {
- let buffer = MultiBuffer::build_simple("abc\ndefghi\n\njk\nlmno\n", cx);
- build_editor(buffer, cx)
- });
+ let view = cx
+ .add_window(|cx| {
+ let buffer = MultiBuffer::build_simple("abc\ndefghi\n\njk\nlmno\n", cx);
+ build_editor(buffer, cx)
+ })
+ .root(cx);
view.update(cx, |view, cx| {
view.change_selections(None, cx, |s| {
@@ -3555,7 +3608,7 @@ async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) {
let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
- let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
+ let view = cx.add_window(|cx| build_editor(buffer, cx)).root(cx);
view.condition(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
.await;
@@ -3718,7 +3771,7 @@ async fn test_autoindent_selections(cx: &mut gpui::TestAppContext) {
let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
- let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
+ let editor = cx.add_window(|cx| build_editor(buffer, cx)).root(cx);
editor
.condition(cx, |editor, cx| !editor.buffer.read(cx).is_parsing(cx))
.await;
@@ -4281,7 +4334,7 @@ async fn test_surround_with_pair(cx: &mut gpui::TestAppContext) {
let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
- let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
+ let view = cx.add_window(|cx| build_editor(buffer, cx)).root(cx);
view.condition(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
.await;
@@ -4429,7 +4482,7 @@ async fn test_delete_autoclose_pair(cx: &mut gpui::TestAppContext) {
let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
- let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
+ let editor = cx.add_window(|cx| build_editor(buffer, cx)).root(cx);
editor
.condition(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
.await;
@@ -4519,7 +4572,7 @@ async fn test_snippets(cx: &mut gpui::TestAppContext) {
);
let buffer = cx.update(|cx| MultiBuffer::build_simple(&text, cx));
- let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
+ let editor = cx.add_window(|cx| build_editor(buffer, cx)).root(cx);
editor.update(cx, |editor, cx| {
let snippet = Snippet::parse("f(${1:one}, ${2:two}, ${1:three})$0").unwrap();
@@ -4649,7 +4702,7 @@ async fn test_document_format_during_save(cx: &mut gpui::TestAppContext) {
let fake_server = fake_servers.next().await.unwrap();
let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
- let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
+ let editor = cx.add_window(|cx| build_editor(buffer, cx)).root(cx);
editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
assert!(cx.read(|cx| editor.is_dirty(cx)));
@@ -4761,7 +4814,7 @@ async fn test_range_format_during_save(cx: &mut gpui::TestAppContext) {
let fake_server = fake_servers.next().await.unwrap();
let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
- let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
+ let editor = cx.add_window(|cx| build_editor(buffer, cx)).root(cx);
editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
assert!(cx.read(|cx| editor.is_dirty(cx)));
@@ -4875,7 +4928,7 @@ async fn test_document_format_manual_trigger(cx: &mut gpui::TestAppContext) {
let fake_server = fake_servers.next().await.unwrap();
let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
- let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
+ let editor = cx.add_window(|cx| build_editor(buffer, cx)).root(cx);
editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
let format = editor.update(cx, |editor, cx| {
@@ -5653,7 +5706,7 @@ fn test_editing_disjoint_excerpts(cx: &mut TestAppContext) {
multibuffer
});
- let (_, view) = cx.add_window(|cx| build_editor(multibuffer, cx));
+ let view = cx.add_window(|cx| build_editor(multibuffer, cx)).root(cx);
view.update(cx, |view, cx| {
assert_eq!(view.text(cx), "aaaa\nbbbb");
view.change_selections(None, cx, |s| {
@@ -5723,7 +5776,7 @@ fn test_editing_overlapping_excerpts(cx: &mut TestAppContext) {
multibuffer
});
- let (_, view) = cx.add_window(|cx| build_editor(multibuffer, cx));
+ let view = cx.add_window(|cx| build_editor(multibuffer, cx)).root(cx);
view.update(cx, |view, cx| {
let (expected_text, selection_ranges) = marked_text_ranges(
indoc! {"
@@ -5799,22 +5852,24 @@ fn test_refresh_selections(cx: &mut TestAppContext) {
multibuffer
});
- let (_, editor) = cx.add_window(|cx| {
- let mut editor = build_editor(multibuffer.clone(), cx);
- let snapshot = editor.snapshot(cx);
- editor.change_selections(None, cx, |s| {
- s.select_ranges([Point::new(1, 3)..Point::new(1, 3)])
- });
- editor.begin_selection(Point::new(2, 1).to_display_point(&snapshot), true, 1, cx);
- assert_eq!(
- editor.selections.ranges(cx),
- [
- Point::new(1, 3)..Point::new(1, 3),
- Point::new(2, 1)..Point::new(2, 1),
- ]
- );
- editor
- });
+ let editor = cx
+ .add_window(|cx| {
+ let mut editor = build_editor(multibuffer.clone(), cx);
+ let snapshot = editor.snapshot(cx);
+ editor.change_selections(None, cx, |s| {
+ s.select_ranges([Point::new(1, 3)..Point::new(1, 3)])
+ });
+ editor.begin_selection(Point::new(2, 1).to_display_point(&snapshot), true, 1, cx);
+ assert_eq!(
+ editor.selections.ranges(cx),
+ [
+ Point::new(1, 3)..Point::new(1, 3),
+ Point::new(2, 1)..Point::new(2, 1),
+ ]
+ );
+ editor
+ })
+ .root(cx);
// Refreshing selections is a no-op when excerpts haven't changed.
editor.update(cx, |editor, cx| {
@@ -5884,16 +5939,18 @@ fn test_refresh_selections_while_selecting_with_mouse(cx: &mut TestAppContext) {
multibuffer
});
- let (_, editor) = cx.add_window(|cx| {
- let mut editor = build_editor(multibuffer.clone(), cx);
- let snapshot = editor.snapshot(cx);
- editor.begin_selection(Point::new(1, 3).to_display_point(&snapshot), false, 1, cx);
- assert_eq!(
- editor.selections.ranges(cx),
- [Point::new(1, 3)..Point::new(1, 3)]
- );
- editor
- });
+ let editor = cx
+ .add_window(|cx| {
+ let mut editor = build_editor(multibuffer.clone(), cx);
+ let snapshot = editor.snapshot(cx);
+ editor.begin_selection(Point::new(1, 3).to_display_point(&snapshot), false, 1, cx);
+ assert_eq!(
+ editor.selections.ranges(cx),
+ [Point::new(1, 3)..Point::new(1, 3)]
+ );
+ editor
+ })
+ .root(cx);
multibuffer.update(cx, |multibuffer, cx| {
multibuffer.remove_excerpts([excerpt1_id.unwrap()], cx);
@@ -5956,7 +6013,7 @@ async fn test_extra_newline_insertion(cx: &mut gpui::TestAppContext) {
let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
- let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
+ let view = cx.add_window(|cx| build_editor(buffer, cx)).root(cx);
view.condition(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
.await;
@@ -5992,10 +6049,12 @@ async fn test_extra_newline_insertion(cx: &mut gpui::TestAppContext) {
fn test_highlighted_ranges(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- let (_, editor) = cx.add_window(|cx| {
- let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
- build_editor(buffer.clone(), cx)
- });
+ let editor = cx
+ .add_window(|cx| {
+ let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
+ build_editor(buffer.clone(), cx)
+ })
+ .root(cx);
editor.update(cx, |editor, cx| {
struct Type1;
@@ -6084,16 +6143,20 @@ async fn test_following(cx: &mut gpui::TestAppContext) {
.unwrap();
cx.add_model(|cx| MultiBuffer::singleton(buffer, cx))
});
- let (_, leader) = cx.add_window(|cx| build_editor(buffer.clone(), cx));
- let (_, follower) = cx.update(|cx| {
- cx.add_window(
- WindowOptions {
- bounds: WindowBounds::Fixed(RectF::from_points(vec2f(0., 0.), vec2f(10., 80.))),
- ..Default::default()
- },
- |cx| build_editor(buffer.clone(), cx),
- )
- });
+ let leader = cx
+ .add_window(|cx| build_editor(buffer.clone(), cx))
+ .root(cx);
+ let follower = cx
+ .update(|cx| {
+ cx.add_window(
+ WindowOptions {
+ bounds: WindowBounds::Fixed(RectF::from_points(vec2f(0., 0.), vec2f(10., 80.))),
+ ..Default::default()
+ },
+ |cx| build_editor(buffer.clone(), cx),
+ )
+ })
+ .root(cx);
let is_still_following = Rc::new(RefCell::new(true));
let follower_edit_event_count = Rc::new(RefCell::new(0));
@@ -6224,7 +6287,9 @@ async fn test_following_with_multiple_excerpts(cx: &mut gpui::TestAppContext) {
let fs = FakeFs::new(cx.background());
let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
- let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let workspace = cx
+ .add_window(|cx| Workspace::test_new(project.clone(), cx))
+ .root(cx);
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
let leader = pane.update(cx, |_, cx| {
@@ -6968,7 +7033,7 @@ async fn test_copilot_multibuffer(
);
multibuffer
});
- let (_, editor) = cx.add_window(|cx| build_editor(multibuffer, cx));
+ let editor = cx.add_window(|cx| build_editor(multibuffer, cx)).root(cx);
handle_copilot_completion_request(
&copilot_lsp,
@@ -7098,7 +7163,7 @@ async fn test_copilot_disabled_globs(
);
multibuffer
});
- let (_, editor) = cx.add_window(|cx| build_editor(multibuffer, cx));
+ let editor = cx.add_window(|cx| build_editor(multibuffer, cx)).root(cx);
let mut copilot_requests = copilot_lsp
.handle_request::<copilot::request::GetCompletions, _, _>(move |_params, _cx| async move {
@@ -7177,7 +7242,9 @@ async fn test_on_type_formatting_not_triggered(cx: &mut gpui::TestAppContext) {
.await;
let project = Project::test(fs, ["/a".as_ref()], cx).await;
project.update(cx, |project, _| project.languages().add(Arc::new(language)));
- let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let workspace = cx
+ .add_window(|cx| Workspace::test_new(project.clone(), cx))
+ .root(cx);
let worktree_id = workspace.update(cx, |workspace, cx| {
workspace.project().read_with(cx, |project, cx| {
project.worktrees(cx).next().unwrap().read(cx).id()
@@ -3002,10 +3002,12 @@ mod tests {
fn test_layout_line_numbers(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- let (_, editor) = cx.add_window(|cx| {
- let buffer = MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx);
- Editor::new(EditorMode::Full, buffer, None, None, cx)
- });
+ let editor = cx
+ .add_window(|cx| {
+ let buffer = MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx);
+ Editor::new(EditorMode::Full, buffer, None, None, cx)
+ })
+ .root(cx);
let element = EditorElement::new(editor.read_with(cx, |editor, cx| editor.style(cx)));
let layouts = editor.update(cx, |editor, cx| {
@@ -3021,10 +3023,12 @@ mod tests {
fn test_layout_with_placeholder_text_and_blocks(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- let (_, editor) = cx.add_window(|cx| {
- let buffer = MultiBuffer::build_simple("", cx);
- Editor::new(EditorMode::Full, buffer, None, None, cx)
- });
+ let editor = cx
+ .add_window(|cx| {
+ let buffer = MultiBuffer::build_simple("", cx);
+ Editor::new(EditorMode::Full, buffer, None, None, cx)
+ })
+ .root(cx);
editor.update(cx, |editor, cx| {
editor.set_placeholder_text("hello", cx);
@@ -3231,10 +3235,12 @@ mod tests {
info!(
"Creating editor with mode {editor_mode:?}, width {editor_width} and text '{input_text}'"
);
- let (_, editor) = cx.add_window(|cx| {
- let buffer = MultiBuffer::build_simple(&input_text, cx);
- Editor::new(editor_mode, buffer, None, None, cx)
- });
+ let editor = cx
+ .add_window(|cx| {
+ let buffer = MultiBuffer::build_simple(&input_text, cx);
+ Editor::new(editor_mode, buffer, None, None, cx)
+ })
+ .root(cx);
let mut element = EditorElement::new(editor.read_with(cx, |editor, cx| editor.style(cx)));
let (_, layout_state) = editor.update(cx, |editor, cx| {
@@ -1135,7 +1135,9 @@ mod tests {
)
.await;
let project = Project::test(fs, ["/a".as_ref()], cx).await;
- let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let workspace = cx
+ .add_window(|cx| Workspace::test_new(project.clone(), cx))
+ .root(cx);
let worktree_id = workspace.update(cx, |workspace, cx| {
workspace.project().read_with(cx, |project, cx| {
project.worktrees(cx).next().unwrap().read(cx).id()
@@ -1835,7 +1837,9 @@ mod tests {
.await;
let project = Project::test(fs, ["/a".as_ref()], cx).await;
project.update(cx, |project, _| project.languages().add(Arc::new(language)));
- let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let workspace = cx
+ .add_window(|cx| Workspace::test_new(project.clone(), cx))
+ .root(cx);
let worktree_id = workspace.update(cx, |workspace, cx| {
workspace.project().read_with(cx, |project, cx| {
project.worktrees(cx).next().unwrap().read(cx).id()
@@ -1988,7 +1992,9 @@ mod tests {
project.update(cx, |project, _| {
project.languages().add(Arc::clone(&language))
});
- let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let workspace = cx
+ .add_window(|cx| Workspace::test_new(project.clone(), cx))
+ .root(cx);
let worktree_id = workspace.update(cx, |workspace, cx| {
workspace.project().read_with(cx, |project, cx| {
project.worktrees(cx).next().unwrap().read(cx).id()
@@ -2074,8 +2080,9 @@ mod tests {
deterministic.run_until_parked();
cx.foreground().run_until_parked();
- let (_, editor) =
- cx.add_window(|cx| Editor::for_multibuffer(multibuffer, Some(project.clone()), cx));
+ let editor = cx
+ .add_window(|cx| Editor::for_multibuffer(multibuffer, Some(project.clone()), cx))
+ .root(cx);
let editor_edited = Arc::new(AtomicBool::new(false));
let fake_server = fake_servers.next().await.unwrap();
let closure_editor_edited = Arc::clone(&editor_edited);
@@ -2327,7 +2334,9 @@ all hints should be invalidated and requeried for all of its visible excerpts"
project.update(cx, |project, _| {
project.languages().add(Arc::clone(&language))
});
- let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let workspace = cx
+ .add_window(|cx| Workspace::test_new(project.clone(), cx))
+ .root(cx);
let worktree_id = workspace.update(cx, |workspace, cx| {
workspace.project().read_with(cx, |project, cx| {
project.worktrees(cx).next().unwrap().read(cx).id()
@@ -2372,8 +2381,9 @@ all hints should be invalidated and requeried for all of its visible excerpts"
deterministic.run_until_parked();
cx.foreground().run_until_parked();
- let (_, editor) =
- cx.add_window(|cx| Editor::for_multibuffer(multibuffer, Some(project.clone()), cx));
+ let editor = cx
+ .add_window(|cx| Editor::for_multibuffer(multibuffer, Some(project.clone()), cx))
+ .root(cx);
let editor_edited = Arc::new(AtomicBool::new(false));
let fake_server = fake_servers.next().await.unwrap();
let closure_editor_edited = Arc::clone(&editor_edited);
@@ -2561,7 +2571,9 @@ all hints should be invalidated and requeried for all of its visible excerpts"
let project = Project::test(fs, ["/a".as_ref()], cx).await;
project.update(cx, |project, _| project.languages().add(Arc::new(language)));
- let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let workspace = cx
+ .add_window(|cx| Workspace::test_new(project.clone(), cx))
+ .root(cx);
let worktree_id = workspace.update(cx, |workspace, cx| {
workspace.project().read_with(cx, |project, cx| {
project.worktrees(cx).next().unwrap().read(cx).id()
@@ -69,7 +69,8 @@ impl<'a> EditorLspTestContext<'a> {
.insert_tree("/root", json!({ "dir": { file_name.clone(): "" }}))
.await;
- let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let workspace = window.root(cx);
project
.update(cx, |project, cx| {
project.find_or_create_local_worktree("/root", true, cx)
@@ -98,7 +99,7 @@ impl<'a> EditorLspTestContext<'a> {
Self {
cx: EditorTestContext {
cx,
- window_id,
+ window_id: window.window_id(),
editor,
},
lsp,
@@ -32,16 +32,14 @@ impl<'a> EditorTestContext<'a> {
let buffer = project
.update(cx, |project, cx| project.create_buffer("", None, cx))
.unwrap();
- let (window_id, editor) = cx.update(|cx| {
- cx.add_window(Default::default(), |cx| {
- cx.focus_self();
- build_editor(MultiBuffer::build_from_buffer(buffer, cx), cx)
- })
+ let window = cx.add_window(|cx| {
+ cx.focus_self();
+ build_editor(MultiBuffer::build_from_buffer(buffer, cx), cx)
});
-
+ let editor = window.root(cx);
Self {
cx,
- window_id,
+ window_id: window.window_id(),
editor,
}
}
@@ -617,8 +617,9 @@ mod tests {
.await;
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
- let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
- cx.dispatch_action(window_id, Toggle);
+ let window = cx.add_window(|cx| Workspace::test_new(project, cx));
+ let workspace = window.root(cx);
+ cx.dispatch_action(window.window_id(), Toggle);
let finder = cx.read(|cx| workspace.read(cx).modal::<FileFinder>().unwrap());
finder
@@ -631,8 +632,8 @@ mod tests {
});
let active_pane = cx.read(|cx| workspace.read(cx).active_pane().clone());
- cx.dispatch_action(window_id, SelectNext);
- cx.dispatch_action(window_id, Confirm);
+ cx.dispatch_action(window.window_id(), SelectNext);
+ cx.dispatch_action(window.window_id(), Confirm);
active_pane
.condition(cx, |pane, _| pane.active_item().is_some())
.await;
@@ -671,8 +672,9 @@ mod tests {
.await;
let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
- let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
- cx.dispatch_action(window_id, Toggle);
+ let window = cx.add_window(|cx| Workspace::test_new(project, cx));
+ let workspace = window.root(cx);
+ cx.dispatch_action(window.window_id(), Toggle);
let finder = cx.read(|cx| workspace.read(cx).modal::<FileFinder>().unwrap());
let file_query = &first_file_name[..3];
@@ -704,8 +706,8 @@ mod tests {
});
let active_pane = cx.read(|cx| workspace.read(cx).active_pane().clone());
- cx.dispatch_action(window_id, SelectNext);
- cx.dispatch_action(window_id, Confirm);
+ cx.dispatch_action(window.window_id(), SelectNext);
+ cx.dispatch_action(window.window_id(), Confirm);
active_pane
.condition(cx, |pane, _| pane.active_item().is_some())
.await;
@@ -754,8 +756,9 @@ mod tests {
.await;
let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
- let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
- cx.dispatch_action(window_id, Toggle);
+ let window = cx.add_window(|cx| Workspace::test_new(project, cx));
+ let workspace = window.root(cx);
+ cx.dispatch_action(window.window_id(), Toggle);
let finder = cx.read(|cx| workspace.read(cx).modal::<FileFinder>().unwrap());
let file_query = &first_file_name[..3];
@@ -787,8 +790,8 @@ mod tests {
});
let active_pane = cx.read(|cx| workspace.read(cx).active_pane().clone());
- cx.dispatch_action(window_id, SelectNext);
- cx.dispatch_action(window_id, Confirm);
+ cx.dispatch_action(window.window_id(), SelectNext);
+ cx.dispatch_action(window.window_id(), Confirm);
active_pane
.condition(cx, |pane, _| pane.active_item().is_some())
.await;
@@ -837,19 +840,23 @@ mod tests {
.await;
let project = Project::test(app_state.fs.clone(), ["/dir".as_ref()], cx).await;
- let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
- let (_, finder) = cx.add_window(|cx| {
- Picker::new(
- FileFinderDelegate::new(
- workspace.downgrade(),
- workspace.read(cx).project().clone(),
- None,
- Vec::new(),
+ let workspace = cx
+ .add_window(|cx| Workspace::test_new(project, cx))
+ .root(cx);
+ let finder = cx
+ .add_window(|cx| {
+ Picker::new(
+ FileFinderDelegate::new(
+ workspace.downgrade(),
+ workspace.read(cx).project().clone(),
+ None,
+ Vec::new(),
+ cx,
+ ),
cx,
- ),
- cx,
- )
- });
+ )
+ })
+ .root(cx);
let query = test_path_like("hi");
finder
@@ -931,19 +938,23 @@ mod tests {
cx,
)
.await;
- let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
- let (_, finder) = cx.add_window(|cx| {
- Picker::new(
- FileFinderDelegate::new(
- workspace.downgrade(),
- workspace.read(cx).project().clone(),
- None,
- Vec::new(),
+ let workspace = cx
+ .add_window(|cx| Workspace::test_new(project, cx))
+ .root(cx);
+ let finder = cx
+ .add_window(|cx| {
+ Picker::new(
+ FileFinderDelegate::new(
+ workspace.downgrade(),
+ workspace.read(cx).project().clone(),
+ None,
+ Vec::new(),
+ cx,
+ ),
cx,
- ),
- cx,
- )
- });
+ )
+ })
+ .root(cx);
finder
.update(cx, |f, cx| {
f.delegate_mut().spawn_search(test_path_like("hi"), cx)
@@ -967,19 +978,23 @@ mod tests {
cx,
)
.await;
- let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
- let (_, finder) = cx.add_window(|cx| {
- Picker::new(
- FileFinderDelegate::new(
- workspace.downgrade(),
- workspace.read(cx).project().clone(),
- None,
- Vec::new(),
+ let workspace = cx
+ .add_window(|cx| Workspace::test_new(project, cx))
+ .root(cx);
+ let finder = cx
+ .add_window(|cx| {
+ Picker::new(
+ FileFinderDelegate::new(
+ workspace.downgrade(),
+ workspace.read(cx).project().clone(),
+ None,
+ Vec::new(),
+ cx,
+ ),
cx,
- ),
- cx,
- )
- });
+ )
+ })
+ .root(cx);
// Even though there is only one worktree, that worktree's filename
// is included in the matching, because the worktree is a single file.
@@ -1015,61 +1030,6 @@ mod tests {
finder.read_with(cx, |f, _| assert_eq!(f.delegate().matches.len(), 0));
}
- #[gpui::test]
- async fn test_multiple_matches_with_same_relative_path(cx: &mut TestAppContext) {
- let app_state = init_test(cx);
- app_state
- .fs
- .as_fake()
- .insert_tree(
- "/root",
- json!({
- "dir1": { "a.txt": "" },
- "dir2": { "a.txt": "" }
- }),
- )
- .await;
-
- let project = Project::test(
- app_state.fs.clone(),
- ["/root/dir1".as_ref(), "/root/dir2".as_ref()],
- cx,
- )
- .await;
- let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
-
- let (_, finder) = cx.add_window(|cx| {
- Picker::new(
- FileFinderDelegate::new(
- workspace.downgrade(),
- workspace.read(cx).project().clone(),
- None,
- Vec::new(),
- cx,
- ),
- cx,
- )
- });
-
- // Run a search that matches two files with the same relative path.
- finder
- .update(cx, |f, cx| {
- f.delegate_mut().spawn_search(test_path_like("a.t"), cx)
- })
- .await;
-
- // Can switch between different matches with the same relative path.
- finder.update(cx, |finder, cx| {
- let delegate = finder.delegate_mut();
- assert_eq!(delegate.matches.len(), 2);
- assert_eq!(delegate.selected_index(), 0);
- delegate.set_selected_index(1, cx);
- assert_eq!(delegate.selected_index(), 1);
- delegate.set_selected_index(0, cx);
- assert_eq!(delegate.selected_index(), 0);
- });
- }
-
#[gpui::test]
async fn test_path_distance_ordering(cx: &mut TestAppContext) {
let app_state = init_test(cx);
@@ -1089,7 +1049,9 @@ 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));
+ let workspace = cx
+ .add_window(|cx| Workspace::test_new(project, cx))
+ .root(cx);
let worktree_id = cx.read(|cx| {
let worktrees = workspace.read(cx).worktrees(cx).collect::<Vec<_>>();
assert_eq!(worktrees.len(), 1);
@@ -1103,18 +1065,20 @@ mod tests {
worktree_id,
path: Arc::from(Path::new("/root/dir2/b.txt")),
}));
- let (_, finder) = cx.add_window(|cx| {
- Picker::new(
- FileFinderDelegate::new(
- workspace.downgrade(),
- workspace.read(cx).project().clone(),
- b_path,
- Vec::new(),
+ let finder = cx
+ .add_window(|cx| {
+ Picker::new(
+ FileFinderDelegate::new(
+ workspace.downgrade(),
+ workspace.read(cx).project().clone(),
+ b_path,
+ Vec::new(),
+ cx,
+ ),
cx,
- ),
- cx,
- )
- });
+ )
+ })
+ .root(cx);
finder
.update(cx, |f, cx| {
@@ -1151,19 +1115,23 @@ 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));
- let (_, finder) = cx.add_window(|cx| {
- Picker::new(
- FileFinderDelegate::new(
- workspace.downgrade(),
- workspace.read(cx).project().clone(),
- None,
- Vec::new(),
+ let workspace = cx
+ .add_window(|cx| Workspace::test_new(project, cx))
+ .root(cx);
+ let finder = cx
+ .add_window(|cx| {
+ Picker::new(
+ FileFinderDelegate::new(
+ workspace.downgrade(),
+ workspace.read(cx).project().clone(),
+ None,
+ Vec::new(),
+ cx,
+ ),
cx,
- ),
- cx,
- )
- });
+ )
+ })
+ .root(cx);
finder
.update(cx, |f, cx| {
f.delegate_mut().spawn_search(test_path_like("dir"), cx)
@@ -1198,7 +1166,9 @@ mod tests {
.await;
let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
- let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project, cx));
+ let workspace = window.root(cx);
+ let window_id = window.window_id();
let worktree_id = cx.read(|cx| {
let worktrees = workspace.read(cx).worktrees(cx).collect::<Vec<_>>();
assert_eq!(worktrees.len(), 1);
@@ -1404,7 +1374,9 @@ mod tests {
.detach();
deterministic.run_until_parked();
- let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project, cx));
+ let workspace = window.root(cx);
+ let window_id = window.window_id();
let worktree_id = cx.read(|cx| {
let worktrees = workspace.read(cx).worktrees(cx).collect::<Vec<_>>();
assert_eq!(worktrees.len(), 1,);
@@ -130,8 +130,14 @@ pub trait BorrowAppContext {
}
pub trait BorrowWindowContext {
- fn read_with<T, F: FnOnce(&WindowContext) -> T>(&self, window_id: usize, f: F) -> T;
- fn update<T, F: FnOnce(&mut WindowContext) -> T>(&mut self, window_id: usize, f: F) -> T;
+ type Result<T>;
+
+ fn read_window_with<T, F>(&self, window_id: usize, f: F) -> Self::Result<T>
+ where
+ F: FnOnce(&WindowContext) -> T;
+ fn update_window<T, F>(&mut self, window_id: usize, f: F) -> Self::Result<T>
+ where
+ F: FnOnce(&mut WindowContext) -> T;
}
#[derive(Clone)]
@@ -402,7 +408,7 @@ impl AsyncAppContext {
&mut self,
window_options: WindowOptions,
build_root_view: F,
- ) -> (usize, ViewHandle<T>)
+ ) -> WindowHandle<T>
where
T: View,
F: FnOnce(&mut ViewContext<T>) -> T,
@@ -452,6 +458,26 @@ impl BorrowAppContext for AsyncAppContext {
}
}
+impl BorrowWindowContext for AsyncAppContext {
+ type Result<T> = Option<T>;
+
+ fn read_window_with<T, F>(&self, window_id: usize, f: F) -> Self::Result<T>
+ where
+ F: FnOnce(&WindowContext) -> T,
+ {
+ self.0.borrow().read_with(|cx| cx.read_window(window_id, f))
+ }
+
+ fn update_window<T, F>(&mut self, window_id: usize, f: F) -> Self::Result<T>
+ where
+ F: FnOnce(&mut WindowContext) -> T,
+ {
+ self.0
+ .borrow_mut()
+ .update(|cx| cx.update_window(window_id, f))
+ }
+}
+
type ActionCallback = dyn FnMut(&mut dyn AnyView, &dyn Action, &mut WindowContext, usize);
type GlobalActionCallback = dyn FnMut(&dyn Action, &mut AppContext);
@@ -494,8 +520,8 @@ pub struct AppContext {
// Action Types -> Action Handlers
global_actions: HashMap<TypeId, Box<GlobalActionCallback>>,
keystroke_matcher: KeymapMatcher,
- next_entity_id: usize,
- next_window_id: usize,
+ next_id: usize,
+ // next_window_id: usize,
next_subscription_id: usize,
frame_count: usize,
@@ -554,8 +580,7 @@ impl AppContext {
actions: Default::default(),
global_actions: Default::default(),
keystroke_matcher: KeymapMatcher::default(),
- next_entity_id: 0,
- next_window_id: 0,
+ next_id: 0,
next_subscription_id: 0,
frame_count: 0,
subscriptions: Default::default(),
@@ -783,7 +808,7 @@ impl AppContext {
result
}
- pub fn read_window<T, F: FnOnce(&WindowContext) -> T>(
+ fn read_window<T, F: FnOnce(&WindowContext) -> T>(
&self,
window_id: usize,
callback: F,
@@ -1226,7 +1251,7 @@ impl AppContext {
F: FnOnce(&mut ModelContext<T>) -> T,
{
self.update(|this| {
- let model_id = post_inc(&mut this.next_entity_id);
+ let model_id = post_inc(&mut this.next_id);
let handle = ModelHandle::new(model_id, &this.ref_counts);
let mut cx = ModelContext::new(this, model_id);
let model = build_model(&mut cx);
@@ -1300,20 +1325,19 @@ impl AppContext {
&mut self,
window_options: WindowOptions,
build_root_view: F,
- ) -> (usize, ViewHandle<V>)
+ ) -> WindowHandle<V>
where
V: View,
F: FnOnce(&mut ViewContext<V>) -> V,
{
self.update(|this| {
- let window_id = post_inc(&mut this.next_window_id);
+ let window_id = 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);
- let root_view = window.root_view().clone().downcast::<V>().unwrap();
this.windows.insert(window_id, window);
- (window_id, root_view)
+ WindowHandle::new(window_id)
})
}
@@ -1323,7 +1347,7 @@ impl AppContext {
F: FnOnce(&mut ViewContext<V>) -> V,
{
self.update(|this| {
- let window_id = post_inc(&mut this.next_window_id);
+ 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::<V>().unwrap();
@@ -1422,7 +1446,7 @@ impl AppContext {
&mut self,
window_id: usize,
build_root_view: F,
- ) -> Option<ViewHandle<V>>
+ ) -> Option<WindowHandle<V>>
where
V: View,
F: FnOnce(&mut ViewContext<V>) -> V,
@@ -2158,6 +2182,24 @@ impl BorrowAppContext for AppContext {
}
}
+impl BorrowWindowContext for AppContext {
+ type Result<T> = Option<T>;
+
+ fn read_window_with<T, F>(&self, window_id: usize, f: F) -> Self::Result<T>
+ where
+ F: FnOnce(&WindowContext) -> T,
+ {
+ AppContext::read_window(self, window_id, f)
+ }
+
+ fn update_window<T, F>(&mut self, window_id: usize, f: F) -> Self::Result<T>
+ where
+ F: FnOnce(&mut WindowContext) -> T,
+ {
+ AppContext::update_window(self, window_id, f)
+ }
+}
+
#[derive(Debug)]
pub enum ParentId {
View(usize),
@@ -3356,12 +3398,18 @@ impl<V> BorrowAppContext for ViewContext<'_, '_, V> {
}
impl<V> BorrowWindowContext for ViewContext<'_, '_, V> {
- fn read_with<T, F: FnOnce(&WindowContext) -> T>(&self, window_id: usize, f: F) -> T {
- BorrowWindowContext::read_with(&*self.window_context, window_id, f)
+ type Result<T> = T;
+
+ fn read_window_with<T, F: FnOnce(&WindowContext) -> T>(&self, window_id: usize, f: F) -> T {
+ BorrowWindowContext::read_window_with(&*self.window_context, window_id, f)
}
- fn update<T, F: FnOnce(&mut WindowContext) -> T>(&mut self, window_id: usize, f: F) -> T {
- BorrowWindowContext::update(&mut *self.window_context, window_id, f)
+ fn update_window<T, F: FnOnce(&mut WindowContext) -> T>(
+ &mut self,
+ window_id: usize,
+ f: F,
+ ) -> T {
+ BorrowWindowContext::update_window(&mut *self.window_context, window_id, f)
}
}
@@ -3461,12 +3509,18 @@ impl<V: View> BorrowAppContext for LayoutContext<'_, '_, '_, V> {
}
impl<V: View> BorrowWindowContext for LayoutContext<'_, '_, '_, V> {
- fn read_with<T, F: FnOnce(&WindowContext) -> T>(&self, window_id: usize, f: F) -> T {
- BorrowWindowContext::read_with(&*self.view_context, window_id, f)
+ type Result<T> = T;
+
+ fn read_window_with<T, F: FnOnce(&WindowContext) -> T>(&self, window_id: usize, f: F) -> T {
+ BorrowWindowContext::read_window_with(&*self.view_context, window_id, f)
}
- fn update<T, F: FnOnce(&mut WindowContext) -> T>(&mut self, window_id: usize, f: F) -> T {
- BorrowWindowContext::update(&mut *self.view_context, window_id, f)
+ fn update_window<T, F: FnOnce(&mut WindowContext) -> T>(
+ &mut self,
+ window_id: usize,
+ f: F,
+ ) -> T {
+ BorrowWindowContext::update_window(&mut *self.view_context, window_id, f)
}
}
@@ -3513,12 +3567,18 @@ impl<V: View> BorrowAppContext for EventContext<'_, '_, '_, V> {
}
impl<V: View> BorrowWindowContext for EventContext<'_, '_, '_, V> {
- fn read_with<T, F: FnOnce(&WindowContext) -> T>(&self, window_id: usize, f: F) -> T {
- BorrowWindowContext::read_with(&*self.view_context, window_id, f)
+ type Result<T> = T;
+
+ fn read_window_with<T, F: FnOnce(&WindowContext) -> T>(&self, window_id: usize, f: F) -> T {
+ BorrowWindowContext::read_window_with(&*self.view_context, window_id, f)
}
- fn update<T, F: FnOnce(&mut WindowContext) -> T>(&mut self, window_id: usize, f: F) -> T {
- BorrowWindowContext::update(&mut *self.view_context, window_id, f)
+ fn update_window<T, F: FnOnce(&mut WindowContext) -> T>(
+ &mut self,
+ window_id: usize,
+ f: F,
+ ) -> T {
+ BorrowWindowContext::update_window(&mut *self.view_context, window_id, f)
}
}
@@ -3802,6 +3862,89 @@ impl<T> Clone for WeakModelHandle<T> {
impl<T> Copy for WeakModelHandle<T> {}
+pub struct WindowHandle<T> {
+ window_id: usize,
+ root_view_type: PhantomData<T>,
+}
+
+#[allow(dead_code)]
+impl<V: View> WindowHandle<V> {
+ fn new(window_id: usize) -> Self {
+ WindowHandle {
+ window_id,
+ root_view_type: PhantomData,
+ }
+ }
+
+ pub fn window_id(&self) -> usize {
+ self.window_id
+ }
+
+ pub fn root<C: BorrowWindowContext>(&self, cx: &C) -> C::Result<ViewHandle<V>> {
+ self.read_with(cx, |cx| cx.root_view().clone().downcast().unwrap())
+ }
+
+ pub fn read_with<C, F, R>(&self, cx: &C, read: F) -> C::Result<R>
+ where
+ C: BorrowWindowContext,
+ F: FnOnce(&WindowContext) -> R,
+ {
+ cx.read_window_with(self.window_id(), |cx| read(cx))
+ }
+
+ pub fn update<C, F, R>(&self, cx: &mut C, update: F) -> C::Result<R>
+ where
+ C: BorrowWindowContext,
+ F: FnOnce(&mut WindowContext) -> R,
+ {
+ cx.update_window(self.window_id(), update)
+ }
+
+ // pub fn update_root<C, F, R>(&self, cx: &mut C, update: F) -> C::Result<Option<R>>
+ // where
+ // C: BorrowWindowContext,
+ // F: FnOnce(&mut V, &mut ViewContext<V>) -> R,
+ // {
+ // cx.update_window(self.window_id, |cx| {
+ // cx.root_view()
+ // .clone()
+ // .downcast::<V>()
+ // .map(|v| v.update(cx, update))
+ // })
+ // }
+
+ pub fn read_root<'a>(&self, cx: &'a AppContext) -> &'a V {
+ let root_view = cx
+ .read_window(self.window_id(), |cx| {
+ cx.root_view().clone().downcast().unwrap()
+ })
+ .unwrap();
+ root_view.read(cx)
+ }
+
+ pub fn read_root_with<C, F, R>(&self, cx: &C, read: F) -> C::Result<R>
+ where
+ C: BorrowWindowContext,
+ F: FnOnce(&V, &ViewContext<V>) -> R,
+ {
+ self.read_with(cx, |cx| {
+ cx.root_view()
+ .downcast_ref::<V>()
+ .unwrap()
+ .read_with(cx, read)
+ })
+ }
+
+ pub fn add_view<C, U, F>(&self, cx: &mut C, build_view: F) -> C::Result<ViewHandle<U>>
+ where
+ C: BorrowWindowContext,
+ U: View,
+ F: FnOnce(&mut ViewContext<U>) -> U,
+ {
+ self.update(cx, |cx| cx.add_view(build_view))
+ }
+}
+
#[repr(transparent)]
pub struct ViewHandle<T> {
any_handle: AnyViewHandle,
@@ -3849,25 +3992,25 @@ impl<T: View> ViewHandle<T> {
cx.read_view(self)
}
- pub fn read_with<C, F, S>(&self, cx: &C, read: F) -> S
+ pub fn read_with<C, F, S>(&self, cx: &C, read: F) -> C::Result<S>
where
C: BorrowWindowContext,
F: FnOnce(&T, &ViewContext<T>) -> S,
{
- cx.read_with(self.window_id, |cx| {
+ cx.read_window_with(self.window_id, |cx| {
let cx = ViewContext::immutable(cx, self.view_id);
read(cx.read_view(self), &cx)
})
}
- pub fn update<C, F, S>(&self, cx: &mut C, update: F) -> S
+ pub fn update<C, F, S>(&self, cx: &mut C, update: F) -> C::Result<S>
where
C: BorrowWindowContext,
F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
{
let mut update = Some(update);
- cx.update(self.window_id, |cx| {
+ cx.update_window(self.window_id, |cx| {
cx.update_view(self, &mut |view, cx| {
let update = update.take().unwrap();
update(view, cx)
@@ -4684,11 +4827,11 @@ mod tests {
}
}
- let (_, view) = cx.add_window(|_| View { render_count: 0 });
+ let window = cx.add_window(|_| View { render_count: 0 });
let called_defer = Rc::new(AtomicBool::new(false));
let called_after_window_update = Rc::new(AtomicBool::new(false));
- view.update(cx, |this, cx| {
+ window.root(cx).update(cx, |this, cx| {
assert_eq!(this.render_count, 1);
cx.defer({
let called_defer = called_defer.clone();
@@ -4712,7 +4855,7 @@ mod tests {
assert!(called_defer.load(SeqCst));
assert!(called_after_window_update.load(SeqCst));
- assert_eq!(view.read_with(cx, |view, _| view.render_count), 3);
+ assert_eq!(window.read_root_with(cx, |view, _| view.render_count), 3);
}
#[crate::test(self)]
@@ -4751,9 +4894,9 @@ mod tests {
}
}
- let (window_id, _root_view) = cx.add_window(|cx| View::new(None, cx));
- let handle_1 = cx.add_view(window_id, |cx| View::new(None, cx));
- let handle_2 = cx.add_view(window_id, |cx| View::new(Some(handle_1.clone()), cx));
+ let window = cx.add_window(|cx| View::new(None, cx));
+ let handle_1 = window.add_view(cx, |cx| View::new(None, cx));
+ let handle_2 = window.add_view(cx, |cx| View::new(Some(handle_1.clone()), cx));
assert_eq!(cx.read(|cx| cx.views.len()), 3);
handle_1.update(cx, |view, cx| {
@@ -4813,11 +4956,11 @@ mod tests {
}
let mouse_down_count = Arc::new(AtomicUsize::new(0));
- let (window_id, _) = cx.add_window(Default::default(), |_| View {
+ let window = cx.add_window(Default::default(), |_| View {
mouse_down_count: mouse_down_count.clone(),
});
- cx.update_window(window_id, |cx| {
+ window.update(cx, |cx| {
// Ensure window's root element is in a valid lifecycle state.
cx.dispatch_event(
Event::MouseDown(MouseButtonEvent {
@@ -4833,7 +4976,7 @@ mod tests {
}
#[crate::test(self)]
- fn test_entity_release_hooks(cx: &mut AppContext) {
+ fn test_entity_release_hooks(cx: &mut TestAppContext) {
struct Model {
released: Rc<Cell<bool>>,
}
@@ -4876,22 +5019,26 @@ mod tests {
let model = cx.add_model(|_| Model {
released: model_released.clone(),
});
- let (window_id, view) = cx.add_window(Default::default(), |_| View {
+ let window = cx.add_window(|_| View {
released: view_released.clone(),
});
+ let view = window.root(cx);
+
assert!(!model_released.get());
assert!(!view_released.get());
- cx.observe_release(&model, {
- let model_release_observed = model_release_observed.clone();
- move |_, _| model_release_observed.set(true)
- })
- .detach();
- cx.observe_release(&view, {
- let view_release_observed = view_release_observed.clone();
- move |_, _| view_release_observed.set(true)
- })
- .detach();
+ cx.update(|cx| {
+ cx.observe_release(&model, {
+ let model_release_observed = model_release_observed.clone();
+ move |_, _| model_release_observed.set(true)
+ })
+ .detach();
+ cx.observe_release(&view, {
+ let view_release_observed = view_release_observed.clone();
+ move |_, _| view_release_observed.set(true)
+ })
+ .detach();
+ });
cx.update(move |_| {
drop(model);
@@ -4900,7 +5047,7 @@ mod tests {
assert!(model_release_observed.get());
drop(view);
- cx.update_window(window_id, |cx| cx.remove_window());
+ window.update(cx, |cx| cx.remove_window());
assert!(view_released.get());
assert!(view_release_observed.get());
}
@@ -4913,8 +5060,9 @@ mod tests {
type Event = String;
}
- let (window_id, handle_1) = cx.add_window(|_| TestView::default());
- let handle_2 = cx.add_view(window_id, |_| TestView::default());
+ let window = cx.add_window(|_| TestView::default());
+ let handle_1 = window.root(cx);
+ let handle_2 = window.add_view(cx, |_| TestView::default());
let handle_3 = cx.add_model(|_| Model);
handle_1.update(cx, |_, cx| {
@@ -5140,9 +5288,9 @@ mod tests {
type Event = ();
}
- let (window_id, _root_view) = cx.add_window(|_| TestView::default());
- let observing_view = cx.add_view(window_id, |_| TestView::default());
- let emitting_view = cx.add_view(window_id, |_| TestView::default());
+ let window = cx.add_window(|_| TestView::default());
+ let observing_view = window.add_view(cx, |_| TestView::default());
+ let emitting_view = window.add_view(cx, |_| TestView::default());
let observing_model = cx.add_model(|_| Model);
let observed_model = cx.add_model(|_| Model);
@@ -5165,7 +5313,7 @@ mod tests {
#[crate::test(self)]
fn test_view_emit_before_subscribe_in_same_update_cycle(cx: &mut AppContext) {
- let (_, view) = cx.add_window::<TestView, _>(Default::default(), |cx| {
+ let window = cx.add_window::<TestView, _>(Default::default(), |cx| {
drop(cx.subscribe(&cx.handle(), {
move |this, _, _, _| this.events.push("dropped before flush".into())
}));
@@ -5181,7 +5329,7 @@ mod tests {
TestView { events: Vec::new() }
});
- assert_eq!(view.read(cx).events, ["before emit"]);
+ assert_eq!(window.read_root(cx).events, ["before emit"]);
}
#[crate::test(self)]
@@ -5195,7 +5343,8 @@ mod tests {
type Event = ();
}
- let (_, view) = cx.add_window(|_| TestView::default());
+ let window = cx.add_window(|_| TestView::default());
+ let view = window.root(cx);
let model = cx.add_model(|_| Model {
state: "old-state".into(),
});
@@ -5216,7 +5365,7 @@ mod tests {
#[crate::test(self)]
fn test_view_notify_before_observe_in_same_update_cycle(cx: &mut AppContext) {
- let (_, view) = cx.add_window::<TestView, _>(Default::default(), |cx| {
+ let window = cx.add_window::<TestView, _>(Default::default(), |cx| {
drop(cx.observe(&cx.handle(), {
move |this, _, _| this.events.push("dropped before flush".into())
}));
@@ -5232,7 +5381,7 @@ mod tests {
TestView { events: Vec::new() }
});
- assert_eq!(view.read(cx).events, ["before notify"]);
+ assert_eq!(window.read_root(cx).events, ["before notify"]);
}
#[crate::test(self)]
@@ -5243,7 +5392,8 @@ mod tests {
}
let model = cx.add_model(|_| Model);
- let (_, view) = cx.add_window(|_| TestView::default());
+ let window = cx.add_window(|_| TestView::default());
+ let view = window.root(cx);
view.update(cx, |_, cx| {
model.update(cx, |_, cx| cx.notify());
@@ -5267,8 +5417,8 @@ mod tests {
type Event = ();
}
- let (window_id, _root_view) = cx.add_window(|_| TestView::default());
- let observing_view = cx.add_view(window_id, |_| TestView::default());
+ let window = cx.add_window(|_| TestView::default());
+ let observing_view = window.add_view(cx, |_| TestView::default());
let observing_model = cx.add_model(|_| Model);
let observed_model = cx.add_model(|_| Model);
@@ -5390,9 +5540,9 @@ mod tests {
}
}
- let (window_id, _root_view) = cx.add_window(|_| View);
- let observing_view = cx.add_view(window_id, |_| View);
- let observed_view = cx.add_view(window_id, |_| View);
+ let window = cx.add_window(|_| View);
+ let observing_view = window.add_view(cx, |_| View);
+ let observed_view = window.add_view(cx, |_| View);
let observation_count = Rc::new(RefCell::new(0));
observing_view.update(cx, |_, cx| {
@@ -5474,25 +5624,24 @@ mod tests {
}
let view_events: Arc<Mutex<Vec<String>>> = Default::default();
- let (window_id, view_1) = cx.add_window(|_| View {
+ let window = cx.add_window(|_| View {
events: view_events.clone(),
name: "view 1".to_string(),
child: None,
});
- let view_2 = cx
- .update_window(window_id, |cx| {
- let view_2 = cx.add_view(|_| View {
- events: view_events.clone(),
- name: "view 2".to_string(),
- child: None,
- });
- view_1.update(cx, |view_1, cx| {
- view_1.child = Some(view_2.clone().into_any());
- cx.notify();
- });
- view_2
- })
- .unwrap();
+ let view_1 = window.root(cx);
+ let view_2 = window.update(cx, |cx| {
+ let view_2 = cx.add_view(|_| View {
+ events: view_events.clone(),
+ name: "view 2".to_string(),
+ child: None,
+ });
+ view_1.update(cx, |view_1, cx| {
+ view_1.child = Some(view_2.clone().into_any());
+ cx.notify();
+ });
+ view_2
+ });
let observed_events: Arc<Mutex<Vec<String>>> = Default::default();
view_1.update(cx, |_, cx| {
@@ -5619,7 +5768,7 @@ mod tests {
}
#[crate::test(self)]
- fn test_dispatch_action(cx: &mut AppContext) {
+ fn test_dispatch_action(cx: &mut TestAppContext) {
struct ViewA {
id: usize,
child: Option<AnyViewHandle>,
@@ -5670,101 +5819,97 @@ mod tests {
impl_actions!(test, [Action]);
let actions = Rc::new(RefCell::new(Vec::new()));
+ let observed_actions = Rc::new(RefCell::new(Vec::new()));
- cx.add_global_action({
- let actions = actions.clone();
- move |_: &Action, _: &mut AppContext| {
- actions.borrow_mut().push("global".to_string());
- }
- });
-
- cx.add_action({
- let actions = actions.clone();
- move |view: &mut ViewA, action: &Action, cx| {
- assert_eq!(action.0, "bar");
- cx.propagate_action();
- actions.borrow_mut().push(format!("{} a", view.id));
- }
- });
+ cx.update(|cx| {
+ cx.add_global_action({
+ let actions = actions.clone();
+ move |_: &Action, _: &mut AppContext| {
+ actions.borrow_mut().push("global".to_string());
+ }
+ });
- cx.add_action({
- let actions = actions.clone();
- move |view: &mut ViewA, _: &Action, cx| {
- if view.id != 1 {
- cx.add_view(|cx| {
- cx.propagate_action(); // Still works on a nested ViewContext
- ViewB { id: 5, child: None }
- });
+ cx.add_action({
+ let actions = actions.clone();
+ move |view: &mut ViewA, action: &Action, cx| {
+ assert_eq!(action.0, "bar");
+ cx.propagate_action();
+ actions.borrow_mut().push(format!("{} a", view.id));
}
- actions.borrow_mut().push(format!("{} b", view.id));
- }
- });
+ });
- cx.add_action({
- let actions = actions.clone();
- move |view: &mut ViewB, _: &Action, cx| {
- cx.propagate_action();
- actions.borrow_mut().push(format!("{} c", view.id));
- }
- });
+ cx.add_action({
+ let actions = actions.clone();
+ move |view: &mut ViewA, _: &Action, cx| {
+ if view.id != 1 {
+ cx.add_view(|cx| {
+ cx.propagate_action(); // Still works on a nested ViewContext
+ ViewB { id: 5, child: None }
+ });
+ }
+ actions.borrow_mut().push(format!("{} b", view.id));
+ }
+ });
- cx.add_action({
- let actions = actions.clone();
- move |view: &mut ViewB, _: &Action, cx| {
- cx.propagate_action();
- actions.borrow_mut().push(format!("{} d", view.id));
- }
- });
+ cx.add_action({
+ let actions = actions.clone();
+ move |view: &mut ViewB, _: &Action, cx| {
+ cx.propagate_action();
+ actions.borrow_mut().push(format!("{} c", view.id));
+ }
+ });
- cx.capture_action({
- let actions = actions.clone();
- move |view: &mut ViewA, _: &Action, cx| {
- cx.propagate_action();
- actions.borrow_mut().push(format!("{} capture", view.id));
- }
- });
+ cx.add_action({
+ let actions = actions.clone();
+ move |view: &mut ViewB, _: &Action, cx| {
+ cx.propagate_action();
+ actions.borrow_mut().push(format!("{} d", view.id));
+ }
+ });
- let observed_actions = Rc::new(RefCell::new(Vec::new()));
- cx.observe_actions({
- let observed_actions = observed_actions.clone();
- move |action_id, _| observed_actions.borrow_mut().push(action_id)
- })
- .detach();
+ cx.capture_action({
+ let actions = actions.clone();
+ move |view: &mut ViewA, _: &Action, cx| {
+ cx.propagate_action();
+ actions.borrow_mut().push(format!("{} capture", view.id));
+ }
+ });
- let (window_id, view_1) =
- cx.add_window(Default::default(), |_| ViewA { id: 1, child: None });
- let view_2 = cx
- .update_window(window_id, |cx| {
- let child = cx.add_view(|_| ViewB { id: 2, child: None });
- view_1.update(cx, |view, cx| {
- view.child = Some(child.clone().into_any());
- cx.notify();
- });
- child
- })
- .unwrap();
- let view_3 = cx
- .update_window(window_id, |cx| {
- let child = cx.add_view(|_| ViewA { id: 3, child: None });
- view_2.update(cx, |view, cx| {
- view.child = Some(child.clone().into_any());
- cx.notify();
- });
- child
+ cx.observe_actions({
+ let observed_actions = observed_actions.clone();
+ move |action_id, _| observed_actions.borrow_mut().push(action_id)
})
- .unwrap();
- let view_4 = cx
- .update_window(window_id, |cx| {
- let child = cx.add_view(|_| ViewB { id: 4, child: None });
- view_3.update(cx, |view, cx| {
- view.child = Some(child.clone().into_any());
- cx.notify();
- });
- child
- })
- .unwrap();
+ .detach();
+ });
- cx.update_window(window_id, |cx| {
+ let window = cx.add_window(|_| ViewA { id: 1, child: None });
+ let view_1 = window.root(cx);
+ let view_2 = window.update(cx, |cx| {
+ let child = cx.add_view(|_| ViewB { id: 2, child: None });
+ view_1.update(cx, |view, cx| {
+ view.child = Some(child.clone().into_any());
+ cx.notify();
+ });
+ child
+ });
+ let view_3 = window.update(cx, |cx| {
+ let child = cx.add_view(|_| ViewA { id: 3, child: None });
+ view_2.update(cx, |view, cx| {
+ view.child = Some(child.clone().into_any());
+ cx.notify();
+ });
+ child
+ });
+ let view_4 = window.update(cx, |cx| {
+ let child = cx.add_view(|_| ViewB { id: 4, child: None });
+ view_3.update(cx, |view, cx| {
+ view.child = Some(child.clone().into_any());
+ cx.notify();
+ });
+ child
+ });
+
+ window.update(cx, |cx| {
cx.dispatch_action(Some(view_4.id()), &Action("bar".to_string()))
});
@@ -5786,31 +5931,27 @@ mod tests {
// Remove view_1, which doesn't propagate the action
- let (window_id, view_2) =
- cx.add_window(Default::default(), |_| ViewB { id: 2, child: None });
- let view_3 = cx
- .update_window(window_id, |cx| {
- let child = cx.add_view(|_| ViewA { id: 3, child: None });
- view_2.update(cx, |view, cx| {
- view.child = Some(child.clone().into_any());
- cx.notify();
- });
- child
- })
- .unwrap();
- let view_4 = cx
- .update_window(window_id, |cx| {
- let child = cx.add_view(|_| ViewB { id: 4, child: None });
- view_3.update(cx, |view, cx| {
- view.child = Some(child.clone().into_any());
- cx.notify();
- });
- child
- })
- .unwrap();
+ let window = cx.add_window(|_| ViewB { id: 2, child: None });
+ let view_2 = window.root(cx);
+ let view_3 = window.update(cx, |cx| {
+ let child = cx.add_view(|_| ViewA { id: 3, child: None });
+ view_2.update(cx, |view, cx| {
+ view.child = Some(child.clone().into_any());
+ cx.notify();
+ });
+ child
+ });
+ let view_4 = window.update(cx, |cx| {
+ let child = cx.add_view(|_| ViewB { id: 4, child: None });
+ view_3.update(cx, |view, cx| {
+ view.child = Some(child.clone().into_any());
+ cx.notify();
+ });
+ child
+ });
actions.borrow_mut().clear();
- cx.update_window(window_id, |cx| {
+ window.update(cx, |cx| {
cx.dispatch_action(Some(view_4.id()), &Action("bar".to_string()))
});
@@ -5887,7 +6028,7 @@ mod tests {
view_3.keymap_context.add_identifier("b");
view_3.keymap_context.add_identifier("c");
- let (window_id, _view_1) = cx.add_window(Default::default(), |cx| {
+ let window = cx.add_window(Default::default(), |cx| {
let view_2 = cx.add_view(|cx| {
let view_3 = cx.add_view(|cx| {
cx.focus_self();
@@ -5947,26 +6088,26 @@ mod tests {
}
});
- cx.update_window(window_id, |cx| {
+ window.update(cx, |cx| {
cx.dispatch_keystroke(&Keystroke::parse("a").unwrap())
});
assert_eq!(&*actions.borrow(), &["2 a"]);
actions.borrow_mut().clear();
- cx.update_window(window_id, |cx| {
+ window.update(cx, |cx| {
cx.dispatch_keystroke(&Keystroke::parse("b").unwrap());
});
assert_eq!(&*actions.borrow(), &["3 b", "2 b", "1 b", "global b"]);
actions.borrow_mut().clear();
- cx.update_window(window_id, |cx| {
+ window.update(cx, |cx| {
cx.dispatch_keystroke(&Keystroke::parse("c").unwrap());
});
assert_eq!(&*actions.borrow(), &["3 c"]);
actions.borrow_mut().clear();
- cx.update_window(window_id, |cx| {
+ window.update(cx, |cx| {
cx.dispatch_keystroke(&Keystroke::parse("d").unwrap());
});
assert_eq!(&*actions.borrow(), &["2 d"]);
@@ -6006,13 +6147,14 @@ mod tests {
}
}
- let (window_id, view_1) = cx.add_window(|cx| {
+ let window = cx.add_window(|cx| {
let view_2 = cx.add_view(|cx| {
cx.focus_self();
View2 {}
});
View1 { child: view_2 }
});
+ let view_1 = window.root(cx);
let view_2 = view_1.read_with(cx, |view, _| view.child.clone());
cx.update(|cx| {
@@ -6076,7 +6218,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_id, view_1.id(), cx),
+ &available_actions(window.window_id(), view_1.id(), cx),
&[
("test::Action1", vec![Keystroke::parse("a").unwrap()]),
("test::GlobalAction", vec![])
@@ -6085,7 +6227,7 @@ mod tests {
// Check that view 1 actions and bindings are available even when called from view 2
assert_eq!(
- &available_actions(window_id, view_2.id(), cx),
+ &available_actions(window.window_id(), view_2.id(), cx),
&[
("test::Action1", vec![Keystroke::parse("a").unwrap()]),
("test::Action2", vec![Keystroke::parse("b").unwrap()]),
@@ -6138,7 +6280,8 @@ mod tests {
impl_actions!(test, [ActionWithArg]);
- let (window_id, view) = cx.add_window(|_| View);
+ let window = cx.add_window(|_| View);
+ let view = window.root(cx);
cx.update(|cx| {
cx.add_global_action(|_: &ActionWithArg, _| {});
cx.add_bindings(vec![
@@ -6147,7 +6290,7 @@ mod tests {
]);
});
- let actions = cx.available_actions(window_id, view.id());
+ let actions = cx.available_actions(window.window_id(), view.id());
assert_eq!(
actions[0].1.as_any().downcast_ref::<ActionWithArg>(),
Some(&ActionWithArg { arg: false })
@@ -6250,7 +6393,8 @@ mod tests {
}
}
- let (_, view) = cx.add_window(|_| Counter(0));
+ let window = cx.add_window(|_| Counter(0));
+ let view = window.root(cx);
let condition1 = view.condition(cx, |view, _| view.0 == 2);
let condition2 = view.condition(cx, |view, _| view.0 == 3);
@@ -6272,15 +6416,15 @@ mod tests {
#[crate::test(self)]
#[should_panic]
async fn test_view_condition_timeout(cx: &mut TestAppContext) {
- let (_, view) = cx.add_window(|_| TestView::default());
- view.condition(cx, |_, _| false).await;
+ let window = cx.add_window(|_| TestView::default());
+ window.root(cx).condition(cx, |_, _| false).await;
}
#[crate::test(self)]
#[should_panic(expected = "view dropped with pending condition")]
async fn test_view_condition_panic_on_drop(cx: &mut TestAppContext) {
- let (window_id, _root_view) = cx.add_window(|_| TestView::default());
- let view = cx.add_view(window_id, |_| TestView::default());
+ let window = cx.add_window(|_| TestView::default());
+ let view = window.add_view(cx, |_| TestView::default());
let condition = view.condition(cx, |_, _| false);
cx.update(|_| drop(view));
@@ -6288,7 +6432,7 @@ mod tests {
}
#[crate::test(self)]
- fn test_refresh_windows(cx: &mut AppContext) {
+ fn test_refresh_windows(cx: &mut TestAppContext) {
struct View(usize);
impl super::Entity for View {
@@ -6305,22 +6449,21 @@ mod tests {
}
}
- let (window_id, root_view) = cx.add_window(Default::default(), |_| View(0));
- cx.update_window(window_id, |cx| {
+ let window = cx.add_window(|_| View(0));
+ let root_view = window.root(cx);
+ window.update(cx, |cx| {
assert_eq!(
cx.window.rendered_views[&root_view.id()].name(),
Some("render count: 0")
);
});
- let view = cx
- .update_window(window_id, |cx| {
- cx.refresh_windows();
- cx.add_view(|_| View(0))
- })
- .unwrap();
+ let view = window.update(cx, |cx| {
+ cx.refresh_windows();
+ cx.add_view(|_| View(0))
+ });
- cx.update_window(window_id, |cx| {
+ window.update(cx, |cx| {
assert_eq!(
cx.window.rendered_views[&root_view.id()].name(),
Some("render count: 1")
@@ -6,7 +6,7 @@ use crate::{
platform::{Event, InputHandler, KeyDownEvent, Platform},
Action, AppContext, BorrowAppContext, BorrowWindowContext, Entity, FontCache, Handle,
ModelContext, ModelHandle, Subscription, Task, View, ViewContext, ViewHandle, WeakHandle,
- WindowContext,
+ WindowContext, WindowHandle,
};
use collections::BTreeMap;
use futures::Future;
@@ -60,7 +60,7 @@ impl TestAppContext {
RefCounts::new(leak_detector),
(),
);
- cx.next_entity_id = first_entity_id;
+ cx.next_id = first_entity_id;
let cx = TestAppContext {
cx: Rc::new(RefCell::new(cx)),
foreground_platform,
@@ -148,17 +148,18 @@ impl TestAppContext {
self.cx.borrow_mut().add_model(build_model)
}
- pub fn add_window<T, F>(&mut self, build_root_view: F) -> (usize, ViewHandle<T>)
+ pub fn add_window<T, F>(&mut self, build_root_view: F) -> WindowHandle<T>
where
T: View,
F: FnOnce(&mut ViewContext<T>) -> T,
{
- let (window_id, view) = self
+ let window = self
.cx
.borrow_mut()
.add_window(Default::default(), build_root_view);
- self.simulate_window_activation(Some(window_id));
- (window_id, view)
+ self.simulate_window_activation(Some(window.window_id()));
+
+ WindowHandle::new(window.window_id())
}
pub fn add_view<T, F>(&mut self, window_id: usize, build_view: F) -> ViewHandle<T>
@@ -405,14 +406,20 @@ impl BorrowAppContext for TestAppContext {
}
impl BorrowWindowContext for TestAppContext {
- fn read_with<T, F: FnOnce(&WindowContext) -> T>(&self, window_id: usize, f: F) -> T {
+ type Result<T> = T;
+
+ fn read_window_with<T, F: FnOnce(&WindowContext) -> T>(&self, window_id: usize, f: F) -> T {
self.cx
.borrow()
.read_window(window_id, f)
.expect("window was closed")
}
- fn update<T, F: FnOnce(&mut WindowContext) -> T>(&mut self, window_id: usize, f: F) -> T {
+ fn update_window<T, F: FnOnce(&mut WindowContext) -> T>(
+ &mut self,
+ window_id: usize,
+ f: F,
+ ) -> T {
self.cx
.borrow_mut()
.update_window(window_id, f)
@@ -15,7 +15,7 @@ use crate::{
util::post_inc,
Action, AnyView, AnyViewHandle, AppContext, BorrowAppContext, BorrowWindowContext, Effect,
Element, Entity, Handle, LayoutContext, MouseRegion, MouseRegionId, SceneBuilder, Subscription,
- View, ViewContext, ViewHandle, WindowInvalidation,
+ View, ViewContext, ViewHandle, WindowHandle, WindowInvalidation,
};
use anyhow::{anyhow, bail, Result};
use collections::{HashMap, HashSet};
@@ -142,7 +142,9 @@ impl BorrowAppContext for WindowContext<'_> {
}
impl BorrowWindowContext for WindowContext<'_> {
- fn read_with<T, F: FnOnce(&WindowContext) -> T>(&self, window_id: usize, f: F) -> T {
+ type Result<T> = T;
+
+ fn read_window_with<T, F: FnOnce(&WindowContext) -> T>(&self, window_id: usize, f: F) -> T {
if self.window_id == window_id {
f(self)
} else {
@@ -150,7 +152,11 @@ impl BorrowWindowContext for WindowContext<'_> {
}
}
- fn update<T, F: FnOnce(&mut WindowContext) -> T>(&mut self, window_id: usize, f: F) -> T {
+ fn update_window<T, F: FnOnce(&mut WindowContext) -> T>(
+ &mut self,
+ window_id: usize,
+ f: F,
+ ) -> T {
if self.window_id == window_id {
f(self)
} else {
@@ -1151,15 +1157,15 @@ impl<'a> WindowContext<'a> {
self.window.platform_window.prompt(level, msg, answers)
}
- pub fn replace_root_view<V, F>(&mut self, build_root_view: F) -> ViewHandle<V>
+ pub fn replace_root_view<V, F>(&mut self, build_root_view: F) -> WindowHandle<V>
where
V: View,
F: FnOnce(&mut ViewContext<V>) -> V,
{
let root_view = self.add_view(|cx| build_root_view(cx));
- self.window.root_view = Some(root_view.clone().into_any());
self.window.focused_view_id = Some(root_view.id());
- root_view
+ self.window.root_view = Some(root_view.into_any());
+ WindowHandle::new(self.window_id)
}
pub fn add_view<T, F>(&mut self, build_view: F) -> ViewHandle<T>
@@ -1176,7 +1182,7 @@ impl<'a> WindowContext<'a> {
F: FnOnce(&mut ViewContext<T>) -> Option<T>,
{
let window_id = self.window_id;
- let view_id = post_inc(&mut self.next_entity_id);
+ let view_id = post_inc(&mut self.next_id);
let mut cx = ViewContext::mutable(self, view_id);
let handle = if let Some(view) = build_view(&mut cx) {
let mut keymap_context = KeymapContext::default();
@@ -61,7 +61,9 @@ async fn test_lsp_logs(cx: &mut TestAppContext) {
.receive_notification::<lsp::notification::DidOpenTextDocument>()
.await;
- let (_, log_view) = cx.add_window(|cx| LspLogView::new(project.clone(), log_store.clone(), cx));
+ let log_view = cx
+ .add_window(|cx| LspLogView::new(project.clone(), log_store.clone(), cx))
+ .root(cx);
language_server.notify::<lsp::notification::LogMessage>(lsp::LogMessageParams {
message: "hello from the server".into(),
@@ -1780,7 +1780,9 @@ mod tests {
.await;
let project = Project::test(fs.clone(), ["/root1".as_ref(), "/root2".as_ref()], cx).await;
- let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let workspace = cx
+ .add_window(|cx| Workspace::test_new(project.clone(), cx))
+ .root(cx);
let panel = workspace.update(cx, |workspace, cx| ProjectPanel::new(workspace, cx));
assert_eq!(
visible_entries_as_strings(&panel, 0..50, cx),
@@ -1868,7 +1870,9 @@ mod tests {
.await;
let project = Project::test(fs.clone(), ["/root1".as_ref(), "/root2".as_ref()], cx).await;
- let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let workspace = window.root(cx);
+ let window_id = window.window_id();
let panel = workspace.update(cx, |workspace, cx| ProjectPanel::new(workspace, cx));
select_path(&panel, "root1", cx);
@@ -2219,7 +2223,9 @@ mod tests {
.await;
let project = Project::test(fs.clone(), ["/root1".as_ref(), "/root2".as_ref()], cx).await;
- let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let workspace = window.root(cx);
+ let window_id = window.window_id();
let panel = workspace.update(cx, |workspace, cx| ProjectPanel::new(workspace, cx));
select_path(&panel, "root1", cx);
@@ -2319,7 +2325,9 @@ mod tests {
.await;
let project = Project::test(fs.clone(), ["/root1".as_ref()], cx).await;
- let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let workspace = cx
+ .add_window(|cx| Workspace::test_new(project.clone(), cx))
+ .root(cx);
let panel = workspace.update(cx, |workspace, cx| ProjectPanel::new(workspace, cx));
panel.update(cx, |panel, cx| {
@@ -2392,7 +2400,9 @@ mod tests {
.await;
let project = Project::test(fs.clone(), ["/src".as_ref()], cx).await;
- let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let workspace = window.root(cx);
+ let window_id = window.window_id();
let panel = workspace.update(cx, |workspace, cx| ProjectPanel::new(workspace, cx));
toggle_expand_dir(&panel, "src/test", cx);
@@ -2481,7 +2491,9 @@ mod tests {
.await;
let project = Project::test(fs.clone(), ["/src".as_ref()], cx).await;
- let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let workspace = window.root(cx);
+ let window_id = window.window_id();
let panel = workspace.update(cx, |workspace, cx| ProjectPanel::new(workspace, cx));
select_path(&panel, "src/", cx);
@@ -2627,7 +2639,9 @@ mod tests {
.await;
let project = Project::test(fs.clone(), ["/src".as_ref()], cx).await;
- let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let workspace = cx
+ .add_window(|cx| Workspace::test_new(project.clone(), cx))
+ .root(cx);
let panel = workspace.update(cx, |workspace, cx| ProjectPanel::new(workspace, cx));
let new_search_events_count = Arc::new(AtomicUsize::new(0));
@@ -2714,7 +2728,9 @@ mod tests {
.await;
let project = Project::test(fs.clone(), ["/project_root".as_ref()], cx).await;
- let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let workspace = cx
+ .add_window(|cx| Workspace::test_new(project.clone(), cx))
+ .root(cx);
let panel = workspace.update(cx, |workspace, cx| ProjectPanel::new(workspace, cx));
panel.update(cx, |panel, cx| {
@@ -326,7 +326,9 @@ mod tests {
},
);
- let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let workspace = window.root(cx);
+ let window_id = window.window_id();
// Create the project symbols view.
let symbols = cx.add_view(window_id, |cx| {
@@ -849,11 +849,13 @@ mod tests {
cx,
)
});
- let (window_id, _root_view) = cx.add_window(|_| EmptyView);
+ let window = cx.add_window(|_| EmptyView);
- let editor = cx.add_view(window_id, |cx| Editor::for_buffer(buffer.clone(), None, cx));
+ let editor = cx.add_view(window.window_id(), |cx| {
+ Editor::for_buffer(buffer.clone(), None, cx)
+ });
- let search_bar = cx.add_view(window_id, |cx| {
+ let search_bar = cx.add_view(window.window_id(), |cx| {
let mut search_bar = BufferSearchBar::new(cx);
search_bar.set_active_pane_item(Some(&editor), cx);
search_bar.show(cx);
@@ -1229,7 +1231,8 @@ mod tests {
"Should pick a query with multiple results"
);
let buffer = cx.add_model(|cx| Buffer::new(0, buffer_text, cx));
- let (window_id, _root_view) = cx.add_window(|_| EmptyView);
+ let window = cx.add_window(|_| EmptyView);
+ let window_id = window.window_id();
let editor = cx.add_view(window_id, |cx| Editor::for_buffer(buffer.clone(), None, cx));
@@ -1416,11 +1419,13 @@ mod tests {
"#
.unindent();
let buffer = cx.add_model(|cx| Buffer::new(0, buffer_text, cx));
- let (window_id, _root_view) = cx.add_window(|_| EmptyView);
+ let window = cx.add_window(|_| EmptyView);
- let editor = cx.add_view(window_id, |cx| Editor::for_buffer(buffer.clone(), None, cx));
+ let editor = cx.add_view(window.window_id(), |cx| {
+ Editor::for_buffer(buffer.clone(), None, cx)
+ });
- let search_bar = cx.add_view(window_id, |cx| {
+ let search_bar = cx.add_view(window.window_id(), |cx| {
let mut search_bar = BufferSearchBar::new(cx);
search_bar.set_active_pane_item(Some(&editor), cx);
search_bar.show(cx);
@@ -1447,7 +1447,9 @@ pub mod tests {
.await;
let project = Project::test(fs.clone(), ["/dir".as_ref()], cx).await;
let search = cx.add_model(|cx| ProjectSearch::new(project, cx));
- let (_, search_view) = cx.add_window(|cx| ProjectSearchView::new(search.clone(), cx));
+ let search_view = cx
+ .add_window(|cx| ProjectSearchView::new(search.clone(), cx))
+ .root(cx);
search_view.update(cx, |search_view, cx| {
search_view
@@ -1564,7 +1566,9 @@ pub mod tests {
)
.await;
let project = Project::test(fs.clone(), ["/dir".as_ref()], cx).await;
- let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project, cx));
+ let workspace = window.root(cx);
+ let window_id = window.window_id();
let active_item = cx.read(|cx| {
workspace
@@ -1748,7 +1752,9 @@ pub mod tests {
let worktree_id = project.read_with(cx, |project, cx| {
project.worktrees(cx).next().unwrap().read(cx).id()
});
- let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
+ let workspace = cx
+ .add_window(|cx| Workspace::test_new(project, cx))
+ .root(cx);
let active_item = cx.read(|cx| {
workspace
@@ -1866,7 +1872,9 @@ pub mod tests {
)
.await;
let project = Project::test(fs.clone(), ["/dir".as_ref()], cx).await;
- let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project, cx));
+ let workspace = window.root(cx);
+ let window_id = window.window_id();
workspace.update(cx, |workspace, cx| {
ProjectSearchView::deploy(workspace, &workspace::NewSearch, cx)
});
@@ -1070,7 +1070,9 @@ mod tests {
});
let project = Project::test(params.fs.clone(), [], cx).await;
- let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let workspace = cx
+ .add_window(|cx| Workspace::test_new(project.clone(), cx))
+ .root(cx);
(project, workspace)
}
@@ -1972,7 +1972,8 @@ mod tests {
let fs = FakeFs::new(cx.background());
let project = Project::test(fs, None, cx).await;
- let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let workspace = window.root(cx);
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
pane.update(cx, |pane, cx| {
@@ -1987,7 +1988,8 @@ mod tests {
let fs = FakeFs::new(cx.background());
let project = Project::test(fs, None, cx).await;
- let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let workspace = window.root(cx);
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
// 1. Add with a destination index
@@ -2065,7 +2067,8 @@ mod tests {
let fs = FakeFs::new(cx.background());
let project = Project::test(fs, None, cx).await;
- let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let workspace = window.root(cx);
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
// 1. Add with a destination index
@@ -2141,7 +2144,8 @@ mod tests {
let fs = FakeFs::new(cx.background());
let project = Project::test(fs, None, cx).await;
- let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let workspace = window.root(cx);
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
// singleton view
@@ -2209,7 +2213,8 @@ mod tests {
let fs = FakeFs::new(cx.background());
let project = Project::test(fs, None, cx).await;
- let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let workspace = window.root(cx);
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
add_labeled_item(&pane, "A", false, cx);
@@ -2256,7 +2261,8 @@ mod tests {
let fs = FakeFs::new(cx.background());
let project = Project::test(fs, None, cx).await;
- let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let workspace = window.root(cx);
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
set_labeled_items(&pane, ["A", "B", "C*", "D", "E"], cx);
@@ -2276,7 +2282,8 @@ mod tests {
let fs = FakeFs::new(cx.background());
let project = Project::test(fs, None, cx).await;
- let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let workspace = window.root(cx);
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
add_labeled_item(&pane, "A", true, cx);
@@ -2299,7 +2306,8 @@ mod tests {
let fs = FakeFs::new(cx.background());
let project = Project::test(fs, None, cx).await;
- let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let workspace = window.root(cx);
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
set_labeled_items(&pane, ["A", "B", "C*", "D", "E"], cx);
@@ -2319,7 +2327,8 @@ mod tests {
let fs = FakeFs::new(cx.background());
let project = Project::test(fs, None, cx).await;
- let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let workspace = window.root(cx);
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
set_labeled_items(&pane, ["A", "B", "C*", "D", "E"], cx);
@@ -2339,7 +2348,8 @@ mod tests {
let fs = FakeFs::new(cx.background());
let project = Project::test(fs, None, cx).await;
- let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let workspace = window.root(cx);
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
add_labeled_item(&pane, "A", false, cx);
@@ -793,67 +793,59 @@ impl Workspace {
DB.next_id().await.unwrap_or(0)
};
- let workspace = 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 = 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)
})
})
- .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?;
-
- // 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;
- }
+ });
+ 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?;
+
+ // 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()
- };
-
- // 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,
- )
- },
- )
- .1
- });
+ 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)
+ },
+ )
+ });
+
+ // We haven't yielded the main thread since obtaining the window handle,
+ // so the window exists.
+ let workspace = window.root(&cx).unwrap();
(app_state.initialize_workspace)(
workspace.downgrade(),
@@ -864,7 +856,7 @@ impl Workspace {
.await
.log_err();
- cx.update_window(workspace.window_id(), |cx| cx.activate_window());
+ window.update(&mut cx, |cx| cx.activate_window());
let workspace = workspace.downgrade();
notify_if_database_failed(&workspace, &mut cx);
@@ -3977,7 +3969,7 @@ pub fn join_remote_project(
.await?;
let window_bounds_override = window_bounds_env_override(&cx);
- let (_, workspace) = cx.add_window(
+ let window = cx.add_window(
(app_state.build_window_options)(
window_bounds_override,
None,
@@ -3985,6 +3977,7 @@ pub fn join_remote_project(
),
|cx| Workspace::new(0, project, app_state.clone(), cx),
);
+ let workspace = window.root(&cx).unwrap();
(app_state.initialize_workspace)(
workspace.downgrade(),
false,
@@ -4113,10 +4106,11 @@ mod tests {
let fs = FakeFs::new(cx.background());
let project = Project::test(fs, [], cx).await;
- let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let workspace = window.root(cx);
// Adding an item with no ambiguity renders the tab without detail.
- let item1 = cx.add_view(window_id, |_| {
+ let item1 = window.add_view(cx, |_| {
let mut item = TestItem::new();
item.tab_descriptions = Some(vec!["c", "b1/c", "a/b1/c"]);
item
@@ -4128,7 +4122,7 @@ mod tests {
// Adding an item that creates ambiguity increases the level of detail on
// both tabs.
- let item2 = cx.add_view(window_id, |_| {
+ let item2 = window.add_view(cx, |_| {
let mut item = TestItem::new();
item.tab_descriptions = Some(vec!["c", "b2/c", "a/b2/c"]);
item
@@ -4142,7 +4136,7 @@ mod tests {
// Adding an item that creates ambiguity increases the level of detail only
// on the ambiguous tabs. In this case, the ambiguity can't be resolved so
// we stop at the highest detail available.
- let item3 = cx.add_view(window_id, |_| {
+ let item3 = window.add_view(cx, |_| {
let mut item = TestItem::new();
item.tab_descriptions = Some(vec!["c", "b2/c", "a/b2/c"]);
item
@@ -4177,16 +4171,17 @@ mod tests {
.await;
let project = Project::test(fs, ["root1".as_ref()], cx).await;
- let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let workspace = window.root(cx);
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
let worktree_id = project.read_with(cx, |project, cx| {
project.worktrees(cx).next().unwrap().read(cx).id()
});
- let item1 = cx.add_view(window_id, |cx| {
+ let item1 = window.add_view(cx, |cx| {
TestItem::new().with_project_items(&[TestProjectItem::new(1, "one.txt", cx)])
});
- let item2 = cx.add_view(window_id, |cx| {
+ let item2 = window.add_view(cx, |cx| {
TestItem::new().with_project_items(&[TestProjectItem::new(2, "two.txt", cx)])
});
@@ -4201,14 +4196,14 @@ mod tests {
);
});
assert_eq!(
- cx.current_window_title(window_id).as_deref(),
+ cx.current_window_title(window.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_id).as_deref(),
+ cx.current_window_title(window.window_id()).as_deref(),
Some("two.txt ā root1")
);
project.read_with(cx, |project, cx| {
@@ -4227,7 +4222,7 @@ mod tests {
.await
.unwrap();
assert_eq!(
- cx.current_window_title(window_id).as_deref(),
+ cx.current_window_title(window.window_id()).as_deref(),
Some("one.txt ā root1")
);
project.read_with(cx, |project, cx| {
@@ -4247,14 +4242,14 @@ mod tests {
.await
.unwrap();
assert_eq!(
- cx.current_window_title(window_id).as_deref(),
+ cx.current_window_title(window.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_id).as_deref(),
+ cx.current_window_title(window.window_id()).as_deref(),
Some("one.txt ā root2")
);
}
@@ -4267,18 +4262,19 @@ mod tests {
fs.insert_tree("/root", json!({ "one": "" })).await;
let project = Project::test(fs, ["root".as_ref()], cx).await;
- let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let workspace = window.root(cx);
// When there are no dirty items, there's nothing to do.
- let item1 = cx.add_view(window_id, |_| TestItem::new());
+ let item1 = window.add_view(cx, |_| TestItem::new());
workspace.update(cx, |w, cx| w.add_item(Box::new(item1.clone()), cx));
let task = workspace.update(cx, |w, cx| w.prepare_to_close(false, cx));
assert!(task.await.unwrap());
// When there are dirty untitled items, prompt to save each one. If the user
// cancels any prompt, then abort.
- let item2 = cx.add_view(window_id, |_| TestItem::new().with_dirty(true));
- let item3 = cx.add_view(window_id, |cx| {
+ let item2 = window.add_view(cx, |_| TestItem::new().with_dirty(true));
+ let item3 = window.add_view(cx, |cx| {
TestItem::new()
.with_dirty(true)
.with_project_items(&[TestProjectItem::new(1, "1.txt", cx)])
@@ -4289,9 +4285,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_id, 2 /* cancel */);
+ cx.simulate_prompt_answer(window.window_id(), 2 /* cancel */);
cx.foreground().run_until_parked();
- assert!(!cx.has_pending_prompt(window_id));
+ assert!(!cx.has_pending_prompt(window.window_id()));
assert!(!task.await.unwrap());
}
@@ -4302,26 +4298,27 @@ mod tests {
let fs = FakeFs::new(cx.background());
let project = Project::test(fs, None, cx).await;
- let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project, cx));
+ let workspace = window.root(cx);
- let item1 = cx.add_view(window_id, |cx| {
+ let item1 = window.add_view(cx, |cx| {
TestItem::new()
.with_dirty(true)
.with_project_items(&[TestProjectItem::new(1, "1.txt", cx)])
});
- let item2 = cx.add_view(window_id, |cx| {
+ let item2 = window.add_view(cx, |cx| {
TestItem::new()
.with_dirty(true)
.with_conflict(true)
.with_project_items(&[TestProjectItem::new(2, "2.txt", cx)])
});
- let item3 = cx.add_view(window_id, |cx| {
+ let item3 = window.add_view(cx, |cx| {
TestItem::new()
.with_dirty(true)
.with_conflict(true)
.with_project_items(&[TestProjectItem::new(3, "3.txt", cx)])
});
- let item4 = cx.add_view(window_id, |cx| {
+ let item4 = window.add_view(cx, |cx| {
TestItem::new()
.with_dirty(true)
.with_project_items(&[TestProjectItem::new_untitled(cx)])
@@ -4349,10 +4346,10 @@ mod tests {
assert_eq!(pane.items_len(), 4);
assert_eq!(pane.active_item().unwrap().id(), item1.id());
});
- assert!(cx.has_pending_prompt(window_id));
+ assert!(cx.has_pending_prompt(window.window_id()));
// Confirm saving item 1.
- cx.simulate_prompt_answer(window_id, 0);
+ cx.simulate_prompt_answer(window.window_id(), 0);
cx.foreground().run_until_parked();
// Item 1 is saved. There's a prompt to save item 3.
@@ -4363,10 +4360,10 @@ mod tests {
assert_eq!(pane.items_len(), 3);
assert_eq!(pane.active_item().unwrap().id(), item3.id());
});
- assert!(cx.has_pending_prompt(window_id));
+ assert!(cx.has_pending_prompt(window.window_id()));
// Cancel saving item 3.
- cx.simulate_prompt_answer(window_id, 1);
+ cx.simulate_prompt_answer(window.window_id(), 1);
cx.foreground().run_until_parked();
// Item 3 is reloaded. There's a prompt to save item 4.
@@ -4377,10 +4374,10 @@ mod tests {
assert_eq!(pane.items_len(), 2);
assert_eq!(pane.active_item().unwrap().id(), item4.id());
});
- assert!(cx.has_pending_prompt(window_id));
+ assert!(cx.has_pending_prompt(window.window_id()));
// Confirm saving item 4.
- cx.simulate_prompt_answer(window_id, 0);
+ cx.simulate_prompt_answer(window.window_id(), 0);
cx.foreground().run_until_parked();
// There's a prompt for a path for item 4.
@@ -4404,13 +4401,14 @@ mod tests {
let fs = FakeFs::new(cx.background());
let project = Project::test(fs, [], cx).await;
- let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project, cx));
+ let workspace = window.root(cx);
// Create several workspace items with single project entries, and two
// workspace items with multiple project entries.
let single_entry_items = (0..=4)
.map(|project_entry_id| {
- cx.add_view(window_id, |cx| {
+ window.add_view(cx, |cx| {
TestItem::new()
.with_dirty(true)
.with_project_items(&[TestProjectItem::new(
@@ -4421,7 +4419,7 @@ mod tests {
})
})
.collect::<Vec<_>>();
- let item_2_3 = cx.add_view(window_id, |cx| {
+ let item_2_3 = window.add_view(cx, |cx| {
TestItem::new()
.with_dirty(true)
.with_singleton(false)
@@ -4430,7 +4428,7 @@ mod tests {
single_entry_items[3].read(cx).project_items[0].clone(),
])
});
- let item_3_4 = cx.add_view(window_id, |cx| {
+ let item_3_4 = window.add_view(cx, |cx| {
TestItem::new()
.with_dirty(true)
.with_singleton(false)
@@ -4482,7 +4480,7 @@ mod tests {
&[ProjectEntryId::from_proto(0)]
);
});
- cx.simulate_prompt_answer(window_id, 0);
+ cx.simulate_prompt_answer(window.window_id(), 0);
cx.foreground().run_until_parked();
left_pane.read_with(cx, |pane, cx| {
@@ -4491,7 +4489,7 @@ mod tests {
&[ProjectEntryId::from_proto(2)]
);
});
- cx.simulate_prompt_answer(window_id, 0);
+ cx.simulate_prompt_answer(window.window_id(), 0);
cx.foreground().run_until_parked();
close.await.unwrap();
@@ -4507,10 +4505,11 @@ mod tests {
let fs = FakeFs::new(cx.background());
let project = Project::test(fs, [], cx).await;
- let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project, cx));
+ let workspace = window.root(cx);
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
- let item = cx.add_view(window_id, |cx| {
+ let item = window.add_view(cx, |cx| {
TestItem::new().with_project_items(&[TestProjectItem::new(1, "1.txt", cx)])
});
let item_id = item.id();
@@ -4550,7 +4549,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_id));
+ cx.simulate_window_activation(Some(window.window_id()));
item.update(cx, |item, cx| {
cx.focus_self();
item.is_dirty = true;
@@ -4592,7 +4591,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_id));
+ assert!(!cx.has_pending_prompt(window.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.
@@ -4613,7 +4612,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_id));
+ assert!(cx.has_pending_prompt(window.window_id()));
item.read_with(cx, |item, _| assert_eq!(item.save_count, 5));
}
@@ -4624,9 +4623,10 @@ mod tests {
let fs = FakeFs::new(cx.background());
let project = Project::test(fs, [], cx).await;
- let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project, cx));
+ let workspace = window.root(cx);
- let item = cx.add_view(window_id, |cx| {
+ let item = window.add_view(cx, |cx| {
TestItem::new().with_project_items(&[TestProjectItem::new(1, "1.txt", cx)])
});
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
@@ -4677,7 +4677,8 @@ mod tests {
let fs = FakeFs::new(cx.background());
let project = Project::test(fs, [], cx).await;
- let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project, cx));
+ let workspace = window.root(cx);
let panel = workspace.update(cx, |workspace, cx| {
let panel = cx.add_view(|_| TestPanel::new(DockPosition::Right));
@@ -4824,7 +4825,8 @@ mod tests {
let fs = FakeFs::new(cx.background());
let project = Project::test(fs, [], cx).await;
- let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project, cx));
+ let workspace = window.root(cx);
let (panel_1, panel_2) = workspace.update(cx, |workspace, cx| {
// Add panel_1 on the left, panel_2 on the right.
@@ -4979,7 +4981,7 @@ mod tests {
// If focus is transferred to another view that's not a panel or another pane, we still show
// the panel as zoomed.
- let focus_receiver = cx.add_view(window_id, |_| EmptyView);
+ let focus_receiver = window.add_view(cx, |_| EmptyView);
focus_receiver.update(cx, |_, cx| cx.focus_self());
workspace.read_with(cx, |workspace, _| {
assert_eq!(workspace.zoomed, Some(panel_1.downgrade().into_any()));
@@ -982,7 +982,9 @@ 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));
+ let workspace = cx
+ .add_window(|cx| Workspace::test_new(project, cx))
+ .root(cx);
let entries = cx.read(|cx| workspace.file_project_paths(cx));
let file1 = entries[0].clone();
@@ -1294,7 +1296,9 @@ mod tests {
.await;
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
- let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project, cx));
+ let workspace = window.root(cx);
+ let window_id = window.window_id();
// Open a file within an existing worktree.
workspace
@@ -1335,7 +1339,9 @@ mod tests {
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
project.update(cx, |project, _| project.languages().add(rust_lang()));
- let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project, cx));
+ let workspace = window.root(cx);
+ let window_id = window.window_id();
let worktree = cx.read(|cx| workspace.read(cx).worktrees(cx).next().unwrap());
// Create a new untitled buffer
@@ -1428,7 +1434,9 @@ mod tests {
let project = Project::test(app_state.fs.clone(), [], cx).await;
project.update(cx, |project, _| project.languages().add(rust_lang()));
- let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project, cx));
+ let workspace = window.root(cx);
+ let window_id = window.window_id();
// Create a new untitled buffer
cx.dispatch_action(window_id, NewFile);
@@ -1479,7 +1487,9 @@ mod tests {
.await;
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
- let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
+ let window = cx.add_window(|cx| Workspace::test_new(project, cx));
+ let workspace = window.root(cx);
+ let window_id = window.window_id();
let entries = cx.read(|cx| workspace.file_project_paths(cx));
let file1 = entries[0].clone();
@@ -1553,7 +1563,9 @@ 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.clone(), cx));
+ let workspace = cx
+ .add_window(|cx| Workspace::test_new(project.clone(), cx))
+ .root(cx);
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
let entries = cx.read(|cx| workspace.file_project_paths(cx));
@@ -1830,7 +1842,9 @@ 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));
+ let workspace = cx
+ .add_window(|cx| Workspace::test_new(project, cx))
+ .root(cx);
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
let entries = cx.read(|cx| workspace.file_project_paths(cx));
@@ -2072,7 +2086,8 @@ mod tests {
cx.foreground().run_until_parked();
- let (window_id, _view) = cx.add_window(|_| TestView);
+ let window = cx.add_window(|_| TestView);
+ let window_id = window.window_id();
// Test loading the keymap base at all
assert_key_bindings_for(
@@ -2242,7 +2257,8 @@ mod tests {
cx.foreground().run_until_parked();
- let (window_id, _view) = cx.add_window(|_| TestView);
+ let window = cx.add_window(|_| TestView);
+ let window_id = window.window_id();
// Test loading the keymap base at all
assert_key_bindings_for(