1#[cfg(feature = "std")]
2mod distinct_reports;
3mod event_scheduler;
4pub mod hid_keyboard_reporter;
6mod input_event_queue;
7#[cfg(feature = "std")]
8mod observed_eb_keymap;
9#[cfg(feature = "std")]
10mod observed_keymap;
11mod pending;
12
13use core::cmp::PartialEq;
14use core::fmt::Debug;
15use core::marker::Copy;
16use core::ops::Index;
17
18use serde::Deserialize;
19
20use crate::input;
21use crate::key;
22
23use key::Event;
24
25#[cfg(feature = "std")]
26pub use distinct_reports::DistinctReports;
27use event_scheduler::EventScheduler;
28use hid_keyboard_reporter::HIDKeyboardReporter;
29use input_event_queue::InputEventQueue;
30#[cfg(feature = "std")]
31pub use observed_eb_keymap::ObservedKeymap as ObservedEventBasedKeymap;
32#[cfg(feature = "std")]
33pub use observed_keymap::ObservedKeymap;
34
35pub const MAX_PRESSED_KEYS: usize = 16;
37
38pub(crate) const MAX_QUEUED_INPUT_EVENTS: usize = 32;
39
40#[derive(Debug, Default, PartialEq)]
42pub struct KeymapOutput {
43 pressed_key_codes: heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }>,
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_consumer_codes(&self) -> heapless::Vec<u8, 24> {
108 self.pressed_key_codes
109 .iter()
110 .flat_map(|ko| match ko.key_code() {
111 key::KeyUsage::Consumer(uc) => Some(uc),
112 _ => None,
113 })
114 .collect()
115 }
116
117 pub fn pressed_custom_codes(&self) -> heapless::Vec<u8, 24> {
119 self.pressed_key_codes
120 .iter()
121 .flat_map(|ko| match ko.key_code() {
122 key::KeyUsage::Custom(kc) => Some(kc),
123 _ => None,
124 })
125 .collect()
126 }
127
128 pub fn pressed_mouse_output(&self) -> key::MouseOutput {
130 self.pressed_key_codes
131 .iter()
132 .filter_map(|ko| match ko.key_code() {
133 key::KeyUsage::Mouse(mo) => Some(mo),
134 _ => None,
135 })
136 .fold(key::MouseOutput::NO_OUTPUT, |acc, mo| acc.combine(&mo))
137 }
138}
139
140#[derive(Deserialize, Debug, Clone, Copy, Eq, PartialEq)]
142pub enum BluetoothProfileCommand {
143 Disconnect,
145 Clear,
147 ClearAll,
149 Previous,
151 Next,
153 Select(u8),
155}
156
157#[derive(Deserialize, Debug, Clone, Copy, Eq, PartialEq)]
159pub enum KeymapCallback {
160 Reset,
162 ResetToBootloader,
164 Bluetooth(BluetoothProfileCommand),
166 Custom(u8, u8),
168}
169
170pub const MAX_RECENT_PRESSES: usize = 8;
172
173#[derive(Debug, Clone, Copy, Default)]
175pub struct KeymapContext {
176 pub time_ms: u32,
178
179 pub idle_time_ms: u32,
181
182 pub pressed_modifiers: key::KeyboardModifiers,
187
188 pub recent_presses: [(u16, u32); MAX_RECENT_PRESSES],
192
193 pub recent_press_count: u8,
195}
196
197impl KeymapContext {
198 pub const fn new() -> Self {
200 KeymapContext {
201 time_ms: 0,
202 idle_time_ms: 0,
203 pressed_modifiers: key::KeyboardModifiers::NONE,
204 recent_presses: [(0, 0); MAX_RECENT_PRESSES],
205 recent_press_count: 0,
206 }
207 }
208
209 pub fn last_press_time_ms(&self, keymap_index: u16) -> Option<u32> {
211 self.recent_presses[..self.recent_press_count as usize]
212 .iter()
213 .rev()
214 .find(|(ki, _)| *ki == keymap_index)
215 .map(|(_, t)| *t)
216 }
217}
218
219fn keymap_context_without_current_press(
226 recent_presses: [(u16, u32); MAX_RECENT_PRESSES],
227 recent_press_count: u8,
228 idle_time_ms: u32,
229 fallback_time_ms: u32,
230 pressed_modifiers: key::KeyboardModifiers,
231 keymap_index: u16,
232) -> KeymapContext {
233 let count = recent_press_count as usize;
234 let occupied = &recent_presses[..count];
235
236 let time_ms = occupied
237 .iter()
238 .rfind(|(ki, _)| *ki == keymap_index)
239 .map(|&(_, t)| t)
240 .unwrap_or(fallback_time_ms);
241
242 let (recent_presses, recent_press_count) =
243 if let Some(idx) = occupied.iter().rposition(|(ki, _)| *ki == keymap_index) {
244 let mut shifted = [(0, 0); MAX_RECENT_PRESSES];
245 shifted[..idx].copy_from_slice(&recent_presses[..idx]);
246 shifted[idx..count - 1].copy_from_slice(&recent_presses[idx + 1..count]);
247 (shifted, recent_press_count - 1)
248 } else {
249 (recent_presses, recent_press_count)
250 };
251
252 KeymapContext {
253 time_ms,
254 idle_time_ms,
255 pressed_modifiers,
256 recent_presses,
257 recent_press_count,
258 }
259}
260
261fn push_recent_press(
266 recent_presses: [(u16, u32); MAX_RECENT_PRESSES],
267 recent_press_count: u8,
268 keymap_index: u16,
269 time_ms: u32,
270) -> ([(u16, u32); MAX_RECENT_PRESSES], u8) {
271 let count = recent_press_count as usize;
272 if count == MAX_RECENT_PRESSES {
273 let mut shifted = [(0, 0); MAX_RECENT_PRESSES];
274 shifted[..MAX_RECENT_PRESSES - 1].copy_from_slice(&recent_presses[1..]);
275 shifted[MAX_RECENT_PRESSES - 1] = (keymap_index, time_ms);
276 (shifted, recent_press_count)
277 } else {
278 let mut recent_presses = recent_presses;
279 recent_presses[count] = (keymap_index, time_ms);
280 (recent_presses, recent_press_count + 1)
281 }
282}
283
284pub trait SetKeymapContext {
286 fn set_keymap_context(&mut self, context: KeymapContext);
288}
289
290pub trait ReportHints {
296 fn suppressed_modifiers(&self) -> key::KeyboardModifiers {
298 key::KeyboardModifiers::NONE
299 }
300}
301
302#[derive(Debug, Clone, Copy, PartialEq, Eq)]
304pub enum KeymapEvent {
305 Callback(KeymapCallback),
307 ResolvedKeyOutput {
309 keymap_index: u16,
311 key_output: key::KeyOutput,
313 },
314}
315
316#[derive(Debug)]
317enum CallbackFunction {
318 ExternC(extern "C" fn() -> ()),
320 Rust(fn() -> ()),
322}
323
324pub struct Keymap<I: Index<usize, Output = R>, R, Ctx, Ev: Debug, PKS, KS, S> {
326 key_refs: I,
327 key_system: S,
328 context: Ctx,
329 pressed_inputs: heapless::Vec<input::PressedInput<R, KS>, { MAX_PRESSED_KEYS }>,
330 event_scheduler: EventScheduler<Ev>,
331 ms_per_tick: u8,
332 idle_time: u32,
333 recent_presses: [(u16, u32); MAX_RECENT_PRESSES],
335 recent_press_count: u8,
336 hid_reporter: HIDKeyboardReporter,
337 pending_state: Option<pending::PendingState<R, Ev, PKS>>,
338 input_queue: InputEventQueue<{ MAX_QUEUED_INPUT_EVENTS }>,
339 callbacks: heapless::LinearMap<KeymapCallback, CallbackFunction, 2>,
340}
341
342impl<
343 I: Debug + Index<usize, Output = R>,
344 R: Debug,
345 Ctx: Debug,
346 Ev: Debug,
347 PKS: Debug,
348 KS: Debug,
349 S: Debug,
350 > core::fmt::Debug for Keymap<I, R, Ctx, Ev, PKS, KS, S>
351{
352 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
353 f.debug_struct("Keymap")
354 .field("context", &self.context)
355 .field("event_scheduler", &self.event_scheduler)
356 .field("ms_per_tick", &self.ms_per_tick)
357 .field("idle_time", &self.idle_time)
358 .field("hid_reporter", &self.hid_reporter)
359 .field("input_queue", &self.input_queue)
360 .field("pending_state", &self.pending_state)
361 .field("pressed_inputs", &self.pressed_inputs)
362 .finish_non_exhaustive()
363 }
364}
365
366impl<
367 I: Debug + Index<usize, Output = R>,
368 R: Copy + Debug,
369 Ctx: Debug + key::Context<Event = Ev> + SetKeymapContext + ReportHints,
370 Ev: Copy + Debug,
371 PKS: Debug,
372 KS: Copy + Debug + From<key::NoOpKeyState>,
373 S: key::System<R, Ref = R, Context = Ctx, Event = Ev, PendingKeyState = PKS, KeyState = KS>,
374 > Keymap<I, R, Ctx, Ev, PKS, KS, S>
375{
376 pub const fn new(key_refs: I, context: Ctx, key_system: S) -> Self {
378 Self {
379 key_refs,
380 key_system,
381 context,
382 pressed_inputs: heapless::Vec::new(),
383 event_scheduler: EventScheduler::new(),
384 ms_per_tick: 1,
385 idle_time: 0,
386 recent_presses: [(0, 0); MAX_RECENT_PRESSES],
387 recent_press_count: 0,
388 hid_reporter: HIDKeyboardReporter::new(),
389 pending_state: None,
390 input_queue: InputEventQueue::new(),
391 callbacks: heapless::LinearMap::new(),
392 }
393 }
394
395 pub fn init(&mut self) {
401 self.context.reset();
402 self.pressed_inputs.clear();
403 self.event_scheduler.init();
404 self.hid_reporter.init();
405 self.pending_state = None;
406 self.input_queue.clear();
407 self.ms_per_tick = 1;
408 self.idle_time = 0;
409 self.recent_presses = [(0, 0); MAX_RECENT_PRESSES];
410 self.recent_press_count = 0;
411 }
412
413 fn record_recent_press(&mut self, keymap_index: u16) {
418 (self.recent_presses, self.recent_press_count) = push_recent_press(
419 self.recent_presses,
420 self.recent_press_count,
421 keymap_index,
422 self.event_scheduler.schedule_counter,
423 );
424 }
425
426 pub fn clear_callbacks(&mut self) {
428 self.callbacks.clear();
429 }
430
431 pub fn set_callback(&mut self, callback_id: KeymapCallback, callback_fn: fn() -> ()) {
435 let _ = self
436 .callbacks
437 .insert(callback_id, CallbackFunction::Rust(callback_fn));
438 }
439
440 pub fn set_callback_extern(
444 &mut self,
445 callback_id: KeymapCallback,
446 callback_fn: extern "C" fn() -> (),
447 ) {
448 let _ = self
449 .callbacks
450 .insert(callback_id, CallbackFunction::ExternC(callback_fn));
451 }
452
453 pub fn set_ms_per_tick(&mut self, ms_per_tick: u8) {
455 self.ms_per_tick = ms_per_tick;
456 }
457
458 fn resolve_pending_key_state(&mut self, key_state: KS) {
468 if let Some(pending::PendingState {
469 keymap_index,
470 key_ref,
471 mut queued_events,
472 mut ingest_queue,
473 ..
474 }) = self.pending_state.take()
475 {
476 self.event_scheduler
478 .cancel_events_for_keymap_index(keymap_index);
479
480 let _ = self.pressed_inputs.push(input::PressedInput::pressed_key(
482 keymap_index,
483 key_ref,
484 key_state,
485 ));
486
487 pending::dispatch_replayed_events(
490 pending::KeyResolution::Resolved { keymap_index },
491 &mut queued_events,
492 &mut self.input_queue,
493 &mut self.event_scheduler,
494 );
495
496 let mut remaining = ingest_queue.take_all();
498 self.input_queue.append_all(&mut remaining);
499
500 self.handle_pending_events();
501
502 if let Some(key_output) = self.key_system.key_output(&key_ref, &key_state) {
504 let km_ev = KeymapEvent::ResolvedKeyOutput {
505 keymap_index,
506 key_output,
507 };
508 self.handle_event(key::Event::Keymap(km_ev));
509 }
510 }
511 }
512
513 pub fn handle_input(&mut self, ev: input::Event) {
524 let ready = if let Some(pending_state) = self.pending_state.as_mut() {
525 pending_state.ingest_queue.push_back_or_ignore(ev);
526 pending_state.ingest_queue.pop_front_if_ready()
527 } else {
528 self.input_queue.push_back_or_ignore(ev);
529 self.input_queue.pop_front_if_ready()
530 };
531
532 if let Some(ie) = ready {
533 self.process_input(ie);
538 self.set_active_input_delay();
539 }
540
541 self.idle_time = 0;
542 }
543
544 fn set_active_input_delay(&mut self) {
549 if let Some(pending_state) = self.pending_state.as_mut() {
550 pending_state.ingest_queue.set_delay();
551 } else {
552 self.input_queue.set_delay();
553 }
554 }
555
556 fn has_pressed_input_with_keymap_index(&self, keymap_index: u16) -> bool {
557 self.pressed_inputs.iter().any(|pi| match pi {
558 &input::PressedInput::Key(input::PressedKey {
559 keymap_index: ki, ..
560 }) => keymap_index == ki,
561 _ => false,
562 })
563 }
564
565 fn update_pending_state(&mut self, ev: key::Event<Ev>) {
566 let Some(keymap_index) = self.pending_state.as_ref().map(|p| p.keymap_index) else {
567 return;
568 };
569 let pressed_modifiers = self.aggregate_pressed_modifiers();
570
571 if let Some(pending::PendingState {
572 key_ref,
573 pending_key_state,
574 queued_events,
575 ingest_queue,
576 press_idle_time_ms,
577 ..
578 }) = self.pending_state.as_mut()
579 {
580 let press_idle_time_ms = *press_idle_time_ms;
581 let (mut maybe_npk, pke) = self.key_system.update_pending_state(
582 pending_key_state,
583 keymap_index,
584 &self.context,
585 *key_ref,
586 ev,
587 );
588
589 pke.into_iter()
590 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
591
592 while let Some(npk) = maybe_npk.take() {
593 let pkr = match npk {
594 key::NewPressedKey::Key(new_key_ref) => {
595 *key_ref = new_key_ref;
596 self.event_scheduler
601 .cancel_events_for_keymap_index(keymap_index);
602 let nested_press_ctx = keymap_context_without_current_press(
609 self.recent_presses,
610 self.recent_press_count,
611 press_idle_time_ms,
612 self.event_scheduler.schedule_counter,
613 pressed_modifiers,
614 keymap_index,
615 );
616 self.context.set_keymap_context(nested_press_ctx);
617 let (pkr, pke) = self.key_system.new_pressed_key(
618 keymap_index,
619 &self.context,
620 new_key_ref,
621 );
622 let elapsed_ms = self
628 .event_scheduler
629 .schedule_counter
630 .saturating_sub(nested_press_ctx.time_ms);
631 let pke = match &pkr {
632 key::PressedKeyResult::Pending(_) => pke.backdate(elapsed_ms),
633 _ => pke,
634 };
635 pke.into_iter()
636 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
637 pkr
638 }
639 key::NewPressedKey::NoOp => {
640 let no_op_ks: KS = key::NoOpKeyState.into();
641 key::PressedKeyResult::Resolved(no_op_ks)
642 }
643 };
644
645 match pkr {
646 key::PressedKeyResult::Resolved(ks) => {
647 self.resolve_pending_key_state(ks);
648 break;
649 }
650 key::PressedKeyResult::NewPressedKey(key::NewPressedKey::Key(new_key_ref)) => {
651 maybe_npk = Some(key::NewPressedKey::Key(new_key_ref));
652 }
653 key::PressedKeyResult::NewPressedKey(key::NewPressedKey::NoOp) => {
654 self.resolve_pending_key_state(key::NoOpKeyState.into());
655 break;
656 }
657 key::PressedKeyResult::Pending(pks) => {
658 *pending_key_state = pks;
659
660 pending::dispatch_replayed_events(
663 pending::KeyResolution::Pending,
664 queued_events,
665 ingest_queue,
666 &mut self.event_scheduler,
667 );
668 }
669 }
670 }
671 }
672 }
673
674 fn process_input(&mut self, ev: input::Event) {
675 if let Some(pending_state) = self.pending_state.as_mut() {
676 pending_state.record_input(ev);
678 self.update_pending_state(ev.into());
679 } else {
680 self.pressed_inputs.iter_mut().for_each(|pi| {
682 if let input::PressedInput::Key(input::PressedKey {
683 key_ref,
684 key_state,
685 keymap_index,
686 }) = pi
687 {
688 self.key_system
689 .update_state(key_state, key_ref, &self.context, *keymap_index, ev.into())
690 .into_iter()
691 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
692 }
693 });
694
695 self.context
696 .handle_event(ev.into())
697 .into_iter()
698 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
699
700 match ev {
701 input::Event::Press { keymap_index }
702 if !self.has_pressed_input_with_keymap_index(keymap_index) =>
703 {
704 self.push_keymap_context();
706
707 let mut maybe_key_ref = Some(self.key_refs[keymap_index as usize]);
708
709 while let Some(key_ref) = maybe_key_ref.take() {
710 let (pkr, pke) =
711 self.key_system
712 .new_pressed_key(keymap_index, &self.context, key_ref);
713
714 pke.into_iter()
715 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
716
717 match pkr {
718 key::PressedKeyResult::Resolved(key_state) => {
719 let _ = self.pressed_inputs.push(input::PressedInput::pressed_key(
720 keymap_index,
721 key_ref,
722 key_state,
723 ));
724
725 if let Some(key_output) =
727 self.key_system.key_output(&key_ref, &key_state)
728 {
729 let km_ev = KeymapEvent::ResolvedKeyOutput {
730 keymap_index,
731 key_output,
732 };
733 self.handle_event(key::Event::Keymap(km_ev));
734 }
735 }
736 key::PressedKeyResult::NewPressedKey(key::NewPressedKey::Key(
737 new_key_ref,
738 )) => {
739 maybe_key_ref = Some(new_key_ref);
740 }
741 key::PressedKeyResult::NewPressedKey(key::NewPressedKey::NoOp) => {
742 let key_state: KS = key::NoOpKeyState.into();
743
744 let _ = self.pressed_inputs.push(input::PressedInput::pressed_key(
745 keymap_index,
746 key_ref,
747 key_state,
748 ));
749 }
750 key::PressedKeyResult::Pending(pending_key_state) => {
751 let mut pending_state = pending::PendingState::new(
758 keymap_index,
759 key_ref,
760 pending_key_state,
761 self.idle_time,
762 );
763 let mut remaining = self.input_queue.take_all();
764 pending_state.ingest_queue.append_all(&mut remaining);
765 self.pending_state = Some(pending_state);
766 }
767 }
768 }
769
770 self.record_recent_press(keymap_index);
772 }
773 input::Event::Release { keymap_index } => {
774 self.pressed_inputs
775 .iter()
776 .position(|pi| match pi {
777 &input::PressedInput::Key(input::PressedKey {
778 keymap_index: ki,
779 ..
780 }) => keymap_index == ki,
781 _ => false,
782 })
783 .map(|i| self.pressed_inputs.remove(i));
784 }
785
786 input::Event::VirtualKeyPress { key_output } => {
787 let pressed_key = input::PressedInput::Virtual(key_output);
788 let _ = self.pressed_inputs.push(pressed_key);
789 }
790 input::Event::VirtualKeyRelease { key_output } => {
791 self.pressed_inputs
793 .iter()
794 .position(|k| match k {
795 input::PressedInput::Virtual(ko) => key_output == *ko,
796 _ => false,
797 })
798 .map(|i| self.pressed_inputs.remove(i));
799 }
800
801 _ => {}
802 }
803 }
804
805 self.handle_pending_events();
806 }
807
808 fn handle_event(&mut self, ev: key::Event<Ev>) {
811 if let key::Event::Keymap(KeymapEvent::Callback(callback_id)) = ev {
812 match self.callbacks.get(&callback_id) {
813 Some(CallbackFunction::Rust(callback_fn)) => {
814 callback_fn();
815 }
816 Some(CallbackFunction::ExternC(callback_fn)) => {
817 callback_fn();
818 }
819 None => {}
820 }
821 }
822
823 let was_pending = self.pending_state.is_some();
824
825 self.update_pending_state(ev);
827
828 self.pressed_inputs.iter_mut().for_each(|pi| {
830 if let input::PressedInput::Key(input::PressedKey {
831 key_state,
832 key_ref,
833 keymap_index,
834 }) = pi
835 {
836 self.key_system
837 .update_state(key_state, key_ref, &self.context, *keymap_index, ev)
838 .into_iter()
839 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
840 }
841 });
842
843 self.context
845 .handle_event(ev)
846 .into_iter()
847 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
848
849 if let Event::Input(input_ev) = ev {
850 if was_pending {
851 if let Some(pending_state) = self.pending_state.as_mut() {
855 pending_state.record_input(input_ev);
856 }
857 self.handle_pending_events();
858 } else {
859 self.process_input(input_ev);
860 }
861 }
862 }
863
864 fn handle_pending_events(&mut self) {
865 while let Some(ev) = self.event_scheduler.dequeue() {
867 self.handle_event(ev);
868 }
869 }
870
871 fn aggregate_pressed_modifiers(&self) -> key::KeyboardModifiers {
876 let base = self
877 .pressed_inputs
878 .iter()
879 .filter_map(|pi| match pi {
880 input::PressedInput::Key(input::PressedKey {
881 key_ref, key_state, ..
882 }) => self.key_system.key_output(key_ref, key_state),
883 &input::PressedInput::Virtual(key_output) => Some(key_output),
884 })
885 .fold(key::KeyboardModifiers::NONE, |acc, ko| {
886 acc.union(&ko.key_modifiers())
887 });
888 let pending_mod = self
889 .pending_state
890 .as_ref()
891 .and_then(|pending| self.key_system.pending_output(&pending.pending_key_state))
892 .map_or(key::KeyboardModifiers::NONE, |ko| ko.key_modifiers());
893 base.union(&pending_mod)
894 }
895
896 fn push_keymap_context(&mut self) {
897 let km_context = KeymapContext {
898 time_ms: self.event_scheduler.schedule_counter,
899 idle_time_ms: self.idle_time,
900 pressed_modifiers: self.aggregate_pressed_modifiers(),
901 recent_presses: self.recent_presses,
902 recent_press_count: self.recent_press_count,
903 };
904 self.context.set_keymap_context(km_context);
905 }
906
907 pub fn tick(&mut self) {
909 self.push_keymap_context();
910
911 let ready = if let Some(pending_state) = self.pending_state.as_mut() {
912 pending_state.ingest_queue.pop_front_if_ready()
913 } else {
914 self.input_queue.pop_front_if_ready()
915 };
916
917 if let Some(ie) = ready {
918 self.process_input(ie);
919 self.set_active_input_delay();
920 }
921
922 self.input_queue.tick_delay();
925 if let Some(pending_state) = self.pending_state.as_mut() {
926 pending_state.ingest_queue.tick_delay();
927 }
928
929 self.event_scheduler.tick(self.ms_per_tick);
930
931 self.handle_pending_events();
932
933 self.idle_time += self.ms_per_tick as u32;
934 }
935
936 pub fn pressed_keys(&self) -> heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }> {
940 let suppress = self.context.suppressed_modifiers();
941 let resolved = self.pressed_inputs.iter().filter_map(|pi| {
942 let ko = match pi {
943 input::PressedInput::Key(input::PressedKey {
944 key_ref, key_state, ..
945 }) => self.key_system.key_output(key_ref, key_state)?,
946 &input::PressedInput::Virtual(key_output) => key_output,
947 };
948 let ko = ko.without_modifiers(suppress);
949 (ko != key::KeyOutput::NO_OUTPUT).then_some(ko)
950 });
951 let pending = self
952 .pending_state
953 .as_ref()
954 .and_then(|pending| self.key_system.pending_output(&pending.pending_key_state))
955 .map(|ko| ko.without_modifiers(suppress))
956 .filter(|ko| *ko != key::KeyOutput::NO_OUTPUT);
957 resolved.chain(pending).take(MAX_PRESSED_KEYS).collect()
958 }
959
960 fn tick_by(&mut self, delta_ms: u32) {
961 if delta_ms == 0 {
962 self.tick();
963 } else {
964 for _ in 0..(delta_ms / self.ms_per_tick as u32) {
965 self.tick();
966 }
967 }
968 }
969
970 pub fn handle_input_after_time(&mut self, delta_ms: u32, ev: input::Event) -> Option<u32> {
977 self.tick_by(delta_ms);
978 self.handle_input(ev);
979 let next_event_time = self.event_scheduler.next_event_time();
980 debug_assert!(next_event_time != Some(0));
981 next_event_time
982 }
983
984 pub fn tick_to_next_scheduled_event(&mut self) -> Option<u32> {
990 if let Some(delta_ms) = self.event_scheduler.next_event_time() {
991 self.tick_by(delta_ms);
992 self.event_scheduler.next_event_time()
993 } else {
994 None
995 }
996 }
997
998 pub fn report_output(&mut self) -> KeymapOutput {
1000 self.hid_reporter.update(self.pressed_keys());
1001 self.hid_reporter.report_sent();
1002
1003 KeymapOutput::new(self.hid_reporter.reportable_key_outputs())
1004 }
1005
1006 #[doc(hidden)]
1008 pub fn boot_keyboard_report(&self) -> [u8; 8] {
1009 KeymapOutput::new(self.pressed_keys()).as_hid_boot_keyboard_report()
1010 }
1011
1012 pub fn requires_polling(&self) -> bool {
1014 !self.event_scheduler.pending_events.is_empty()
1015 || !self.input_queue.is_empty()
1016 || self
1017 .pending_state
1018 .as_ref()
1019 .is_some_and(|ps| !ps.ingest_queue.is_empty())
1020 }
1021
1022 #[doc(hidden)]
1023 pub fn has_scheduled_events(&self) -> bool {
1024 !self.event_scheduler.pending_events.is_empty()
1025 || !self.event_scheduler.scheduled_events.is_empty()
1026 || !self.input_queue.is_empty()
1027 || self
1028 .pending_state
1029 .as_ref()
1030 .is_some_and(|ps| !ps.ingest_queue.is_empty())
1031 }
1032}
1033
1034#[cfg(feature = "std")]
1039#[doc(hidden)]
1040impl<
1041 I: Debug + Index<usize, Output = R>,
1042 R: Copy + Debug,
1043 Ctx: Debug + key::Context<Event = Ev> + SetKeymapContext + ReportHints,
1044 Ev: Copy + Debug,
1045 PKS: Debug,
1046 KS: Copy + Debug + From<key::NoOpKeyState>,
1047 S: key::System<R, Ref = R, Context = Ctx, Event = Ev, PendingKeyState = PKS, KeyState = KS>,
1048 > Keymap<I, R, Ctx, Ev, PKS, KS, S>
1049{
1050 pub fn test_is_pending(&self) -> bool {
1052 self.pending_state.is_some()
1053 }
1054
1055 pub fn test_pending_queued_events_len(&self) -> Option<usize> {
1057 self.pending_state
1058 .as_ref()
1059 .map(|pending_state| pending_state.queued_events.len())
1060 }
1061
1062 pub fn test_pending_session_log_inputs(&self) -> Option<heapless::Vec<input::Event, 16>> {
1065 self.pending_state.as_ref().map(|pending_state| {
1066 let mut inputs = heapless::Vec::new();
1067 for ev in pending_state.queued_events.iter() {
1068 if let key::Event::Input(ie) = ev {
1069 let _ = inputs.push(*ie);
1070 }
1071 }
1072 inputs
1073 })
1074 }
1075
1076 pub fn test_input_queue_len(&self) -> usize {
1079 if let Some(pending_state) = self.pending_state.as_ref() {
1080 pending_state.ingest_queue.len()
1081 } else {
1082 self.input_queue.len()
1083 }
1084 }
1085
1086 pub fn test_input_queue_delay(&self) -> bool {
1089 if let Some(pending_state) = self.pending_state.as_ref() {
1090 pending_state.ingest_queue.delay()
1091 } else {
1092 self.input_queue.delay()
1093 }
1094 }
1095
1096 pub fn test_handle_scheduled_key_event(&mut self, ev: key::Event<Ev>) {
1098 self.event_scheduler
1099 .schedule_event(key::ScheduledEvent::immediate(ev));
1100 self.handle_pending_events();
1101 }
1102}
1103
1104#[cfg(test)]
1105#[allow(clippy::unwrap_used, clippy::expect_used)]
1106mod tests {
1107 use super::*;
1108
1109 #[test]
1110 fn test_keymap_output_pressed_key_codes_includes_modifier_key_code() {
1111 let mut input: heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }> = heapless::Vec::new();
1113 input.push(key::KeyOutput::from_key_code(0x04)).unwrap();
1114 input.push(key::KeyOutput::from_key_code(0xE0)).unwrap();
1115
1116 let keymap_output = KeymapOutput::new(input);
1118 let pressed_key_codes = keymap_output.pressed_key_codes();
1119
1120 assert!(pressed_key_codes.contains(&0xE0))
1122 }
1123
1124 #[test]
1125 fn test_keymap_output_as_hid_boot_keyboard_report_gathers_modifiers() {
1126 let mut input: heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }> = heapless::Vec::new();
1128 input.push(key::KeyOutput::from_key_code(0x04)).unwrap();
1129 input.push(key::KeyOutput::from_key_code(0xE0)).unwrap();
1130
1131 let keymap_output = KeymapOutput::new(input);
1133 let actual_report: [u8; 8] = keymap_output.as_hid_boot_keyboard_report();
1134
1135 let expected_report: [u8; 8] = [0x01, 0, 0x04, 0, 0, 0, 0, 0];
1137 assert_eq!(expected_report, actual_report);
1138 }
1139
1140 #[test]
1141 fn test_keymap_output_pressed_consumer_codes() {
1142 let mut input: heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }> = heapless::Vec::new();
1143 input
1144 .push(key::KeyOutput::from_consumer_code(0xE9))
1145 .unwrap();
1146
1147 let keymap_output = KeymapOutput::new(input);
1148 assert_eq!(
1149 heapless::Vec::<u8, 24>::from_slice(&[0xE9]).unwrap(),
1150 keymap_output.pressed_consumer_codes()
1151 );
1152 }
1153
1154 #[test]
1155 fn test_keymap_output_pressed_mouse_output_combines_buttons() {
1156 let mut input: heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }> = heapless::Vec::new();
1157 input
1158 .push(key::KeyOutput::from_mouse_output(key::MouseOutput {
1159 pressed_buttons: 0b001,
1160 ..key::MouseOutput::NO_OUTPUT
1161 }))
1162 .unwrap();
1163 input
1164 .push(key::KeyOutput::from_mouse_output(key::MouseOutput {
1165 pressed_buttons: 0b010,
1166 ..key::MouseOutput::NO_OUTPUT
1167 }))
1168 .unwrap();
1169
1170 let keymap_output = KeymapOutput::new(input);
1171 assert_eq!(
1172 key::MouseOutput {
1173 pressed_buttons: 0b011,
1174 ..key::MouseOutput::NO_OUTPUT
1175 },
1176 keymap_output.pressed_mouse_output()
1177 );
1178 }
1179
1180 #[test]
1181 fn test_keymap_context_default_is_zeroed() {
1182 let context = KeymapContext::new();
1183 assert_eq!(0, context.time_ms);
1184 assert_eq!(0, context.idle_time_ms);
1185 }
1186
1187 fn recent_presses_from(entries: &[(u16, u32)]) -> ([(u16, u32); MAX_RECENT_PRESSES], u8) {
1188 let mut presses = [(0, 0); MAX_RECENT_PRESSES];
1189 presses[..entries.len()].copy_from_slice(entries);
1190 (presses, entries.len() as u8)
1191 }
1192
1193 #[test]
1194 fn test_push_recent_press_appends_same_index() {
1195 let presses = [(0, 0); MAX_RECENT_PRESSES];
1197
1198 let (presses, count) = push_recent_press(presses, 0, 2, 0);
1200 let (presses, count) = push_recent_press(presses, count, 2, 50);
1201
1202 assert_eq!(2, count);
1204 assert_eq!([(2, 0), (2, 50)], &presses[..2]);
1205 }
1206
1207 #[test]
1208 fn test_push_recent_press_appends_distinct_indices() {
1209 let presses = [(0, 0); MAX_RECENT_PRESSES];
1211
1212 let (presses, count) = push_recent_press(presses, 0, 1, 10);
1214 let (presses, count) = push_recent_press(presses, count, 2, 20);
1215
1216 assert_eq!(2, count);
1218 assert_eq!([(1, 10), (2, 20)], &presses[..2]);
1219 }
1220
1221 #[test]
1222 fn test_push_recent_press_evicts_oldest_when_full() {
1223 let (presses, count) = (0..MAX_RECENT_PRESSES).fold(
1225 ([(0, 0); MAX_RECENT_PRESSES], 0u8),
1226 |(presses, count), i| push_recent_press(presses, count, i as u16, i as u32 * 10),
1227 );
1228
1229 let (presses, count) = push_recent_press(presses, count, 99, 1000);
1231
1232 assert_eq!(MAX_RECENT_PRESSES as u8, count);
1234 assert_eq!((1, 10), presses[0]);
1235 assert_eq!((99, 1000), presses[MAX_RECENT_PRESSES - 1]);
1236 }
1237
1238 #[test]
1239 fn test_without_current_press_keeps_prior_same_index() {
1240 let (presses, count) = recent_presses_from(&[(2, 0), (2, 50)]);
1242
1243 let ctx = keymap_context_without_current_press(
1245 presses,
1246 count,
1247 0,
1248 50,
1249 key::KeyboardModifiers::NONE,
1250 2,
1251 );
1252
1253 assert_eq!(50, ctx.time_ms);
1255 assert_eq!(1, ctx.recent_press_count);
1256 assert_eq!(Some(0), ctx.last_press_time_ms(2));
1257 }
1258
1259 #[test]
1260 fn test_without_current_press_uses_fallback_when_index_absent() {
1261 let (presses, count) = recent_presses_from(&[(1, 10)]);
1263
1264 let ctx = keymap_context_without_current_press(
1266 presses,
1267 count,
1268 7,
1269 99,
1270 key::KeyboardModifiers::NONE,
1271 2,
1272 );
1273
1274 assert_eq!(99, ctx.time_ms);
1276 assert_eq!(7, ctx.idle_time_ms);
1277 assert_eq!(1, ctx.recent_press_count);
1278 assert_eq!(Some(10), ctx.last_press_time_ms(1));
1279 assert_eq!(None, ctx.last_press_time_ms(2));
1280 }
1281
1282 #[test]
1283 fn test_without_current_press_compacts_after_dropped_index() {
1284 let (presses, count) = recent_presses_from(&[(1, 10), (2, 20), (3, 30)]);
1286
1287 let ctx = keymap_context_without_current_press(
1289 presses,
1290 count,
1291 0,
1292 99,
1293 key::KeyboardModifiers::NONE,
1294 2,
1295 );
1296
1297 assert_eq!(20, ctx.time_ms);
1299 assert_eq!(2, ctx.recent_press_count);
1300 assert_eq!([(1, 10), (3, 30)], &ctx.recent_presses[..2]);
1301 assert_eq!((0, 0), ctx.recent_presses[2]);
1302 }
1303
1304 #[test]
1305 fn test_without_current_press_time_is_physical_press_not_live_fallback() {
1306 let (presses, count) = recent_presses_from(&[(0, 50)]);
1309
1310 let ctx = keymap_context_without_current_press(
1312 presses,
1313 count,
1314 40,
1315 250,
1316 key::KeyboardModifiers::NONE,
1317 0,
1318 );
1319
1320 assert_eq!(50, ctx.time_ms);
1322 }
1323
1324 #[test]
1325 fn test_without_current_press_idle_is_stored_press_idle() {
1326 let (presses, count) = recent_presses_from(&[(2, 50)]);
1328
1329 let ctx = keymap_context_without_current_press(
1331 presses,
1332 count,
1333 40,
1334 250,
1335 key::KeyboardModifiers::NONE,
1336 2,
1337 );
1338
1339 assert_eq!(40, ctx.idle_time_ms);
1341 assert_eq!(50, ctx.time_ms);
1342 }
1343
1344 #[test]
1345 fn test_without_current_press_keeps_later_other_index() {
1346 let (presses, count) = recent_presses_from(&[(0, 50), (1, 80)]);
1349
1350 let ctx = keymap_context_without_current_press(
1352 presses,
1353 count,
1354 40,
1355 250,
1356 key::KeyboardModifiers::NONE,
1357 0,
1358 );
1359
1360 assert_eq!(50, ctx.time_ms);
1362 assert_eq!(1, ctx.recent_press_count);
1363 assert_eq!(None, ctx.last_press_time_ms(0));
1364 assert_eq!(Some(80), ctx.last_press_time_ms(1));
1365 }
1366
1367 #[test]
1368 fn test_without_current_press_passes_modifiers_through() {
1369 let (presses, count) = recent_presses_from(&[(0, 50)]);
1371 let mods = key::KeyboardModifiers::LEFT_CTRL;
1372
1373 let ctx = keymap_context_without_current_press(presses, count, 0, 50, mods, 0);
1375
1376 assert_eq!(mods, ctx.pressed_modifiers);
1378 }
1379}