kbd_global/error.rs
1//! Error types for the kbd-global runtime.
2//!
3//! Extends the core error types from `kbd` with platform-specific
4//! errors for backend initialization, device access, and permissions.
5
6/// Library-wide error type.
7///
8/// Covers hotkey parsing, registration conflicts, backend initialization,
9/// device access, permissions, and layer operations.
10#[derive(Debug, thiserror::Error)]
11pub enum Error {
12 /// A hotkey string like `"Ctrl+A"` could not be parsed.
13 #[error("parse error: {0}")]
14 Parse(#[from] kbd::error::ParseHotkeyError),
15 /// The hotkey is already bound to another action.
16 #[error("hotkey registration conflicts with an existing binding")]
17 AlreadyRegistered,
18 /// The selected backend could not be initialized.
19 #[error("failed to initialize the selected backend")]
20 BackendInit,
21 /// The selected backend is not available on this system.
22 #[error("selected backend is not available on this system")]
23 BackendUnavailable,
24 /// The current user lacks permissions to access input devices.
25 ///
26 /// On Linux, add your user to the `input` group:
27 /// ```bash
28 /// sudo usermod -aG input $USER
29 /// ```
30 #[error("missing permissions to access input devices")]
31 PermissionDenied,
32 /// An input device operation failed (open, read, ioctl, etc.).
33 #[error("input device operation failed")]
34 DeviceError,
35 /// The requested feature is not supported by the selected backend.
36 ///
37 /// Returned when calling [`HotkeyManagerBuilder::grab()`](crate::HotkeyManagerBuilder::grab)
38 /// without the `grab` feature enabled.
39 #[error("requested feature is unsupported by the selected backend")]
40 UnsupportedFeature,
41 /// The manager has been shut down or the engine thread has exited.
42 #[error("hotkey manager is no longer running")]
43 ManagerStopped,
44 /// An internal engine failure occurred (thread panic, fd error, etc.).
45 #[error("hotkey engine encountered an internal failure")]
46 EngineError,
47 /// A layer with the given name was already defined.
48 #[error("a layer with this name is already defined")]
49 LayerAlreadyDefined,
50 /// No layer with the given name has been defined.
51 #[error("no layer with this name has been defined")]
52 LayerNotDefined,
53 /// No active layers to pop from the stack.
54 #[error("no active layer to pop")]
55 EmptyLayerStack,
56}
57
58impl From<kbd::error::Error> for Error {
59 fn from(error: kbd::error::Error) -> Self {
60 match error {
61 kbd::error::Error::Parse(e) => Self::Parse(e),
62 kbd::error::Error::AlreadyRegistered => Self::AlreadyRegistered,
63 kbd::error::Error::LayerAlreadyDefined => Self::LayerAlreadyDefined,
64 kbd::error::Error::LayerNotDefined => Self::LayerNotDefined,
65 kbd::error::Error::EmptyLayerStack => Self::EmptyLayerStack,
66 _ => Self::EngineError,
67 }
68 }
69}
70
71impl From<kbd_evdev::error::Error> for Error {
72 fn from(error: kbd_evdev::error::Error) -> Self {
73 tracing::warn!(%error, "evdev backend error");
74 Self::DeviceError
75 }
76}