Skip to main content

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