diff --git a/openless-all/app/src-tauri/Cargo.lock b/openless-all/app/src-tauri/Cargo.lock index 19efbbef..60ac8b5c 100644 --- a/openless-all/app/src-tauri/Cargo.lock +++ b/openless-all/app/src-tauri/Cargo.lock @@ -3270,6 +3270,7 @@ dependencies = [ "objc2-foundation 0.2.2", "once_cell", "parking_lot", + "raw-window-handle", "rdev", "reqwest 0.12.28", "serde", diff --git a/openless-all/app/src-tauri/Cargo.toml b/openless-all/app/src-tauri/Cargo.toml index d93315c8..6a69b47a 100644 --- a/openless-all/app/src-tauri/Cargo.toml +++ b/openless-all/app/src-tauri/Cargo.toml @@ -35,6 +35,7 @@ uuid = { version = "1", features = ["v4", "serde"] } chrono = { version = "0.4", features = ["serde"] } bytes = "1" url = "2" +raw-window-handle = "0.6" # Hotkey + audio + insertion global-hotkey = "0.6" diff --git a/openless-all/app/src-tauri/src/lib.rs b/openless-all/app/src-tauri/src/lib.rs index 12056a11..2baeddd3 100644 --- a/openless-all/app/src-tauri/src/lib.rs +++ b/openless-all/app/src-tauri/src/lib.rs @@ -514,7 +514,16 @@ pub(crate) fn show_qa_window(app: &AppHandle, content_kind } }); } - #[cfg(not(target_os = "macos"))] + #[cfg(target_os = "windows")] + { + if !show_qa_window_no_activate(&window) { + log::warn!("[qa] show_no_activate failed; falling back to window.show()"); + if let Err(e) = window.show() { + log::warn!("[qa] show fallback failed: {e}"); + } + } + } + #[cfg(all(not(target_os = "macos"), not(target_os = "windows")))] if let Err(e) = window.show() { log::warn!("[qa] show failed: {e}"); } @@ -560,6 +569,41 @@ pub(crate) fn hide_qa_window(app: &AppHandle) { } } +#[cfg(target_os = "windows")] +fn show_qa_window_no_activate(window: &tauri::WebviewWindow) -> bool { + use raw_window_handle::{HasWindowHandle, RawWindowHandle}; + use windows::Win32::Foundation::HWND; + use windows::Win32::UI::WindowsAndMessaging::{ + SetWindowPos, ShowWindow, HWND_TOPMOST, SWP_NOACTIVATE, SWP_NOMOVE, SWP_NOSIZE, + SWP_SHOWWINDOW, SW_SHOWNOACTIVATE, + }; + + let Ok(handle) = window.window_handle() else { + return false; + }; + let RawWindowHandle::Win32(raw) = handle.as_raw() else { + return false; + }; + let hwnd = HWND(raw.hwnd.get() as *mut _); + if hwnd.0.is_null() { + return false; + } + + let _ = unsafe { ShowWindow(hwnd, SW_SHOWNOACTIVATE) }; + let _ = unsafe { + SetWindowPos( + hwnd, + HWND_TOPMOST, + 0, + 0, + 0, + 0, + SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOACTIVATE, + ) + }; + true +} + /// 把 capsule 窗口移到屏幕底部居中,与 Swift `CapsuleWindowController.repositionToBottomCenter` 同效。 /// 留 80pt 给 macOS Dock;Windows 任务栏一般在底部 48pt 以内,整体也合适。 pub(crate) fn position_capsule_bottom_center(