smart_keymap/key/
tap_dance.rs

1use core::fmt::Debug;
2use core::ops::Index;
3
4use serde::Deserialize;
5
6use crate::input;
7use crate::key;
8
9/// Reference for a tap dance key.
10#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
11pub struct Ref(pub u8);
12
13/// Configuration settings for tap dance keys.
14#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
15pub struct Config {
16    /// The timeout (in number of milliseconds) for the next press of the tap-dance.
17    #[serde(default = "default_timeout")]
18    pub timeout: u16,
19}
20
21/// The default timeout.
22pub const DEFAULT_TIMEOUT: u16 = 200;
23
24fn default_timeout() -> u16 {
25    DEFAULT_TIMEOUT
26}
27
28/// Default tap dance config.
29pub const DEFAULT_CONFIG: Config = Config {
30    timeout: DEFAULT_TIMEOUT,
31};
32
33impl Config {
34    /// Constructs a new default [Config].
35    pub const fn new() -> Self {
36        DEFAULT_CONFIG
37    }
38}
39
40impl Default for Config {
41    /// Returns the default context.
42    fn default() -> Self {
43        DEFAULT_CONFIG
44    }
45}
46
47/// A key with tap-dance functionality.
48#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
49pub struct Key<R, const MAX_TAP_DANCE_DEFINITIONS: usize> {
50    /// Tap-Dance definitions.
51    #[serde(bound(deserialize = "R: Deserialize<'de>"))]
52    #[serde(deserialize_with = "deserialize_definitions")]
53    definitions: [Option<R>; MAX_TAP_DANCE_DEFINITIONS],
54}
55
56/// Deserialize definitions.
57fn deserialize_definitions<'de, R, D, const MAX_TAP_DANCE_DEFINITIONS: usize>(
58    deserializer: D,
59) -> Result<[Option<R>; MAX_TAP_DANCE_DEFINITIONS], D::Error>
60where
61    R: Deserialize<'de>,
62    D: serde::Deserializer<'de>,
63{
64    let defs_vec: heapless::Vec<Option<R>, MAX_TAP_DANCE_DEFINITIONS> =
65        Deserialize::deserialize(deserializer)?;
66
67    match defs_vec.into_array() {
68        Ok(arr) => Ok(arr),
69        Err(_) => Err(serde::de::Error::custom(
70            "Unable to deserialize tap_dance definitions",
71        )),
72    }
73}
74
75impl<R: Copy, const MAX_TAP_DANCE_DEFINITIONS: usize> Key<R, MAX_TAP_DANCE_DEFINITIONS> {
76    /// Constructs a new tap-dance key.
77    pub const fn new(
78        definitions: [Option<R>; MAX_TAP_DANCE_DEFINITIONS],
79    ) -> Key<R, MAX_TAP_DANCE_DEFINITIONS> {
80        Key { definitions }
81    }
82
83    /// Construct the tap-dance key from the given slice of keys.
84    pub const fn from_definitions(defs: &[R]) -> Self {
85        let mut definitions: [Option<R>; MAX_TAP_DANCE_DEFINITIONS] =
86            [None; MAX_TAP_DANCE_DEFINITIONS];
87        let mut idx = 0;
88        while idx < definitions.len() && idx < defs.len() {
89            definitions[idx] = Some(defs[idx]);
90            idx += 1;
91        }
92        Self::new(definitions)
93    }
94}
95
96/// Context for [Key].
97#[derive(Debug, Clone, Copy, PartialEq)]
98pub struct Context {
99    config: Config,
100}
101
102impl Context {
103    /// Constructs a context from the given config
104    pub const fn from_config(config: Config) -> Context {
105        Context { config }
106    }
107}
108
109/// Resolution of a tap-dance key. (Index of the tap-dance definition).
110#[derive(Debug, Clone, Copy, PartialEq)]
111pub struct TapDanceResolution(u8);
112
113/// Events emitted by a tap-dance key.
114#[derive(Debug, Clone, Copy, PartialEq)]
115pub enum Event {
116    /// Timed out waiting for the next press of the tap-dance key.
117    NextPressTimeout(u8),
118}
119
120/// The state of a pressed tap-dance key.
121#[derive(Debug, Clone, Copy, PartialEq)]
122pub struct PendingKeyState {
123    press_count: u8,
124}
125
126impl PendingKeyState {
127    /// Constructs the initial pressed key state
128    fn new() -> PendingKeyState {
129        PendingKeyState { press_count: 0 }
130    }
131
132    fn handle_event(
133        &mut self,
134        context: &Context,
135        keymap_index: u16,
136        event: key::Event<Event>,
137    ) -> (Option<TapDanceResolution>, key::KeyEvents<Event>) {
138        match event {
139            key::Event::Key {
140                key_event: Event::NextPressTimeout(press_timed_out),
141                keymap_index: ev_kmi,
142            } if ev_kmi == keymap_index && press_timed_out == self.press_count => (
143                Some(TapDanceResolution(self.press_count)),
144                key::KeyEvents::no_events(),
145            ),
146
147            key::Event::Input(input::Event::Press {
148                keymap_index: ev_kmi,
149            }) if ev_kmi == keymap_index => {
150                self.press_count += 1;
151
152                let Context { config } = context;
153                let timeout_ev = Event::NextPressTimeout(self.press_count);
154
155                let key_ev = key::Event::Key {
156                    keymap_index,
157                    key_event: timeout_ev,
158                };
159                let pke = key::KeyEvents::scheduled_event(key::ScheduledEvent::after(
160                    config.timeout,
161                    key_ev,
162                ));
163
164                (None, pke)
165            }
166
167            _ => (None, key::KeyEvents::no_events()),
168        }
169    }
170}
171
172/// The key state for System. (No state).
173#[derive(Debug, Clone, Copy, PartialEq)]
174pub struct KeyState;
175
176/// The [key::System] implementation for tap dance keys.
177#[derive(Debug, Clone, Copy, PartialEq)]
178pub struct System<
179    R,
180    Keys: Index<usize, Output = Key<R, MAX_TAP_DANCE_DEFINITIONS>>,
181    const MAX_TAP_DANCE_DEFINITIONS: usize,
182> {
183    keys: Keys,
184}
185
186impl<
187        R,
188        Keys: Index<usize, Output = Key<R, MAX_TAP_DANCE_DEFINITIONS>>,
189        const MAX_TAP_DANCE_DEFINITIONS: usize,
190    > System<R, Keys, MAX_TAP_DANCE_DEFINITIONS>
191{
192    /// Constructs a new [System] with the given key data.
193    pub const fn new(key_data: Keys) -> Self {
194        Self { keys: key_data }
195    }
196}
197
198impl<
199        R: Copy + Debug,
200        Keys: Debug + Index<usize, Output = Key<R, MAX_TAP_DANCE_DEFINITIONS>>,
201        const MAX_TAP_DANCE_DEFINITIONS: usize,
202    > key::System<R> for System<R, Keys, MAX_TAP_DANCE_DEFINITIONS>
203{
204    type Ref = Ref;
205    type Context = Context;
206    type Event = Event;
207    type PendingKeyState = PendingKeyState;
208    type KeyState = KeyState;
209
210    fn new_pressed_key(
211        &self,
212        keymap_index: u16,
213        context: &Self::Context,
214        _key_ref: Ref,
215    ) -> (
216        key::PressedKeyResult<R, Self::PendingKeyState, Self::KeyState>,
217        key::KeyEvents<Self::Event>,
218    ) {
219        let td_pks = PendingKeyState::new();
220        let pk = key::PressedKeyResult::Pending(td_pks);
221
222        let timeout_ev = Event::NextPressTimeout(0);
223        let key_ev = key::Event::Key {
224            keymap_index,
225            key_event: timeout_ev,
226        };
227        let pke = key::KeyEvents::scheduled_event(key::ScheduledEvent::after(
228            context.config.timeout,
229            key_ev,
230        ));
231
232        (pk, pke)
233    }
234
235    fn update_pending_state(
236        &self,
237        pending_state: &mut Self::PendingKeyState,
238        keymap_index: u16,
239        context: &Self::Context,
240        Ref(key_index): Ref,
241        event: key::Event<Self::Event>,
242    ) -> (Option<key::NewPressedKey<R>>, key::KeyEvents<Self::Event>) {
243        let key = &self.keys[key_index as usize];
244        let (maybe_resolution, pke) = pending_state.handle_event(context, keymap_index, event);
245
246        if let Some(TapDanceResolution(idx)) = maybe_resolution {
247            let new_key_ref = key.definitions[idx as usize].unwrap();
248
249            (
250                Some(key::NewPressedKey::key(new_key_ref)),
251                pke.into_events(),
252            )
253        } else {
254            // check pending_state press_count against key definitions
255            let definition_count = key.definitions.iter().filter(|o| o.is_some()).count();
256            if pending_state.press_count as usize >= definition_count - 1 {
257                let idx = definition_count - 1;
258                let new_key_ref = key.definitions[idx].unwrap();
259
260                (
261                    Some(key::NewPressedKey::key(new_key_ref)),
262                    pke.into_events(),
263                )
264            } else {
265                (None, pke.into_events())
266            }
267        }
268    }
269
270    fn update_state(
271        &self,
272        _key_state: &mut Self::KeyState,
273        _ref: &Self::Ref,
274        _context: &Self::Context,
275        _keymap_index: u16,
276        _event: key::Event<Self::Event>,
277    ) -> key::KeyEvents<Self::Event> {
278        panic!() // tap dance has no key state
279    }
280
281    fn key_output(
282        &self,
283        _key_ref: &Self::Ref,
284        _key_state: &Self::KeyState,
285    ) -> Option<key::KeyOutput> {
286        panic!() // tap dance has no key state
287    }
288}
289
290#[cfg(test)]
291mod tests {
292    use super::*;
293
294    #[test]
295    fn test_sizeof_ref() {
296        assert_eq!(1, core::mem::size_of::<Ref>());
297    }
298
299    #[test]
300    fn test_sizeof_event() {
301        assert_eq!(1, core::mem::size_of::<Event>());
302    }
303}