diff --git a/app.vue b/app.vue index 72fdf7e..f3d4bfc 100644 --- a/app.vue +++ b/app.vue @@ -14,12 +14,36 @@ onMounted(async () => { await navigateTo('/keybind') await app.show(); await window.getCurrentWindow().show(); + manageFocus(); }) await listen('main_route', async () => { await navigateTo('/') }) }) + +function manageFocus() { + if (process.platform === 'win32') { + const { SetForegroundWindow, AttachThreadInput, GetForegroundWindow, GetWindowThreadProcessId } = require('windows-api'); + const foregroundWindow = GetForegroundWindow(); + const currentThreadId = GetWindowThreadProcessId(foregroundWindow, null); + const targetThreadId = GetWindowThreadProcessId(window.hwnd(), null); + + AttachThreadInput(currentThreadId, targetThreadId, 1); + SetForegroundWindow(window.hwnd()); + AttachThreadInput(currentThreadId, targetThreadId, 0); + } else if (process.platform === 'darwin') { + const { NSWindow } = require('cocoa'); + const nsWindow = window.ns_window(); + nsWindow.makeKeyAndOrderFront(true); + } else if (process.platform === 'linux') { + const { XOpenDisplay, XDefaultRootWindow, XSetInputFocus, XCloseDisplay, RevertToParent } = require('xlib'); + const display = XOpenDisplay(null); + const rootWindow = XDefaultRootWindow(display); + XSetInputFocus(display, rootWindow, RevertToParent, 0); + XCloseDisplay(display); + } +} \ No newline at end of file + diff --git a/src-tauri/src/api/hotkeys.rs b/src-tauri/src/api/hotkeys.rs index 8edcd7f..44774e9 100644 --- a/src-tauri/src/api/hotkeys.rs +++ b/src-tauri/src/api/hotkeys.rs @@ -3,6 +3,52 @@ use crate::utils::commands::center_window_on_current_monitor; use rdev::{listen, EventType, Key}; use tauri::Manager; +#[cfg(target_os = "windows")] +mod platform { + use std::ptr::null_mut; + use winapi::um::winuser::{AttachThreadInput, GetForegroundWindow, GetWindowThreadProcessId, SetForegroundWindow}; + + pub fn manage_focus(window: &tauri::Window) { + unsafe { + let foreground_window = GetForegroundWindow(); + let current_thread_id = GetWindowThreadProcessId(foreground_window, null_mut()); + let target_thread_id = GetWindowThreadProcessId(window.hwnd() as _, null_mut()); + + AttachThreadInput(current_thread_id, target_thread_id, 1); + SetForegroundWindow(window.hwnd() as _); + AttachThreadInput(current_thread_id, target_thread_id, 0); + } + } +} + +#[cfg(target_os = "macos")] +mod platform { + use cocoa::appkit::NSWindow; + use cocoa::base::id; + use objc::runtime::YES; + + pub fn manage_focus(window: &tauri::Window) { + unsafe { + let ns_window: id = window.ns_window().unwrap() as _; + ns_window.makeKeyAndOrderFront_(YES); + } + } +} + +#[cfg(target_os = "linux")] +mod platform { + use x11::xlib::{Display, XSetInputFocus, XDefaultRootWindow, XOpenDisplay, XCloseDisplay, RevertToParent}; + + pub fn manage_focus(window: &tauri::Window) { + unsafe { + let display: *mut Display = XOpenDisplay(null_mut()); + let root_window = XDefaultRootWindow(display); + XSetInputFocus(display, root_window, RevertToParent, 0); + XCloseDisplay(display); + } + } +} + fn key_to_string(key: &Key) -> String { format!("{:?}", key) } @@ -35,10 +81,10 @@ pub fn setup(app_handle: tauri::AppHandle) { pressed_keys.iter_mut().for_each(|k| *k = false); let window = app_handle.get_webview_window("main").unwrap(); window.show().unwrap(); - window.set_focus().unwrap(); center_window_on_current_monitor(&window); + platform::manage_focus(&window); } }) .unwrap(); }); -} \ No newline at end of file +} diff --git a/src-tauri/src/api/tray.rs b/src-tauri/src/api/tray.rs index 6b78b8c..abd4c07 100644 --- a/src-tauri/src/api/tray.rs +++ b/src-tauri/src/api/tray.rs @@ -2,6 +2,52 @@ use tauri::{ menu::{MenuBuilder, MenuItemBuilder}, tray::TrayIconBuilder, Emitter, Manager }; +#[cfg(target_os = "windows")] +mod platform { + use std::ptr::null_mut; + use winapi::um::winuser::{AttachThreadInput, GetForegroundWindow, GetWindowThreadProcessId, SetForegroundWindow}; + + pub fn manage_focus(window: &tauri::Window) { + unsafe { + let foreground_window = GetForegroundWindow(); + let current_thread_id = GetWindowThreadProcessId(foreground_window, null_mut()); + let target_thread_id = GetWindowThreadProcessId(window.hwnd() as _, null_mut()); + + AttachThreadInput(current_thread_id, target_thread_id, 1); + SetForegroundWindow(window.hwnd() as _); + AttachThreadInput(current_thread_id, target_thread_id, 0); + } + } +} + +#[cfg(target_os = "macos")] +mod platform { + use cocoa::appkit::NSWindow; + use cocoa::base::id; + use objc::runtime::YES; + + pub fn manage_focus(window: &tauri::Window) { + unsafe { + let ns_window: id = window.ns_window().unwrap() as _; + ns_window.makeKeyAndOrderFront_(YES); + } + } +} + +#[cfg(target_os = "linux")] +mod platform { + use x11::xlib::{Display, XSetInputFocus, XDefaultRootWindow, XOpenDisplay, XCloseDisplay, RevertToParent}; + + pub fn manage_focus(window: &tauri::Window) { + unsafe { + let display: *mut Display = XOpenDisplay(null_mut()); + let root_window = XDefaultRootWindow(display); + XSetInputFocus(display, root_window, RevertToParent, 0); + XCloseDisplay(display); + } + } +} + pub fn setup(app: &mut tauri::App) -> Result<(), Box> { let window = app.get_webview_window("main").unwrap(); let window_clone_for_tray = window.clone(); @@ -30,7 +76,7 @@ pub fn setup(app: &mut tauri::App) -> Result<(), Box> { window_clone_for_tray.hide().unwrap(); } else { window_clone_for_tray.show().unwrap(); - window_clone_for_tray.set_focus().unwrap(); + platform::manage_focus(&window_clone_for_tray); } window_clone_for_tray.emit("main_route", ()).unwrap(); } diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 10c61f3..758274b 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -64,9 +64,7 @@ fn main() { .on_window_event(|app, event| { #[cfg(not(dev))] if let tauri::WindowEvent::Focused(false) = event { - if let Some(window) = app.get_webview_window("main") { - let _ = window.hide(); - } + return; } }) .invoke_handler(tauri::generate_handler![