-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[bug] ExitRequested
not fired on macOS
#9198
Comments
For those who are looking for a way to reliably run async functions on exit in a Tauri app, this is how I managed to do it: First make an exit lock, this is responsible for blocking your Tauri app from exiting, I made a use once_cell::sync::Lazy;
pub static EXIT_LOCKED: Lazy<std::sync::Mutex<bool>> = Lazy::new(|| {
std::sync::Mutex::new(true)
}); Then, make an fn on_exit(app: &AppHandle, need_exiting: bool) {
futures::executor::block_on(async move {
tauri::async_runtime::spawn(async move {
// Execute your cleanup actions here
stop_all_downloads().await;
*EXIT_LOCKED.lock().unwrap() = false;
})
});
let win = app.get_window("main").unwrap();
win.hide().unwrap();
loop {
if !*EXIT_LOCKED.lock().unwrap() {
break;
}
};
win.close().unwrap();
if need_exiting {
app.exit(0);
}
} Intercept window events to run cleanup actions when a window is closed, this implementation is for single-window apps. Make sure your storing your let app = tauri::Builder::default()
.invoke_handler(tauri::generate_handler![
// Your handlers
])
.on_window_event(|event| match event {
WindowEvent::CloseRequested { api, .. } => {
api.prevent_close();
on_exit(&event.window().app_handle(), true);
},
_ => {}
})
.build(tauri::generate_context!())
.expect("error while running tauri application"); Intercept events from the app lifecycle events( app.run(move |app, event| match event {
RunEvent::Exit => {
// Since RunEvent:Exit already executes exit, we'll pass false to on_exit so it won't exit twice
on_exit(app, false);
},
_ => {}
}); This is a janky workaround but it works reliably enough, if there's a better way, please share. Hopefully, Tauri will handle pre-exit events reliably in v2 🤞 |
How exactly are you exiting the app? Closing Windows via the red button for example should trigger ExitRequested once all windows are closed (even though that's not really how macos apps should behave). right click -> Quit on the dock item may be the same as #3084 if it's not working. |
Using Command+Q or Quit from menu bar |
Is this still currently the best way to do this? |
I ran across this because of a slightly different use case: I wanted to merely "hide" the window when Quit was requested, similar to a lot of menubar apps where Close or Quit keeps the menubar icon visible and running in the background. I found a workaround by replacing the native Quit menu with a custom one, and implementing my own handler for it. Note this doesn't intercept right-clicking the dock icon and clicking Quit. For that it seems like we'd need to intercept fn run() {
tauri::Builder::default()
.on_menu_event(|app, event| match event.id.as_ref() {
"custom_quit" => {
let Some(window) = app.get_webview_window("main") else {
return;
};
// Hide the window, etc.
// To hide the dock icon, app.set_activation_policy(ActivationPolicy::Accessory)
let _ = window.hide();
}
_ => {}
})
.setup(|app| {
// On Mac, replace the Quit menu item with a custom one so that we can
// intercept the Cmd+Q shortcut and clicks on App > Quit
#[cfg(target_os = "macos")]
let _ = replace_quit_menu(app.app_handle());
// other setup code ...
})
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
fn replace_quit_menu<R: tauri::Runtime>(app: &tauri::AppHandle<R>) -> tauri::Result<()> {
// Get the top-level menu
if let Some(menu) = app.menu() {
// Get the AppName menu (first one on Mac)
if let Some(app_menu) = menu.items()?.first().and_then(|i| i.as_submenu()) {
// Remove the last item, which is the Quit menu
let last_index = app_menu.items()?.len() - 1;
app_menu.remove_at(last_index)?;
// Add a new Quit item
let new_quit_item = MenuItem::with_id(
app.app_handle(),
"custom_quit",
"Quit",
true,
Some("Command+Q"),
)?;
app_menu.append(&new_quit_item)?;
}
}
Ok(())
} |
Describe the bug
nothing gets run when exit is requested
Reproduction
No response
Expected behavior
No response
Full
tauri info
outputThe text was updated successfully, but these errors were encountered: