1#[cfg(feature = "std")]
2mod distinct_reports;
3mod event_scheduler;
4pub mod hid_keyboard_reporter;
6
7use core::cmp::PartialEq;
8use core::fmt::Debug;
9use core::marker::Copy;
10use core::ops::Index;
11
12use serde::Deserialize;
13
14use crate::input;
15use crate::key;
16
17use key::Event;
18
19#[cfg(feature = "std")]
20pub use distinct_reports::DistinctReports;
21use event_scheduler::EventScheduler;
22use hid_keyboard_reporter::HIDKeyboardReporter;
23
24pub const MAX_PRESSED_KEYS: usize = 16;
26
27const MAX_QUEUED_INPUT_EVENTS: usize = 32;
28
29pub const INPUT_QUEUE_TICK_DELAY: u8 = 1;
31
32#[derive(Debug, PartialEq)]
34pub struct KeymapOutput {
35 pressed_key_codes: heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }>,
36}
37
38impl Default for KeymapOutput {
39 fn default() -> Self {
40 Self {
41 pressed_key_codes: heapless::Vec::new(),
42 }
43 }
44}
45
46impl KeymapOutput {
47 pub fn new(pressed_key_codes: heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }>) -> Self {
49 Self { pressed_key_codes }
50 }
51
52 pub fn pressed_key_codes(&self) -> heapless::Vec<u8, 24> {
54 let mut result = heapless::Vec::new();
55
56 let modifiers = self
57 .pressed_key_codes
58 .iter()
59 .fold(key::KeyboardModifiers::new(), |acc, &ko| {
60 acc.union(&ko.key_modifiers())
61 });
62
63 result.extend(modifiers.as_key_codes());
64
65 result.extend(
66 self.pressed_key_codes
67 .iter()
68 .flat_map(|ko| match ko.key_code() {
69 key::KeyUsage::Keyboard(kc) => Some(kc),
70 _ => None,
71 }),
72 );
73
74 result
75 }
76
77 pub fn as_hid_boot_keyboard_report(&self) -> [u8; 8] {
79 let mut report = [0u8; 8];
80
81 let modifiers = self
82 .pressed_key_codes
83 .iter()
84 .fold(key::KeyboardModifiers::new(), |acc, &ko| {
85 acc.union(&ko.key_modifiers())
86 });
87
88 report[0] = modifiers.as_byte();
89
90 let key_codes = self
91 .pressed_key_codes
92 .iter()
93 .flat_map(|ko| match ko.key_code() {
94 key::KeyUsage::Keyboard(kc) => Some(kc),
95 _ => None,
96 })
97 .filter(|&kc| kc != 0);
98
99 for (i, key_code) in key_codes.take(6).enumerate() {
100 report[i + 2] = key_code;
101 }
102
103 report
104 }
105
106 pub fn pressed_custom_codes(&self) -> heapless::Vec<u8, 24> {
108 self.pressed_key_codes
109 .iter()
110 .flat_map(|ko| match ko.key_code() {
111 key::KeyUsage::Custom(kc) => Some(kc),
112 _ => None,
113 })
114 .collect()
115 }
116}
117
118#[derive(Debug)]
119struct PendingState<Ev, PKS> {
120 key_path: key::KeyPath,
121 pending_key_state: PKS,
122 queued_events: heapless::Vec<key::Event<Ev>, { MAX_PRESSED_KEYS }>,
123}
124
125#[derive(Deserialize, Debug, Clone, Copy, Eq, PartialEq)]
127pub enum KeymapCallback {
128 Reset,
130 ResetToBootloader,
132 Custom(u8, u8),
134}
135
136#[derive(Debug, Clone, Copy)]
138pub struct KeymapContext {
139 pub time_ms: u32,
141
142 pub idle_time_ms: u32,
144}
145
146pub const DEFAULT_KEYMAP_CONTEXT: KeymapContext = KeymapContext {
148 time_ms: 0,
149 idle_time_ms: 0,
150};
151
152pub trait SetKeymapContext {
154 fn set_keymap_context(&mut self, context: KeymapContext);
156}
157
158#[derive(Debug, Clone, Copy, PartialEq, Eq)]
160pub enum KeymapEvent {
161 Callback(KeymapCallback),
163 ResolvedKeyOutput {
165 keymap_index: u16,
167 key_output: key::KeyOutput,
169 },
170}
171
172#[derive(Debug)]
173enum CallbackFunction {
174 ExternC(extern "C" fn() -> ()),
176 Rust(fn() -> ()),
178}
179
180pub struct Keymap<Ctx, Ev: Debug, PKS, KS, I> {
182 key_definitions: I,
183 context: Ctx,
184 pressed_inputs: heapless::Vec<input::PressedInput<KS>, { MAX_PRESSED_KEYS }>,
185 event_scheduler: EventScheduler<Ev>,
186 ms_per_tick: u8,
187 idle_time: u32,
188 hid_reporter: HIDKeyboardReporter,
189 pending_key_state: Option<PendingState<Ev, PKS>>,
190 input_queue: heapless::spsc::Queue<input::Event, { MAX_QUEUED_INPUT_EVENTS }>,
191 input_queue_delay_counter: u8,
192 callbacks: heapless::LinearMap<KeymapCallback, CallbackFunction, 2>,
193}
194
195impl<
196 Ctx: Debug,
197 Ev: Debug,
198 PKS: Debug,
199 KS: Debug,
200 K: key::Key<Context = Ctx, Event = Ev, PendingKeyState = PKS, KeyState = KS> + ?Sized,
201 I: Index<usize, Output = K>,
202 > core::fmt::Debug for Keymap<Ctx, Ev, PKS, KS, I>
203{
204 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
205 f.debug_struct("Keymap")
206 .field("context", &self.context)
207 .field("event_scheduler", &self.event_scheduler)
208 .field("ms_per_tick", &self.ms_per_tick)
209 .field("idle_time", &self.idle_time)
210 .field("hid_reporter", &self.hid_reporter)
211 .field("input_queue", &self.input_queue)
212 .field("input_queue_delay_counter", &self.input_queue_delay_counter)
213 .field("pending_key_state", &self.pending_key_state)
214 .field("pressed_inputs", &self.pressed_inputs)
215 .finish_non_exhaustive()
216 }
217}
218
219impl<
220 Ctx: key::Context<Event = Ev> + SetKeymapContext,
221 Ev: Copy + Debug + PartialEq,
222 PKS,
223 KS: key::KeyState<Context = Ctx, Event = Ev> + Copy,
224 K: key::Key<Context = Ctx, Event = Ev, PendingKeyState = PKS, KeyState = KS> + ?Sized,
225 I: Index<usize, Output = K>,
226 > Keymap<Ctx, Ev, PKS, KS, I>
227where
228 KS: From<key::NoOpKeyState<K::Context, K::Event>>,
229{
230 pub const fn new(key_definitions: I, context: Ctx) -> Self {
232 Self {
233 key_definitions,
234 context,
235 pressed_inputs: heapless::Vec::new(),
236 event_scheduler: EventScheduler::new(),
237 ms_per_tick: 1,
238 idle_time: 0,
239 hid_reporter: HIDKeyboardReporter::new(),
240 pending_key_state: None,
241 input_queue: heapless::spsc::Queue::new(),
242 input_queue_delay_counter: 0,
243 callbacks: heapless::LinearMap::new(),
244 }
245 }
246
247 pub fn init(&mut self) {
249 self.pressed_inputs.clear();
250 self.event_scheduler.init();
251 self.hid_reporter.init();
252 self.pending_key_state = None;
253 while !self.input_queue.is_empty() {
254 self.input_queue.dequeue().unwrap();
255 }
256 self.input_queue_delay_counter = 0;
257 self.ms_per_tick = 1;
258 self.idle_time = 0;
259 }
260
261 pub fn set_callback(&mut self, callback_id: KeymapCallback, callback_fn: fn() -> ()) {
265 self.callbacks
266 .insert(callback_id, CallbackFunction::Rust(callback_fn))
267 .unwrap();
268 }
269
270 pub fn set_callback_extern(
274 &mut self,
275 callback_id: KeymapCallback,
276 callback_fn: extern "C" fn() -> (),
277 ) {
278 self.callbacks
279 .insert(callback_id, CallbackFunction::ExternC(callback_fn))
280 .unwrap();
281 }
282
283 pub fn set_ms_per_tick(&mut self, ms_per_tick: u8) {
285 self.ms_per_tick = ms_per_tick;
286 }
287
288 fn resolve_pending_key_state(&mut self, key_state: KS) {
291 if let Some(PendingState {
292 key_path,
293 queued_events,
294 ..
295 }) = self.pending_key_state.take()
296 {
297 let keymap_index = key_path.keymap_index();
299 self.event_scheduler
300 .cancel_events_for_keymap_index(keymap_index);
301
302 self.pressed_inputs
304 .push(input::PressedInput::pressed_key(key_state, keymap_index))
305 .unwrap();
306
307 let mut i = 1;
311 let mut old_input_queue: heapless::spsc::Queue<input::Event, MAX_QUEUED_INPUT_EVENTS> =
312 core::mem::take(&mut self.input_queue);
313
314 let (pending_input_ev, queued_events): (
318 heapless::Vec<key::Event<Ev>, { MAX_PRESSED_KEYS }>,
319 heapless::Vec<key::Event<Ev>, { MAX_PRESSED_KEYS }>,
320 ) = queued_events.iter().partition(|ev| match ev {
321 key::Event::Input(input::Event::Press {
322 keymap_index: queued_kmi,
323 }) => *queued_kmi == keymap_index,
324 key::Event::Input(input::Event::Release {
325 keymap_index: queued_kmi,
326 }) => *queued_kmi == keymap_index,
327 key::Event::Key {
328 keymap_index: queued_kmi,
329 ..
330 } => *queued_kmi == keymap_index,
331 _ => false,
332 });
333
334 for ev in queued_events.iter().chain(pending_input_ev.last()) {
335 match ev {
336 key::Event::Input(ie) => {
337 self.input_queue.enqueue(*ie).unwrap();
338 }
339 _ => {
340 self.event_scheduler.schedule_after(i, *ev);
341 i += 1;
342 }
343 }
344 }
345
346 while let Some(ie) = old_input_queue.dequeue() {
347 self.input_queue.enqueue(ie).unwrap();
348 }
349
350 self.handle_pending_events();
351
352 if let Some(key_state) = key_state.key_output() {
354 let km_ev = KeymapEvent::ResolvedKeyOutput {
355 keymap_index,
356 key_output: key_state,
357 };
358 self.handle_event(key::Event::Keymap(km_ev));
359 }
360 }
361 }
362
363 pub fn handle_input(&mut self, ev: input::Event) {
365 self.idle_time = 0;
366
367 if self.input_queue.is_full() {
368 return;
369 }
370
371 self.input_queue.enqueue(ev).unwrap();
372
373 if self.input_queue_delay_counter == 0 {
374 let ie = self.input_queue.dequeue().unwrap();
375 self.process_input(ie);
376 self.input_queue_delay_counter = INPUT_QUEUE_TICK_DELAY;
377 }
378 }
379
380 fn has_pressed_input_with_keymap_index(&self, keymap_index: u16) -> bool {
381 self.pressed_inputs.iter().any(|pi| match pi {
382 &input::PressedInput::Key(input::PressedKey {
383 keymap_index: ki, ..
384 }) => keymap_index == ki,
385 _ => false,
386 })
387 }
388
389 fn process_input(&mut self, ev: input::Event) {
390 if let Some(PendingState {
391 key_path,
392 pending_key_state,
393 queued_events,
394 ..
395 }) = &mut self.pending_key_state
396 {
397 queued_events.push(ev.into()).unwrap();
398
399 let pending_key = &self.key_definitions[key_path.keymap_index() as usize];
400 let pending_key = pending_key.lookup(&key_path[1..]);
401 let (mut maybe_npk, pke) = pending_key.handle_event(
402 pending_key_state,
403 &self.context,
404 key_path.clone(),
405 ev.into(),
406 );
407
408 pke.into_iter()
409 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
410
411 while let Some(npk) = maybe_npk.take() {
412 let pkr = match npk {
413 key::NewPressedKey::Key(new_key_path) => {
414 let new_key = &self.key_definitions[new_key_path.keymap_index() as usize];
415 let new_key = new_key.lookup(&new_key_path[1..]);
416 let (pkr, pke) =
417 new_key.new_pressed_key(&self.context, new_key_path.clone());
418 pke.into_iter()
419 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
420 pkr
421 }
422 key::NewPressedKey::NoOp => {
423 let no_op_ks: KS = key::NoOpKeyState::new().into();
424 key::PressedKeyResult::Resolved(no_op_ks)
425 }
426 };
427
428 match pkr {
429 key::PressedKeyResult::Resolved(ks) => {
430 self.resolve_pending_key_state(ks);
431 break;
432 }
433 key::PressedKeyResult::NewPressedKey(key::NewPressedKey::Key(new_key_path)) => {
434 maybe_npk = Some(key::NewPressedKey::Key(new_key_path));
435 }
436 key::PressedKeyResult::NewPressedKey(key::NewPressedKey::NoOp) => {
437 self.resolve_pending_key_state(key::NoOpKeyState::new().into());
438 break;
439 }
440 key::PressedKeyResult::Pending(kp, pks) => {
441 *key_path = kp;
442 *pending_key_state = pks;
443
444 let orig_input_queue = core::mem::take(&mut self.input_queue);
447 while let Some(ev) = queued_events.pop() {
448 match ev {
449 key::Event::Input(input_ev) => {
450 self.input_queue.enqueue(input_ev).unwrap();
451 }
452 _ => {}
453 }
454 }
455 orig_input_queue.iter().for_each(|&ev| {
456 self.input_queue.enqueue(ev).unwrap();
457 });
458 }
459 }
460 }
461 } else {
462 self.pressed_inputs.iter_mut().for_each(|pi| {
464 if let input::PressedInput::Key(pressed_key) = pi {
465 pressed_key
466 .handle_event(&self.context, ev.into())
467 .into_iter()
468 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
469 }
470 });
471
472 self.context
473 .handle_event(ev.into())
474 .into_iter()
475 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
476
477 match ev {
478 input::Event::Press { keymap_index }
479 if !self.has_pressed_input_with_keymap_index(keymap_index) =>
480 {
481 let mut maybe_key_path = Some(key::key_path(keymap_index));
482
483 while let Some(key_path) = maybe_key_path.take() {
484 let key = &self.key_definitions[key_path.keymap_index() as usize]
485 .lookup(&key_path[1..]);
486
487 let (pkr, pke) = key.new_pressed_key(&self.context, key_path);
488
489 pke.into_iter()
490 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
491
492 match pkr {
493 key::PressedKeyResult::Resolved(key_state) => {
494 self.pressed_inputs
495 .push(input::PressedInput::pressed_key(key_state, keymap_index))
496 .unwrap();
497
498 if let Some(key_output) = key_state.key_output() {
500 let km_ev = KeymapEvent::ResolvedKeyOutput {
501 keymap_index,
502 key_output,
503 };
504 self.handle_event(key::Event::Keymap(km_ev));
505 }
506 }
507 key::PressedKeyResult::NewPressedKey(key::NewPressedKey::Key(
508 new_key_path,
509 )) => {
510 maybe_key_path = Some(new_key_path);
511 }
512 key::PressedKeyResult::NewPressedKey(key::NewPressedKey::NoOp) => {
513 let key_state: KS = key::NoOpKeyState::new().into();
514
515 self.pressed_inputs
516 .push(input::PressedInput::pressed_key(key_state, keymap_index))
517 .unwrap();
518 }
519 key::PressedKeyResult::Pending(key_path, pending_key_state) => {
520 self.pending_key_state = Some(PendingState {
521 key_path,
522 pending_key_state,
523 queued_events: heapless::Vec::new(),
524 });
525 }
526 }
527 }
528 }
529 input::Event::Release { keymap_index } => {
530 self.pressed_inputs
531 .iter()
532 .position(|pi| match pi {
533 &input::PressedInput::Key(input::PressedKey {
534 keymap_index: ki,
535 ..
536 }) => keymap_index == ki,
537 _ => false,
538 })
539 .map(|i| self.pressed_inputs.remove(i));
540
541 self.event_scheduler
542 .cancel_events_for_keymap_index(keymap_index);
543 }
544
545 input::Event::VirtualKeyPress { key_output } => {
546 let pressed_key = input::PressedInput::Virtual(key_output);
547 self.pressed_inputs.push(pressed_key).unwrap();
548 }
549 input::Event::VirtualKeyRelease { key_output } => {
550 self.pressed_inputs
552 .iter()
553 .position(|k| match k {
554 input::PressedInput::Virtual(ko) => key_output == *ko,
555 _ => false,
556 })
557 .map(|i| self.pressed_inputs.remove(i));
558 }
559
560 _ => {}
561 }
562 }
563
564 self.handle_pending_events();
565 }
566
567 fn handle_event(&mut self, ev: key::Event<Ev>) {
570 if let key::Event::Keymap(KeymapEvent::Callback(callback_id)) = ev {
571 match self.callbacks.get(&callback_id) {
572 Some(CallbackFunction::Rust(callback_fn)) => {
573 callback_fn();
574 }
575 Some(CallbackFunction::ExternC(callback_fn)) => {
576 callback_fn();
577 }
578 None => {}
579 }
580 }
581
582 if let Some(PendingState {
584 key_path,
585 pending_key_state,
586 queued_events,
587 ..
588 }) = &mut self.pending_key_state
589 {
590 let pending_key = &self.key_definitions[key_path.keymap_index() as usize];
591 let pending_key = pending_key.lookup(&key_path[1..]);
592 let (mut maybe_npk, pke) =
593 pending_key.handle_event(pending_key_state, &self.context, key_path.clone(), ev);
594
595 pke.into_iter()
596 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
597
598 while let Some(npk) = maybe_npk.take() {
599 let pkr = match npk {
600 key::NewPressedKey::Key(new_key_path) => {
601 let new_key = &self.key_definitions[new_key_path.keymap_index() as usize];
602 let new_key = new_key.lookup(&new_key_path[1..]);
603 let (pkr, pke) =
604 new_key.new_pressed_key(&self.context, new_key_path.clone());
605 pke.into_iter()
606 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
607 pkr
608 }
609 key::NewPressedKey::NoOp => {
610 let no_op_ks: KS = key::NoOpKeyState::new().into();
611 key::PressedKeyResult::Resolved(no_op_ks)
612 }
613 };
614
615 match pkr {
616 key::PressedKeyResult::Resolved(ks) => {
617 self.resolve_pending_key_state(ks);
618 break;
619 }
620 key::PressedKeyResult::NewPressedKey(key::NewPressedKey::Key(new_key_path)) => {
621 maybe_npk = Some(key::NewPressedKey::Key(new_key_path));
622 }
623 key::PressedKeyResult::NewPressedKey(key::NewPressedKey::NoOp) => {
624 self.resolve_pending_key_state(key::NoOpKeyState::new().into());
625 break;
626 }
627 key::PressedKeyResult::Pending(kp, pks) => {
628 *key_path = kp;
629 *pending_key_state = pks;
630
631 let orig_input_queue = core::mem::take(&mut self.input_queue);
634 while let Some(ev) = queued_events.pop() {
635 match ev {
636 key::Event::Input(input_ev) => {
637 self.input_queue.enqueue(input_ev).unwrap();
638 }
639 _ => {}
640 }
641 }
642 orig_input_queue.iter().for_each(|&ev| {
643 self.input_queue.enqueue(ev).unwrap();
644 });
645 }
646 }
647 }
648 }
649
650 self.pressed_inputs.iter_mut().for_each(|pi| {
652 if let input::PressedInput::Key(input::PressedKey {
653 key_state,
654 keymap_index,
655 }) = pi
656 {
657 key_state
658 .handle_event(&self.context, *keymap_index, ev)
659 .into_iter()
660 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
661 }
662 });
663
664 self.context
666 .handle_event(ev)
667 .into_iter()
668 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
669
670 if let Event::Input(input_ev) = ev {
671 self.process_input(input_ev);
672 }
673 }
674
675 fn handle_pending_events(&mut self) {
676 while let Some(ev) = self.event_scheduler.dequeue() {
678 self.handle_event(ev);
679 }
680 }
681
682 pub fn tick(&mut self) {
684 let km_context = KeymapContext {
685 time_ms: self.event_scheduler.schedule_counter,
686 idle_time_ms: self.idle_time,
687 };
688 self.context.set_keymap_context(km_context);
689
690 if !self.input_queue.is_empty() && self.input_queue_delay_counter == 0 {
691 let ie = self.input_queue.dequeue().unwrap();
692 self.process_input(ie);
693 self.input_queue_delay_counter = INPUT_QUEUE_TICK_DELAY;
694 }
695
696 if self.input_queue_delay_counter > 0 {
697 self.input_queue_delay_counter -= 1;
698 }
699
700 self.event_scheduler.tick(self.ms_per_tick);
701
702 self.handle_pending_events();
703
704 self.idle_time += self.ms_per_tick as u32;
705 }
706
707 pub fn pressed_keys(&self) -> heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }> {
709 let pressed_key_codes = self.pressed_inputs.iter().filter_map(|pi| match pi {
710 input::PressedInput::Key(pressed_key) => pressed_key.key_output(),
711 &input::PressedInput::Virtual(key_output) => Some(key_output),
712 });
713
714 pressed_key_codes.collect()
715 }
716
717 pub fn report_output(&mut self) -> KeymapOutput {
719 self.hid_reporter.update(self.pressed_keys());
720 self.hid_reporter.report_sent();
721
722 KeymapOutput::new(self.hid_reporter.reportable_key_outputs())
723 }
724
725 #[doc(hidden)]
727 pub fn boot_keyboard_report(&self) -> [u8; 8] {
728 KeymapOutput::new(self.pressed_keys()).as_hid_boot_keyboard_report()
729 }
730
731 #[doc(hidden)]
732 pub fn has_scheduled_events(&self) -> bool {
733 !self.event_scheduler.pending_events.is_empty()
734 || !self.event_scheduler.scheduled_events.is_empty()
735 || !self.input_queue.is_empty()
736 }
737}
738
739#[cfg(test)]
740mod tests {
741 use super::*;
742
743 use crate::tuples;
744
745 #[test]
746 fn test_keymap_output_pressed_key_codes_includes_modifier_key_code() {
747 let mut input: heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }> = heapless::Vec::new();
749 input.push(key::KeyOutput::from_key_code(0x04)).unwrap();
750 input.push(key::KeyOutput::from_key_code(0xE0)).unwrap();
751
752 let keymap_output = KeymapOutput::new(input);
754 let pressed_key_codes = keymap_output.pressed_key_codes();
755
756 assert!(pressed_key_codes.contains(&0xE0))
758 }
759
760 #[test]
761 fn test_keymap_output_as_hid_boot_keyboard_report_gathers_modifiers() {
762 let mut input: heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }> = heapless::Vec::new();
764 input.push(key::KeyOutput::from_key_code(0x04)).unwrap();
765 input.push(key::KeyOutput::from_key_code(0xE0)).unwrap();
766
767 let keymap_output = KeymapOutput::new(input);
769 let actual_report: [u8; 8] = keymap_output.as_hid_boot_keyboard_report();
770
771 let expected_report: [u8; 8] = [0x01, 0, 0x04, 0, 0, 0, 0, 0];
773 assert_eq!(expected_report, actual_report);
774 }
775
776 #[test]
777 fn test_keymap_with_keyboard_key_with_composite_context() {
778 use key::composite;
779 use key::keyboard;
780 use tuples::Keys1;
781
782 use composite::{Context, Event, KeyState, PendingKeyState};
783
784 type Ctx = Context;
786 type K = composite::Chorded<composite::Layered<composite::TapHold<keyboard::Key>>>;
787 let keys: Keys1<K, Context, Event, PendingKeyState, KeyState> =
788 Keys1::new((composite::Chorded(composite::Layered(composite::TapHold(
789 keyboard::Key::new(0x04),
790 ))),));
791 let context: Ctx = composite::DEFAULT_CONTEXT;
792 let mut keymap = Keymap::new(keys, context);
793
794 keymap.handle_input(input::Event::Press { keymap_index: 0 });
796 let actual_report = keymap.boot_keyboard_report();
797
798 let expected_report: [u8; 8] = [0, 0, 0x04, 0, 0, 0, 0, 0];
800 assert_eq!(expected_report, actual_report);
801 }
802
803 #[test]
804 fn test_keymap_with_composite_keyboard_key() {
805 use key::{composite, keyboard};
806 use tuples::Keys1;
807
808 use composite::{Context, Event, KeyState, PendingKeyState};
809
810 let keys: Keys1<composite::Key, Context, Event, PendingKeyState, KeyState> =
812 Keys1::new((composite::Key::keyboard(keyboard::Key::new(0x04)),));
813 let context: Context = composite::DEFAULT_CONTEXT;
814 let mut keymap = Keymap::new(keys, context);
815
816 keymap.handle_input(input::Event::Press { keymap_index: 0 });
818 let actual_report = keymap.boot_keyboard_report();
819
820 let expected_report: [u8; 8] = [0, 0, 0x04, 0, 0, 0, 0, 0];
822 assert_eq!(expected_report, actual_report);
823 }
824
825 #[test]
826 fn test_keymap_many_input_events_without_tick_or_report() {
827 use key::{composite, keyboard};
828 use tuples::Keys1;
829
830 use composite::{Context, Event, KeyState, PendingKeyState};
831
832 let keys: Keys1<composite::Key, Context, Event, PendingKeyState, KeyState> =
834 Keys1::new((composite::Key::keyboard(keyboard::Key::new(0x04)),));
835 let context: Context = composite::DEFAULT_CONTEXT;
836 let mut keymap = Keymap::new(keys, context);
837
838 for _ in 0..100 {
840 keymap.handle_input(input::Event::Press { keymap_index: 0 });
841 keymap.handle_input(input::Event::Release { keymap_index: 0 });
842 }
843
844 }
847}