use super::screenshot;
use crate::core::log;
use enigo::{Direction, Enigo, Key, Keyboard, Settings};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc;
use std::thread;
use std::time::Duration;
static SWITCHING: AtomicBool = AtomicBool::new(false);
fn switch_desktop(right: bool) {
if SWITCHING.swap(true, Ordering::SeqCst) {
return;
}
let mut enigo = match Enigo::new(&Settings::default()) {
Ok(e) => e,
Err(e) => {
log::warn!("Enigo 初始化失败: {}", e);
SWITCHING.store(false, Ordering::SeqCst);
return;
}
};
let arrow = if right {
Key::RightArrow
} else {
Key::LeftArrow
};
let _ = enigo.key(Key::Meta, Direction::Press);
let _ = enigo.key(Key::Control, Direction::Press);
thread::sleep(Duration::from_millis(10));
let _ = enigo.key(arrow, Direction::Click);
thread::sleep(Duration::from_millis(10));
let _ = enigo.key(Key::Control, Direction::Release);
let _ = enigo.key(Key::Meta, Direction::Release);
thread::sleep(Duration::from_millis(300));
SWITCHING.store(false, Ordering::SeqCst);
}
pub fn start_listener() {
let (tx, rx) = mpsc::channel::<bool>();
thread::spawn(move || {
#[cfg(target_os = "windows")]
{
use std::ptr::null_mut;
use winapi::shared::minwindef::{HINSTANCE, LPARAM, LRESULT, WPARAM};
use winapi::um::libloaderapi::GetModuleHandleW;
use winapi::um::winuser::{
CallNextHookEx, GetMessageW, SetWindowsHookExW, UnhookWindowsHookEx, HC_ACTION,
KBDLLHOOKSTRUCT, MSG, WH_KEYBOARD_LL,
};
static mut FIRST_KEY: bool = true;
unsafe extern "system" fn low_level_keyboard_proc(
n_code: i32,
w_param: WPARAM,
l_param: LPARAM,
) -> LRESULT {
if n_code == HC_ACTION {
let kb = unsafe { &*(l_param as *const KBDLLHOOKSTRUCT) };
let vk = kb.vkCode as i32;
unsafe {
if FIRST_KEY {
FIRST_KEY = false;
log::info!("[DEBUG] 首次捕获按键: vkCode={}, wParam={}", vk, w_param);
}
}
if w_param == 0x0100 || w_param == 0x0104 {
match vk {
0x70 => {
log::info!("[F1] 切换到上一个桌面(已拦截)");
switch_desktop(false);
return 1; }
0x71 => {
log::info!("[F2] 切换到下一个桌面(已拦截)");
switch_desktop(true);
return 1; }
0x72 => {
log::info!("[F3] 截图上传");
thread::spawn(|| {
screenshot::capture_and_upload();
});
}
_ => {}
}
}
}
unsafe { CallNextHookEx(null_mut(), n_code, w_param, l_param) }
}
let h_instance = unsafe { GetModuleHandleW(null_mut()) as HINSTANCE };
let hook = unsafe {
SetWindowsHookExW(WH_KEYBOARD_LL, Some(low_level_keyboard_proc), h_instance, 0)
};
if hook.is_null() {
log::warn!("全局键盘钩子注册失败");
let _ = tx.send(false);
return;
}
log::info!("全局键盘钩子已注册");
log::info!(" F1: 上一个桌面 | F2: 下一个桌面 | F3: 截图上传");
let _ = tx.send(true);
let mut msg: MSG = unsafe { std::mem::zeroed() };
loop {
let ret = unsafe { GetMessageW(&mut msg, null_mut(), 0, 0) };
if ret <= 0 {
break;
}
}
unsafe { UnhookWindowsHookEx(hook) };
log::info!("全局键盘钩子已卸载");
}
#[cfg(not(target_os = "windows"))]
{
log::warn!("当前平台暂不支持全局快捷键");
let _ = tx.send(false);
}
});
match rx.recv_timeout(Duration::from_secs(3)) {
Ok(true) => log::info!("快捷键监听线程已就绪"),
Ok(false) => log::warn!("快捷键监听启动失败"),
Err(_) => log::warn!("快捷键监听启动超时"),
}
}