Skip to main content

kbd_global/
binding_guard.rs

1//! [`BindingGuard`] — RAII guard that keeps a binding alive.
2//!
3//! When dropped, sends `Command::Unregister` to the engine. No shared
4//! state, no locks — just a binding ID and a command sender.
5//!
6//! One guard type for all binding kinds (replaces v0's `Handle`,
7//! `SequenceHandle`, `TapHoldHandle`).
8//!
9
10use std::fmt;
11
12use kbd::binding::BindingId;
13
14use crate::Error;
15use crate::engine::Command;
16use crate::engine::CommandSender;
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19enum HandleState {
20    Active,
21    Released,
22}
23
24/// Keeps a registered binding alive.
25pub struct BindingGuard {
26    id: BindingId,
27    commands: CommandSender,
28    state: HandleState,
29}
30
31impl fmt::Debug for BindingGuard {
32    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33        f.debug_struct("BindingGuard")
34            .field("id", &self.id)
35            .field("state", &self.state)
36            .finish_non_exhaustive()
37    }
38}
39
40impl BindingGuard {
41    pub(crate) fn new(id: BindingId, commands: CommandSender) -> Self {
42        Self {
43            id,
44            commands,
45            state: HandleState::Active,
46        }
47    }
48
49    /// Returns the unique identifier for this guard's binding.
50    #[must_use]
51    pub const fn binding_id(&self) -> BindingId {
52        self.id
53    }
54
55    /// Explicitly unregister this guard's binding.
56    ///
57    /// Sends an unregister command to the engine. The same unregistration
58    /// is attempted automatically when the guard is dropped.
59    ///
60    /// # Errors
61    ///
62    /// Returns [`Error::ManagerStopped`](crate::Error::ManagerStopped) if
63    /// the manager has already been shut down.
64    pub fn unregister(mut self) -> Result<(), Error> {
65        self.unregister_inner()
66    }
67
68    fn unregister_inner(&mut self) -> Result<(), Error> {
69        match self.state {
70            HandleState::Active => {
71                self.state = HandleState::Released;
72                self.commands.send(Command::Unregister { id: self.id })
73            }
74            HandleState::Released => Ok(()),
75        }
76    }
77}
78
79impl Drop for BindingGuard {
80    fn drop(&mut self) {
81        let _ = self.unregister_inner();
82    }
83}