use std::cell::RefCell;
#[cfg(target_os = "linux")]
mod linux;
#[cfg(target_os = "macos")]
mod macos;
#[cfg(target_os = "windows")]
mod windows;
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum ListenError {
#[cfg(target_os = "linux")]
#[error("Failed to connect to X display server")]
XOpenDisplay,
#[cfg(target_os = "linux")]
#[error("X Record extension does not exist")]
XRecordExtensionMissing,
#[cfg(target_os = "linux")]
#[error("Failed to allocate X RecordRange structure")]
XRecordAllocRange,
#[cfg(target_os = "linux")]
#[error("Failed to create X Record context")]
XRecordCreateContext,
#[cfg(target_os = "linux")]
#[error("Failed to enable X Record context")]
XRecordEnableContext,
#[cfg(target_os = "macos")]
#[error("Failed to create CGEvent tap")]
CGEventTap,
#[cfg(target_os = "macos")]
#[error("Failed to create CFRunLoop source")]
CFRunLoopSource,
#[cfg(target_os = "windows")]
#[error("Failed to install WH_MOUSE_LL hook, error code: {0}")]
WHMouseHook(u32),
}
#[derive(Debug)]
pub struct MouseMoveEvent {
pub x: f64,
pub y: f64,
}
type MouseMoveCallback = Box<dyn FnMut(MouseMoveEvent)>;
thread_local! {
pub(crate) static GLOBAL_CALLBACK: RefCell<Option<MouseMoveCallback>> = RefCell::new(None);
}
pub fn listen<T>(callback: T) -> Result<(), ListenError>
where
T: FnMut(MouseMoveEvent) + 'static,
{
#[cfg(target_os = "linux")]
crate::linux::listen(callback)?;
#[cfg(target_os = "macos")]
crate::macos::listen(callback)?;
#[cfg(target_os = "windows")]
crate::windows::listen(callback)?;
Ok(())
}