kbd_global/lib.rs
1#![cfg_attr(docsrs, feature(doc_cfg))]
2
3//! Global hotkey runtime for `kbd` on Linux.
4//!
5//! `kbd-global` wraps the pure matching engine from [`kbd`] in a threaded
6//! runtime that owns device discovery, hotplug handling, and command-based
7//! registration APIs. It reads from evdev devices directly, so it works
8//! on Wayland, X11, and TTY without display-server integration.
9//!
10//! # Quick start
11//!
12//! ```rust,no_run
13//! use kbd::hotkey::{Hotkey, Modifier};
14//! use kbd::key::Key;
15//! use kbd_global::manager::HotkeyManager;
16//!
17//! let manager = HotkeyManager::new()?;
18//!
19//! let _guard = manager.register(
20//! Hotkey::new(Key::C).modifier(Modifier::Ctrl).modifier(Modifier::Shift),
21//! || println!("fired"),
22//! )?;
23//! # Ok::<(), Box<dyn std::error::Error>>(())
24//! ```
25//!
26//! [`HotkeyManager`](manager::HotkeyManager) is the main entry point.
27//! Registration returns a [`BindingGuard`](binding_guard::BindingGuard)
28//! that keeps the binding alive — drop it to unregister. Key types,
29//! actions, and layer definitions come from [`kbd`].
30//!
31//! # Layers
32//!
33//! Layers let you swap between different binding sets at runtime:
34//!
35//! ```rust,no_run
36//! use kbd::action::Action;
37//! use kbd::key::Key;
38//! use kbd::layer::Layer;
39//! use kbd_global::manager::HotkeyManager;
40//!
41//! let manager = HotkeyManager::new()?;
42//!
43//! let layer = Layer::new("vim-normal")
44//! .bind(Key::J, || println!("down"))?
45//! .bind(Key::K, || println!("up"))?;
46//!
47//! manager.define_layer(layer)?;
48//! manager.push_layer("vim-normal")?;
49//! # Ok::<(), Box<dyn std::error::Error>>(())
50//! ```
51//!
52//! Layers stack — the most recently pushed layer is checked first.
53//! See [`kbd::layer`] for oneshot, swallow, and timeout options.
54//!
55//! # Architecture
56//!
57//! [`HotkeyManager`](manager::HotkeyManager) sends typed commands to a
58//! dedicated engine thread over a channel, using an `eventfd` wake
59//! mechanism to interrupt `poll()`. All mutable runtime state lives in
60//! the engine thread.
61//!
62//! ```text
63//! +------------------+ +------------------+
64//! | HotkeyManager | -- commands -->| Engine thread |
65//! | (command sender) |<--- replies ---| (event loop) |
66//! +------------------+ +------------------+
67//! |
68//! v
69//! poll(devices + wake_fd)
70//! ```
71//!
72//! Create a manager with [`HotkeyManager::new()`](manager::HotkeyManager::new)
73//! or [`HotkeyManager::builder()`](manager::HotkeyManager::builder), register
74//! bindings, and keep the returned guards alive. Dropping a guard unregisters
75//! its binding; dropping the manager stops the runtime.
76//!
77//! # Backend selection
78//!
79//! Currently only [`Backend::Evdev`](backend::Backend::Evdev) is available.
80//! It reads `/dev/input/event*` directly and requires permission to access
81//! Linux input devices:
82//!
83//! ```bash
84//! sudo usermod -aG input $USER
85//! ```
86//!
87//! Use the builder for explicit backend selection or grab mode:
88//!
89//! ```rust,no_run
90//! use kbd_global::backend::Backend;
91//! use kbd_global::manager::HotkeyManager;
92//!
93//! let manager = HotkeyManager::builder()
94//! .backend(Backend::Evdev)
95//! .build()?;
96//! # Ok::<(), Box<dyn std::error::Error>>(())
97//! ```
98//!
99//! # Feature flags
100//!
101//! | Feature | Effect |
102//! |---------|--------|
103//! | `grab` | Exclusive device capture via `EVIOCGRAB` with uinput forwarding for unmatched events |
104//! | `serde` | Adds `Serialize`/`Deserialize` to shared key and hotkey types via [`kbd`] |
105//!
106//! # Current limitations
107//!
108//! - Linux only
109//! - evdev is the only backend
110//! - [`Action::EmitHotkey`](kbd::action::Action::EmitHotkey) and [`Action::EmitSequence`](kbd::action::Action::EmitSequence) are not yet implemented in the runtime
111//!
112//! # See also
113//!
114//! - [`kbd`] — core dispatch engine, key types, and layer logic
115//! - [`kbd-evdev`](https://docs.rs/kbd-evdev) — low-level device backend used by this crate
116
117pub mod backend;
118pub mod binding_guard;
119mod engine;
120pub mod error;
121pub mod manager;