### Example: Build hook for both mouse and keyboard Source: https://docs.rs/willhook/0.6.3/willhook/hook/struct.HookBuilder.html Demonstrates how to create a hook that captures both mouse and keyboard input. ```APIDOC ```rust use willhook::hook::HookBuilder; fn main() { let hook = HookBuilder::new() .with_mouse() .with_keyboard() .build(); assert!(hook.is_some()); } ``` ``` -------------------------------- ### Example Usage of HookBuilder Source: https://docs.rs/willhook/0.6.3/src/willhook/hook.rs.html Demonstrates creating and dropping a hook, then creating another. Ensures that hooks can be managed and replaced. ```rust /// // It could go out of scope as well, but let's drop it explicitly: /// drop(hook); /// // Since there is no "active" hook at the moment, now we can create another: /// let another_hook = HookBuilder::new().with_keyboard().build(); /// assert!(another_hook.is_some()); /// # } ``` -------------------------------- ### Create Mouse Hook Source: https://docs.rs/willhook/0.6.3/src/willhook/hook.rs.html A simple example demonstrating the creation of a mouse-specific low-level hook using `HookBuilder::new().with_mouse().build()`. ```rust # fn main() { # use willhook::hook::HookBuilder; let hook = HookBuilder::new() .with_mouse() .build(); assert!(hook.is_some()); # } ``` -------------------------------- ### Synchronizing Hook Start Source: https://docs.rs/willhook/0.6.3/src/willhook/hook/inner.rs.html This snippet shows how to wait for the hook to be fully initialized and ready. It uses a condition variable (`start_cvar`) and a mutex (`start_lock`) to ensure that subsequent operations do not proceed until the hook has started. ```rust { // Wait for the hook to start and set the value. let (start_lock, start_cvar) = &*is_started; let mut started = start_lock.lock().unwrap(); while !*started { started = start_cvar.wait(started).unwrap(); } } ``` -------------------------------- ### GlobalHooks Struct and Methods Source: https://docs.rs/willhook/0.6.3/src/willhook/hook/inner.rs.html Manages global keyboard and mouse hooks. Use `setup_mouse_hook` and `setup_keyboard_hook` to install hooks, and `drop_hooks` to remove them. `is_any_hook_present` checks if any hook is active. ```rust pub struct GlobalHooks { keyboard: Option, mouse: Option, } impl GlobalHooks { pub fn is_any_hook_present(&self) -> bool { self.keyboard.is_some() || self.mouse.is_some() } pub fn setup_mouse_hook(&mut self) { use crate::hook::inner::low_level::mouse_procedure; self.mouse = Some(InnerHook::new(WH_MOUSE_LL, Some(mouse_procedure))); } pub fn setup_keyboard_hook(&mut self) { use crate::hook::inner::low_level::keyboard_procedure; self.keyboard = Some(InnerHook::new(WH_KEYBOARD_LL, Some(keyboard_procedure))); } pub fn drop_hooks(&mut self) { self.keyboard = None; self.mouse = None; } } ``` -------------------------------- ### Build new hook after dropping the old one Source: https://docs.rs/willhook/0.6.3/willhook/hook/struct.HookBuilder.html After the existing hook is dropped, a new hook can be created. This example shows explicitly dropping the mouse hook, then successfully creating a keyboard hook. ```rust let hook = HookBuilder::new() .with_mouse() .build(); assert!(hook.is_some()); // It could go out of scope as well, but let's drop it explicitly: drop(hook); // Since there is no "active" hook at the moment, now we can create another: let another_hook = HookBuilder::new().with_keyboard().build(); assert!(another_hook.is_some()); ``` -------------------------------- ### Get Keyboard Hook Handle Source: https://docs.rs/willhook/0.6.3/src/willhook/lib.rs.html Returns the Keyboard Hook handle. Refer to Hook and HookBuilder for more details. ```rust pub fn keyboard_hook() -> Option { ``` -------------------------------- ### InnerHook New Function Source: https://docs.rs/willhook/0.6.3/src/willhook/hook/inner.rs.html Creates a new `InnerHook` by spawning a thread to install the Windows hook. It initializes `RawHook` with the hook handle and thread ID, then notifies the owner thread that the hook is ready. ```rust impl InnerHook { pub fn new(hook_id: INT, handler: HOOKPROC) -> InnerHook { // The raw hook data that will be set by the background thread let raw_hook = Arc::new(Mutex::new(RawHook::new())); let deferred_handle = raw_hook.clone(); // Used to notify the "owner" of the hook that thread started let is_started = Arc::new((Mutex::new(false), Condvar::new())); let set_started = is_started.clone(); // Start a new thread and in that thread: // - install the hook // - set the raw hook data // - notify the owner thread that raw hook data are available // - wait for the message to quit let install_hook = Arc::new(Mutex::new(Some(std::thread::spawn(move || { let hhook; unsafe { hhook = SetWindowsHookExA(hook_id, handler, NULL as HINSTANCE, NULL as DWORD); } // Set the HHOOK and ThreadID so that the "owner" thread can later kill hook and join with it if hhook != NULL as HHOOK { if let Ok(mut exclusive) = deferred_handle.lock() { exclusive.raw_handle = hhook; exclusive.thread_id = unsafe { GetCurrentThreadId() }; } } // Notify the "owner" thread that the hook is started { let (start_lock, start_cvar) = &*set_started; let mut started = start_lock.lock().unwrap(); *started = true; start_cvar.notify_one(); } ``` -------------------------------- ### HookChannels::new Source: https://docs.rs/willhook/0.6.3/src/willhook/hook/inner/channels.rs.html Creates a new HookChannels instance, initializing the necessary channels for keyboard, mouse, and general input events. ```APIDOC ## HookChannels::new ### Description Initializes and returns a new `HookChannels` struct. This involves setting up the underlying MPSC channels for sending and receiving `InputEvent`s. ### Returns A new `HookChannels` instance. ``` -------------------------------- ### From and Into Implementations Source: https://docs.rs/willhook/0.6.3/willhook/event/struct.MousePressEvent.html Provides methods for converting between types. ```rust fn from(t: T) -> T ``` ```rust fn into(self) -> U ``` -------------------------------- ### CloneToUninit Implementation (Nightly) Source: https://docs.rs/willhook/0.6.3/willhook/event/enum.KeyPress.html An experimental nightly-only API for performing copy-assignment from a KeyPress value to uninitialized memory. Use with caution. ```rust unsafe fn clone_to_uninit(&self, dest: *mut u8) ``` -------------------------------- ### mouse_hook Source: https://docs.rs/willhook/0.6.3/willhook/index.html Returns a handle for the mouse hook. This function starts a background thread to register a low-level mouse hook and returns a `Hook` object that can be used to receive mouse events. ```APIDOC ## mouse_hook ### Description Return the Mouse Hook handle. For more details see Hook and HookBuilder ### Returns - `hook::Hook`: A handle to the mouse hook. ``` -------------------------------- ### HookBuilder::new Source: https://docs.rs/willhook/0.6.3/src/willhook/hook.rs.html Creates a new instance of HookBuilder with default settings (no hooks enabled). ```APIDOC ## HookBuilder::new ### Description Creates a new instance of HookBuilder with default settings (no hooks enabled). ### Method `HookBuilder::new()` ### Returns - `Self`: A new HookBuilder instance. ``` -------------------------------- ### From and Into Implementations Source: https://docs.rs/willhook/0.6.3/willhook/event/struct.KeyboardEvent.html Standard conversions for KeyboardEvent, allowing it to be created from itself and converted into other types that implement From. ```rust fn from(t: T) -> T ``` ```rust fn into(self) -> U where U: From, ``` -------------------------------- ### Build Hook for Both Mouse and Keyboard Source: https://docs.rs/willhook/0.6.3/src/willhook/hook.rs.html Demonstrates how to construct a `Hook` instance that captures both mouse and keyboard events by chaining `with_mouse()` and `with_keyboard()` methods on `HookBuilder` before calling `build()`. ```rust use willhook::hook::HookBuilder; fn main() { let hook = HookBuilder::new() .with_mouse() .with_keyboard() .build(); assert!(hook.is_some()); } ``` -------------------------------- ### HookBuilder::new().with_mouse().with_keyboard().build() Source: https://docs.rs/willhook/0.6.3/src/willhook/hook.rs.html Builds a low-level hook that captures both mouse and keyboard events simultaneously. ```APIDOC ## HookBuilder::new().with_mouse().with_keyboard().build() ### Description Creates a low-level hook capable of capturing both mouse and keyboard input events. This allows for comprehensive input monitoring. ### Method ```rust HookBuilder::new().with_mouse().with_keyboard().build() ``` ### Parameters None directly on `build()`, configuration is done via chained methods like `with_mouse()` and `with_keyboard()`. ### Request Example ```rust use willhook::hook::HookBuilder; let hook = HookBuilder::new() .with_mouse() .with_keyboard() .build() .unwrap(); // The hook is active for both mouse and keyboard events // ... // When `hook` goes out of scope, the low-level hook is removed. ``` ### Response #### Success Response - **Hook** (struct) - A handle to the active low-level hook monitoring both mouse and keyboard. ``` -------------------------------- ### Create and Manage Low-Level Hook Handle Source: https://docs.rs/willhook/0.6.3/src/willhook/hook.rs.html Demonstrates creating a low-level mouse hook using `HookBuilder`. The hook handle is managed within a scope, and upon exiting the scope, the underlying Windows hook is automatically removed. ```rust # fn main() { # use willhook::hook::HookBuilder; { // create low-level hook and return the handle let hook = HookBuilder::new().with_mouse().build().unwrap(); } // hook handle goes out of scope, // underlying low-level hook(s) are unhooked from Windows # } ``` -------------------------------- ### Create MouseWheel Event Source: https://docs.rs/willhook/0.6.3/src/willhook/event/details.rs.html Initializes a MouseWheel event structure using the WPARAM parameter, which contains information about the wheel delta. ```rust impl MouseWheel { pub fn new(wm_mouse_param: WPARAM) -> MouseWheel { use MouseWheel::*; ``` -------------------------------- ### Test Utilities for Keyboard Procedure Source: https://docs.rs/willhook/0.6.3/src/willhook/hook/inner/low_level.rs.html Provides helper functions for testing the `keyboard_procedure`. This includes asserting calls to `call_next_hook`, checking received input events, and setting return values for mocked functions. ```rust mod keyboard_procedure_tests { use quickcheck::TestResult; use winapi::{ shared::{ minwindef::{WPARAM, LPARAM, UINT, INT, DWORD, LRESULT}, basetsd::ULONG_PTR}, um::winuser::{WM_KEYDOWN, HC_ACTION, WM_INPUT, WM_SYSKEYDOWN, WM_KEYUP, WM_SYSKEYUP}}; use crate::event::{InputEvent, KeyPress, KeyboardEvent}; use super::{keyboard_procedure, CALL_NEXT_HOOK_CALLS, CALL_NEXT_HOOK_RETURN}; use super::GLOBAL_CHANNEL; use quickcheck::*; struct MOCK_KBD_LL_HOOK_STRUCT { vk_code: DWORD, scan_code: DWORD, flags: DWORD, time: DWORD, a_info: ULONG_PTR, } unsafe fn assert_call_next_hook_called_once(expected: (usize, i32, usize, isize)) { assert_call_next_hook_equals(Ok(expected)); assert_call_next_hook_equals(Err(std::sync::mpsc::TryRecvError::Empty)); } unsafe fn assert_call_next_hook_equals(expected: Result<(usize, i32, usize, isize), std::sync::mpsc::TryRecvError>) { let actual = CALL_NEXT_HOOK_CALLS.1.try_recv(); assert_eq!(expected, actual); } unsafe fn assert_one_input_event_present(ie: InputEvent) { assert_current_input_event_equals(Ok(ie)); assert_there_are_no_more_input_events(); } unsafe fn assert_there_are_no_more_input_events() { assert_current_input_event_equals(Err(std::sync::mpsc::TryRecvError::Empty)); } unsafe fn assert_current_input_event_equals(r: Result) { let ie = GLOBAL_CHANNEL.try_recv(); assert_eq!(r, ie); } unsafe fn set_call_next_hook_return_value(rv: LPARAM) { *(CALL_NEXT_HOOK_RETURN.lock().unwrap()) = rv; } quickcheck! { fn invalid_code_calls_next_hook(code: INT, rv: LRESULT) -> TestResult { if code == HC_ACTION { return TestResult::discard() } let w_param = WM_INPUT as WPARAM; let l_param = NULL as LPARAM; unsafe { set_call_next_hook_return_value(rv); assert_eq!(rv, keyboard_procedure(code, w_param, l_param)); assert_call_next_hook_called_once((NULL as usize, code, w_param, l_param)); assert_there_are_no_more_input_events(); } TestResult::from_bool(true) } } unsafe fn run_invalid_kbd_ll_hook_struct(w_param: UINT, press: KeyPress) { let w_param = w_param as WPARAM; ``` -------------------------------- ### Blanket Implementations for KeyboardKey Source: https://docs.rs/willhook/0.6.3/willhook/event/enum.KeyboardKey.html Lists various blanket implementations available for KeyboardKey. ```APIDOC ## T::type_id ### Description Gets the `TypeId` of `self`. ### Method `type_id` ### Response - `TypeId` - The type identifier of the instance. ``` ```APIDOC ## T::borrow ### Description Immutably borrows from an owned value. ### Method `borrow` ### Response - `&T` - An immutable reference to the borrowed value. ``` ```APIDOC ## T::borrow_mut ### Description Mutably borrows from an owned value. ### Method `borrow_mut` ### Response - `&mut T` - A mutable reference to the borrowed value. ``` ```APIDOC ## T::clone_to_uninit ### Description Performs copy-assignment from `self` to `dest`. This is a nightly-only experimental API. ### Method `clone_to_uninit` ### Parameters - **dest** (`*mut u8`) - A mutable pointer to the destination memory. ### Safety This method is unsafe and requires the caller to ensure `dest` is valid memory. ``` ```APIDOC ## T::from ### Description Returns the argument unchanged. ### Method `from` ### Parameters - **t** (`T`) - The value to convert. ### Response - `T` - The original value. ``` ```APIDOC ## T::into ### Description Calls `U::from(self)`. That is, this conversion is whatever the implementation of `From for U` chooses to do. ### Method `into` ### Response - `U` - The converted value. ``` ```APIDOC ## T::to_owned ### Description Creates owned data from borrowed data, usually by cloning. ### Method `to_owned` ### Response - `T` - An owned version of the data. ``` ```APIDOC ## T::clone_into ### Description Uses borrowed data to replace owned data, usually by cloning. ### Method `clone_into` ### Parameters - **target** (`&mut T`) - A mutable reference to the owned data to be replaced. ``` ```APIDOC ## T::try_from ### Description Performs the conversion. ### Method `try_from` ### Parameters - **value** (`U`) - The value to convert. ### Response - `Result>::Error>` - A result containing the converted value or an error. ``` ```APIDOC ## T::try_into ### Description Performs the conversion. ### Method `try_into` ### Response - `Result>::Error>` - A result containing the converted value or an error. ``` -------------------------------- ### PartialOrd Implementation for KeyboardKey Source: https://docs.rs/willhook/0.6.3/willhook/event/enum.KeyboardKey.html Provides methods for partial ordering comparisons between KeyboardKey instances. ```APIDOC ## KeyboardKey::partial_cmp ### Description This method returns an ordering between `self` and `other` values if one exists. ### Method `partial_cmp` ### Parameters - **other** (`&KeyboardKey`) - The other KeyboardKey to compare against. ### Response - `Option` - An optional ordering value. ``` ```APIDOC ## KeyboardKey::lt ### Description Tests less than (for `self` and `other`) and is used by the `<` operator. ### Method `lt` ### Parameters - **other** (`&Rhs`) - The other value to compare against. ### Response - `bool` - True if `self` is less than `other`, false otherwise. ``` ```APIDOC ## KeyboardKey::le ### Description Tests less than or equal to (for `self` and `other`) and is used by the `<=` operator. ### Method `le` ### Parameters - **other** (`&Rhs`) - The other value to compare against. ### Response - `bool` - True if `self` is less than or equal to `other`, false otherwise. ``` ```APIDOC ## KeyboardKey::gt ### Description Tests greater than (for `self` and `other`) and is used by the `>` operator. ### Method `gt` ### Parameters - **other** (`&Rhs`) - The other value to compare against. ### Response - `bool` - True if `self` is greater than `other`, false otherwise. ``` ```APIDOC ## KeyboardKey::ge ### Description Tests greater than or equal to (for `self` and `other`) and is used by the `>=` operator. ### Method `ge` ### Parameters - **other** (`&Rhs`) - The other value to compare against. ### Response - `bool` - True if `self` is greater than or equal to `other`, false otherwise. ``` ```APIDOC ## KeyboardKey::ne ### Description Tests for `!=`. The default implementation is almost always sufficient, and should not be overridden without very good reason. ### Method `ne` ### Parameters - **other** (`&Rhs`) - The other value to compare against. ### Response - `bool` - True if `self` is not equal to `other`, false otherwise. ``` -------------------------------- ### Limitation: At least one hook type must be specified Source: https://docs.rs/willhook/0.6.3/willhook/hook/struct.HookBuilder.html Illustrates that the build process fails if no hook types (mouse or keyboard) are selected. ```APIDOC ```rust let bad_hook = HookBuilder::new().build(); assert!(bad_hook.is_none()); ``` ``` -------------------------------- ### from Function Source: https://docs.rs/willhook/0.6.3/willhook/event/enum.MouseButton.html Creates a MouseButton enum variant from raw Windows message parameters and a low-level hook structure. ```APIDOC ## `impl MouseButton` ### `pub unsafe fn from(wm_mouse_param: WPARAM, ms_ll_hook_struct: *const MSLLHOOKSTRUCT) -> Self` Creates a `MouseButton` enum variant from the provided Windows message parameters and low-level hook structure. ``` -------------------------------- ### MouseWheel::new Constructor Source: https://docs.rs/willhook/0.6.3/willhook/event/enum.MouseWheel.html Creates a new MouseWheel enum variant from a WPARAM. ```APIDOC ## MouseWheel::new ### Description Creates a new `MouseWheel` enum variant. ### Method `pub fn new(wm_mouse_param: WPARAM) -> MouseWheel` ``` -------------------------------- ### Partial Comparison of MouseButtons Source: https://docs.rs/willhook/0.6.3/willhook/event/enum.MouseButton.html Provides partial ordering comparison for MouseButton values, returning an `Option`. This is used for types that may not always be comparable. ```rust fn partial_cmp(&self, other: &MouseButton) -> Option ``` -------------------------------- ### Any Trait Implementation Source: https://docs.rs/willhook/0.6.3/willhook/event/enum.KeyPress.html Provides runtime type information for KeyPress values. This is part of Rust's trait system for dynamic dispatch. ```rust fn type_id(&self) -> TypeId ``` -------------------------------- ### Safely Create KeyboardKey from Raw Pointer Source: https://docs.rs/willhook/0.6.3/src/willhook/event/details.rs.html Safely creates a KeyboardKey from a raw pointer to KBDLLHOOKSTRUCT, returning None if the pointer is null. ```rust impl KeyboardKey { pub unsafe fn optionally_from(value: *const KBDLLHOOKSTRUCT) -> Option { if value.is_null() { None } else { Some(KeyboardKey::from((*value).vkCode)) } } } ``` -------------------------------- ### from Method Source: https://docs.rs/willhook/0.6.3/willhook/event/enum.KeyboardKey.html This method converts a u32 value into a KeyboardKey enum variant. This is useful for mapping raw key codes received from the operating system to the defined KeyboardKey enum. ```APIDOC ## fn from(code: DWORD) -> Self ### Description Converts a `DWORD` (unsigned 32-bit integer) representing a key code into a `KeyboardKey` enum variant. ### Parameters - **code** (DWORD): The unsigned 32-bit integer representing the key code. ``` -------------------------------- ### try_into Method Source: https://docs.rs/willhook/0.6.3/willhook/event/enum.MouseWheel.html Performs a conversion operation for the Mouse Wheel event, returning a Result that may contain an error. ```APIDOC #### fn try_into(self) -> Result>::Error> Performs the conversion. ``` -------------------------------- ### Order KeyboardKey Variants Source: https://docs.rs/willhook/0.6.3/willhook/event/enum.KeyboardKey.html Implements ordering for `KeyboardKey` variants, allowing them to be compared and sorted. This is useful for algorithms that require ordered collections or comparisons. ```rust fn cmp(&self, other: &KeyboardKey) -> Ordering ``` ```rust fn max(self, other: Self) -> Self where Self: Sized, ``` ```rust fn min(self, other: Self) -> Self where Self: Sized, ``` ```rust fn clamp(self, min: Self, max: Self) -> Self where Self: Sized, ``` -------------------------------- ### HookBuilder::new() - Initialize Hook Builder Source: https://docs.rs/willhook/0.6.3/src/willhook/hook.rs.html Creates a new instance of HookBuilder with default settings (no hooks enabled). ```rust pub fn new() -> Self { Self { mouse: false, keyboard: false, } } ``` -------------------------------- ### Create KeyboardEvent from WinAPI data Source: https://docs.rs/willhook/0.6.3/src/willhook/event/details.rs.html Constructs a KeyboardEvent from raw Windows API key code and hook struct. Requires unsafe block due to raw pointer dereferencing. ```rust #![allow(non_snake_case)] use std::convert::From; use winapi::shared::windef::* use winapi::shared::minwindef::* use winapi::um::winuser::* use crate::event::* impl KeyboardEvent { pub unsafe fn new(wm_key_code: WPARAM, kbd_hook_struct: *const KBDLLHOOKSTRUCT) -> Self { KeyboardEvent{ pressed: KeyPress::from(wm_key_code), key: KeyboardKey::optionally_from(kbd_hook_struct), is_injected: IsEventInjected::optionally_from_keyboard(kbd_hook_struct), } } } ``` -------------------------------- ### KeyboardKey::optionally_from Source: https://docs.rs/willhook/0.6.3/src/willhook/event/details.rs.html Safely creates a KeyboardKey from a raw pointer to KBDLLHOOKSTRUCT, returning None if the pointer is null. ```APIDOC ## KeyboardKey::optionally_from ### Description Safely creates a `KeyboardKey` from a raw pointer to `KBDLLHOOKSTRUCT`. If the pointer is null, it returns `None`. ### Parameters - `value` (*const KBDLLHOOKSTRUCT) - A raw pointer to the keyboard hook structure. ### Returns - `Option` - `Some(KeyboardKey)` if the pointer is valid, `None` otherwise. ``` -------------------------------- ### MousePressEvent::new Source: https://docs.rs/willhook/0.6.3/willhook/event/struct.MousePressEvent.html Constructor for creating a new MousePressEvent instance from raw Windows message parameters. ```APIDOC ### `new` ```rust pub unsafe fn new( wm_mouse_param: WPARAM, ms_ll_hook_struct: *const MSLLHOOKSTRUCT, ) -> MousePressEvent ``` Constructor for creating a new MousePressEvent instance from raw Windows message parameters. ``` -------------------------------- ### Clone Implementation for Point Source: https://docs.rs/willhook/0.6.3/willhook/event/struct.Point.html Provides methods for cloning Point instances. ```APIDOC ### impl Clone for Point #### fn clone(&self) -> Point Returns a duplicate of the value. Read more #### fn clone_from(&mut self, source: &Self) Performs copy-assignment from `source`. Read more ``` -------------------------------- ### HookBuilder::with_keyboard Source: https://docs.rs/willhook/0.6.3/src/willhook/hook.rs.html Configures the builder to include a keyboard hook when `build()` is called. ```APIDOC ## HookBuilder::with_keyboard ### Description Instructs the builder to spawn a new keyboard hook in a background thread when `HookBuilder::build()` is called. ### Method `builder.with_keyboard()` ### Returns - `Self`: The modified HookBuilder instance. ``` -------------------------------- ### MouseWheel::new Source: https://docs.rs/willhook/0.6.3/src/willhook/event/details.rs.html Initializes a MouseWheel event, typically used for scroll wheel actions. ```APIDOC ## MouseWheel::new ### Description Initializes a `MouseWheel` event. This is typically used for handling scroll wheel movements (vertical or horizontal). ### Parameters - `wm_mouse_param` (WPARAM) - The window message parameter, which can provide information about the scroll direction and amount. ### Returns - `MouseWheel` - A `MouseWheel` object representing the scroll event. ``` -------------------------------- ### Keyboard Procedure for Event Handling Source: https://docs.rs/willhook/0.6.3/src/willhook/hook/inner/low_level.rs.html Handles incoming keyboard events. If the code is not `HC_ACTION`, it forwards the message to `CallNextHookEx`. Otherwise, it creates a `KeyboardEvent` and sends it through the global channel. ```rust pub unsafe extern "system" fn keyboard_procedure( code: INT, wm_key_code: WPARAM, win_hook_struct: LPARAM, ) -> LRESULT { // If code is less than zero then the hook procedure // must pass the message to the CallNextHookEx function // without further processing and should return the value returned by CallNextHookEx. if code != HC_ACTION { // hhk - This parameter (the 1st one) is ignored, according to MSDN // args... - The subsequent parameters are simply forwarded return call_next_hook(null_mut() as HHOOK, code, wm_key_code, win_hook_struct); } let kbd_hook_struct: *mut KBDLLHOOKSTRUCT = win_hook_struct as *mut _; let keyboard_event = KeyboardEvent::new(wm_key_code, kbd_hook_struct); let _ignore_error = GLOBAL_CHANNEL.send_keyboard_event(keyboard_event).is_err(); call_next_hook(null_mut() as HHOOK, code, wm_key_code, win_hook_struct) } ``` -------------------------------- ### PartialEq Implementation for MousePressEvent Source: https://docs.rs/willhook/0.6.3/willhook/event/struct.MousePressEvent.html Provides methods for testing equality between MousePressEvent values. ```rust fn eq(&self, other: &MousePressEvent) -> bool ``` ```rust fn ne(&self, other: &Rhs) -> bool ``` -------------------------------- ### Create Keyboard Hook Source: https://docs.rs/willhook/0.6.3/src/willhook/lib.rs.html Use this function to create a hook that captures keyboard events. Refer to Hook and HookBuilder for more details. ```rust pub fn keyboard_hook() -> Option { HookBuilder::new().with_keyboard().build() } ``` -------------------------------- ### PartialEq Implementation for Point Source: https://docs.rs/willhook/0.6.3/willhook/event/struct.Point.html Enables equality checks for Point instances. ```APIDOC ### impl PartialEq for Point #### fn eq(&self, other: &Point) -> bool Tests for `self` and `other` values to be equal, and is used by `==`. #### fn ne(&self, other: &Rhs) -> bool Tests for `!=`. The default implementation is almost always sufficient, and should not be overridden without very good reason. ``` -------------------------------- ### Clone Implementation for KeyboardEvent Source: https://docs.rs/willhook/0.6.3/willhook/event/struct.KeyboardEvent.html Provides methods to duplicate KeyboardEvent instances. `clone_from` allows for efficient in-place copying. ```rust fn clone(&self) -> KeyboardEvent ``` ```rust fn clone_from(&mut self, source: &Self) ``` -------------------------------- ### From for KeyPress Source: https://docs.rs/willhook/0.6.3/willhook/event/enum.KeyPress.html Allows conversion from a usize (representing a key code) into a KeyPress enum variant. ```APIDOC ## impl From for KeyPress ### fn from(code: WPARAM) -> Self Converts to this type from the input type. ``` -------------------------------- ### Keyboard Procedure for Low-Level Hooks Source: https://docs.rs/willhook/0.6.3/src/willhook/hook/inner/low_level.rs.html Handles keyboard events for low-level hooks. It processes keyboard actions, asserts that the next hook is called, and verifies the input event structure. ```rust let l_param = NULL as LPARAM; keyboard_procedure(HC_ACTION, w_param as usize, l_param); assert_call_next_hook_called_once((NULL as usize, HC_ACTION, w_param, l_param)); assert_one_input_event_present(InputEvent::Keyboard(KeyboardEvent{ pressed: press, key: None, is_injected: None, })); ``` -------------------------------- ### Handle Hook Build Failure (No Hook Type Specified) Source: https://docs.rs/willhook/0.6.3/src/willhook/hook.rs.html Illustrates a scenario where `HookBuilder::build()` returns `None`. This occurs when no specific hook types (like mouse or keyboard) are enabled, violating the requirement that at least one hook type must be selected. ```rust # fn main() { # use willhook::hook::HookBuilder; let bad_hook = HookBuilder::new().build(); assert!(bad_hook.is_none()); # } ``` -------------------------------- ### HookBuilder::build Source: https://docs.rs/willhook/0.6.3/src/willhook/hook.rs.html Builds the requested hooks and returns a handle. Fails if any hooks are already active. ```APIDOC ## HookBuilder::build ### Description Builds the requested hooks (mouse and/or keyboard) and returns a common handle for them. If any hooks are already active, the build fails and returns `None`. ### Method `builder.build()` ### Returns - `Option`: A `Some(Hook)` if the hooks were successfully built, or `None` if no hooks were requested or if hooks were already active. ``` -------------------------------- ### KeyboardEvent Constructor Source: https://docs.rs/willhook/0.6.3/willhook/event/struct.KeyboardEvent.html Provides an unsafe constructor for creating a KeyboardEvent instance from raw window message parameters. ```APIDOC ## impl KeyboardEvent ### `pub unsafe fn new(wm_key_code: WPARAM, kbd_hook_struct: *const KBDLLHOOKSTRUCT) -> Self` Creates a new KeyboardEvent instance. ``` -------------------------------- ### TryFrom Implementation Source: https://docs.rs/willhook/0.6.3/willhook/event/enum.MouseWheelDirection.html Provides fallible conversion from one type to another. ```rust impl TryFrom for T where U: Into, ``` -------------------------------- ### Create MouseEvent from Windows Message Parameters Source: https://docs.rs/willhook/0.6.3/src/willhook/event/details.rs.html Constructs a MouseEvent from Windows message parameters (WPARAM and MSLLHOOKSTRUCT). Differentiates between press, move, and wheel events. ```rust impl MouseEvent { pub unsafe fn new(wm_mouse_param: WPARAM, ms_ll_hook_struct: *const MSLLHOOKSTRUCT) -> Self { use MouseEventType::*; MouseEvent{ is_injected: IsEventInjected::optionally_from_mouse(ms_ll_hook_struct), event: match wm_mouse_param as u32 { // Mouse press WM_LBUTTONDOWN | WM_LBUTTONUP | WM_LBUTTONDBLCLK => Press(MousePressEvent::new(wm_mouse_param, ms_ll_hook_struct)), WM_RBUTTONDOWN | WM_RBUTTONUP | WM_RBUTTONDBLCLK => Press(MousePressEvent::new(wm_mouse_param, ms_ll_hook_struct)), WM_MBUTTONDOWN | WM_MBUTTONUP | WM_MBUTTONDBLCLK => Press(MousePressEvent::new(wm_mouse_param, ms_ll_hook_struct)), WM_XBUTTONDOWN | WM_XBUTTONUP | WM_XBUTTONDBLCLK => Press(MousePressEvent::new(wm_mouse_param, ms_ll_hook_struct)), // Mouse move WM_MOUSEMOVE => Move(MouseMoveEvent::new(ms_ll_hook_struct)), // Wheel move WM_MOUSEWHEEL | WM_MOUSEHWHEEL => Wheel(MouseWheelEvent::new(wm_mouse_param, ms_ll_hook_struct)), _ => Other(wm_mouse_param), } } } } ``` -------------------------------- ### willhook() Source: https://docs.rs/willhook/0.6.3/willhook/fn.willhook.html Retrieves the handle for mouse and keyboard hooks. ```APIDOC ## willhook() ### Description Returns the handle for both mouse and keyboard hook. For more details see Hook and HookBuilder. ### Signature ```rust pub fn willhook() -> Option ``` ### Returns - `Option`: An Option containing a Hook handle if successful, otherwise None. ``` -------------------------------- ### From Implementation for Point Source: https://docs.rs/willhook/0.6.3/willhook/event/struct.Point.html Allows conversion from POINT type to Point. ```APIDOC ### impl From for Point #### fn from(value: POINT) -> Self Converts to this type from the input type. ``` -------------------------------- ### Into Implementation Source: https://docs.rs/willhook/0.6.3/willhook/event/enum.MouseWheelDirection.html Converts a value into another type that implements From. ```rust fn into(self) -> U where U: From, ``` -------------------------------- ### TryFrom for T Source: https://docs.rs/willhook/0.6.3/willhook/event/enum.InputEvent.html Provides the `try_from` method for attempting conversions. ```APIDOC #### fn try_from(value: U) -> Result>::Error> Performs the conversion from `value` (type `U`) into type `T`. Returns a `Result` which is `Ok(T)` on success or `Err(>::Error)` on failure. ``` -------------------------------- ### HookBuilder::with_keyboard() - Enable Keyboard Hook Source: https://docs.rs/willhook/0.6.3/src/willhook/hook.rs.html Configures the builder to include a keyboard hook when build() is called. This method consumes the builder and returns it. ```rust /// Instructs builder to spawn a new keyboard hook in background thread on HookBuilder::build(). pub fn with_keyboard(mut self) -> Self { self.keyboard = true; self } ``` -------------------------------- ### TryInto for MouseEvent Source: https://docs.rs/willhook/0.6.3/willhook/event/struct.MouseEvent.html Provides the `try_into` method for converting a type `T` into a `U` where `U` implements `TryFrom`. This is useful for safe, fallible conversions. ```APIDOC ### impl TryInto for T where U: TryFrom, #### type Error = >::Error The type returned in the event of a conversion error. #### fn try_into(self) -> Result>::Error> Performs the conversion. ``` -------------------------------- ### PartialEq Implementation for KeyPress Source: https://docs.rs/willhook/0.6.3/willhook/event/enum.KeyPress.html Enables equality checks between KeyPress enum values. Use this for comparing if two key press events are the same. ```rust fn eq(&self, other: &KeyPress) -> bool ``` ```rust fn ne(&self, other: &Rhs) -> bool ``` -------------------------------- ### StructuralPartialEq Implementation for Point Source: https://docs.rs/willhook/0.6.3/willhook/event/struct.Point.html Indicates that Point implements the StructuralPartialEq trait. ```APIDOC ### impl StructuralPartialEq for Point ``` -------------------------------- ### Partial Comparison Implementation for MouseWheelDirection Source: https://docs.rs/willhook/0.6.3/willhook/event/enum.MouseWheelDirection.html Provides partial ordering comparison for MouseWheelDirection values. ```rust fn partial_cmp(&self, other: &MouseWheelDirection) -> Option ``` -------------------------------- ### Copy Implementation for Point Source: https://docs.rs/willhook/0.6.3/willhook/event/struct.Point.html Indicates that Point implements the Copy trait. ```APIDOC ### impl Copy for Point ``` -------------------------------- ### Debug Implementation for Point Source: https://docs.rs/willhook/0.6.3/willhook/event/struct.Point.html Enables debugging output for Point instances. ```APIDOC ### impl Debug for Point #### fn fmt(&self, f: &mut Formatter<'_>) -> Result Formats the value using the given formatter. Read more ``` -------------------------------- ### PartialOrd Implementation for Point Source: https://docs.rs/willhook/0.6.3/willhook/event/struct.Point.html Provides partial ordering comparisons for Point instances. ```APIDOC ### impl PartialOrd for Point #### fn partial_cmp(&self, other: &Point) -> Option This method returns an ordering between `self` and `other` values if one exists. Read more #### fn lt(&self, other: &Rhs) -> bool Tests less than (for `self` and `other`) and is used by the `<` operator. Read more #### fn le(&self, other: &Rhs) -> bool Tests less than or equal to (for `self` and `other`) and is used by the `<=` operator. Read more #### fn gt(&self, other: &Rhs) -> bool Tests greater than (for `self` and `other`) and is used by the `>` operator. Read more #### fn ge(&self, other: &Rhs) -> bool Tests greater than or equal to (for `self` and `other`) and is used by the `>=` operator. Read more ``` -------------------------------- ### Handle Hook Build Failure (Existing Hook) Source: https://docs.rs/willhook/0.6.3/src/willhook/hook.rs.html Shows that attempting to build a new hook while another hook is still active will result in `build()` returning `None`. This enforces the library's limitation of allowing only one active hook at a time. ```rust # fn main() { # use willhook::hook::HookBuilder; let hook = HookBuilder::new() .with_mouse() .build(); assert!(hook.is_some()); // Building second hook while the first one is still in scope will fail. // Even if that second hook is keyboard hook: let another_hook = HookBuilder::new().with_keyboard().build(); assert!(another_hook.is_none()); # } ``` -------------------------------- ### PartialEq Implementation for MouseWheelEvent Source: https://docs.rs/willhook/0.6.3/willhook/event/struct.MouseWheelEvent.html Defines equality comparison for MouseWheelEvent instances. ```rust fn eq(&self, other: &MouseWheelEvent) -> bool ``` ```rust fn ne(&self, other: &Rhs) -> bool ``` -------------------------------- ### Freeze Implementation for Point Source: https://docs.rs/willhook/0.6.3/willhook/event/struct.Point.html Indicates that Point data does not need to be frozen. ```rust impl Freeze for Point ``` -------------------------------- ### PartialOrd Implementation for KeyboardEvent Source: https://docs.rs/willhook/0.6.3/willhook/event/struct.KeyboardEvent.html Defines a partial ordering for KeyboardEvent instances, supporting comparison operators like <, <=, >, and >=. ```rust fn partial_cmp(&self, other: &KeyboardEvent) -> Option ``` ```rust fn lt(&self, other: &Rhs) -> bool ``` ```rust fn le(&self, other: &Rhs) -> bool ``` ```rust fn gt(&self, other: &Rhs) -> bool ``` ```rust fn ge(&self, other: &Rhs) -> bool ``` -------------------------------- ### Create a Low-Level Hook Source: https://docs.rs/willhook/0.6.3/willhook/hook/struct.Hook.html Creates a low-level hook for mouse events and returns a handle. The hook is automatically removed when the handle goes out of scope. ```rust { // create low-level hook and return the handle let hook = HookBuilder::new().with_mouse().build().unwrap(); } // hook handle goes out of scope, // underlying low-level hook(s) are unhooked from Windows ``` -------------------------------- ### PartialEq Implementation for KeyboardEvent Source: https://docs.rs/willhook/0.6.3/willhook/event/struct.KeyboardEvent.html Enables equality checks between KeyboardEvent instances. ```rust fn eq(&self, other: &KeyboardEvent) -> bool ``` ```rust fn ne(&self, other: &Rhs) -> bool ``` -------------------------------- ### CloneInto Implementation Source: https://docs.rs/willhook/0.6.3/willhook/event/enum.MouseWheelDirection.html Uses borrowed data to replace owned data, usually by cloning. ```rust fn clone_into(&self, target: &mut T) where T: Clone, ``` -------------------------------- ### Hash Implementation for Point Source: https://docs.rs/willhook/0.6.3/willhook/event/struct.Point.html Provides hashing capabilities for Point instances. ```APIDOC ### impl Hash for Point #### fn hash<__H: Hasher>(&self, state: &mut __H) Feeds this value into the given `Hasher`. Read more #### fn hash_slice(data: &[Self], state: &mut H) where H: Hasher, Self: Sized, Feeds a slice of this type into the given `Hasher`. Read more ``` -------------------------------- ### Eq Implementation for Point Source: https://docs.rs/willhook/0.6.3/willhook/event/struct.Point.html Indicates that Point implements the Eq trait. ```APIDOC ### impl Eq for Point ``` -------------------------------- ### HookBuilder::new().with_keyboard().build() Source: https://docs.rs/willhook/0.6.3/src/willhook/hook.rs.html Builds a low-level hook for keyboard events. Similar to the mouse hook, it returns a handle that manages the hook's lifecycle. ```APIDOC ## HookBuilder::new().with_keyboard().build() ### Description Creates a low-level hook that captures keyboard events. The `Hook` handle ensures the hook is properly unhooked when it is no longer needed. ### Method ```rust HookBuilder::new().with_keyboard().build() ``` ### Parameters None directly on `build()`, configuration is done via chained methods like `with_keyboard()`. ### Request Example ```rust use willhook::hook::HookBuilder; let hook = HookBuilder::new().with_keyboard().build().unwrap(); // The hook is active here // ... // When `hook` goes out of scope, the low-level hook is removed. ``` ### Response #### Success Response - **Hook** (struct) - A handle to the active low-level keyboard hook. ``` -------------------------------- ### HookBuilder::with_mouse Source: https://docs.rs/willhook/0.6.3/src/willhook/hook.rs.html Configures the builder to include a mouse hook when `build()` is called. ```APIDOC ## HookBuilder::with_mouse ### Description Instructs the builder to spawn a new mouse hook in a background thread when `HookBuilder::build()` is called. ### Method `builder.with_mouse()` ### Returns - `Self`: The modified HookBuilder instance. ``` -------------------------------- ### Conditional CallNextHookEx Implementation Source: https://docs.rs/willhook/0.6.3/src/willhook/hook/inner/low_level.rs.html Provides a conditional implementation of `CallNextHookEx`. It uses the actual Windows API function during normal compilation and a mock implementation during tests. ```rust use crate::event::*; use crate::hook::inner::GLOBAL_CHANNEL; use std::ptr::null_mut(); use winapi::{shared::{minwindef::*, windef::*}, um::winuser::{CallNextHookEx, KBDLLHOOKSTRUCT, MSLLHOOKSTRUCT, HC_ACTION}}; // In the case of normal compilation, just call CallNextHookEx #[cfg(not(test))] unsafe fn call_next_hook(hhk: HHOOK, n_code: INT, w_param: WPARAM, l_param: LPARAM) -> LRESULT { CallNextHookEx(hhk, n_code, w_param, l_param) } // In the case of tests, use home-made mock for CallNextHookEx #[cfg(test)] use std::sync::Mutex; #[cfg(test)] use std::sync::mpsc::*; #[cfg(test)] use once_cell::sync::Lazy; #[cfg(test)] static mut CALL_NEXT_HOOK_CALLS: Lazy<(Sender<(usize, INT, WPARAM, LPARAM)>, Receiver<(usize, INT, WPARAM, LPARAM)>)> = Lazy::new(|| { channel() }); #[cfg(test)] static mut CALL_NEXT_HOOK_RETURN: Mutex = Mutex::new(0 as LRESULT); #[cfg(test)] unsafe fn call_next_hook(hhk: HHOOK, n_code: INT, w_param: WPARAM, l_param: LPARAM) -> LRESULT { assert!(CALL_NEXT_HOOK_CALLS.0.send((hhk as usize, n_code, w_param, l_param)).is_ok()); let rv = *(CALL_NEXT_HOOK_RETURN.lock().unwrap()); rv } ``` -------------------------------- ### Create Mouse Hook Source: https://docs.rs/willhook/0.6.3/src/willhook/lib.rs.html Use this function to create a hook that captures mouse events. Refer to Hook and HookBuilder for more details. ```rust pub fn mouse_hook() -> Option { HookBuilder::new().with_mouse().build() } ``` -------------------------------- ### Compare Implementation for MouseWheelDirection Source: https://docs.rs/willhook/0.6.3/willhook/event/enum.MouseWheelDirection.html Compares two MouseWheelDirection values and returns an Ordering. ```rust fn cmp(&self, other: &MouseWheelDirection) -> Ordering ``` -------------------------------- ### Min Implementation for MouseWheelDirection Source: https://docs.rs/willhook/0.6.3/willhook/event/enum.MouseWheelDirection.html Returns the minimum of two MouseWheelDirection values. ```rust fn min(self, other: Self) -> Self where Self: Sized, ``` -------------------------------- ### PartialEq Implementation for Point Source: https://docs.rs/willhook/0.6.3/willhook/event/struct.Point.html Enables equality comparisons between Point values. ```rust fn eq(&self, other: &Point) -> bool ``` ```rust fn ne(&self, other: &Rhs) -> bool ``` -------------------------------- ### Try Receiving Events from Hook Source: https://docs.rs/willhook/0.6.3/willhook/hook/struct.Hook.html Attempts to receive an event from the background hook thread without blocking. Returns an error if no events are currently available. ```rust // create low-level hook and store handle in `hook` let hook = HookBuilder::new().with_mouse().build().unwrap(); // This example definitely can't receive any user input, so the try_recv will fail: assert!(hook.try_recv().is_err()); assert_eq!(hook.try_recv().err(), Some(TryRecvError::Empty)); ``` -------------------------------- ### Compare MouseButton for Ordering Source: https://docs.rs/willhook/0.6.3/willhook/event/enum.MouseButton.html Implements total ordering for MouseButton variants, enabling comparisons like less than, greater than, and equality. This is essential for sorting or using MouseButton in ordered data structures. ```rust fn cmp(&self, other: &MouseButton) -> Ordering ``` -------------------------------- ### KeyboardEvent::new Source: https://docs.rs/willhook/0.6.3/src/willhook/event/details.rs.html Constructs a new KeyboardEvent from a window message key code and keyboard hook structure. ```APIDOC ## KeyboardEvent::new ### Description Constructs a new `KeyboardEvent` from a `WPARAM` representing the key code and a `KBDLLHOOKSTRUCT` pointer. ### Signature `pub unsafe fn new(wm_key_code: WPARAM, kbd_hook_struct: *const KBDLLHOOKSTRUCT) -> Self` ### Parameters * `wm_key_code` (WPARAM) - The virtual-key code of the key event. * `kbd_hook_struct` (*const KBDLLHOOKSTRUCT) - A pointer to the keyboard hook structure containing additional event details. ### Returns A new `KeyboardEvent` instance. ``` -------------------------------- ### Enable Serde Support for Willhook Source: https://docs.rs/willhook/0.6.3/src/willhook/lib.rs.html To enable Serde support for event serialization, add the 'serde' feature to your willhook dependency in Cargo.toml. ```toml willhook = { version = "^0.6.2", features = ["serde"]} ``` -------------------------------- ### Create MousePressEvent from Raw Data Source: https://docs.rs/willhook/0.6.3/src/willhook/event/details.rs.html Initializes a MousePressEvent using the mouse message parameter and hook structure. Determines the pressed button and its state. ```rust impl MousePressEvent { pub unsafe fn new(wm_mouse_param: WPARAM, ms_ll_hook_struct: *const MSLLHOOKSTRUCT) -> MousePressEvent { MousePressEvent { pressed: MouseButtonPress::from(wm_mouse_param), button: MouseButton::from(wm_mouse_param, ms_ll_hook_struct), } } } ``` -------------------------------- ### From for T Implementation Source: https://docs.rs/willhook/0.6.3/willhook/event/enum.KeyPress.html A trivial implementation of From for T, where the value is returned unchanged. This is a common identity conversion. ```rust fn from(t: T) -> T ``` -------------------------------- ### Try Receiving an Event from a Hook Source: https://docs.rs/willhook/0.6.3/src/willhook/hook.rs.html Shows how to use `try_recv` to non-blockingly check for incoming events from a hook. If no events are available, it returns `TryRecvError::Empty`. This is useful for polling for events without halting execution. ```rust # fn main() { # use willhook::hook::HookBuilder; # use std::sync::mpsc::TryRecvError; // create low-level hook and store handle in `hook` let hook = HookBuilder::new().with_mouse().build().unwrap(); // This example definitely can't receive any user input, so the try_recv will fail: assert!(hook.try_recv().is_err()); assert_eq!(hook.try_recv().err(), Some(TryRecvError::Empty)); # } ``` -------------------------------- ### HookBuilder::with_mouse() - Enable Mouse Hook Source: https://docs.rs/willhook/0.6.3/src/willhook/hook.rs.html Configures the builder to include a mouse hook when build() is called. This method consumes the builder and returns it. ```rust /// Instructs builder to spawn a new mouse hook in background thread on HookBuilder::build(). pub fn with_mouse(mut self) -> Self { self.mouse = true; self } ``` -------------------------------- ### MouseWheel::new Constructor Source: https://docs.rs/willhook/0.6.3/willhook/event/enum.MouseWheel.html Creates a new MouseWheel enum variant from a WPARAM value. This is useful for converting raw window messages into typed mouse wheel events. ```rust pub fn new(wm_mouse_param: WPARAM) -> MouseWheel ``` -------------------------------- ### Create Combined Keyboard and Mouse Hook Source: https://docs.rs/willhook/0.6.3/src/willhook/lib.rs.html Use this function to create a hook that captures both keyboard and mouse events. Refer to Hook and HookBuilder for more details. ```rust pub fn willhook() -> Option { HookBuilder::new().with_keyboard().with_mouse().build() } ```