1use alloc::vec::Vec;
5use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, Not};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
8pub struct KeyModifiers(u8);
14
15impl KeyModifiers {
16 pub const NONE: Self = Self(0);
18 pub const SHIFT: Self = Self(1 << 0);
20 pub const CONTROL: Self = Self(1 << 1);
22 pub const ALT: Self = Self(1 << 2);
24 pub const SUPER: Self = Self(1 << 3);
26
27 #[must_use]
33 pub const fn from_bits_truncate(bits: u8) -> Self {
34 Self(bits & 0b1111)
35 }
36
37 #[must_use]
43 #[allow(clippy::fn_params_excessive_bools)]
45 pub const fn from_parts(shift: bool, control: bool, alt: bool, super_: bool) -> Self {
46 Self((shift as u8) | (control as u8) << 1 | (alt as u8) << 2 | (super_ as u8) << 3)
47 }
48
49 #[must_use]
52 pub const fn bits(self) -> u8 {
53 self.0
54 }
55
56 #[must_use]
58 pub const fn contains(self, other: Self) -> bool {
59 (self.0 & other.0) == other.0
60 }
61
62 #[must_use]
64 pub const fn is_empty(self) -> bool {
65 self.0 == 0
66 }
67}
68
69impl BitOr for KeyModifiers {
70 type Output = Self;
71 fn bitor(self, rhs: Self) -> Self {
72 Self(self.0 | rhs.0)
73 }
74}
75
76impl BitOrAssign for KeyModifiers {
77 fn bitor_assign(&mut self, rhs: Self) {
78 self.0 |= rhs.0;
79 }
80}
81
82impl BitAnd for KeyModifiers {
83 type Output = Self;
84 fn bitand(self, rhs: Self) -> Self {
85 Self(self.0 & rhs.0)
86 }
87}
88
89impl BitAndAssign for KeyModifiers {
90 fn bitand_assign(&mut self, rhs: Self) {
91 self.0 &= rhs.0;
92 }
93}
94
95impl Not for KeyModifiers {
96 type Output = Self;
97 fn not(self) -> Self {
98 Self(!self.0 & 0b1111)
101 }
102}
103
104#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
105#[non_exhaustive]
106pub enum ModifierKey {
117 Shift,
119 Control,
121 Alt,
123 Super,
125}
126
127#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
128#[non_exhaustive]
129pub enum KeyCode {
131 Char(char),
133 F(u8),
135 Backspace,
137 Enter,
139 Left,
141 Right,
143 Up,
145 Down,
147 Home,
149 End,
151 PageUp,
153 PageDown,
155 Tab,
157 BackTab,
159 Delete,
161 Insert,
163 Escape,
165 Modifier(ModifierKey),
168 CapsLock,
170 ScrollLock,
172 NumLock,
174 PrintScreen,
176 Pause,
178 Menu,
180}
181
182#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
183#[non_exhaustive]
184pub enum KeyEventKind {
199 #[default]
201 Press,
202 Repeat,
204 Release,
206}
207
208#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
209#[non_exhaustive]
210pub enum KeyLocation {
217 #[default]
220 Standard,
221 Left,
223 Right,
225 Numpad,
227}
228
229#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
230#[non_exhaustive]
231pub struct KeyEvent {
233 pub code: KeyCode,
235 pub modifiers: KeyModifiers,
237 pub kind: KeyEventKind,
242 pub location: KeyLocation,
246}
247
248impl KeyEvent {
249 #[must_use]
252 pub const fn new(code: KeyCode, modifiers: KeyModifiers) -> Self {
253 Self {
254 code,
255 modifiers,
256 kind: KeyEventKind::Press,
257 location: KeyLocation::Standard,
258 }
259 }
260
261 #[must_use]
263 pub const fn with_kind(code: KeyCode, modifiers: KeyModifiers, kind: KeyEventKind) -> Self {
264 Self {
265 code,
266 modifiers,
267 kind,
268 location: KeyLocation::Standard,
269 }
270 }
271
272 #[must_use]
274 pub const fn with_location(
275 code: KeyCode,
276 modifiers: KeyModifiers,
277 kind: KeyEventKind,
278 location: KeyLocation,
279 ) -> Self {
280 Self {
281 code,
282 modifiers,
283 kind,
284 location,
285 }
286 }
287
288 #[must_use]
291 pub const fn is_down(self) -> bool {
292 matches!(self.kind, KeyEventKind::Press | KeyEventKind::Repeat)
293 }
294}
295
296#[derive(Debug, Clone, Default)]
318pub struct KeyState {
319 held: Vec<(KeyCode, KeyLocation)>,
320}
321
322impl KeyState {
323 #[must_use]
325 pub const fn new() -> Self {
326 Self { held: Vec::new() }
327 }
328
329 pub fn apply(&mut self, event: KeyEvent) {
334 let entry = (event.code, event.location);
335 match event.kind {
336 KeyEventKind::Press | KeyEventKind::Repeat => {
337 if !self.held.contains(&entry) {
338 self.held.push(entry);
339 }
340 }
341 KeyEventKind::Release => {
342 self.held.retain(|&e| e != entry);
343 }
344 }
345 }
346
347 pub fn apply_event(&mut self, event: &super::Event) {
353 match event {
354 super::Event::Key(key) => self.apply(*key),
355 super::Event::FocusLost => self.clear(),
356 _ => {}
357 }
358 }
359
360 #[must_use]
362 pub fn is_held(&self, code: KeyCode, location: KeyLocation) -> bool {
363 self.held.contains(&(code, location))
364 }
365
366 pub fn held(&self) -> impl Iterator<Item = (KeyCode, KeyLocation)> + '_ {
368 self.held.iter().copied()
369 }
370
371 pub fn clear(&mut self) {
373 self.held.clear();
374 }
375}
376
377#[cfg(test)]
378mod tests {
379 use super::super::Event;
380 use super::*;
381 use alloc::vec;
382
383 #[test]
384 fn test_key_modifiers() {
385 let mods = KeyModifiers::SHIFT | KeyModifiers::CONTROL;
386 assert!(mods.contains(KeyModifiers::SHIFT));
387 assert!(mods.contains(KeyModifiers::CONTROL));
388 assert!(!mods.contains(KeyModifiers::ALT));
389 assert!(!mods.is_empty());
390
391 let inverse = !mods;
392 assert!(inverse.contains(KeyModifiers::ALT));
393 assert!(inverse.contains(KeyModifiers::SUPER));
394 assert!(!inverse.contains(KeyModifiers::SHIFT));
395 assert!(!inverse.contains(KeyModifiers::CONTROL));
396 }
397
398 #[derive(Default)]
401 struct TestHasher(u64);
402
403 impl core::hash::Hasher for TestHasher {
404 fn finish(&self) -> u64 {
405 self.0
406 }
407 fn write(&mut self, bytes: &[u8]) {
408 for byte in bytes {
409 self.0 = self.0.wrapping_mul(31).wrapping_add(u64::from(*byte));
410 }
411 }
412 }
413
414 #[test]
415 fn test_key_modifiers_not_masks_unused_bits() {
416 use core::hash::Hash;
417
418 let all =
419 KeyModifiers::SHIFT | KeyModifiers::CONTROL | KeyModifiers::ALT | KeyModifiers::SUPER;
420 let inverse = !KeyModifiers::NONE;
421
422 assert_eq!(inverse, all, "NOT NONE should equal ALL");
425
426 let mut inverse_hasher = TestHasher::default();
427 inverse.hash(&mut inverse_hasher);
428 let mut all_hasher = TestHasher::default();
429 all.hash(&mut all_hasher);
430 assert_eq!(
431 core::hash::Hasher::finish(&inverse_hasher),
432 core::hash::Hasher::finish(&all_hasher),
433 "NOT NONE should hash the same as ALL"
434 );
435 }
436
437 #[test]
438 fn test_key_modifiers_super() {
439 let mods = KeyModifiers::SUPER;
440 assert!(mods.contains(KeyModifiers::SUPER));
441 assert!(!mods.contains(KeyModifiers::SHIFT));
442 assert!(!mods.contains(KeyModifiers::CONTROL));
443 assert!(!mods.contains(KeyModifiers::ALT));
444
445 let all =
446 KeyModifiers::SHIFT | KeyModifiers::CONTROL | KeyModifiers::ALT | KeyModifiers::SUPER;
447 assert!(all.contains(KeyModifiers::SUPER));
448 assert!(all.contains(KeyModifiers::SHIFT));
449 assert!(all.contains(KeyModifiers::CONTROL));
450 assert!(all.contains(KeyModifiers::ALT));
451 }
452
453 #[test]
454 fn test_key_modifiers_from_bits_truncate() {
455 assert_eq!(KeyModifiers::from_bits_truncate(0), KeyModifiers::NONE);
456 assert_eq!(KeyModifiers::from_bits_truncate(1), KeyModifiers::SHIFT);
457 assert_eq!(KeyModifiers::from_bits_truncate(2), KeyModifiers::CONTROL);
458 assert_eq!(KeyModifiers::from_bits_truncate(4), KeyModifiers::ALT);
459 assert_eq!(KeyModifiers::from_bits_truncate(8), KeyModifiers::SUPER);
460 assert_eq!(
461 KeyModifiers::from_bits_truncate(0b1111),
462 KeyModifiers::SHIFT | KeyModifiers::CONTROL | KeyModifiers::ALT | KeyModifiers::SUPER
463 );
464 assert_eq!(
466 KeyModifiers::from_bits_truncate(0xFF),
467 KeyModifiers::SHIFT | KeyModifiers::CONTROL | KeyModifiers::ALT | KeyModifiers::SUPER
468 );
469 }
470
471 #[test]
472 fn test_key_modifiers_bits_round_trip() {
473 for bits in 0..=u8::MAX {
474 assert_eq!(KeyModifiers::from_bits_truncate(bits).bits(), bits & 0b1111);
475 }
476 }
477
478 #[test]
479 fn test_key_modifiers_from_parts() {
480 assert_eq!(
481 KeyModifiers::from_parts(false, false, false, false),
482 KeyModifiers::NONE
483 );
484 assert_eq!(
485 KeyModifiers::from_parts(true, false, false, false),
486 KeyModifiers::SHIFT
487 );
488 assert_eq!(
489 KeyModifiers::from_parts(false, true, false, false),
490 KeyModifiers::CONTROL
491 );
492 assert_eq!(
493 KeyModifiers::from_parts(false, false, true, false),
494 KeyModifiers::ALT
495 );
496 assert_eq!(
497 KeyModifiers::from_parts(false, false, false, true),
498 KeyModifiers::SUPER
499 );
500 assert_eq!(
501 KeyModifiers::from_parts(true, true, true, true),
502 KeyModifiers::SHIFT | KeyModifiers::CONTROL | KeyModifiers::ALT | KeyModifiers::SUPER
503 );
504 }
505
506 #[test]
507 fn test_event_construction() {
508 let key_event = KeyEvent::new(KeyCode::Char('a'), KeyModifiers::SHIFT);
509 let event = Event::Key(key_event);
510
511 if let Event::Key(ke) = event {
512 assert_eq!(ke.code, KeyCode::Char('a'));
513 assert!(ke.modifiers.contains(KeyModifiers::SHIFT));
514 assert_eq!(ke.kind, KeyEventKind::Press);
515 } else {
516 panic!("Expected Event::Key");
517 }
518 }
519
520 #[test]
521 fn test_key_event_kind_helpers() {
522 let press = KeyEvent::new(KeyCode::Char('x'), KeyModifiers::NONE);
523 assert_eq!(press.kind, KeyEventKind::Press);
524 assert!(press.is_down());
525
526 let repeat =
527 KeyEvent::with_kind(KeyCode::Char('x'), KeyModifiers::NONE, KeyEventKind::Repeat);
528 assert!(repeat.is_down());
529
530 let release = KeyEvent::with_kind(
531 KeyCode::Char('x'),
532 KeyModifiers::NONE,
533 KeyEventKind::Release,
534 );
535 assert!(!release.is_down());
536 }
537
538 #[test]
539 fn test_key_state_tracks_held_keys() {
540 let mut state = KeyState::new();
541 assert!(!state.is_held(KeyCode::Left, KeyLocation::Standard));
542
543 state.apply(KeyEvent::new(KeyCode::Left, KeyModifiers::NONE));
544 assert!(state.is_held(KeyCode::Left, KeyLocation::Standard));
545
546 state.apply(KeyEvent::with_kind(
548 KeyCode::Left,
549 KeyModifiers::NONE,
550 KeyEventKind::Repeat,
551 ));
552 assert!(state.is_held(KeyCode::Left, KeyLocation::Standard));
553
554 state.apply(KeyEvent::with_kind(
555 KeyCode::Left,
556 KeyModifiers::NONE,
557 KeyEventKind::Release,
558 ));
559 assert!(!state.is_held(KeyCode::Left, KeyLocation::Standard));
560 }
561
562 #[test]
563 fn test_key_state_distinguishes_numpad_from_standard() {
564 let mut state = KeyState::new();
565 state.apply(KeyEvent::with_location(
566 KeyCode::Char('8'),
567 KeyModifiers::NONE,
568 KeyEventKind::Press,
569 KeyLocation::Numpad,
570 ));
571 assert!(state.is_held(KeyCode::Char('8'), KeyLocation::Numpad));
572 assert!(!state.is_held(KeyCode::Char('8'), KeyLocation::Standard));
573
574 state.apply(KeyEvent::new(KeyCode::Char('8'), KeyModifiers::NONE));
575 assert!(state.is_held(KeyCode::Char('8'), KeyLocation::Standard));
576 assert!(state.is_held(KeyCode::Char('8'), KeyLocation::Numpad));
577
578 state.apply(KeyEvent::with_kind(
579 KeyCode::Char('8'),
580 KeyModifiers::NONE,
581 KeyEventKind::Release,
582 ));
583 assert!(!state.is_held(KeyCode::Char('8'), KeyLocation::Standard));
584 assert!(state.is_held(KeyCode::Char('8'), KeyLocation::Numpad));
585 }
586
587 #[test]
588 fn test_key_state_apply_event_ignores_non_key() {
589 let mut state = KeyState::new();
590 state.apply_event(&Event::Resize(1, 1));
591 assert!(state.held().next().is_none());
592 state.apply_event(&Event::Key(KeyEvent::new(KeyCode::Up, KeyModifiers::NONE)));
593 assert!(state.is_held(KeyCode::Up, KeyLocation::Standard));
594 }
595
596 #[test]
597 fn test_key_state_apply_event_clears_on_focus_lost() {
598 let mut state = KeyState::new();
599 state.apply_event(&Event::Key(KeyEvent::new(KeyCode::Up, KeyModifiers::NONE)));
600 state.apply_event(&Event::Key(KeyEvent::new(
601 KeyCode::Left,
602 KeyModifiers::NONE,
603 )));
604 assert!(state.is_held(KeyCode::Up, KeyLocation::Standard));
605 assert!(state.is_held(KeyCode::Left, KeyLocation::Standard));
606
607 state.apply_event(&Event::FocusLost);
611 assert!(!state.is_held(KeyCode::Up, KeyLocation::Standard));
612 assert!(!state.is_held(KeyCode::Left, KeyLocation::Standard));
613 assert!(state.held().next().is_none());
614 }
615
616 #[test]
617 fn test_key_state_clear() {
618 let mut state = KeyState::new();
619 state.apply(KeyEvent::new(KeyCode::Left, KeyModifiers::NONE));
620 state.apply(KeyEvent::new(KeyCode::Right, KeyModifiers::NONE));
621 assert_eq!(state.held().count(), 2);
622
623 state.clear();
624 assert!(state.held().next().is_none());
625 assert!(!state.is_held(KeyCode::Left, KeyLocation::Standard));
626 assert!(!state.is_held(KeyCode::Right, KeyLocation::Standard));
627
628 state.clear();
630 assert!(state.held().next().is_none());
631 }
632
633 #[test]
634 fn test_key_state_held_is_in_first_pressed_order() {
635 let mut state = KeyState::new();
636 state.apply(KeyEvent::new(KeyCode::Left, KeyModifiers::NONE));
637 state.apply(KeyEvent::new(KeyCode::Up, KeyModifiers::NONE));
638 state.apply(KeyEvent::new(KeyCode::Right, KeyModifiers::NONE));
639 assert_eq!(
640 state.held().collect::<Vec<_>>(),
641 vec![
642 (KeyCode::Left, KeyLocation::Standard),
643 (KeyCode::Up, KeyLocation::Standard),
644 (KeyCode::Right, KeyLocation::Standard),
645 ]
646 );
647
648 state.apply(KeyEvent::with_kind(
651 KeyCode::Left,
652 KeyModifiers::NONE,
653 KeyEventKind::Release,
654 ));
655 state.apply(KeyEvent::new(KeyCode::Left, KeyModifiers::NONE));
656 assert_eq!(
657 state.held().collect::<Vec<_>>(),
658 vec![
659 (KeyCode::Up, KeyLocation::Standard),
660 (KeyCode::Right, KeyLocation::Standard),
661 (KeyCode::Left, KeyLocation::Standard),
662 ]
663 );
664 }
665
666 #[test]
667 fn test_key_state_release_of_unpressed_key_is_a_no_op() {
668 let mut state = KeyState::new();
669 state.apply(KeyEvent::new(KeyCode::Up, KeyModifiers::NONE));
670
671 state.apply(KeyEvent::with_kind(
673 KeyCode::Down,
674 KeyModifiers::NONE,
675 KeyEventKind::Release,
676 ));
677 assert!(!state.is_held(KeyCode::Down, KeyLocation::Standard));
678 assert!(state.is_held(KeyCode::Up, KeyLocation::Standard));
679 assert_eq!(state.held().count(), 1);
680 }
681
682 #[test]
683 fn test_key_state_double_press_without_release_does_not_duplicate() {
684 let mut state = KeyState::new();
685 state.apply(KeyEvent::new(KeyCode::Up, KeyModifiers::NONE));
686 state.apply(KeyEvent::new(KeyCode::Up, KeyModifiers::NONE));
687 assert_eq!(state.held().count(), 1);
688
689 state.apply(KeyEvent::with_kind(
692 KeyCode::Up,
693 KeyModifiers::NONE,
694 KeyEventKind::Release,
695 ));
696 assert!(!state.is_held(KeyCode::Up, KeyLocation::Standard));
697 assert!(state.held().next().is_none());
698 }
699}