@@ -169,6 +169,13 @@ impl Application {
self
}
+ /// Configures when the application should automatically quit.
+ /// By default, [`QuitMode::Default`] is used.
+ pub fn with_quit_mode(self, mode: QuitMode) -> Self {
+ self.0.borrow_mut().quit_mode = mode;
+ self
+ }
+
/// Start the application. The provided callback will be called once the
/// app is fully launched.
pub fn run<F>(self, on_finish_launching: F)
@@ -238,6 +245,18 @@ type WindowClosedHandler = Box<dyn FnMut(&mut App)>;
type ReleaseListener = Box<dyn FnOnce(&mut dyn Any, &mut App) + 'static>;
type NewEntityListener = Box<dyn FnMut(AnyEntity, &mut Option<&mut Window>, &mut App) + 'static>;
+/// Defines when the application should automatically quit.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
+pub enum QuitMode {
+ /// Use [`QuitMode::Explicit`] on macOS and [`QuitMode::LastWindowClosed`] on other platforms.
+ #[default]
+ Default,
+ /// Quit automatically when the last window is closed.
+ LastWindowClosed,
+ /// Quit only when requested via [`App::quit`].
+ Explicit,
+}
+
#[doc(hidden)]
#[derive(Clone, PartialEq, Eq)]
pub struct SystemWindowTab {
@@ -588,6 +607,7 @@ pub struct App {
pub(crate) inspector_element_registry: InspectorElementRegistry,
#[cfg(any(test, feature = "test-support", debug_assertions))]
pub(crate) name: Option<&'static str>,
+ quit_mode: QuitMode,
quitting: bool,
}
@@ -659,6 +679,7 @@ impl App {
inspector_renderer: None,
#[cfg(any(feature = "inspector", debug_assertions))]
inspector_element_registry: InspectorElementRegistry::default(),
+ quit_mode: QuitMode::default(),
quitting: false,
#[cfg(any(test, feature = "test-support", debug_assertions))]
@@ -1172,6 +1193,12 @@ impl App {
self.http_client = new_client;
}
+ /// Configures when the application should automatically quit.
+ /// By default, [`QuitMode::Default`] is used.
+ pub fn set_quit_mode(&mut self, mode: QuitMode) {
+ self.quit_mode = mode;
+ }
+
/// Returns the SVG renderer used by the application.
pub fn svg_renderer(&self) -> SvgRenderer {
self.svg_renderer.clone()
@@ -1379,6 +1406,16 @@ impl App {
callback(cx);
true
});
+
+ let quit_on_empty = match cx.quit_mode {
+ QuitMode::Explicit => false,
+ QuitMode::LastWindowClosed => true,
+ QuitMode::Default => !cfg!(macos),
+ };
+
+ if quit_on_empty && cx.windows.is_empty() {
+ cx.quit();
+ }
} else {
cx.windows.get_mut(id)?.replace(window);
}
@@ -15,7 +15,7 @@ use extension::ExtensionHostProxy;
use fs::{Fs, RealFs};
use futures::{StreamExt, channel::oneshot, future};
use git::GitHostingProviderRegistry;
-use gpui::{App, AppContext, Application, AsyncApp, Focusable as _, UpdateGlobal as _};
+use gpui::{App, AppContext, Application, AsyncApp, Focusable as _, QuitMode, UpdateGlobal as _};
use gpui_tokio::Tokio;
use language::LanguageRegistry;
@@ -87,31 +87,33 @@ fn files_not_created_on_launch(errors: HashMap<io::ErrorKind, Vec<&Path>>) {
.collect::<Vec<_>>().join("\n\n");
eprintln!("{message}: {error_details}");
- Application::new().run(move |cx| {
- if let Ok(window) = cx.open_window(gpui::WindowOptions::default(), |_, cx| {
- cx.new(|_| gpui::Empty)
- }) {
- window
- .update(cx, |_, window, cx| {
- let response = window.prompt(
- gpui::PromptLevel::Critical,
- message,
- Some(&error_details),
- &["Exit"],
- cx,
- );
-
- cx.spawn_in(window, async move |_, cx| {
- response.await?;
- cx.update(|_, cx| cx.quit())
+ Application::new()
+ .with_quit_mode(QuitMode::Explicit)
+ .run(move |cx| {
+ if let Ok(window) = cx.open_window(gpui::WindowOptions::default(), |_, cx| {
+ cx.new(|_| gpui::Empty)
+ }) {
+ window
+ .update(cx, |_, window, cx| {
+ let response = window.prompt(
+ gpui::PromptLevel::Critical,
+ message,
+ Some(&error_details),
+ &["Exit"],
+ cx,
+ );
+
+ cx.spawn_in(window, async move |_, cx| {
+ response.await?;
+ cx.update(|_, cx| cx.quit())
+ })
+ .detach_and_log_err(cx);
})
- .detach_and_log_err(cx);
- })
- .log_err();
- } else {
- fail_to_open_window(anyhow::anyhow!("{message}: {error_details}"), cx)
- }
- })
+ .log_err();
+ } else {
+ fail_to_open_window(anyhow::anyhow!("{message}: {error_details}"), cx)
+ }
+ })
}
fn fail_to_open_window_async(e: anyhow::Error, cx: &mut AsyncApp) {