mirror of
https://github.com/tauri-apps/tauri.git
synced 2024-12-01 11:13:40 +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},
|
dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Position, Size},
|
||||||
DetachedWindow, PendingWindow, WindowEvent,
|
DetachedWindow, PendingWindow, WindowEvent,
|
||||||
},
|
},
|
||||||
ClipboardManager, Dispatch, Error, GlobalShortcutManager, Icon, Result, RunEvent, RunIteration,
|
ClipboardManager, Dispatch, Error, ExitRequestedEventAction, GlobalShortcutManager, Icon, Result,
|
||||||
Runtime, RuntimeHandle, UserAttentionType,
|
RunEvent, RunIteration, Runtime, RuntimeHandle, UserAttentionType,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "menu")]
|
#[cfg(feature = "menu")]
|
||||||
@ -2063,8 +2063,16 @@ fn on_window_close<'a>(
|
|||||||
callback(RunEvent::WindowClose(webview.label));
|
callback(RunEvent::WindowClose(webview.label));
|
||||||
}
|
}
|
||||||
if windows.is_empty() {
|
if windows.is_empty() {
|
||||||
*control_flow = ControlFlow::Exit;
|
let (tx, rx) = channel();
|
||||||
callback(RunEvent::Exit);
|
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
|
// TODO: tao does not fire the destroyed event properly
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
|
@ -170,6 +170,10 @@ impl Icon {
|
|||||||
pub enum RunEvent {
|
pub enum RunEvent {
|
||||||
/// Event loop is exiting.
|
/// Event loop is exiting.
|
||||||
Exit,
|
Exit,
|
||||||
|
/// Event loop is about to exit
|
||||||
|
ExitRequested {
|
||||||
|
tx: Sender<ExitRequestedEventAction>,
|
||||||
|
},
|
||||||
/// Window close was requested by the user.
|
/// Window close was requested by the user.
|
||||||
CloseRequested {
|
CloseRequested {
|
||||||
/// The window label.
|
/// The window label.
|
||||||
@ -181,6 +185,13 @@ pub enum RunEvent {
|
|||||||
WindowClose(String),
|
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.
|
/// A system tray event.
|
||||||
pub enum SystemTrayEvent {
|
pub enum SystemTrayEvent {
|
||||||
MenuItemClick(u16),
|
MenuItemClick(u16),
|
||||||
|
@ -15,7 +15,7 @@ use crate::{
|
|||||||
runtime::{
|
runtime::{
|
||||||
webview::{CustomProtocol, WebviewAttributes, WindowBuilder},
|
webview::{CustomProtocol, WebviewAttributes, WindowBuilder},
|
||||||
window::{PendingWindow, WindowEvent},
|
window::{PendingWindow, WindowEvent},
|
||||||
Dispatch, RunEvent, Runtime,
|
Dispatch, ExitRequestedEventAction, RunEvent, Runtime,
|
||||||
},
|
},
|
||||||
sealed::{ManagerBase, RuntimeOrDispatch},
|
sealed::{ManagerBase, RuntimeOrDispatch},
|
||||||
Context, Invoke, InvokeError, Manager, StateManager, Window,
|
Context, Invoke, InvokeError, Manager, StateManager, Window,
|
||||||
@ -47,7 +47,19 @@ pub(crate) type GlobalWindowEventListener<R> = Box<dyn Fn(GlobalWindowEvent<R>)
|
|||||||
#[cfg(feature = "system-tray")]
|
#[cfg(feature = "system-tray")]
|
||||||
type SystemTrayEventListener<R> = Box<dyn Fn(&AppHandle<R>, tray::SystemTrayEvent) + Send + Sync>;
|
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.
|
/// Api exposed on the `CloseRequested` event.
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct CloseRequestApi(Sender<bool>);
|
pub struct CloseRequestApi(Sender<bool>);
|
||||||
|
|
||||||
impl CloseRequestApi {
|
impl CloseRequestApi {
|
||||||
@ -58,10 +70,17 @@ impl CloseRequestApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// An application event, triggered from the event loop.
|
/// An application event, triggered from the event loop.
|
||||||
|
#[derive(Debug)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
/// Event loop is exiting.
|
/// Event loop is exiting.
|
||||||
Exit,
|
Exit,
|
||||||
|
/// The app is about to exit
|
||||||
|
#[non_exhaustive]
|
||||||
|
ExitRequested {
|
||||||
|
/// Event API
|
||||||
|
api: ExitRequestApi,
|
||||||
|
},
|
||||||
/// Window close was requested by the user.
|
/// Window close was requested by the user.
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
CloseRequested {
|
CloseRequested {
|
||||||
@ -223,6 +242,23 @@ impl<R: Runtime> AppHandle<R> {
|
|||||||
.register(plugin);
|
.register(plugin);
|
||||||
Ok(())
|
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> {}
|
impl<R: Runtime> Manager<R> for AppHandle<R> {}
|
||||||
@ -356,14 +392,7 @@ impl<R: Runtime> App<R> {
|
|||||||
let manager = self.manager.clone();
|
let manager = self.manager.clone();
|
||||||
self.runtime.take().unwrap().run(move |event| match event {
|
self.runtime.take().unwrap().run(move |event| match event {
|
||||||
RunEvent::Exit => {
|
RunEvent::Exit => {
|
||||||
#[cfg(shell_execute)]
|
app_handle.cleanup_before_exit();
|
||||||
{
|
|
||||||
crate::api::process::kill_children();
|
|
||||||
}
|
|
||||||
#[cfg(all(windows, feature = "system-tray"))]
|
|
||||||
{
|
|
||||||
let _ = app_handle.remove_system_tray();
|
|
||||||
}
|
|
||||||
callback(&app_handle, Event::Exit);
|
callback(&app_handle, Event::Exit);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@ -372,6 +401,9 @@ impl<R: Runtime> App<R> {
|
|||||||
&app_handle,
|
&app_handle,
|
||||||
match event {
|
match event {
|
||||||
RunEvent::Exit => Event::Exit,
|
RunEvent::Exit => Event::Exit,
|
||||||
|
RunEvent::ExitRequested { tx } => Event::ExitRequested {
|
||||||
|
api: ExitRequestApi(tx),
|
||||||
|
},
|
||||||
RunEvent::CloseRequested { label, signal_tx } => Event::CloseRequested {
|
RunEvent::CloseRequested { label, signal_tx } => Event::CloseRequested {
|
||||||
label: label.parse().unwrap_or_else(|_| unreachable!()),
|
label: label.parse().unwrap_or_else(|_| unreachable!()),
|
||||||
api: CloseRequestApi(signal_tx),
|
api: CloseRequestApi(signal_tx),
|
||||||
|
Loading…
Reference in New Issue
Block a user