Skip to main content

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}