diff --git a/assets/settings/default.json b/assets/settings/default.json index 671653708d..aba8037190 100644 --- a/assets/settings/default.json +++ b/assets/settings/default.json @@ -210,6 +210,13 @@ // 3. Never close the window // "when_closing_with_no_tabs": "keep_window_open", "when_closing_with_no_tabs": "platform_default", + // What to show when opening a new window. + // May take 2 values: + // 1. Show an empty untitled buffer + // "on_new_window": "empty_tab" + // 2. Show the launchpad with recent projects + // "on_new_window": "launchpad" + "on_new_window": "launchpad", // What to do when the last window is closed. // May take 2 values: // 1. Use the current platform's convention diff --git a/crates/settings/src/vscode_import.rs b/crates/settings/src/vscode_import.rs index 3e25d4ecc6..a776e23df9 100644 --- a/crates/settings/src/vscode_import.rs +++ b/crates/settings/src/vscode_import.rs @@ -1062,6 +1062,7 @@ impl VsCodeSettings { } else { None }, + on_new_window: None, on_last_window_closed: None, pane_split_direction_horizontal: None, pane_split_direction_vertical: None, diff --git a/crates/settings_content/src/workspace.rs b/crates/settings_content/src/workspace.rs index 7aa8bc42a8..cfe76bb4ca 100644 --- a/crates/settings_content/src/workspace.rs +++ b/crates/settings_content/src/workspace.rs @@ -109,6 +109,10 @@ pub struct WorkspaceSettingsContent { /// /// Default: none pub max_tabs: Option, + /// What to show when opening a new window. + /// Values: empty_tab, launchpad + /// Default: launchpad + pub on_new_window: Option, /// What to do when the last window is closed /// /// Default: auto (nothing on macOS, "app quit" otherwise) @@ -683,6 +687,29 @@ pub struct CenteredLayoutSettings { pub right_padding: Option, } +#[derive( + Copy, + Clone, + Default, + Serialize, + Deserialize, + JsonSchema, + MergeFrom, + PartialEq, + Eq, + Debug, + strum::VariantArray, + strum::VariantNames, +)] +#[serde(rename_all = "snake_case")] +pub enum OnNewWindow { + /// Show an empty untitled buffer when opening a new window + EmptyTab, + /// Show the launchpad with recent projects when opening a new window + #[default] + Launchpad, +} + #[derive( Copy, Clone, diff --git a/crates/settings_ui/src/page_data.rs b/crates/settings_ui/src/page_data.rs index 5d3a5f7ce9..6d328ca24c 100644 --- a/crates/settings_ui/src/page_data.rs +++ b/crates/settings_ui/src/page_data.rs @@ -172,6 +172,20 @@ fn general_page(cx: &App) -> SettingsPage { metadata: None, files: USER, }), + SettingsPageItem::SettingItem(SettingItem { + title: "On New Window", + description: "What to show when opening a new window.", + field: Box::new(SettingField { + organization_override: None, + json_path: Some("on_new_window"), + pick: |settings_content| settings_content.workspace.on_new_window.as_ref(), + write: |settings_content, value, _| { + settings_content.workspace.on_new_window = value; + }, + }), + metadata: None, + files: USER, + }), SettingsPageItem::SettingItem(SettingItem { title: "On Last Window Closed", description: "What to do when the last window is closed.", diff --git a/crates/settings_ui/src/settings_ui.rs b/crates/settings_ui/src/settings_ui.rs index eee5c6e3ec..7f4d4c53b5 100644 --- a/crates/settings_ui/src/settings_ui.rs +++ b/crates/settings_ui/src/settings_ui.rs @@ -554,6 +554,7 @@ fn init_renderers(cx: &mut App) { .add_basic_renderer::(render_toggle_button) .add_basic_renderer::(render_dropdown) .add_basic_renderer::(render_dropdown) + .add_basic_renderer::(render_dropdown) .add_basic_renderer::(render_dropdown) .add_basic_renderer::(render_dropdown) .add_basic_renderer::(render_dropdown) diff --git a/crates/workspace/src/workspace_settings.rs b/crates/workspace/src/workspace_settings.rs index b88658fea4..2a84de6fb2 100644 --- a/crates/workspace/src/workspace_settings.rs +++ b/crates/workspace/src/workspace_settings.rs @@ -33,6 +33,7 @@ pub struct WorkspaceSettings { pub command_aliases: HashMap, pub max_tabs: Option, pub when_closing_with_no_tabs: settings::CloseWindowWhenNoItems, + pub on_new_window: settings::OnNewWindow, pub on_last_window_closed: settings::OnLastWindowClosed, pub text_rendering_mode: settings::TextRenderingMode, pub resize_all_panels_in_dock: Vec, @@ -129,6 +130,7 @@ impl Settings for WorkspaceSettings { command_aliases: workspace.command_aliases.clone(), max_tabs: workspace.max_tabs, when_closing_with_no_tabs: workspace.when_closing_with_no_tabs.unwrap(), + on_new_window: workspace.on_new_window.unwrap(), on_last_window_closed: workspace.on_last_window_closed.unwrap(), text_rendering_mode: workspace.text_rendering_mode.unwrap(), resize_all_panels_in_dock: workspace diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 0f7c563b39..ebe3776df3 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -1340,24 +1340,7 @@ fn register_actions( cx, |workspace, window, cx| { cx.activate(true); - // Create buffer synchronously to avoid flicker - let project = workspace.project().clone(); - let buffer = project.update(cx, |project, cx| { - project.create_local_buffer("", None, true, cx) - }); - buffer.update(cx, |buffer, _| { - buffer.set_content_language_detection_enabled(true); - }); - let editor = cx.new(|cx| { - Editor::for_buffer(buffer, Some(project), window, cx) - }); - workspace.add_item_to_active_pane( - Box::new(editor), - None, - true, - window, - cx, - ); + initialize_new_window(workspace, window, cx); }, ) .detach(); @@ -2418,6 +2401,30 @@ fn filter_disabled_ai_bindings(bindings: Vec, cx: &App) -> Vec, +) { + if WorkspaceSettings::get_global(cx).on_new_window == settings::OnNewWindow::Launchpad { + return; + } + // Create buffer synchronously to avoid flicker + let project = workspace.project().clone(); + let buffer = project.update(cx, |project, cx| { + project.create_local_buffer("", None, true, cx) + }); + buffer.update(cx, |buffer, _| { + buffer.set_content_language_detection_enabled(true); + }); + let editor = cx.new(|cx| Editor::for_buffer(buffer, Some(project), window, cx)); + workspace.add_item_to_active_pane(Box::new(editor), None, true, window, cx); +} + pub fn open_new_ssh_project_from_project( workspace: &mut Workspace, paths: Vec, @@ -3779,6 +3786,50 @@ mod tests { .unwrap(); } + #[gpui::test] + async fn test_new_window_launchpad_opens_without_items(cx: &mut TestAppContext) { + let app_state = init_test(cx); + cx.update(|cx| { + SettingsStore::update_global(cx, |store, cx| { + store.update_user_settings(cx, |settings| { + settings.workspace.on_new_window = Some(settings::OnNewWindow::Launchpad); + }); + }); + }); + + cx.update(|cx| { + open_new( + Default::default(), + app_state.clone(), + cx, + |workspace, window, cx| initialize_new_window(workspace, window, cx), + ) + }) + .await + .unwrap(); + cx.run_until_parked(); + + let multi_workspace = cx + .update(|cx| cx.windows().first().unwrap().downcast::()) + .unwrap(); + + multi_workspace + .update(cx, |multi_workspace, _, cx| { + multi_workspace.workspace().update(cx, |workspace, cx| { + assert!( + workspace.active_item(cx).is_none(), + "launchpad window should not open any items" + ); + assert_eq!( + workspace.active_pane().read(cx).items_len(), + 0, + "launchpad window should have an empty pane so the launchpad is shown" + ); + }); + }) + .unwrap(); + } + #[gpui::test] async fn test_open_entry(cx: &mut TestAppContext) { let app_state = init_test(cx); diff --git a/docs/src/reference/all-settings.md b/docs/src/reference/all-settings.md index 35ae9bb8dd..9dee351809 100644 --- a/docs/src/reference/all-settings.md +++ b/docs/src/reference/all-settings.md @@ -3438,6 +3438,30 @@ If you wish to exclude certain hosts from using the proxy, set the `NO_PROXY` en } ``` +## On New Window + +- Description: What to show when opening a new window. +- Setting: `on_new_window` +- Default: `"launchpad"` + +**Options** + +1. Show an empty untitled buffer: + +```json [settings] +{ + "on_new_window": "empty_tab" +} +``` + +2. Show the launchpad with recent projects: + +```json [settings] +{ + "on_new_window": "launchpad" +} +``` + ## Instrumentation - Description: Configuration for developer-oriented instrumentation tools (profilers, tracers, etc.) that can be toggled at runtime.