mirror of
https://github.com/tauri-apps/tauri.git
synced 2024-12-01 03:02:28 +03:00
Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
This commit is contained in:
parent
fd80dd97e8
commit
892c63a053
7
.changes/exit-requested-event.md
Normal file
7
.changes/exit-requested-event.md
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
"tauri": patch
|
||||
"tauri-runtime": patch
|
||||
"tauri-runtime-wry": patch
|
||||
---
|
||||
|
||||
Add `ExitRequested` event that allows preventing the app from exiting when all windows are closed, and an `AppHandle.exit()` function to exit the app manually.
|
@ -13,8 +13,8 @@ use tauri_runtime::{
|
||||
dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Position, Size},
|
||||
DetachedWindow, PendingWindow, WindowEvent,
|
||||
},
|
||||
ClipboardManager, Dispatch, Error, GlobalShortcutManager, Icon, Result, RunEvent, RunIteration,
|
||||
Runtime, RuntimeHandle, UserAttentionType,
|
||||
ClipboardManager, Dispatch, Error, ExitRequestedEventAction, GlobalShortcutManager, Icon, Result,
|
||||
RunEvent, RunIteration, Runtime, RuntimeHandle, UserAttentionType,
|
||||
};
|
||||
|
||||
#[cfg(feature = "menu")]
|
||||
@ -2063,8 +2063,16 @@ fn on_window_close<'a>(
|
||||
callback(RunEvent::WindowClose(webview.label));
|
||||
}
|
||||
if windows.is_empty() {
|
||||
*control_flow = ControlFlow::Exit;
|
||||
callback(RunEvent::Exit);
|
||||
let (tx, rx) = channel();
|
||||
callback(RunEvent::ExitRequested { tx });
|
||||
|
||||
let recv = rx.try_recv();
|
||||
let should_prevent = matches!(recv, Ok(ExitRequestedEventAction::Prevent));
|
||||
|
||||
if !should_prevent {
|
||||
*control_flow = ControlFlow::Exit;
|
||||
callback(RunEvent::Exit);
|
||||
}
|
||||
}
|
||||
// TODO: tao does not fire the destroyed event properly
|
||||
#[cfg(target_os = "linux")]
|
||||
|
@ -170,6 +170,10 @@ impl Icon {
|
||||
pub enum RunEvent {
|
||||
/// Event loop is exiting.
|
||||
Exit,
|
||||
/// Event loop is about to exit
|
||||
ExitRequested {
|
||||
tx: Sender<ExitRequestedEventAction>,
|
||||
},
|
||||
/// Window close was requested by the user.
|
||||
CloseRequested {
|
||||
/// The window label.
|
||||
@ -181,6 +185,13 @@ pub enum RunEvent {
|
||||
WindowClose(String),
|
||||
}
|
||||
|
||||
/// Action to take when the event loop is about to exit
|
||||
#[derive(Debug)]
|
||||
pub enum ExitRequestedEventAction {
|
||||
/// Prevent the event loop from exiting
|
||||
Prevent,
|
||||
}
|
||||
|
||||
/// A system tray event.
|
||||
pub enum SystemTrayEvent {
|
||||
MenuItemClick(u16),
|
||||
|
@ -15,7 +15,7 @@ use crate::{
|
||||
runtime::{
|
||||
webview::{CustomProtocol, WebviewAttributes, WindowBuilder},
|
||||
window::{PendingWindow, WindowEvent},
|
||||
Dispatch, RunEvent, Runtime,
|
||||
Dispatch, ExitRequestedEventAction, RunEvent, Runtime,
|
||||
},
|
||||
sealed::{ManagerBase, RuntimeOrDispatch},
|
||||
Context, Invoke, InvokeError, Manager, StateManager, Window,
|
||||
@ -47,7 +47,19 @@ pub(crate) type GlobalWindowEventListener<R> = Box<dyn Fn(GlobalWindowEvent<R>)
|
||||
#[cfg(feature = "system-tray")]
|
||||
type SystemTrayEventListener<R> = Box<dyn Fn(&AppHandle<R>, tray::SystemTrayEvent) + Send + Sync>;
|
||||
|
||||
/// Api exposed on the `ExitRequested` event.
|
||||
#[derive(Debug)]
|
||||
pub struct ExitRequestApi(Sender<ExitRequestedEventAction>);
|
||||
|
||||
impl ExitRequestApi {
|
||||
/// Prevents the app from exiting
|
||||
pub fn prevent_exit(&self) {
|
||||
self.0.send(ExitRequestedEventAction::Prevent).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
/// Api exposed on the `CloseRequested` event.
|
||||
#[derive(Debug)]
|
||||
pub struct CloseRequestApi(Sender<bool>);
|
||||
|
||||
impl CloseRequestApi {
|
||||
@ -58,10 +70,17 @@ impl CloseRequestApi {
|
||||
}
|
||||
|
||||
/// An application event, triggered from the event loop.
|
||||
#[derive(Debug)]
|
||||
#[non_exhaustive]
|
||||
pub enum Event {
|
||||
/// Event loop is exiting.
|
||||
Exit,
|
||||
/// The app is about to exit
|
||||
#[non_exhaustive]
|
||||
ExitRequested {
|
||||
/// Event API
|
||||
api: ExitRequestApi,
|
||||
},
|
||||
/// Window close was requested by the user.
|
||||
#[non_exhaustive]
|
||||
CloseRequested {
|
||||
@ -223,6 +242,23 @@ impl<R: Runtime> AppHandle<R> {
|
||||
.register(plugin);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Exits the app
|
||||
pub fn exit(&self, exit_code: i32) {
|
||||
std::process::exit(exit_code);
|
||||
}
|
||||
|
||||
/// Runs necessary cleanup tasks before exiting the process
|
||||
fn cleanup_before_exit(&self) {
|
||||
#[cfg(shell_execute)]
|
||||
{
|
||||
crate::api::process::kill_children();
|
||||
}
|
||||
#[cfg(all(windows, feature = "system-tray"))]
|
||||
{
|
||||
let _ = self.remove_system_tray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Runtime> Manager<R> for AppHandle<R> {}
|
||||
@ -356,14 +392,7 @@ impl<R: Runtime> App<R> {
|
||||
let manager = self.manager.clone();
|
||||
self.runtime.take().unwrap().run(move |event| match event {
|
||||
RunEvent::Exit => {
|
||||
#[cfg(shell_execute)]
|
||||
{
|
||||
crate::api::process::kill_children();
|
||||
}
|
||||
#[cfg(all(windows, feature = "system-tray"))]
|
||||
{
|
||||
let _ = app_handle.remove_system_tray();
|
||||
}
|
||||
app_handle.cleanup_before_exit();
|
||||
callback(&app_handle, Event::Exit);
|
||||
}
|
||||
_ => {
|
||||
@ -372,6 +401,9 @@ impl<R: Runtime> App<R> {
|
||||
&app_handle,
|
||||
match event {
|
||||
RunEvent::Exit => Event::Exit,
|
||||
RunEvent::ExitRequested { tx } => Event::ExitRequested {
|
||||
api: ExitRequestApi(tx),
|
||||
},
|
||||
RunEvent::CloseRequested { label, signal_tx } => Event::CloseRequested {
|
||||
label: label.parse().unwrap_or_else(|_| unreachable!()),
|
||||
api: CloseRequestApi(signal_tx),
|
||||
|
Loading…
Reference in New Issue
Block a user