From 4dee08e4412b7265d2aca5999551d6e5caa98516 Mon Sep 17 00:00:00 2001 From: Nanako Tsai Date: Wed, 3 Jun 2026 11:40:01 +0800 Subject: [PATCH 1/2] Fix menubar popover across macOS spaces --- src-tauri/src/tray.rs | 55 +++++++++++++++++++++++++++++++++++++-- src-tauri/tauri.conf.json | 1 + 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/src-tauri/src/tray.rs b/src-tauri/src/tray.rs index ee3295e..5e4534e 100644 --- a/src-tauri/src/tray.rs +++ b/src-tauri/src/tray.rs @@ -83,15 +83,21 @@ pub fn setup(app: &AppHandle) -> tauri::Result<()> { if visible { hide_popover(app); } else { + prepare_popover_window(&w); let _ = position_window_under_tray(tray, &w); let _ = w.show(); + bring_popover_to_front(&w); let _ = w.set_focus(); + bring_popover_to_front(&w); let _ = app.emit("popover-shown", ()); } } } }) .build(app)?; + if let Some(w) = app.get_webview_window("main") { + prepare_popover_window(&w); + } Ok(()) } @@ -130,15 +136,59 @@ pub fn toggle_popover(app: &AppHandle) { fn show_popover(app: &AppHandle) { if let Some(w) = app.get_webview_window("main") { + prepare_popover_window(&w); if let Some(tray) = app.tray_by_id("main-tray") { let _ = position_window_under_tray(&tray, &w); } let _ = w.show(); + bring_popover_to_front(&w); let _ = w.set_focus(); + bring_popover_to_front(&w); let _ = app.emit("popover-shown", ()); } } +#[cfg(target_os = "macos")] +fn prepare_popover_window(window: &WebviewWindow) { + use objc2_app_kit::{NSPopUpMenuWindowLevel, NSWindow, NSWindowCollectionBehavior}; + + let _ = window.set_visible_on_all_workspaces(true); + + let Ok(ns_window) = window.ns_window() else { + return; + }; + + let ns_window = unsafe { &*(ns_window.cast::()) }; + let behavior = ns_window.collectionBehavior() + | NSWindowCollectionBehavior::CanJoinAllSpaces + | NSWindowCollectionBehavior::CanJoinAllApplications + | NSWindowCollectionBehavior::FullScreenAuxiliary + | NSWindowCollectionBehavior::IgnoresCycle + | NSWindowCollectionBehavior::Transient; + ns_window.setCollectionBehavior(behavior); + ns_window.setLevel(NSPopUpMenuWindowLevel); +} + +#[cfg(not(target_os = "macos"))] +fn prepare_popover_window(window: &WebviewWindow) { + let _ = window.set_visible_on_all_workspaces(true); +} + +#[cfg(target_os = "macos")] +fn bring_popover_to_front(window: &WebviewWindow) { + use objc2_app_kit::NSWindow; + + let Ok(ns_window) = window.ns_window() else { + return; + }; + + let ns_window = unsafe { &*(ns_window.cast::()) }; + ns_window.orderFrontRegardless(); +} + +#[cfg(not(target_os = "macos"))] +fn bring_popover_to_front(_window: &WebviewWindow) {} + fn position_window_under_tray( tray: &tauri::tray::TrayIcon, window: &WebviewWindow, @@ -166,8 +216,9 @@ fn position_window_under_tray( .unwrap_or(POPOVER_DEFAULT_H) .clamp(POPOVER_MIN_H, POPOVER_MAX_H); - // Clamp to monitor bounds - if let Ok(Some(monitor)) = window.current_monitor() { + // Clamp to the monitor that owns the tray icon, not the monitor remembered + // by the hidden popover window from its last Space. + if let Ok(Some(monitor)) = window.monitor_from_point(tray_x_logical, tray_y_logical) { let m_pos = monitor.position(); let m_size = monitor.size(); let m_scale = monitor.scale_factor(); diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 849f120..51b7b1a 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -25,6 +25,7 @@ "alwaysOnTop": false, "skipTaskbar": true, "visible": false, + "visibleOnAllWorkspaces": true, "center": true, "shadow": true, "windowEffects": { From 9b61b9646ee6c7de639366f8a0682f7656413602 Mon Sep 17 00:00:00 2001 From: handlecusion Date: Thu, 4 Jun 2026 13:37:09 +0900 Subject: [PATCH 2/2] fix(tray): prepare shortcut popover window --- src-tauri/src/tray.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src-tauri/src/tray.rs b/src-tauri/src/tray.rs index 5e4534e..d46963f 100644 --- a/src-tauri/src/tray.rs +++ b/src-tauri/src/tray.rs @@ -124,11 +124,14 @@ pub fn toggle_popover(app: &AppHandle) { if w.is_visible().unwrap_or(false) { hide_popover(app); } else { + prepare_popover_window(&w); if let Some(tray) = app.tray_by_id("main-tray") { let _ = position_window_under_tray(&tray, &w); } let _ = w.show(); + bring_popover_to_front(&w); let _ = w.set_focus(); + bring_popover_to_front(&w); let _ = app.emit("popover-shown", ()); } }