1#[derive(Debug, Clone, PartialEq, Eq)]
7pub enum Event {
8 Key(KeyEvent),
10 Mouse(MouseEvent),
12 Resize(u32, u32),
14}
15
16#[derive(Debug, Clone, PartialEq, Eq)]
18pub struct KeyEvent {
19 pub code: KeyCode,
21 pub modifiers: KeyModifiers,
23}
24
25#[derive(Debug, Clone, PartialEq, Eq)]
31pub enum KeyCode {
32 Char(char),
34 Enter,
36 Backspace,
38 Tab,
40 BackTab,
42 Esc,
44 Up,
46 Down,
48 Left,
50 Right,
52 Home,
54 End,
56 PageUp,
58 PageDown,
60 Delete,
62 F(u8),
64}
65
66#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
71pub struct KeyModifiers(pub u8);
72
73impl KeyModifiers {
74 pub const NONE: Self = Self(0);
76 pub const SHIFT: Self = Self(1 << 0);
78 pub const CONTROL: Self = Self(1 << 1);
80 pub const ALT: Self = Self(1 << 2);
82
83 #[inline]
85 pub fn contains(self, other: Self) -> bool {
86 (self.0 & other.0) == other.0
87 }
88}
89
90#[derive(Debug, Clone, PartialEq, Eq)]
96pub struct MouseEvent {
97 pub kind: MouseKind,
99 pub x: u32,
101 pub y: u32,
103 pub modifiers: KeyModifiers,
105}
106
107#[derive(Debug, Clone, PartialEq, Eq)]
109pub enum MouseKind {
110 Down(MouseButton),
112 Up(MouseButton),
114 Drag(MouseButton),
116 ScrollUp,
118 ScrollDown,
120 Moved,
122}
123
124#[derive(Debug, Clone, Copy, PartialEq, Eq)]
126pub enum MouseButton {
127 Left,
129 Right,
131 Middle,
133}
134
135fn convert_modifiers(modifiers: crossterm::event::KeyModifiers) -> KeyModifiers {
136 let mut out = KeyModifiers::NONE;
137 if modifiers.contains(crossterm::event::KeyModifiers::SHIFT) {
138 out.0 |= KeyModifiers::SHIFT.0;
139 }
140 if modifiers.contains(crossterm::event::KeyModifiers::CONTROL) {
141 out.0 |= KeyModifiers::CONTROL.0;
142 }
143 if modifiers.contains(crossterm::event::KeyModifiers::ALT) {
144 out.0 |= KeyModifiers::ALT.0;
145 }
146 out
147}
148
149fn convert_button(button: crossterm::event::MouseButton) -> MouseButton {
150 match button {
151 crossterm::event::MouseButton::Left => MouseButton::Left,
152 crossterm::event::MouseButton::Right => MouseButton::Right,
153 crossterm::event::MouseButton::Middle => MouseButton::Middle,
154 }
155}
156
157pub(crate) fn from_crossterm(raw: crossterm::event::Event) -> Option<Event> {
162 match raw {
163 crossterm::event::Event::Key(k) => {
164 if k.kind != crossterm::event::KeyEventKind::Press {
166 return None;
167 }
168 let code = match k.code {
169 crossterm::event::KeyCode::Char(c) => KeyCode::Char(c),
170 crossterm::event::KeyCode::Enter => KeyCode::Enter,
171 crossterm::event::KeyCode::Backspace => KeyCode::Backspace,
172 crossterm::event::KeyCode::Tab => KeyCode::Tab,
173 crossterm::event::KeyCode::BackTab => KeyCode::BackTab,
174 crossterm::event::KeyCode::Esc => KeyCode::Esc,
175 crossterm::event::KeyCode::Up => KeyCode::Up,
176 crossterm::event::KeyCode::Down => KeyCode::Down,
177 crossterm::event::KeyCode::Left => KeyCode::Left,
178 crossterm::event::KeyCode::Right => KeyCode::Right,
179 crossterm::event::KeyCode::Home => KeyCode::Home,
180 crossterm::event::KeyCode::End => KeyCode::End,
181 crossterm::event::KeyCode::PageUp => KeyCode::PageUp,
182 crossterm::event::KeyCode::PageDown => KeyCode::PageDown,
183 crossterm::event::KeyCode::Delete => KeyCode::Delete,
184 crossterm::event::KeyCode::F(n) => KeyCode::F(n),
185 _ => return None,
186 };
187 let modifiers = convert_modifiers(k.modifiers);
188 Some(Event::Key(KeyEvent { code, modifiers }))
189 }
190 crossterm::event::Event::Mouse(m) => {
191 let kind = match m.kind {
192 crossterm::event::MouseEventKind::Down(btn) => MouseKind::Down(convert_button(btn)),
193 crossterm::event::MouseEventKind::Up(btn) => MouseKind::Up(convert_button(btn)),
194 crossterm::event::MouseEventKind::Drag(btn) => MouseKind::Drag(convert_button(btn)),
195 crossterm::event::MouseEventKind::Moved => MouseKind::Moved,
196 crossterm::event::MouseEventKind::ScrollUp => MouseKind::ScrollUp,
197 crossterm::event::MouseEventKind::ScrollDown => MouseKind::ScrollDown,
198 _ => return None,
199 };
200
201 Some(Event::Mouse(MouseEvent {
202 kind,
203 x: m.column as u32,
204 y: m.row as u32,
205 modifiers: convert_modifiers(m.modifiers),
206 }))
207 }
208 crossterm::event::Event::Resize(cols, rows) => {
209 Some(Event::Resize(cols as u32, rows as u32))
210 }
211 _ => None,
212 }
213}