1use core::fmt::Debug;
2use core::ops::Index;
3
4use serde::Deserialize;
5
6use crate::input;
7use crate::key;
8use crate::keymap;
9
10#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
12pub struct Ref(pub u8);
13
14#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
16pub struct Key<R> {
17 pub tap: R,
19 pub hold: R,
21}
22
23impl<R> Key<R> {
24 pub const fn new(tap: R, hold: R) -> Key<R> {
26 Key { tap, hold }
27 }
28}
29
30#[cfg(feature = "std")]
31impl<R: Default> Default for Key<R> {
32 fn default() -> Self {
33 Key {
34 tap: R::default(),
35 hold: R::default(),
36 }
37 }
38}
39
40#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
42pub enum InterruptResponse {
43 Ignore,
46 HoldOnKeyPress,
48 HoldOnKeyTap,
51}
52
53#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
55pub struct Config {
56 #[serde(default = "default_timeout")]
62 pub timeout: Option<u16>,
63
64 #[serde(default = "default_interrupt_response")]
66 pub interrupt_response: InterruptResponse,
67
68 pub required_idle_time: Option<u16>,
74}
75
76pub const DEFAULT_TIMEOUT: u16 = 200;
78
79pub const DEFAULT_INTERRUPT_RESPONSE: InterruptResponse = InterruptResponse::Ignore;
81
82fn default_timeout() -> Option<u16> {
83 Some(DEFAULT_TIMEOUT)
84}
85
86fn default_interrupt_response() -> InterruptResponse {
87 DEFAULT_INTERRUPT_RESPONSE
88}
89
90pub const DEFAULT_CONFIG: Config = Config {
92 timeout: Some(DEFAULT_TIMEOUT),
93 interrupt_response: DEFAULT_INTERRUPT_RESPONSE,
94 required_idle_time: None,
95};
96
97impl Config {
98 pub const fn new() -> Self {
100 DEFAULT_CONFIG
101 }
102}
103
104impl Default for Config {
105 fn default() -> Self {
107 DEFAULT_CONFIG
108 }
109}
110
111#[derive(Debug, Clone, Copy, PartialEq)]
113pub struct Context {
114 config: Config,
115 idle_time_ms: u32,
116}
117
118impl Context {
119 pub const fn from_config(config: Config) -> Context {
121 Context {
122 config,
123 idle_time_ms: 0,
124 }
125 }
126
127 pub fn reset(&mut self) {
129 *self = Self::from_config(self.config);
130 }
131
132 pub fn update_keymap_context(
134 &mut self,
135 keymap::KeymapContext { idle_time_ms, .. }: &keymap::KeymapContext,
136 ) {
137 self.idle_time_ms = *idle_time_ms;
138 }
139}
140
141#[derive(Debug, Clone, Copy, PartialEq)]
143pub enum TapHoldState {
144 Tap,
146 Hold,
148}
149
150#[derive(Debug, Clone, Copy, PartialEq)]
152pub enum Event {
153 TapHoldTimeout,
155}
156
157#[derive(Debug, Clone, PartialEq)]
159pub struct PendingKeyState {
160 other_pressed_keymap_index: Option<u16>,
162}
163
164impl PendingKeyState {
165 fn new() -> PendingKeyState {
167 PendingKeyState {
168 other_pressed_keymap_index: None,
169 }
170 }
171
172 fn hold_resolution(
175 &self,
176 interrupt_response: InterruptResponse,
177 keymap_index: u16,
178 event: key::Event<Event>,
179 ) -> Option<TapHoldState> {
180 match interrupt_response {
181 InterruptResponse::HoldOnKeyPress => {
182 match event {
183 key::Event::Input(input::Event::Press { .. }) => {
184 Some(TapHoldState::Hold)
186 }
187 key::Event::Input(input::Event::Release { keymap_index: ki }) => {
188 if keymap_index == ki {
189 Some(TapHoldState::Tap)
191 } else {
192 None
193 }
194 }
195 key::Event::Key {
196 key_event: Event::TapHoldTimeout,
197 ..
198 } => {
199 Some(TapHoldState::Hold)
201 }
202 _ => None,
203 }
204 }
205 InterruptResponse::HoldOnKeyTap => {
206 match event {
207 key::Event::Input(input::Event::Release { keymap_index: ki }) => {
208 if keymap_index == ki {
209 Some(TapHoldState::Tap)
211 } else if Some(ki) == self.other_pressed_keymap_index {
212 Some(TapHoldState::Hold)
214 } else {
215 None
216 }
217 }
218 key::Event::Key {
219 key_event: Event::TapHoldTimeout,
220 ..
221 } => {
222 Some(TapHoldState::Hold)
224 }
225 _ => None,
226 }
227 }
228 InterruptResponse::Ignore => {
229 match event {
230 key::Event::Input(input::Event::Release { keymap_index: ki }) => {
231 if keymap_index == ki {
232 Some(TapHoldState::Tap)
234 } else {
235 None
236 }
237 }
238 key::Event::Key {
239 key_event: Event::TapHoldTimeout,
240 ..
241 } => {
242 Some(TapHoldState::Hold)
244 }
245 _ => None,
246 }
247 }
248 }
249 }
250
251 pub fn handle_event(
253 &mut self,
254 context: &Context,
255 keymap_index: u16,
256 event: key::Event<Event>,
257 ) -> Option<TapHoldState> {
258 if let key::Event::Input(input::Event::Press { keymap_index: ki }) = event {
261 self.other_pressed_keymap_index = Some(ki);
262 }
263
264 let Context { config, .. } = context;
266 self.hold_resolution(config.interrupt_response, keymap_index, event)
267 }
268}
269
270#[derive(Debug, Clone, Copy, PartialEq)]
272pub struct KeyState;
273
274#[derive(Debug, Clone, Copy, PartialEq)]
276pub struct System<R, Keys: Index<usize, Output = Key<R>>> {
277 keys: Keys,
278}
279
280impl<R, Keys: Index<usize, Output = Key<R>>> System<R, Keys> {
281 pub const fn new(key_data: Keys) -> Self {
283 Self { keys: key_data }
284 }
285
286 fn new_pending_key(
287 &self,
288 context: &Context,
289 keymap_index: u16,
290 ) -> (PendingKeyState, Option<key::ScheduledEvent<Event>>) {
291 let pending = PendingKeyState::new();
292 let scheduled = context.config.timeout.map(|timeout| {
293 key::ScheduledEvent::after(
294 timeout,
295 key::Event::key_event(keymap_index, Event::TapHoldTimeout),
296 )
297 });
298 (pending, scheduled)
299 }
300}
301
302impl<R: Copy + Debug, Keys: Debug + Index<usize, Output = Key<R>>> key::System<R>
303 for System<R, Keys>
304{
305 type Ref = Ref;
306 type Context = Context;
307 type Event = Event;
308 type PendingKeyState = PendingKeyState;
309 type KeyState = KeyState;
310
311 fn new_pressed_key(
312 &self,
313 keymap_index: u16,
314 context: &Self::Context,
315 Ref(key_index): Ref,
316 ) -> (
317 key::PressedKeyResult<R, Self::PendingKeyState, Self::KeyState>,
318 key::KeyEvents<Self::Event>,
319 ) {
320 match context.config.required_idle_time {
321 Some(required_idle_time) => {
322 if context.idle_time_ms >= required_idle_time as u32 {
323 let (th_pks, maybe_sch_ev) = self.new_pending_key(context, keymap_index);
325 let pk = key::PressedKeyResult::Pending(th_pks);
326 let pke = match maybe_sch_ev {
327 Some(sch_ev) => {
328 key::KeyEvents::scheduled_event(sch_ev.into_scheduled_event())
329 }
330 None => key::KeyEvents::no_events(),
331 };
332 (pk, pke)
333 } else {
334 let Key {
337 tap: tap_key_ref, ..
338 } = self.keys[key_index as usize];
339 (
340 key::PressedKeyResult::NewPressedKey(key::NewPressedKey::key(tap_key_ref)),
341 key::KeyEvents::no_events(),
342 )
343 }
344 }
345 None => {
346 let (th_pks, maybe_sch_ev) = self.new_pending_key(context, keymap_index);
348 let pk = key::PressedKeyResult::Pending(th_pks);
349 let pke = match maybe_sch_ev {
350 Some(sch_ev) => key::KeyEvents::scheduled_event(sch_ev.into_scheduled_event()),
351 None => key::KeyEvents::no_events(),
352 };
353 (pk, pke)
354 }
355 }
356 }
357
358 fn update_pending_state(
359 &self,
360 pending_state: &mut Self::PendingKeyState,
361 keymap_index: u16,
362 context: &Self::Context,
363 Ref(key_index): Ref,
364 event: key::Event<Self::Event>,
365 ) -> (Option<key::NewPressedKey<R>>, key::KeyEvents<Self::Event>) {
366 let th_state = pending_state.handle_event(context, keymap_index, event);
367 if let Some(th_state) = th_state {
368 let Key { tap, hold } = self.keys[key_index as usize];
369 let new_key_ref = match th_state {
370 key::tap_hold::TapHoldState::Tap => tap,
371 key::tap_hold::TapHoldState::Hold => hold,
372 };
373
374 (
375 Some(key::NewPressedKey::key(new_key_ref)),
376 key::KeyEvents::no_events(),
377 )
378 } else {
379 (None, key::KeyEvents::no_events())
380 }
381 }
382
383 fn update_state(
384 &self,
385 _key_state: &mut Self::KeyState,
386 _ref: &Self::Ref,
387 _context: &Self::Context,
388 _keymap_index: u16,
389 _event: key::Event<Self::Event>,
390 ) -> key::KeyEvents<Self::Event> {
391 panic!() }
393
394 fn key_output(
395 &self,
396 _key_ref: &Self::Ref,
397 _key_state: &Self::KeyState,
398 ) -> Option<key::KeyOutput> {
399 panic!() }
401}
402
403#[cfg(test)]
404mod tests {
405 use super::*;
406
407 #[test]
408 fn test_sizeof_ref() {
409 assert_eq!(1, core::mem::size_of::<Ref>());
410 }
411
412 #[test]
413 fn test_sizeof_event() {
414 assert_eq!(0, core::mem::size_of::<Event>());
415 }
416}