// Windows platform state management use std::sync::{Mutex, atomic::{AtomicBool, AtomicPtr}}; use std::time::Instant; use winapi::{ shared::windef::POINT, shared::minwindef::DWORD, }; use ::image::RgbaImage; use once_cell::sync::{Lazy, OnceCell}; use super::types::*; // --- Thread-Safe Static Variables --- // Use AtomicBool for simple flags pub static CURSOR_HIDDEN: AtomicBool = AtomicBool::new(false); pub static CTRL_HANDLER_REGISTERED: AtomicBool = AtomicBool::new(false); // Use Lazy> for complex Option types pub static ORIGINAL_CURSORS: Lazy>>> = Lazy::new(|| Mutex::new(None)); pub static CURRENT_CURSOR_IMAGE: Lazy>> = Lazy::new(|| Mutex::new(None)); pub static LAST_CURSOR_POS: Lazy>> = Lazy::new(|| Mutex::new(None)); // Use Lazy>> for WinAPI handles with our thread-safe wrappers pub static CURSOR_WINDOW: Lazy>> = Lazy::new(|| Mutex::new(None)); pub static CURSOR_BITMAP: Lazy>> = Lazy::new(|| Mutex::new(None)); pub static CURSOR_DC: Lazy>> = Lazy::new(|| Mutex::new(None)); // Mouse hook related variables pub static MOUSE_HOOK_HANDLE: Lazy>> = Lazy::new(|| Mutex::new(None)); // This one is for CallNextHookEx to avoid locking inside the hook callback pub static CURRENT_HOOK_FOR_CALLBACK: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); pub static LAST_MOUSE_MOVE_TIME: Lazy>> = Lazy::new(|| Mutex::new(None)); // Use OnceCell for INIT to avoid `static mut` pub static INIT: OnceCell<()> = OnceCell::new(); // Reset system cursors using the Windows API pub fn reset_system_cursors() { unsafe { // Use both versions for maximum compatibility winapi::um::winuser::SystemParametersInfoW( winapi::um::winuser::SPI_SETCURSORS, 0, std::ptr::null_mut(), 0 ); // Import the Windows API function to reset system cursors #[link(name = "user32")] extern "system" { fn SystemParametersInfoA(uiAction: u32, uiParam: u32, pvParam: *mut std::ffi::c_void, fWinIni: u32) -> i32; } SystemParametersInfoA( SPI_SETCURSORS_A, 0, std::ptr::null_mut(), SPIF_UPDATEINIFILE | SPIF_SENDCHANGE ); } }