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