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 update_keymap_context(
129 &mut self,
130 keymap::KeymapContext { idle_time_ms, .. }: &keymap::KeymapContext,
131 ) {
132 self.idle_time_ms = *idle_time_ms;
133 }
134}
135
136#[derive(Debug, Clone, Copy, PartialEq)]
138pub enum TapHoldState {
139 Tap,
141 Hold,
143}
144
145#[derive(Debug, Clone, Copy, PartialEq)]
147pub enum Event {
148 TapHoldTimeout,
150}
151
152#[derive(Debug, Clone, PartialEq)]
154pub struct PendingKeyState {
155 other_pressed_keymap_index: Option<u16>,
157}
158
159impl PendingKeyState {
160 fn new() -> PendingKeyState {
162 PendingKeyState {
163 other_pressed_keymap_index: None,
164 }
165 }
166
167 fn hold_resolution(
170 &self,
171 interrupt_response: InterruptResponse,
172 keymap_index: u16,
173 event: key::Event<Event>,
174 ) -> Option<TapHoldState> {
175 match interrupt_response {
176 InterruptResponse::HoldOnKeyPress => {
177 match event {
178 key::Event::Input(input::Event::Press { .. }) => {
179 Some(TapHoldState::Hold)
181 }
182 key::Event::Input(input::Event::Release { keymap_index: ki }) => {
183 if keymap_index == ki {
184 Some(TapHoldState::Tap)
186 } else {
187 None
188 }
189 }
190 key::Event::Key {
191 key_event: Event::TapHoldTimeout,
192 ..
193 } => {
194 Some(TapHoldState::Hold)
196 }
197 _ => None,
198 }
199 }
200 InterruptResponse::HoldOnKeyTap => {
201 match event {
202 key::Event::Input(input::Event::Release { keymap_index: ki }) => {
203 if keymap_index == ki {
204 Some(TapHoldState::Tap)
206 } else if Some(ki) == self.other_pressed_keymap_index {
207 Some(TapHoldState::Hold)
209 } else {
210 None
211 }
212 }
213 key::Event::Key {
214 key_event: Event::TapHoldTimeout,
215 ..
216 } => {
217 Some(TapHoldState::Hold)
219 }
220 _ => None,
221 }
222 }
223 InterruptResponse::Ignore => {
224 match event {
225 key::Event::Input(input::Event::Release { keymap_index: ki }) => {
226 if keymap_index == ki {
227 Some(TapHoldState::Tap)
229 } else {
230 None
231 }
232 }
233 key::Event::Key {
234 key_event: Event::TapHoldTimeout,
235 ..
236 } => {
237 Some(TapHoldState::Hold)
239 }
240 _ => None,
241 }
242 }
243 }
244 }
245
246 pub fn handle_event(
248 &mut self,
249 context: &Context,
250 keymap_index: u16,
251 event: key::Event<Event>,
252 ) -> Option<TapHoldState> {
253 if let key::Event::Input(input::Event::Press { keymap_index: ki }) = event {
256 self.other_pressed_keymap_index = Some(ki);
257 }
258
259 let Context { config, .. } = context;
261 self.hold_resolution(config.interrupt_response, keymap_index, event)
262 }
263}
264
265#[derive(Debug, Clone, Copy, PartialEq)]
267pub struct KeyState;
268
269#[derive(Debug, Clone, Copy, PartialEq)]
271pub struct System<R, Keys: Index<usize, Output = Key<R>>> {
272 keys: Keys,
273}
274
275impl<R, Keys: Index<usize, Output = Key<R>>> System<R, Keys> {
276 pub const fn new(key_data: Keys) -> Self {
278 Self { keys: key_data }
279 }
280
281 fn new_pending_key(
282 &self,
283 context: &Context,
284 keymap_index: u16,
285 ) -> (PendingKeyState, Option<key::ScheduledEvent<Event>>) {
286 let pending = PendingKeyState::new();
287 let scheduled = context.config.timeout.map(|timeout| {
288 key::ScheduledEvent::after(
289 timeout,
290 key::Event::key_event(keymap_index, Event::TapHoldTimeout),
291 )
292 });
293 (pending, scheduled)
294 }
295}
296
297impl<R: Copy + Debug, Keys: Debug + Index<usize, Output = Key<R>>> key::System<R>
298 for System<R, Keys>
299{
300 type Ref = Ref;
301 type Context = Context;
302 type Event = Event;
303 type PendingKeyState = PendingKeyState;
304 type KeyState = KeyState;
305
306 fn new_pressed_key(
307 &self,
308 keymap_index: u16,
309 context: &Self::Context,
310 Ref(key_index): Ref,
311 ) -> (
312 key::PressedKeyResult<R, Self::PendingKeyState, Self::KeyState>,
313 key::KeyEvents<Self::Event>,
314 ) {
315 match context.config.required_idle_time {
316 Some(required_idle_time) => {
317 if context.idle_time_ms >= required_idle_time as u32 {
318 let (th_pks, maybe_sch_ev) = self.new_pending_key(context, keymap_index);
320 let pk = key::PressedKeyResult::Pending(th_pks);
321 let pke = match maybe_sch_ev {
322 Some(sch_ev) => {
323 key::KeyEvents::scheduled_event(sch_ev.into_scheduled_event())
324 }
325 None => key::KeyEvents::no_events(),
326 };
327 (pk, pke)
328 } else {
329 let Key {
332 tap: tap_key_ref, ..
333 } = self.keys[key_index as usize];
334 (
335 key::PressedKeyResult::NewPressedKey(key::NewPressedKey::key(tap_key_ref)),
336 key::KeyEvents::no_events(),
337 )
338 }
339 }
340 None => {
341 let (th_pks, maybe_sch_ev) = self.new_pending_key(context, keymap_index);
343 let pk = key::PressedKeyResult::Pending(th_pks);
344 let pke = match maybe_sch_ev {
345 Some(sch_ev) => key::KeyEvents::scheduled_event(sch_ev.into_scheduled_event()),
346 None => key::KeyEvents::no_events(),
347 };
348 (pk, pke)
349 }
350 }
351 }
352
353 fn update_pending_state(
354 &self,
355 pending_state: &mut Self::PendingKeyState,
356 keymap_index: u16,
357 context: &Self::Context,
358 Ref(key_index): Ref,
359 event: key::Event<Self::Event>,
360 ) -> (Option<key::NewPressedKey<R>>, key::KeyEvents<Self::Event>) {
361 let th_state = pending_state.handle_event(context, keymap_index, event);
362 if let Some(th_state) = th_state {
363 let Key { tap, hold } = self.keys[key_index as usize];
364 let new_key_ref = match th_state {
365 key::tap_hold::TapHoldState::Tap => tap,
366 key::tap_hold::TapHoldState::Hold => hold,
367 };
368
369 (
370 Some(key::NewPressedKey::key(new_key_ref)),
371 key::KeyEvents::no_events(),
372 )
373 } else {
374 (None, key::KeyEvents::no_events())
375 }
376 }
377
378 fn update_state(
379 &self,
380 _key_state: &mut Self::KeyState,
381 _ref: &Self::Ref,
382 _context: &Self::Context,
383 _keymap_index: u16,
384 _event: key::Event<Self::Event>,
385 ) -> key::KeyEvents<Self::Event> {
386 panic!() }
388
389 fn key_output(
390 &self,
391 _key_ref: &Self::Ref,
392 _key_state: &Self::KeyState,
393 ) -> Option<key::KeyOutput> {
394 panic!() }
396}
397
398#[cfg(test)]
399mod tests {
400 use super::*;
401
402 #[test]
403 fn test_sizeof_ref() {
404 assert_eq!(1, core::mem::size_of::<Ref>());
405 }
406
407 #[test]
408 fn test_sizeof_event() {
409 assert_eq!(0, core::mem::size_of::<Event>());
410 }
411}