Another project
1use crate::input::{InputSnapshot, KeyCode, KeyEvent, ModifierMask, NamedKey};
2
3#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4pub struct TakeKey {
5 pub code: KeyCode,
6 pub modifiers: ModifierMask,
7}
8
9impl TakeKey {
10 #[must_use]
11 pub const fn new(code: KeyCode, modifiers: ModifierMask) -> Self {
12 Self { code, modifiers }
13 }
14
15 #[must_use]
16 pub const fn named(key: NamedKey) -> Self {
17 Self::new(KeyCode::Named(key), ModifierMask::NONE)
18 }
19
20 fn matches(self, event: KeyEvent) -> bool {
21 event.code == self.code && event.modifiers == self.modifiers
22 }
23}
24
25#[must_use]
26pub fn take_key(input: &mut InputSnapshot, candidates: &[TakeKey]) -> Option<KeyEvent> {
27 let position = input
28 .keys_pressed
29 .iter()
30 .position(|event| candidates.iter().any(|target| target.matches(*event)));
31 position.map(|index| input.keys_pressed.remove(index))
32}
33
34pub(super) fn take_activation(input: &mut InputSnapshot) -> bool {
35 take_key(
36 input,
37 &[
38 TakeKey::named(NamedKey::Enter),
39 TakeKey::named(NamedKey::Space),
40 ],
41 )
42 .is_some()
43}
44
45#[cfg(test)]
46mod tests {
47 use super::{TakeKey, take_key};
48 use crate::input::{
49 FrameInstant, InputSnapshot, KeyChar, KeyCode, KeyEvent, ModifierMask, NamedKey,
50 };
51
52 fn snap_with(events: Vec<KeyEvent>) -> InputSnapshot {
53 let mut snap = InputSnapshot::idle(FrameInstant::ZERO);
54 snap.keys_pressed = events;
55 snap
56 }
57
58 #[test]
59 fn take_key_drains_first_match_and_keeps_rest() {
60 let enter = KeyEvent::new(KeyCode::Named(NamedKey::Enter), ModifierMask::NONE);
61 let other = KeyEvent::new(KeyCode::Char(KeyChar::from_char('x')), ModifierMask::NONE);
62 let mut snap = snap_with(vec![other, enter, other]);
63 let taken = take_key(&mut snap, &[TakeKey::named(NamedKey::Enter)]);
64 assert_eq!(taken, Some(enter));
65 assert_eq!(snap.keys_pressed, vec![other, other]);
66 }
67
68 #[test]
69 fn take_key_returns_none_on_no_match() {
70 let other = KeyEvent::new(KeyCode::Char(KeyChar::from_char('x')), ModifierMask::NONE);
71 let mut snap = snap_with(vec![other]);
72 let taken = take_key(&mut snap, &[TakeKey::named(NamedKey::Enter)]);
73 assert!(taken.is_none());
74 assert_eq!(snap.keys_pressed, vec![other]);
75 }
76
77 #[test]
78 fn take_key_respects_modifier_mask() {
79 let plain = KeyEvent::new(KeyCode::Char(KeyChar::from_char('s')), ModifierMask::NONE);
80 let ctrl = KeyEvent::new(KeyCode::Char(KeyChar::from_char('s')), ModifierMask::CTRL);
81 let mut snap = snap_with(vec![plain, ctrl]);
82 let target = TakeKey::new(KeyCode::Char(KeyChar::from_char('s')), ModifierMask::CTRL);
83 let taken = take_key(&mut snap, &[target]);
84 assert_eq!(taken, Some(ctrl));
85 assert_eq!(snap.keys_pressed, vec![plain]);
86 }
87}