hookmap 0.5.1

Registers hotkeys and simulates keyboard and mouse input.
Documentation
mod button_state;
mod event_broker;
pub mod interceptor;

use hookmap_core::event::{Event, NativeEventHandler, NativeEventOperation};

use self::button_state::RealButtonState;
use crate::hook::{ButtonState, Hook, HookStorage};

use std::thread;

#[derive(Debug)]
pub(crate) struct Runtime<T, S: ButtonState = RealButtonState>
where
    T: HookStorage + Send + 'static,
    <T as HookStorage>::ButtonHook: Send,
    <T as HookStorage>::MouseWheelHook: Send,
    <T as HookStorage>::MouseCursorHook: Send,
{
    storage: T,
    state: S,
}

impl<T> Runtime<T, RealButtonState>
where
    T: HookStorage + Send,
    <T as HookStorage>::ButtonHook: Send,
    <T as HookStorage>::MouseWheelHook: Send,
    <T as HookStorage>::MouseCursorHook: Send,
{
    pub(crate) fn new(storage: T) -> Self {
        Self::with_state(storage, RealButtonState)
    }
}

impl<T, S: ButtonState> Runtime<T, S>
where
    T: HookStorage + Send + 'static,
    <T as HookStorage>::ButtonHook: Send,
    <T as HookStorage>::MouseWheelHook: Send,
    <T as HookStorage>::MouseCursorHook: Send,
{
    pub(crate) fn with_state(storage: T, state: S) -> Self {
        Self { storage, state }
    }

    fn handle_event<F, E, H>(&self, fetch: F, event: E, native_handler: NativeEventHandler)
    where
        F: FnOnce(&T, E, &S) -> Vec<H>,
        E: Copy + Send + 'static,
        H: Hook<E> + Send + 'static,
    {
        let hooks = fetch(&self.storage, event, &self.state);
        let has_block_operation = hooks
            .iter()
            .map(|hook| hook.native_event_operation())
            .any(|operation| operation == NativeEventOperation::Block);
        let operation = if has_block_operation {
            NativeEventOperation::Block
        } else {
            NativeEventOperation::Dispatch
        };
        native_handler.handle(operation);
        thread::spawn(move || hooks.iter().for_each(|hook| hook.run(event)));
    }

    pub(crate) fn start(&self) {
        let event_receiver = hookmap_core::install_hook();

        while let Ok((event, native_handler)) = event_receiver.recv() {
            match event {
                Event::Button(event) => {
                    if interceptor::publish_event(event) == NativeEventOperation::Block {
                        native_handler.block();
                        continue;
                    }
                    self.handle_event(HookStorage::fetch_button_hook, event, native_handler);
                }
                Event::Wheel(event) => {
                    self.handle_event(HookStorage::fetch_mouse_wheel_hook, event, native_handler);
                }
                Event::Cursor(event) => {
                    self.handle_event(HookStorage::fetch_mouse_cursor_hook, event, native_handler);
                }
            }
        }
    }
}