1use crate::keymap::{Key, KeyChord, Modifiers};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum KeyKind {
8 Press,
10 Repeat,
13 Release,
15}
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19pub struct KeyEvent {
20 pub chord: KeyChord,
23 pub kind: KeyKind,
25 pub text: Option<char>,
27}
28
29impl KeyEvent {
30 #[must_use]
36 pub fn press(chord: &str) -> Self {
37 let chord: KeyChord = chord.parse().unwrap_or_else(|message| panic!("invalid chord `{chord}`: {message}"));
38 Self::from_chord(chord)
39 }
40
41 #[must_use]
43 pub fn from_chord(chord: KeyChord) -> Self {
44 let typing = !chord.mods.ctrl && !chord.mods.alt;
45 let text = match chord.key {
46 Key::Char(c) if typing && chord.mods.shift => Some(c.to_uppercase().next().unwrap_or(c)),
47 Key::Char(c) if typing => Some(c),
48 Key::Space if typing => Some(' '),
49 _ => None,
50 };
51 Self { chord, kind: KeyKind::Press, text }
52 }
53
54 #[must_use]
56 pub fn is_plain(&self, key: Key) -> bool {
57 self.kind != KeyKind::Release && self.chord.key == key && self.chord.mods == Modifiers::default()
58 }
59}
60
61#[derive(Debug, Clone, Copy, PartialEq, Eq)]
63pub enum MouseButton {
64 Left,
66 Right,
68 Middle,
70}
71
72#[derive(Debug, Clone, Copy, PartialEq, Eq)]
74pub enum MouseKind {
75 Down(MouseButton),
77 Up(MouseButton),
79 Drag(MouseButton),
81 Moved,
83 ScrollUp,
85 ScrollDown,
87}
88
89#[derive(Debug, Clone, Copy, PartialEq, Eq)]
91pub struct MouseEvent {
92 pub kind: MouseKind,
94 pub x: i32,
96 pub y: i32,
98 pub mods: Modifiers,
100}
101
102#[derive(Debug, Clone, PartialEq, Eq)]
104pub enum Event {
105 Key(KeyEvent),
107 Mouse(MouseEvent),
109 Paste(String),
111 PointerOutside,
114}
115
116#[cfg(test)]
117mod tests {
118 use super::*;
119
120 #[test]
121 fn press_derives_typed_text() {
122 assert_eq!(KeyEvent::press("a").text, Some('a'));
123 assert_eq!(KeyEvent::press("shift+a").text, Some('A'));
124 assert_eq!(KeyEvent::press("space").text, Some(' '));
125 assert_eq!(KeyEvent::press("ctrl+a").text, None);
126 assert_eq!(KeyEvent::press("enter").text, None);
127 assert!(KeyEvent::press("enter").is_plain(Key::Enter));
128 assert!(!KeyEvent::press("shift+enter").is_plain(Key::Enter));
129 }
130}