Add QuitMode policy to GPUI (#42391)
Applications can select a policy for when the app quits using the new function `Application::with_quit_mode`: - Only on explicit calls to `App::quit` - When the last window is closed - Platform default (former on macOS, latter everywhere else) Release Notes: - N/A
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
+26
-24
@@ -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,
|
||||
);
|
||||
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())
|
||||
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) {
|
||||
|
||||
Reference in New Issue
Block a user