diff --git a/assets/keymaps/default-linux.json b/assets/keymaps/default-linux.json index dd9610d4a1..f7dd30012b 100644 --- a/assets/keymaps/default-linux.json +++ b/assets/keymaps/default-linux.json @@ -514,8 +514,8 @@ "bindings": { // Change the default action on `menu::Confirm` by setting the parameter // "alt-ctrl-o": ["projects::OpenRecent", { "create_new_window": true }], - "alt-open": "projects::OpenRecent", - "alt-ctrl-o": "projects::OpenRecent", + "alt-open": ["projects::OpenRecent", { "create_new_window": false }], + "alt-ctrl-o": ["projects::OpenRecent", { "create_new_window": false }], "alt-shift-open": "projects::OpenRemote", "alt-ctrl-shift-o": "projects::OpenRemote", // Change to open path modal for existing remote connection by setting the parameter diff --git a/assets/keymaps/default-macos.json b/assets/keymaps/default-macos.json index 4dfce63b46..8e3e895d11 100644 --- a/assets/keymaps/default-macos.json +++ b/assets/keymaps/default-macos.json @@ -584,7 +584,7 @@ "bindings": { // Change the default action on `menu::Confirm` by setting the parameter // "alt-cmd-o": ["projects::OpenRecent", {"create_new_window": true }], - "alt-cmd-o": "projects::OpenRecent", + "alt-cmd-o": ["projects::OpenRecent", { "create_new_window": false }], "ctrl-cmd-o": "projects::OpenRemote", "ctrl-cmd-shift-o": ["projects::OpenRemote", { "from_existing_connection": true }], "alt-cmd-b": "branches::OpenRecent", diff --git a/crates/recent_projects/src/recent_projects.rs b/crates/recent_projects/src/recent_projects.rs index 60f7b38d56..1e5361e1e6 100644 --- a/crates/recent_projects/src/recent_projects.rs +++ b/crates/recent_projects/src/recent_projects.rs @@ -27,14 +27,42 @@ use ui::{KeyBinding, ListItem, ListItemSpacing, Tooltip, prelude::*, tooltip_con use util::{ResultExt, paths::PathExt}; use workspace::{ CloseIntent, HistoryManager, ModalView, OpenOptions, SerializedWorkspaceLocation, WORKSPACE_DB, - Workspace, WorkspaceId, + Workspace, WorkspaceId, with_active_or_new_workspace, }; use zed_actions::{OpenRecent, OpenRemote}; pub fn init(cx: &mut App) { SshSettings::register(cx); - cx.observe_new(RecentProjects::register).detach(); - cx.observe_new(RemoteServerProjects::register).detach(); + cx.on_action(|open_recent: &OpenRecent, cx| { + let create_new_window = open_recent.create_new_window; + with_active_or_new_workspace(cx, move |workspace, window, cx| { + let Some(recent_projects) = workspace.active_modal::(cx) else { + RecentProjects::open(workspace, create_new_window, window, cx); + return; + }; + + recent_projects.update(cx, |recent_projects, cx| { + recent_projects + .picker + .update(cx, |picker, cx| picker.cycle_selection(window, cx)) + }); + }); + }); + cx.on_action(|open_remote: &OpenRemote, cx| { + let from_existing_connection = open_remote.from_existing_connection; + with_active_or_new_workspace(cx, move |workspace, window, cx| { + if from_existing_connection { + cx.propagate(); + return; + } + let handle = cx.entity().downgrade(); + let fs = workspace.project().read(cx).fs().clone(); + workspace.toggle_modal(window, cx, |window, cx| { + RemoteServerProjects::new(fs, window, cx, handle) + }) + }); + }); + cx.observe_new(DisconnectedOverlay::register).detach(); } @@ -86,25 +114,6 @@ impl RecentProjects { } } - fn register( - workspace: &mut Workspace, - _window: Option<&mut Window>, - _cx: &mut Context, - ) { - workspace.register_action(|workspace, open_recent: &OpenRecent, window, cx| { - let Some(recent_projects) = workspace.active_modal::(cx) else { - Self::open(workspace, open_recent.create_new_window, window, cx); - return; - }; - - recent_projects.update(cx, |recent_projects, cx| { - recent_projects - .picker - .update(cx, |picker, cx| picker.cycle_selection(window, cx)) - }); - }); - } - pub fn open( workspace: &mut Workspace, create_new_window: bool, diff --git a/crates/recent_projects/src/remote_servers.rs b/crates/recent_projects/src/remote_servers.rs index f90db17fa8..b0ee050b79 100644 --- a/crates/recent_projects/src/remote_servers.rs +++ b/crates/recent_projects/src/remote_servers.rs @@ -50,7 +50,6 @@ use workspace::{ open_ssh_project_with_existing_connection, }; -use crate::OpenRemote; use crate::ssh_config::parse_ssh_config_hosts; use crate::ssh_connections::RemoteSettingsContent; use crate::ssh_connections::SshConnection; @@ -362,22 +361,6 @@ impl Mode { } } impl RemoteServerProjects { - pub fn register( - workspace: &mut Workspace, - _window: Option<&mut Window>, - _: &mut Context, - ) { - workspace.register_action(|workspace, action: &OpenRemote, window, cx| { - if action.from_existing_connection { - cx.propagate(); - return; - } - let handle = cx.entity().downgrade(); - let fs = workspace.project().read(cx).fs().clone(); - workspace.toggle_modal(window, cx, |window, cx| Self::new(fs, window, cx, handle)) - }); - } - pub fn open(workspace: Entity, window: &mut Window, cx: &mut App) { workspace.update(cx, |workspace, cx| { let handle = cx.entity().downgrade(); diff --git a/crates/settings_ui/src/settings_ui.rs b/crates/settings_ui/src/settings_ui.rs index 58d0ce9147..b7bb4b77e7 100644 --- a/crates/settings_ui/src/settings_ui.rs +++ b/crates/settings_ui/src/settings_ui.rs @@ -15,8 +15,8 @@ use schemars::JsonSchema; use serde::Deserialize; use settings::{SettingsStore, VsCodeSettingsSource}; use ui::prelude::*; -use workspace::Workspace; use workspace::item::{Item, ItemEvent}; +use workspace::{Workspace, with_active_or_new_workspace}; use crate::appearance_settings_controls::AppearanceSettingsControls; @@ -42,12 +42,8 @@ impl_actions!(zed, [ImportVsCodeSettings, ImportCursorSettings]); actions!(zed, [OpenSettingsEditor]); pub fn init(cx: &mut App) { - cx.observe_new(|workspace: &mut Workspace, window, cx| { - let Some(window) = window else { - return; - }; - - workspace.register_action(|workspace, _: &OpenSettingsEditor, window, cx| { + cx.on_action(|_: &OpenSettingsEditor, cx| { + with_active_or_new_workspace(cx, move |workspace, window, cx| { let existing = workspace .active_pane() .read(cx) @@ -61,6 +57,12 @@ pub fn init(cx: &mut App) { workspace.add_item_to_active_pane(Box::new(settings_page), None, true, window, cx) } }); + }); + + cx.observe_new(|workspace: &mut Workspace, window, cx| { + let Some(window) = window else { + return; + }; workspace.register_action(|_workspace, action: &ImportVsCodeSettings, window, cx| { let fs = ::global(cx); diff --git a/crates/theme_selector/src/theme_selector.rs b/crates/theme_selector/src/theme_selector.rs index 97acbc3359..e6cc08483f 100644 --- a/crates/theme_selector/src/theme_selector.rs +++ b/crates/theme_selector/src/theme_selector.rs @@ -12,7 +12,7 @@ use std::sync::Arc; use theme::{Appearance, Theme, ThemeMeta, ThemeRegistry, ThemeSettings}; use ui::{ListItem, ListItemSpacing, prelude::*, v_flex}; use util::ResultExt; -use workspace::{ModalView, Workspace, ui::HighlightedLabel}; +use workspace::{ModalView, Workspace, ui::HighlightedLabel, with_active_or_new_workspace}; use zed_actions::{ExtensionCategoryFilter, Extensions}; use crate::icon_theme_selector::{IconThemeSelector, IconThemeSelectorDelegate}; @@ -20,14 +20,18 @@ use crate::icon_theme_selector::{IconThemeSelector, IconThemeSelectorDelegate}; actions!(theme_selector, [Reload]); pub fn init(cx: &mut App) { - cx.observe_new( - |workspace: &mut Workspace, _window, _cx: &mut Context| { - workspace - .register_action(toggle_theme_selector) - .register_action(toggle_icon_theme_selector); - }, - ) - .detach(); + cx.on_action(|action: &zed_actions::theme_selector::Toggle, cx| { + let action = action.clone(); + with_active_or_new_workspace(cx, move |workspace, window, cx| { + toggle_theme_selector(workspace, &action, window, cx); + }); + }); + cx.on_action(|action: &zed_actions::icon_theme_selector::Toggle, cx| { + let action = action.clone(); + with_active_or_new_workspace(cx, move |workspace, window, cx| { + toggle_icon_theme_selector(workspace, &action, window, cx); + }); + }); } fn toggle_theme_selector( diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index e16cf0038a..b289078e33 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -7642,6 +7642,33 @@ pub fn ssh_workspace_position_from_db( }) } +pub fn with_active_or_new_workspace( + cx: &mut App, + f: impl FnOnce(&mut Workspace, &mut Window, &mut Context) + Send + 'static, +) { + match cx.active_window().and_then(|w| w.downcast::()) { + Some(workspace) => { + cx.defer(move |cx| { + workspace + .update(cx, |workspace, window, cx| f(workspace, window, cx)) + .log_err(); + }); + } + None => { + let app_state = AppState::global(cx); + if let Some(app_state) = app_state.upgrade() { + open_new( + OpenOptions::default(), + app_state, + cx, + move |workspace, window, cx| f(workspace, window, cx), + ) + .detach_and_log_err(cx); + } + } + } +} + #[cfg(test)] mod tests { use std::{cell::RefCell, rc::Rc}; diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 92b11507b3..0c284661aa 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -70,7 +70,7 @@ use workspace::{ create_and_open_local_file, notifications::simple_message_notification::MessageNotification, open_new, }; -use workspace::{CloseIntent, RestoreBanner}; +use workspace::{CloseIntent, CloseWindow, RestoreBanner, with_active_or_new_workspace}; use workspace::{Pane, notifications::DetachAndPromptErr}; use zed_actions::{ OpenAccountSettings, OpenBrowser, OpenDocs, OpenServerSettings, OpenSettings, OpenZedUrl, Quit, @@ -111,6 +111,98 @@ pub fn init(cx: &mut App) { if ReleaseChannel::global(cx) == ReleaseChannel::Dev { cx.on_action(test_panic); } + + cx.on_action(|_: &OpenLog, cx| { + with_active_or_new_workspace(cx, |workspace, window, cx| { + open_log_file(workspace, window, cx); + }); + }); + cx.on_action(|_: &zed_actions::OpenLicenses, cx| { + with_active_or_new_workspace(cx, |workspace, window, cx| { + open_bundled_file( + workspace, + asset_str::("licenses.md"), + "Open Source License Attribution", + "Markdown", + window, + cx, + ); + }); + }); + cx.on_action(|_: &zed_actions::OpenTelemetryLog, cx| { + with_active_or_new_workspace(cx, |workspace, window, cx| { + open_telemetry_log_file(workspace, window, cx); + }); + }); + cx.on_action(|&zed_actions::OpenKeymap, cx| { + with_active_or_new_workspace(cx, |_, window, cx| { + open_settings_file( + paths::keymap_file(), + || settings::initial_keymap_content().as_ref().into(), + window, + cx, + ); + }); + }); + cx.on_action(|_: &OpenSettings, cx| { + with_active_or_new_workspace(cx, |_, window, cx| { + open_settings_file( + paths::settings_file(), + || settings::initial_user_settings_content().as_ref().into(), + window, + cx, + ); + }); + }); + cx.on_action(|_: &OpenAccountSettings, cx| { + with_active_or_new_workspace(cx, |_, _, cx| { + cx.open_url(&zed_urls::account_url(cx)); + }); + }); + cx.on_action(|_: &OpenTasks, cx| { + with_active_or_new_workspace(cx, |_, window, cx| { + open_settings_file( + paths::tasks_file(), + || settings::initial_tasks_content().as_ref().into(), + window, + cx, + ); + }); + }); + cx.on_action(|_: &OpenDebugTasks, cx| { + with_active_or_new_workspace(cx, |_, window, cx| { + open_settings_file( + paths::debug_scenarios_file(), + || settings::initial_debug_tasks_content().as_ref().into(), + window, + cx, + ); + }); + }); + cx.on_action(|_: &OpenDefaultSettings, cx| { + with_active_or_new_workspace(cx, |workspace, window, cx| { + open_bundled_file( + workspace, + settings::default_settings(), + "Default Settings", + "JSON", + window, + cx, + ); + }); + }); + cx.on_action(|_: &zed_actions::OpenDefaultKeymap, cx| { + with_active_or_new_workspace(cx, |workspace, window, cx| { + open_bundled_file( + workspace, + settings::default_keymap(), + "Default Key Bindings", + "JSON", + window, + cx, + ); + }); + }); } fn bind_on_window_closed(cx: &mut App) -> Option { @@ -255,7 +347,7 @@ pub fn initialize_workspace( handle .update(cx, |workspace, cx| { // We'll handle closing asynchronously - workspace.close_window(&Default::default(), window, cx); + workspace.close_window(&CloseWindow, window, cx); false }) .unwrap_or(true) @@ -683,99 +775,9 @@ fn register_actions( |_, _, _| None, ); }) - .register_action(|workspace, _: &OpenLog, window, cx| { - open_log_file(workspace, window, cx); - }) - .register_action(|workspace, _: &zed_actions::OpenLicenses, window, cx| { - open_bundled_file( - workspace, - asset_str::("licenses.md"), - "Open Source License Attribution", - "Markdown", - window, - cx, - ); - }) - .register_action( - move |workspace: &mut Workspace, - _: &zed_actions::OpenTelemetryLog, - window: &mut Window, - cx: &mut Context| { - open_telemetry_log_file(workspace, window, cx); - }, - ) - .register_action( - move |_: &mut Workspace, _: &zed_actions::OpenKeymap, window, cx| { - open_settings_file( - paths::keymap_file(), - || settings::initial_keymap_content().as_ref().into(), - window, - cx, - ); - }, - ) - .register_action(move |_: &mut Workspace, _: &OpenSettings, window, cx| { - open_settings_file( - paths::settings_file(), - || settings::initial_user_settings_content().as_ref().into(), - window, - cx, - ); - }) - .register_action( - |_: &mut Workspace, _: &OpenAccountSettings, _: &mut Window, cx| { - cx.open_url(&zed_urls::account_url(cx)); - }, - ) - .register_action(move |_: &mut Workspace, _: &OpenTasks, window, cx| { - open_settings_file( - paths::tasks_file(), - || settings::initial_tasks_content().as_ref().into(), - window, - cx, - ); - }) - .register_action(move |_: &mut Workspace, _: &OpenDebugTasks, window, cx| { - open_settings_file( - paths::debug_scenarios_file(), - || settings::initial_debug_tasks_content().as_ref().into(), - window, - cx, - ); - }) - .register_action(move |_: &mut Workspace, _: &OpenDebugTasks, window, cx| { - open_settings_file( - paths::debug_scenarios_file(), - || settings::initial_debug_tasks_content().as_ref().into(), - window, - cx, - ); - }) .register_action(open_project_settings_file) .register_action(open_project_tasks_file) .register_action(open_project_debug_tasks_file) - .register_action( - move |workspace, _: &zed_actions::OpenDefaultKeymap, window, cx| { - open_bundled_file( - workspace, - settings::default_keymap(), - "Default Key Bindings", - "JSON", - window, - cx, - ); - }, - ) - .register_action(move |workspace, _: &OpenDefaultSettings, window, cx| { - open_bundled_file( - workspace, - settings::default_settings(), - "Default Settings", - "JSON", - window, - cx, - ); - }) .register_action( |workspace: &mut Workspace, _: &project_panel::ToggleFocus, diff --git a/crates/zed/src/zed/app_menus.rs b/crates/zed/src/zed/app_menus.rs index 4c0077585d..ec98bb9122 100644 --- a/crates/zed/src/zed/app_menus.rs +++ b/crates/zed/src/zed/app_menus.rs @@ -67,7 +67,7 @@ pub fn app_menus() -> Vec { MenuItem::action( "Open Recent...", zed_actions::OpenRecent { - create_new_window: true, + create_new_window: false, }, ), MenuItem::action(