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")]
58 pub timeout: u16,
59
60 #[serde(default = "default_interrupt_response")]
62 pub interrupt_response: InterruptResponse,
63
64 pub required_idle_time: Option<u16>,
70}
71
72pub const DEFAULT_TIMEOUT: u16 = 200;
74
75pub const DEFAULT_INTERRUPT_RESPONSE: InterruptResponse = InterruptResponse::Ignore;
77
78fn default_timeout() -> u16 {
79 DEFAULT_TIMEOUT
80}
81
82fn default_interrupt_response() -> InterruptResponse {
83 DEFAULT_INTERRUPT_RESPONSE
84}
85
86pub const DEFAULT_CONFIG: Config = Config {
88 timeout: DEFAULT_TIMEOUT,
89 interrupt_response: DEFAULT_INTERRUPT_RESPONSE,
90 required_idle_time: None,
91};
92
93impl Config {
94 pub const fn new() -> Self {
96 DEFAULT_CONFIG
97 }
98}
99
100impl Default for Config {
101 fn default() -> Self {
103 DEFAULT_CONFIG
104 }
105}
106
107#[derive(Debug, Clone, Copy, PartialEq)]
109pub struct Context {
110 config: Config,
111 idle_time_ms: u32,
112}
113
114impl Context {
115 pub const fn from_config(config: Config) -> Context {
117 Context {
118 config,
119 idle_time_ms: 0,
120 }
121 }
122
123 pub fn update_keymap_context(
125 &mut self,
126 keymap::KeymapContext { idle_time_ms, .. }: &keymap::KeymapContext,
127 ) {
128 self.idle_time_ms = *idle_time_ms;
129 }
130}
131
132#[derive(Debug, Clone, Copy, PartialEq)]
134pub enum TapHoldState {
135 Tap,
137 Hold,
139}
140
141#[derive(Debug, Clone, Copy, PartialEq)]
143pub enum Event {
144 TapHoldTimeout,
146}
147
148#[derive(Debug, Clone, PartialEq)]
150pub struct PendingKeyState {
151 other_pressed_keymap_index: Option<u16>,
153}
154
155impl PendingKeyState {
156 fn new() -> PendingKeyState {
158 PendingKeyState {
159 other_pressed_keymap_index: None,
160 }
161 }
162
163 fn hold_resolution(
166 &self,
167 interrupt_response: InterruptResponse,
168 keymap_index: u16,
169 event: key::Event<Event>,
170 ) -> Option<TapHoldState> {
171 match interrupt_response {
172 InterruptResponse::HoldOnKeyPress => {
173 match event {
174 key::Event::Input(input::Event::Press { .. }) => {
175 Some(TapHoldState::Hold)
177 }
178 key::Event::Input(input::Event::Release { keymap_index: ki }) => {
179 if keymap_index == ki {
180 Some(TapHoldState::Tap)
182 } else {
183 None
184 }
185 }
186 key::Event::Key {
187 key_event: Event::TapHoldTimeout,
188 ..
189 } => {
190 Some(TapHoldState::Hold)
192 }
193 _ => None,
194 }
195 }
196 InterruptResponse::HoldOnKeyTap => {
197 match event {
198 key::Event::Input(input::Event::Release { keymap_index: ki }) => {
199 if keymap_index == ki {
200 Some(TapHoldState::Tap)
202 } else if Some(ki) == self.other_pressed_keymap_index {
203 Some(TapHoldState::Hold)
205 } else {
206 None
207 }
208 }
209 key::Event::Key {
210 key_event: Event::TapHoldTimeout,
211 ..
212 } => {
213 Some(TapHoldState::Hold)
215 }
216 _ => None,
217 }
218 }
219 InterruptResponse::Ignore => {
220 match event {
221 key::Event::Input(input::Event::Release { keymap_index: ki }) => {
222 if keymap_index == ki {
223 Some(TapHoldState::Tap)
225 } else {
226 None
227 }
228 }
229 key::Event::Key {
230 key_event: Event::TapHoldTimeout,
231 ..
232 } => {
233 Some(TapHoldState::Hold)
235 }
236 _ => None,
237 }
238 }
239 }
240 }
241
242 pub fn handle_event(
244 &mut self,
245 context: &Context,
246 keymap_index: u16,
247 event: key::Event<Event>,
248 ) -> Option<TapHoldState> {
249 if let key::Event::Input(input::Event::Press { keymap_index: ki }) = event {
252 self.other_pressed_keymap_index = Some(ki);
253 }
254
255 let Context { config, .. } = context;
257 self.hold_resolution(config.interrupt_response, keymap_index, event)
258 }
259}
260
261#[derive(Debug, Clone, Copy, PartialEq)]
263pub struct KeyState;
264
265#[derive(Debug, Clone, Copy, PartialEq)]
267pub struct System<R, Keys: Index<usize, Output = Key<R>>> {
268 keys: Keys,
269}
270
271impl<R, Keys: Index<usize, Output = Key<R>>> System<R, Keys> {
272 pub const fn new(key_data: Keys) -> Self {
274 Self { keys: key_data }
275 }
276
277 fn new_pending_key(
278 &self,
279 context: &Context,
280 keymap_index: u16,
281 ) -> (PendingKeyState, key::ScheduledEvent<Event>) {
282 let timeout_ev = Event::TapHoldTimeout;
283 (
284 PendingKeyState::new(),
285 key::ScheduledEvent::after(
286 context.config.timeout,
287 key::Event::key_event(keymap_index, timeout_ev),
288 ),
289 )
290 }
291}
292
293impl<R: Copy + Debug, Keys: Debug + Index<usize, Output = Key<R>>> key::System<R>
294 for System<R, Keys>
295{
296 type Ref = Ref;
297 type Context = Context;
298 type Event = Event;
299 type PendingKeyState = PendingKeyState;
300 type KeyState = KeyState;
301
302 fn new_pressed_key(
303 &self,
304 keymap_index: u16,
305 context: &Self::Context,
306 Ref(key_index): Ref,
307 ) -> (
308 key::PressedKeyResult<R, Self::PendingKeyState, Self::KeyState>,
309 key::KeyEvents<Self::Event>,
310 ) {
311 match context.config.required_idle_time {
312 Some(required_idle_time) => {
313 if context.idle_time_ms >= required_idle_time as u32 {
314 let (th_pks, sch_ev) = self.new_pending_key(context, keymap_index);
316 let pk = key::PressedKeyResult::Pending(th_pks);
317 let pke = key::KeyEvents::scheduled_event(sch_ev.into_scheduled_event());
318 (pk, pke)
319 } else {
320 let Key {
323 tap: tap_key_ref, ..
324 } = self.keys[key_index as usize];
325 (
326 key::PressedKeyResult::NewPressedKey(key::NewPressedKey::key(tap_key_ref)),
327 key::KeyEvents::no_events(),
328 )
329 }
330 }
331 None => {
332 let (th_pks, sch_ev) = self.new_pending_key(context, keymap_index);
334 let pk = key::PressedKeyResult::Pending(th_pks);
335 let pke = key::KeyEvents::scheduled_event(sch_ev.into_scheduled_event());
336 (pk, pke)
337 }
338 }
339 }
340
341 fn update_pending_state(
342 &self,
343 pending_state: &mut Self::PendingKeyState,
344 keymap_index: u16,
345 context: &Self::Context,
346 Ref(key_index): Ref,
347 event: key::Event<Self::Event>,
348 ) -> (Option<key::NewPressedKey<R>>, key::KeyEvents<Self::Event>) {
349 let th_state = pending_state.handle_event(context, keymap_index, event);
350 if let Some(th_state) = th_state {
351 let Key { tap, hold } = self.keys[key_index as usize];
352 let new_key_ref = match th_state {
353 key::tap_hold::TapHoldState::Tap => tap,
354 key::tap_hold::TapHoldState::Hold => hold,
355 };
356
357 (
358 Some(key::NewPressedKey::key(new_key_ref)),
359 key::KeyEvents::no_events(),
360 )
361 } else {
362 (None, key::KeyEvents::no_events())
363 }
364 }
365
366 fn update_state(
367 &self,
368 _key_state: &mut Self::KeyState,
369 _ref: &Self::Ref,
370 _context: &Self::Context,
371 _keymap_index: u16,
372 _event: key::Event<Self::Event>,
373 ) -> key::KeyEvents<Self::Event> {
374 panic!() }
376
377 fn key_output(
378 &self,
379 _key_ref: &Self::Ref,
380 _key_state: &Self::KeyState,
381 ) -> Option<key::KeyOutput> {
382 panic!() }
384}
385
386#[cfg(test)]
387mod tests {
388 use super::*;
389
390 #[test]
391 fn test_sizeof_ref() {
392 assert_eq!(1, core::mem::size_of::<Ref>());
393 }
394
395 #[test]
396 fn test_sizeof_event() {
397 assert_eq!(0, core::mem::size_of::<Event>());
398 }
399}