Skip to content

Commit ec0011f

Browse files
committed
keymap: extract pending session module and unify replay dispatch
Move pending state, resolution filter, and replay routing into pending.rs. Introduce PendingKeySession, ReplayPolicy, and dispatch_replayed_events for the resolve vs nested-pending paths.
1 parent f7df32c commit ec0011f

3 files changed

Lines changed: 269 additions & 159 deletions

File tree

‎src/key.rs‎

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,53 @@ impl<T: Copy> Event<T> {
755755
Event::Keymap(cb) => Ok(Event::Keymap(cb)),
756756
}
757757
}
758+
759+
/// Whether this event targets the given `keymap_index`.
760+
///
761+
/// Input press/release and key-specific events carry a `keymap_index`;
762+
/// keymap callbacks and other variants do not.
763+
pub(crate) fn targets_keymap_index(&self, keymap_index: u16) -> bool {
764+
match self {
765+
Event::Input(input::Event::Press {
766+
keymap_index: queued_kmi,
767+
})
768+
| Event::Input(input::Event::Release {
769+
keymap_index: queued_kmi,
770+
}) => *queued_kmi == keymap_index,
771+
Event::Key {
772+
keymap_index: queued_kmi,
773+
..
774+
} => *queued_kmi == keymap_index,
775+
_ => false,
776+
}
777+
}
778+
}
779+
780+
/// Returns the events that should be replayed when a pending key resolves.
781+
///
782+
/// Resolution filter:
783+
/// - All queued events **not** targeting `keymap_index` are included.
784+
/// - Only the **last** event targeting `keymap_index` is included (if any).
785+
///
786+
/// **Example:**
787+
/// session log `[Press(1), Press(0), Release(0)]` for resolving key 0:
788+
/// yields `[Press(1), Release(0)]`
789+
/// — other-key inputs are kept,
790+
/// - but only the final self-event (`Release(0)`) remains from key 0's own press/release pair.
791+
pub(crate) fn pending_resolution_events<Ev: Copy, const N: usize>(
792+
queued_events: &heapless::Vec<Event<Ev>, N>,
793+
keymap_index: u16,
794+
) -> heapless::Vec<Event<Ev>, N> {
795+
let (self_events, other_events): (heapless::Vec<Event<Ev>, N>, heapless::Vec<Event<Ev>, N>) =
796+
queued_events
797+
.iter()
798+
.partition(|ev| ev.targets_keymap_index(keymap_index));
799+
800+
let mut result = heapless::Vec::new();
801+
for ev in other_events.iter().chain(self_events.last()) {
802+
let _ = result.push(*ev);
803+
}
804+
result
758805
}
759806

760807
impl<T> From<input::Event> for Event<T> {
@@ -816,3 +863,70 @@ impl<T: Copy> ScheduledEvent<T> {
816863
self.map_scheduled_event(|e| e.into())
817864
}
818865
}
866+
867+
#[cfg(test)]
868+
#[allow(clippy::unwrap_used, clippy::expect_used)]
869+
mod tests {
870+
use super::*;
871+
872+
#[test]
873+
fn pending_resolution_events_empty_returns_empty() {
874+
let queued: heapless::Vec<Event<()>, 16> = heapless::Vec::new();
875+
let result = pending_resolution_events(&queued, 0);
876+
assert!(result.is_empty());
877+
}
878+
879+
#[test]
880+
fn pending_resolution_events_other_key_events_all_included() {
881+
let mut queued: heapless::Vec<Event<()>, 16> = heapless::Vec::new();
882+
queued
883+
.push(Event::Input(input::Event::Press { keymap_index: 1 }))
884+
.unwrap();
885+
queued
886+
.push(Event::Input(input::Event::Release { keymap_index: 2 }))
887+
.unwrap();
888+
let result = pending_resolution_events(&queued, 0);
889+
assert_eq!(2, result.len());
890+
}
891+
892+
#[test]
893+
fn pending_resolution_events_resolving_key_only_last_included() {
894+
let mut queued: heapless::Vec<Event<()>, 16> = heapless::Vec::new();
895+
queued
896+
.push(Event::Input(input::Event::Press { keymap_index: 0 }))
897+
.unwrap();
898+
queued
899+
.push(Event::Input(input::Event::Release { keymap_index: 0 }))
900+
.unwrap();
901+
let result = pending_resolution_events(&queued, 0);
902+
assert_eq!(1, result.len());
903+
assert_eq!(
904+
Event::Input(input::Event::Release { keymap_index: 0 }),
905+
result[0]
906+
);
907+
}
908+
909+
#[test]
910+
fn pending_resolution_events_mix_other_and_resolving_key() {
911+
let mut queued: heapless::Vec<Event<()>, 16> = heapless::Vec::new();
912+
queued
913+
.push(Event::Input(input::Event::Press { keymap_index: 1 }))
914+
.unwrap();
915+
queued
916+
.push(Event::Input(input::Event::Press { keymap_index: 0 }))
917+
.unwrap();
918+
queued
919+
.push(Event::Input(input::Event::Release { keymap_index: 0 }))
920+
.unwrap();
921+
let result = pending_resolution_events(&queued, 0);
922+
assert_eq!(2, result.len());
923+
assert_eq!(
924+
Event::Input(input::Event::Press { keymap_index: 1 }),
925+
result[0]
926+
);
927+
assert_eq!(
928+
Event::Input(input::Event::Release { keymap_index: 0 }),
929+
result[1]
930+
);
931+
}
932+
}

0 commit comments

Comments
 (0)