diff --git a/src/lib.rs b/src/lib.rs index 7e1e1fc..47da67c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,12 +5,23 @@ pub use crate::windows::*; use crate::keyboard::Key; use crate::mouse::Button; +use once_cell::sync::Lazy; use serde::{Deserialize, Serialize}; -use std::time::SystemTime; +use std::{ + collections::hash_map::HashMap, + sync::{Arc, Mutex}, + time::SystemTime, +}; pub mod keyboard; pub mod mouse; +#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize, Eq, Hash)] +pub enum EventListenType { + Mouse, + Keyboard, +} + #[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)] pub enum EventType { KeyPress(Key), @@ -26,7 +37,55 @@ pub struct Event { pub event_type: EventType, } -// pub type HookCallback = fn(event: Event); -pub type HookCallback = for<'a> fn(&'a Event); +pub enum BlockInput { + Block, + DontBlock, +} + +pub enum Bind { + NormalBind(BindHandler), + BlockBind(BlockBindHandler), + BlockableBind(BlockableBindHandler), +} + +pub type BindHandler = Arc; +pub type BlockBindHandler = Arc; +pub type BlockableBindHandler = Arc BlockInput + Send + Sync + 'static>; + +pub type EventBindMap = HashMap; +pub static EVENT_BINDS: Lazy> = Lazy::new(|| Mutex::new(EventBindMap::new())); pub struct Robot; + +impl Robot { + pub fn bind(listen_type: EventListenType, callback: F) { + EVENT_BINDS + .lock() + .unwrap() + .insert(listen_type, Bind::NormalBind(Arc::new(callback))); + } + + pub fn block_bind( + listen_type: EventListenType, + callback: F, + ) { + EVENT_BINDS + .lock() + .unwrap() + .insert(listen_type, Bind::BlockBind(Arc::new(callback))); + } + + pub fn blockable_bind BlockInput + Send + Sync + 'static>( + listen_type: EventListenType, + callback: F, + ) { + EVENT_BINDS + .lock() + .unwrap() + .insert(listen_type, Bind::BlockableBind(Arc::new(callback))); + } + + pub fn unbind(listen_type: EventListenType) { + EVENT_BINDS.lock().unwrap().remove(&listen_type); + } +} diff --git a/src/windows/keyboard.rs b/src/windows/keyboard.rs index 24a297c..ea8d82e 100644 --- a/src/windows/keyboard.rs +++ b/src/windows/keyboard.rs @@ -1,11 +1,18 @@ use crate::windows; -use crate::{Event, EventType, HookCallback, Key, Robot}; +use crate::{Bind, BlockInput, Event, EventListenType, EventType, Key, Robot, EVENT_BINDS}; use once_cell::sync::Lazy; -use std::collections::HashMap; -use std::mem::{size_of, transmute_copy}; -use std::ptr::null_mut; -use std::sync::atomic::{AtomicPtr, Ordering}; -use std::time::SystemTime; +use std::{ + collections::HashMap, + mem::{size_of, transmute_copy}, + ptr::null_mut, + sync::{ + atomic::{AtomicPtr, Ordering}, + Arc, + }, + thread::spawn, + time::SystemTime, +}; + use winapi::ctypes::c_int; use winapi::shared::minwindef::{LPARAM, LRESULT, WORD, WPARAM}; use winapi::shared::windef::HHOOK__; @@ -257,17 +264,10 @@ static VK_2_KEY_MAP: Lazy> = Lazy::new(|| { m }); -fn default_callback(event: Event) { - println!("Default : Event {:?}", event); -} - static KEYBOARD_HHOOK: Lazy> = Lazy::new(AtomicPtr::default); -static mut HOOK_CALLBACK: HookCallback = |event| { - default_callback(*event); -}; impl Robot { - pub unsafe fn key_listen(callback: HookCallback) -> Result<(), windows::HookError> { + pub unsafe fn key_listen() -> Result<(), windows::HookError> { if KEYBOARD_HHOOK.load(Ordering::Relaxed).is_null() { let r = windows::hook(WH_KEYBOARD_LL, &*KEYBOARD_HHOOK, Self::key_raw_callback); @@ -276,8 +276,6 @@ impl Robot { } } - HOOK_CALLBACK = callback; - Ok(()) } @@ -289,10 +287,6 @@ impl Robot { } } - HOOK_CALLBACK = |event| { - default_callback(*event); - }; - Ok(()) } @@ -379,7 +373,25 @@ impl Robot { event_type, time: SystemTime::now(), }; - HOOK_CALLBACK(&event); + + if let Some(bind) = EVENT_BINDS.lock().unwrap().get_mut(&EventListenType::Mouse) { + match bind { + Bind::NormalBind(cb) => { + let cb = Arc::clone(cb); + spawn(move || cb(event)); + } + Bind::BlockBind(cb) => { + let cb = Arc::clone(cb); + spawn(move || cb(event)); + return 1; + } + Bind::BlockableBind(cb) => { + if let BlockInput::Block = cb(event) { + return 1; + } + } + } + } } } CallNextHookEx(null_mut(), code, w_param, l_param) diff --git a/src/windows/mouse.rs b/src/windows/mouse.rs index 8f4cd40..5982a5d 100644 --- a/src/windows/mouse.rs +++ b/src/windows/mouse.rs @@ -1,10 +1,16 @@ use crate::windows; -use crate::{Button, Event, EventType, HookCallback, Robot}; +use crate::{Bind, BlockInput, Button, Event, EventListenType, EventType, Robot, EVENT_BINDS}; use once_cell::sync::Lazy; -use std::mem::{size_of, transmute}; -use std::ptr::null_mut; -use std::sync::atomic::{AtomicPtr, Ordering}; -use std::time::SystemTime; +use std::{ + mem::{size_of, transmute}, + ptr::null_mut, + sync::{ + atomic::{AtomicPtr, Ordering}, + Arc, + }, + thread::spawn, + time::SystemTime, +}; use winapi::ctypes::c_int; use winapi::shared::minwindef::{DWORD, HIWORD, LPARAM, LRESULT, WPARAM}; use winapi::shared::windef::{HHOOK__, POINT}; @@ -19,17 +25,10 @@ use winapi::um::winuser::{ WM_RBUTTONUP, WM_XBUTTONDOWN, WM_XBUTTONUP, XBUTTON1, XBUTTON2, }; -fn default_callback(event: Event) { - println!("Default : Event {:?}", event); -} - static MOUSE_HHOOK: Lazy> = Lazy::new(AtomicPtr::default); -static mut HOOK_CALLBACK: HookCallback = |event| { - default_callback(*event); -}; impl Robot { - pub unsafe fn mouse_listen(callback: HookCallback) -> Result<(), windows::HookError> { + pub unsafe fn mouse_listen() -> Result<(), windows::HookError> { if MOUSE_HHOOK.load(Ordering::Relaxed).is_null() { let r = windows::hook(WH_MOUSE_LL, &*MOUSE_HHOOK, Self::mouse_raw_callback); @@ -38,8 +37,6 @@ impl Robot { } } - HOOK_CALLBACK = callback; - Ok(()) } @@ -51,10 +48,6 @@ impl Robot { } } - HOOK_CALLBACK = |event| { - default_callback(*event); - }; - Ok(()) } @@ -229,7 +222,24 @@ impl Robot { time: SystemTime::now(), }; - HOOK_CALLBACK(&event); + if let Some(bind) = EVENT_BINDS.lock().unwrap().get_mut(&EventListenType::Mouse) { + match bind { + Bind::NormalBind(cb) => { + let cb = Arc::clone(cb); + spawn(move || cb(event)); + } + Bind::BlockBind(cb) => { + let cb = Arc::clone(cb); + spawn(move || cb(event)); + return 1; + } + Bind::BlockableBind(cb) => { + if let BlockInput::Block = cb(event) { + return 1; + } + } + } + } } } CallNextHookEx(null_mut(), code, w_param, l_param)