hookmap-core 0.2.1

Global hooks and input simulation fo keyboard and mouse.
Documentation
//! Representation of keyboard and mouse events.
//!
//! When an event is generated, [`EventReceiver::recv`] can be called to receive the event.
//! The received event is blocked (other programs are not yet notified).
//!
//! Calling [`NativeEventHandler::block`] will continue blocking and no notification will be made.
//! Alternatively, calling [`NativeEventHandler::dispatch`] will notify other programs of the event.
//! If neither is called, the event is notified.
//!
//! # Warning
//!
//! On Windows, Calling function that perform input (e.g. [`Button::press`]) before calling [`NativeEventHandler::block`]
//! or [`NativeEventHandler::dispatch`] will take time.
//! Therefore, call these functions before calling function that performs the input.
//!
//! # Examples
//!
//! ```no_run
//! let rx = hookmap_core::install_hook();
//! while let Ok((event, native_handler)) = rx.recv() {
//!     // Blocks all the events
//!     native_handler.block();
//! }
//! ```

use super::button::{Button, ButtonAction};
use std::sync::mpsc::{self, Receiver, Sender, SyncSender};

/// Indicates whether to pass the generated event to the next program or not.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum NativeEventOperation {
    /// Do not pass the generated event to the next program.
    Block,

    /// Pass the generated event to the next program.
    Dispatch,
}

impl Default for &NativeEventOperation {
    fn default() -> Self {
        &NativeEventOperation::Dispatch
    }
}

impl Default for NativeEventOperation {
    fn default() -> Self {
        *<&NativeEventOperation>::default()
    }
}

/// Indicates button event.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ButtonEvent {
    /// Target of the generated event.
    pub target: Button,

    /// Action of the generated event.
    pub action: ButtonAction,

    /// Whether this event was generated by this program.
    /// If you type on your keyboard and an event is generated, this value will be `false`.
    pub injected: bool,
}

/// Indicates mouse cursor event.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct CursorEvent {
    /// Mouse cursor movement `(x, y)`
    pub delta: (i32, i32),

    /// Whether this event was generated by this program.
    pub injected: bool,
}

/// Indicates mouse wheel event.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct WheelEvent {
    /// Amout of mouse wheel rotation
    /// Upward rotation takes a positive value, downward rotation a negative value.
    pub delta: i32,

    /// Whether this event was generated by this program.
    pub injected: bool,
}

/// An event
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Event {
    /// Button event
    Button(ButtonEvent),

    /// Mouse wheel event
    Wheel(WheelEvent),

    /// Mouse cursor event
    Cursor(CursorEvent),
}

/// Decide whether to notify other programs of generated events.
#[derive(Debug)]
pub struct NativeEventHandler {
    tx: Option<Sender<NativeEventOperation>>,
}

impl NativeEventHandler {
    fn new(tx: Sender<NativeEventOperation>) -> Self {
        Self { tx: Some(tx) }
    }

    /// Decides whether or not to notify by argument.
    pub fn handle(mut self, operation: NativeEventOperation) {
        self.tx.take().unwrap().send(operation).unwrap();
    }

    // Notifies an event.
    pub fn dispatch(self) {
        self.handle(NativeEventOperation::Dispatch);
    }

    // Does not notify an event.
    pub fn block(self) {
        self.handle(NativeEventOperation::Block);
    }
}

impl Drop for NativeEventHandler {
    fn drop(&mut self) {
        if let Some(tx) = self.tx.take() {
            tx.send(NativeEventOperation::default()).unwrap();
        }
    }
}

#[derive(Debug, Clone)]
pub(crate) struct EventSender {
    tx: SyncSender<(Event, NativeEventHandler)>,
}

impl EventSender {
    pub(crate) fn new(tx: SyncSender<(Event, NativeEventHandler)>) -> Self {
        Self { tx }
    }

    pub(crate) fn send(&self, event: Event) -> NativeEventOperation {
        let (tx, rx) = mpsc::channel();
        let sent_data = (event, NativeEventHandler::new(tx));

        self.tx.send(sent_data).unwrap();
        rx.recv().unwrap()
    }
}

pub type EventReceiver = Receiver<(Event, NativeEventHandler)>;

pub(crate) fn channel() -> (EventSender, EventReceiver) {
    const BOUND: usize = 1;
    let (tx, rx) = mpsc::sync_channel(BOUND);
    (EventSender::new(tx), rx)
}