fix(desktop): macos quit flash, first click and press feedback
This commit is contained in:
5 files changed
+91
-11
No files matched your search
@@ -86,6 +86,15 @@ pub async fn complete_app_close(app: AppHandle, window: Window, action: String)
|
||||
if let Some(state) = app.try_state::<CloseBehaviorState>() {
|
||||
state.allow_next_exit();
|
||||
}
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
// Take the whole app off-screen first so WKWebView teardown during
|
||||
// process exit cannot flash the window red on macOS 12. `AppHandle::hide`
|
||||
// is macOS-only, so this block is compiled per-platform.
|
||||
let _ = window.hide();
|
||||
let _ = app.hide();
|
||||
tokio::time::sleep(std::time::Duration::from_millis(crate::EXIT_HIDE_GRACE_MS)).await;
|
||||
}
|
||||
app.exit(0);
|
||||
}
|
||||
"hide" => {
|
||||
|
||||
+31
-4
@@ -115,6 +115,18 @@ fn should_hide_window_on_close(target_os: &str) -> bool {
|
||||
matches!(target_os, "macos" | "windows")
|
||||
}
|
||||
|
||||
/// How long to keep the app off-screen after hiding it and before the process
|
||||
/// exits, so WindowServer has removed the window before WKWebView teardown.
|
||||
#[cfg(target_os = "macos")]
|
||||
pub(crate) const EXIT_HIDE_GRACE_MS: u64 = 250;
|
||||
|
||||
/// On macOS, tearing down WKWebView while the window is still on screen can
|
||||
/// paint the window red for a frame before the process exits, so the app is
|
||||
/// hidden first. Windows and Linux keep their existing exit behavior.
|
||||
fn should_hide_window_before_exit(target_os: &str) -> bool {
|
||||
target_os == "macos"
|
||||
}
|
||||
|
||||
fn should_setup_desktop_tray(target_os: &str, show_tray_icon: bool, linux_appindicator_available: bool) -> bool {
|
||||
show_tray_icon
|
||||
&& (matches!(target_os, "macos" | "windows") || (target_os == "linux" && linux_appindicator_available))
|
||||
@@ -973,10 +985,10 @@ mod tests {
|
||||
linux_drm_render_devices_from_paths, linux_nvidia_driver_from_state, linux_pci_id_from_sysfs_value,
|
||||
linux_selected_drm_render_device, linux_uses_native_wayland, linux_webkit_environment_override,
|
||||
linux_webkit_rendering_workarounds, native_window_decorations_override, should_confirm_app_exit_request,
|
||||
should_enable_single_instance, should_fallback_to_native_quit, should_hide_window_on_close,
|
||||
should_setup_desktop_tray, should_show_main_window_after_setup, should_show_main_window_before_setup_tasks,
|
||||
startup_data_dir_mode, tray_menu_labels_for_locale, uses_application_level_icon, LinuxDrmRenderDevice,
|
||||
LinuxNvidiaDriver,
|
||||
should_enable_single_instance, should_fallback_to_native_quit, should_hide_window_before_exit,
|
||||
should_hide_window_on_close, should_setup_desktop_tray, should_show_main_window_after_setup,
|
||||
should_show_main_window_before_setup_tasks, startup_data_dir_mode, tray_menu_labels_for_locale,
|
||||
uses_application_level_icon, LinuxDrmRenderDevice, LinuxNvidiaDriver,
|
||||
};
|
||||
use crate::data_dir::DataDirMode;
|
||||
use std::ffi::OsStr;
|
||||
@@ -1027,6 +1039,13 @@ mod tests {
|
||||
assert!(!should_hide_window_on_close("linux"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hides_window_before_exit_only_on_macos() {
|
||||
assert!(should_hide_window_before_exit("macos"));
|
||||
assert!(!should_hide_window_before_exit("windows"));
|
||||
assert!(!should_hide_window_before_exit("linux"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sets_up_desktop_tray_for_windows_macos_and_linux() {
|
||||
assert!(should_setup_desktop_tray("windows", true, false));
|
||||
@@ -2528,6 +2547,14 @@ pub fn run() {
|
||||
api.prevent_exit();
|
||||
request_app_close(app_handle, "quit");
|
||||
} else {
|
||||
// Restart exits and the no-frontend native quit bypass
|
||||
// `complete_app_close`, so hide the window here too; the
|
||||
// shutdown below gives WindowServer time to remove it.
|
||||
if should_hide_window_before_exit(std::env::consts::OS) {
|
||||
if let Some(window) = app_handle.get_webview_window("main") {
|
||||
let _ = window.hide();
|
||||
}
|
||||
}
|
||||
tauri::async_runtime::block_on(async {
|
||||
if let Some(server) = app_handle.try_state::<commands::redis_pubsub_server::PubSubServerState>()
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user