pub(crate) mod details;
mod keyboard;
#[cfg(target_os = "linux")]
mod linux;
mod mouse;
mod parse;
mod sequence;
#[cfg(target_os = "windows")]
mod windows;
#[cfg(target_os = "linux")]
use crate::linux::keyboard_mouse::kimpl;
#[cfg(target_os = "linux")]
use crate::linux::keyboard_mouse::mimpl;
#[cfg(target_os = "windows")]
use crate::windows::keyboard::kimpl;
#[cfg(target_os = "windows")]
use crate::windows::mouse::mimpl;
pub use keyboard::*;
#[cfg(target_os = "linux")]
pub use linux::*;
pub use mouse::*;
pub use parse::load_config;
pub use sequence::Sequence;
#[cfg(target_os = "windows")]
pub use windows::*;
use crate::details::registry;
use std::fmt;
use std::sync::Arc;
#[derive(Copy, Clone, Ord, PartialOrd, Hash, Eq, PartialEq, Debug)]
pub enum State {
Pressed,
Released,
}
impl Keyboard {
pub fn press(&self) {
kimpl::press(*self)
}
pub fn release(&self) {
kimpl::release(*self)
}
pub fn click(&self) {
kimpl::click(*self);
}
pub fn is_toggled(&self) -> bool {
kimpl::is_toggled(*self)
}
pub fn bind(&self, handler: impl Fn(Keyboard) + Send + Sync + 'static) {
bind_key(*self, Action::handle_kb(handler))
}
pub fn clear_bind(&self) {
remove_key_bind(*self);
}
pub fn act_on(&self, action: Action) {
bind_key(*self, action)
}
pub fn is_pressed(&self) -> bool {
registry().is_pressed(Event::Keyboard(*self))
}
}
impl Mouse {
pub fn press(&self) {
mimpl::press(*self)
}
pub fn click(&self) {
mimpl::click(*self)
}
pub fn release(&self) {
mimpl::release(*self)
}
pub fn move_to(x: i32, y: i32) {
mimpl::move_to(x, y)
}
pub fn move_by(x: i32, y: i32) {
mimpl::move_by(x, y)
}
pub fn click_at(&self, x: i32, y: i32) {
mimpl::click_at(x, y, *self);
}
pub fn track(f: impl Fn(i32, i32) + Send + Sync + 'static) {
registry().set_mouse_tracker(Some(Arc::new(Box::new(f))));
}
pub fn bind(&self, handler: impl Fn(Mouse) + Send + Sync + 'static) {
bind_button(*self, Action::handle_mouse(handler))
}
pub fn clear_bind(&self) {
remove_button_bind(*self);
}
pub fn act_on(&self, action: Action) {
bind_button(*self, action)
}
pub fn is_pressed(&self) -> bool {
registry().is_pressed(Event::Mouse(*self))
}
}
#[derive(Clone)]
pub enum InhibitEvent {
Yes,
Maybe(Arc<dyn Fn() -> InhibitEvent + Send + Sync>),
No,
}
impl InhibitEvent {
#[cfg(target_os = "windows")]
fn should_inhibit(&self) -> bool {
match self {
InhibitEvent::Yes => true,
InhibitEvent::Maybe(f) => {
matches!(f(), InhibitEvent::Yes)
}
InhibitEvent::No => false,
}
}
pub fn maybe(f: impl Fn() -> InhibitEvent + Send + Sync + 'static) -> Self {
InhibitEvent::Maybe(Arc::new(f))
}
}
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug)]
pub enum Event {
Keyboard(Keyboard),
Mouse(Mouse),
}
impl fmt::Display for Event {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Event::Keyboard(k) => f.write_fmt(format_args!("k ({})", k)),
Event::Mouse(m) => f.write_fmt(format_args!("m ({})", m)),
}
}
}
pub struct Action {
pub callback: Box<dyn Fn(Event, State) + Send + Sync + 'static>,
pub inhibit: InhibitEvent,
pub defer: bool,
pub sequencer: bool,
}
impl Action {
pub fn handle_kb(action: impl Fn(Keyboard) + Send + Sync + 'static) -> Self {
Self::handle(move |event| {
if let Event::Keyboard(key) = event {
action(key);
}
})
}
pub fn handle_mouse(action: impl Fn(Mouse) + Send + Sync + 'static) -> Self {
Self::handle(move |event| {
if let Event::Mouse(button) = event {
action(button);
}
})
}
pub fn handle(action: impl Fn(Event) + Send + Sync + 'static) -> Self {
Action {
callback: Box::new(move |event, state| {
if state == State::Pressed {
action(event)
}
}),
inhibit: InhibitEvent::No,
defer: true,
sequencer: false,
}
}
pub fn callback_kb(action: impl Fn(Keyboard) + Send + Sync + 'static) -> Self {
Self::callback(move |event| {
if let Event::Keyboard(key) = event {
action(key);
}
})
}
pub fn callback_mouse(action: impl Fn(Mouse) + Send + Sync + 'static) -> Self {
Self::callback(move |event| {
if let Event::Mouse(button) = event {
action(button);
}
})
}
pub fn callback(action: impl Fn(Event) + Send + Sync + 'static) -> Self {
Action {
callback: Box::new(move |event, state| {
if state == State::Pressed {
action(event)
}
}),
inhibit: InhibitEvent::No,
defer: false,
sequencer: false,
}
}
pub fn sequencing_kb(action: impl Fn(Keyboard) + Send + Sync + 'static) -> Self {
Self::sequencing(move |event| {
if let Event::Keyboard(key) = event {
action(key);
}
})
}
pub fn sequencing_mouse(action: impl Fn(Mouse) + Send + Sync + 'static) -> Self {
Self::sequencing(move |event| {
if let Event::Mouse(button) = event {
action(button);
}
})
}
pub fn sequencing(action: impl Fn(Event) + Send + Sync + 'static) -> Self {
Action {
callback: Box::new(move |event, state| {
if state == State::Pressed {
action(event)
}
}),
inhibit: InhibitEvent::No,
defer: false,
sequencer: true,
}
}
}
pub fn bind_any_key(action: Action) {
*registry().any_key_callback.lock().unwrap() = Some(Arc::new(action))
}
pub fn bind_key(key: Keyboard, action: Action) {
registry()
.key_callbacks
.lock()
.unwrap()
.insert(key, Arc::new(action));
}
pub fn remove_any_key_bind() {
*registry().any_key_callback.lock().unwrap() = None;
}
pub fn remove_key_bind(key: Keyboard) {
registry().key_callbacks.lock().unwrap().remove(&key);
}
pub fn bind_any_button(action: Action) {
*registry().any_button_callback.lock().unwrap() = Some(Arc::new(action))
}
pub fn bind_button(button: Mouse, action: Action) {
registry()
.button_callbacks
.lock()
.unwrap()
.insert(button, Arc::new(action));
}
pub fn remove_any_button_bind() {
*registry().any_button_callback.lock().unwrap() = None;
}
pub fn remove_button_bind(button: Mouse) {
registry().button_callbacks.lock().unwrap().remove(&button);
}
pub fn register_hotkey(sequence: &[Keyboard], callback: impl Fn() + Send + Sync + 'static) {
registry().register_hotkey(sequence, callback);
}
pub fn are_pressed(sequence: &[Keyboard]) -> bool {
registry().are_pressed(sequence)
}
pub fn set_state(key: &str, value: &str) {
registry().set_state(key, value)
}
pub fn get_state(key: &str) -> Option<String> {
registry().get_state(key)
}
pub fn unregister_hotkey(sequence: &[Keyboard]) {
registry().unregister_hotkey(sequence);
}
pub fn enable_debug() {
registry().enable_debug();
}
pub fn print_pressed_state() {
registry().print_pressed_state();
}