mirror of
https://github.com/0PandaDEV/Qopy.git
synced 2025-04-22 13:44:05 +02:00
Fix focus issue when opening Qopy
Fixes #10 Implement platform-specific focus management to prevent the underlying window from losing focus when the shortcut is pressed. * **src-tauri/src/api/hotkeys.rs** - Add platform-specific modules for Windows, macOS, and Linux to manage focus between windows. - Modify the `setup` function to use platform-specific APIs to manage focus between windows. - Replace `window.set_focus()` with `platform::manage_focus(&window)`. * **src-tauri/src/api/tray.rs** - Add platform-specific modules for Windows, macOS, and Linux to manage focus between windows when the tray menu is used. - Modify the `setup` function to use platform-specific APIs to manage focus between windows. - Replace `window_clone_for_tray.set_focus()` with `platform::manage_focus(&window_clone_for_tray)`. * **app.vue** - Add `manageFocus` function to handle platform-specific focus management. - Call `manageFocus` function when the `change_keybind` event is triggered. * **src-tauri/src/main.rs** - Remove logic to hide the window when it loses focus. --- For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/0PandaDEV/Qopy/issues/10?shareId=XXXX-XXXX-XXXX-XXXX).
This commit is contained in:
parent
fd0fdd2d51
commit
fbd159c68b
4 changed files with 121 additions and 7 deletions
24
app.vue
24
app.vue
|
@ -14,12 +14,36 @@ onMounted(async () => {
|
||||||
await navigateTo('/keybind')
|
await navigateTo('/keybind')
|
||||||
await app.show();
|
await app.show();
|
||||||
await window.getCurrentWindow().show();
|
await window.getCurrentWindow().show();
|
||||||
|
manageFocus();
|
||||||
})
|
})
|
||||||
|
|
||||||
await listen('main_route', async () => {
|
await listen('main_route', async () => {
|
||||||
await navigateTo('/')
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|
|
@ -3,6 +3,52 @@ use crate::utils::commands::center_window_on_current_monitor;
|
||||||
use rdev::{listen, EventType, Key};
|
use rdev::{listen, EventType, Key};
|
||||||
use tauri::Manager;
|
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 {
|
fn key_to_string(key: &Key) -> String {
|
||||||
format!("{:?}", key)
|
format!("{:?}", key)
|
||||||
}
|
}
|
||||||
|
@ -35,8 +81,8 @@ pub fn setup(app_handle: tauri::AppHandle) {
|
||||||
pressed_keys.iter_mut().for_each(|k| *k = false);
|
pressed_keys.iter_mut().for_each(|k| *k = false);
|
||||||
let window = app_handle.get_webview_window("main").unwrap();
|
let window = app_handle.get_webview_window("main").unwrap();
|
||||||
window.show().unwrap();
|
window.show().unwrap();
|
||||||
window.set_focus().unwrap();
|
|
||||||
center_window_on_current_monitor(&window);
|
center_window_on_current_monitor(&window);
|
||||||
|
platform::manage_focus(&window);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
|
@ -2,6 +2,52 @@ use tauri::{
|
||||||
menu::{MenuBuilder, MenuItemBuilder}, tray::TrayIconBuilder, Emitter, Manager
|
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<dyn std::error::Error>> {
|
pub fn setup(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let window = app.get_webview_window("main").unwrap();
|
let window = app.get_webview_window("main").unwrap();
|
||||||
let window_clone_for_tray = window.clone();
|
let window_clone_for_tray = window.clone();
|
||||||
|
@ -30,7 +76,7 @@ pub fn setup(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
window_clone_for_tray.hide().unwrap();
|
window_clone_for_tray.hide().unwrap();
|
||||||
} else {
|
} else {
|
||||||
window_clone_for_tray.show().unwrap();
|
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();
|
window_clone_for_tray.emit("main_route", ()).unwrap();
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,9 +64,7 @@ fn main() {
|
||||||
.on_window_event(|app, event| {
|
.on_window_event(|app, event| {
|
||||||
#[cfg(not(dev))]
|
#[cfg(not(dev))]
|
||||||
if let tauri::WindowEvent::Focused(false) = event {
|
if let tauri::WindowEvent::Focused(false) = event {
|
||||||
if let Some(window) = app.get_webview_window("main") {
|
return;
|
||||||
let _ = window.hide();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.invoke_handler(tauri::generate_handler![
|
.invoke_handler(tauri::generate_handler![
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue