kbd-global
Global hotkey runtime for kbd — threaded engine, device management, and backend selection for Linux.
When a key combination happens on a Linux keyboard, do something. Works on Wayland, X11, and TTY — it reads evdev directly, no display server integration needed.
[]
= "0.1"
= "0.1"
Quick start
use *;
use HotkeyManager;
let manager = new?;
let _guard = manager.register?;
park;
# Ok::
Key types, actions, and layers come from kbd. kbd-global provides the runtime ([HotkeyManager], [BindingGuard], [Backend]).
Prerequisites
Your user must be in the input group to read /dev/input/event* devices:
Log out and back in for the group change to take effect.
Architecture
HotkeyManager is the public API. Internally it sends commands to a
dedicated engine thread over an mpsc channel, with an eventfd wake
mechanism to interrupt poll(). All mutable state lives in the engine —
no locks, no shared mutation.
┌──────────────────┐ Command ┌──────────────────┐
│ HotkeyManager │ ─────────────► │ Engine thread │
│ (command sender) │ ◄───────────── │ (event loop) │
└──────────────────┘ Reply └──────────────────┘
│
poll(devices + wake_fd)
Layers
Layers let you define context-dependent bindings. Define a layer, push it onto the stack, and its bindings take priority over global ones:
use *;
use HotkeyManager;
let manager = new?;
let layer = new
.bind;
manager.define_layer?;
manager.push_layer?;
// Key::J now fires "down" instead of any global binding
# Ok::
Feature flags
| Feature | Effect |
|---|---|
grab |
Enables exclusive device capture via EVIOCGRAB with uinput forwarding for non-hotkey events |
serde |
Adds Serialize/Deserialize to key and hotkey types (via kbd) |
The grab feature requires udev rules for uinput access — see the docs for setup instructions.
License
kbd-global is licensed under the MIT license. See the LICENSE file for more information.