1#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
3pub enum MouseButton {
4 Left,
6 Right,
8 Middle,
10}
11
12#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
14pub enum MouseKind {
15 Down(MouseButton),
17 Up(MouseButton),
19 Drag(MouseButton),
21 Moved,
23 ScrollUp,
25 ScrollDown,
27}
28
29#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
31pub struct MouseEvent {
32 pub x: u16,
34 pub y: u16,
36 pub kind: MouseKind,
38 pub mods: KeyMods,
40}
41
42#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
44pub struct MouseMoveEvent {
45 pub x: u16,
47 pub y: u16,
49 pub local_x: u16,
51 pub local_y: u16,
53 pub target_w: u16,
55 pub target_h: u16,
57 pub mods: KeyMods,
59}
60
61#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
63pub struct MouseDragEvent {
64 pub from_x: u16,
66 pub from_y: u16,
68 pub from_local_x: u16,
70 pub from_local_y: u16,
72 pub x: u16,
74 pub y: u16,
76 pub local_x: u16,
78 pub local_y: u16,
80 pub delta_x: i16,
82 pub delta_y: i16,
84 pub target_w: u16,
86 pub target_h: u16,
88 pub mods: KeyMods,
90}
91
92#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
94pub struct KeyMods {
95 pub ctrl: bool,
97 pub alt: bool,
99 pub shift: bool,
101 pub super_key: bool,
103}
104
105impl KeyMods {
106 pub const NONE: Self = Self {
108 ctrl: false,
109 alt: false,
110 shift: false,
111 super_key: false,
112 };
113
114 pub const SHIFT: Self = Self {
116 ctrl: false,
117 alt: false,
118 shift: true,
119 super_key: false,
120 };
121
122 pub const CTRL: Self = Self {
124 ctrl: true,
125 alt: false,
126 shift: false,
127 super_key: false,
128 };
129
130 pub const ALT: Self = Self {
132 ctrl: false,
133 alt: true,
134 shift: false,
135 super_key: false,
136 };
137
138 pub fn is_empty(&self) -> bool {
140 !self.ctrl && !self.alt && !self.shift && !self.super_key
141 }
142}
143
144#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
146pub enum KeyCode {
147 Char(char),
149 Insert,
151 Enter,
153 Esc,
155 Tab,
157 BackTab,
159 Backspace,
161 Delete,
163 Home,
165 End,
167 PageUp,
169 PageDown,
171 Up,
173 Down,
175 Left,
177 Right,
179 F(u8),
181}
182
183#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
189pub struct KeyEvent {
190 pub code: KeyCode,
192 pub mods: KeyMods,
194}
195
196impl KeyEvent {
197 pub fn is(&self, code: KeyCode) -> bool {
199 self.code == code && self.mods.is_empty()
200 }
201
202 pub fn is_with(&self, code: KeyCode, mods: KeyMods) -> bool {
204 self.code == code && self.mods == mods
205 }
206
207 pub fn to_formatted_string(&self, lowercase: bool) -> String {
211 let mut parts = Vec::new();
212
213 if self.mods.ctrl {
214 parts.push("Ctrl");
215 }
216 if self.mods.alt {
217 parts.push("Alt");
218 }
219 if self.mods.super_key {
220 parts.push("Super");
221 }
222 if self.mods.shift {
223 parts.push("Shift");
224 }
225
226 let code_str = match self.code {
227 KeyCode::Char(c) => {
228 if c == ' ' {
229 "Space".to_string()
230 } else {
231 c.to_uppercase().to_string()
232 }
233 }
234 KeyCode::Insert => "Insert".to_string(),
235 KeyCode::Enter => "Enter".to_string(),
236 KeyCode::Esc => "Esc".to_string(),
237 KeyCode::Tab => "Tab".to_string(),
238 KeyCode::BackTab => "BackTab".to_string(),
239 KeyCode::Backspace => "Backspace".to_string(),
240 KeyCode::Delete => "Delete".to_string(),
241 KeyCode::Home => "Home".to_string(),
242 KeyCode::End => "End".to_string(),
243 KeyCode::PageUp => "PageUp".to_string(),
244 KeyCode::PageDown => "PageDown".to_string(),
245 KeyCode::Up => "Up".to_string(),
246 KeyCode::Down => "Down".to_string(),
247 KeyCode::Left => "Left".to_string(),
248 KeyCode::Right => "Right".to_string(),
249 KeyCode::F(n) => format!("F{n}"),
250 };
251 parts.push(&code_str);
252
253 let result = parts.join("+");
254 if lowercase {
255 result.to_lowercase()
256 } else {
257 result
258 }
259 }
260}
261
262impl std::fmt::Display for KeyEvent {
263 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
264 write!(f, "{}", self.to_formatted_string(false))
265 }
266}
267
268#[cfg(test)]
269mod tests {
270 use super::*;
271
272 #[test]
273 fn test_key_event_formatting() {
274 let key1 = KeyEvent {
275 code: KeyCode::Char('e'),
276 mods: KeyMods {
277 ctrl: true,
278 alt: false,
279 shift: false,
280 super_key: false,
281 },
282 };
283 assert_eq!(key1.to_formatted_string(false), "Ctrl+E");
284 assert_eq!(key1.to_formatted_string(true), "ctrl+e");
285 assert_eq!(key1.to_string(), "Ctrl+E");
286
287 let key2 = KeyEvent {
288 code: KeyCode::Enter,
289 mods: KeyMods {
290 ctrl: true,
291 alt: true,
292 shift: true,
293 super_key: false,
294 },
295 };
296 assert_eq!(key2.to_formatted_string(false), "Ctrl+Alt+Shift+Enter");
297 assert_eq!(key2.to_formatted_string(true), "ctrl+alt+shift+enter");
298 assert_eq!(key2.to_string(), "Ctrl+Alt+Shift+Enter");
299
300 let key3 = KeyEvent {
301 code: KeyCode::Char(' '),
302 mods: KeyMods {
303 ctrl: false,
304 alt: false,
305 shift: false,
306 super_key: false,
307 },
308 };
309 assert_eq!(key3.to_formatted_string(false), "Space");
310 assert_eq!(key3.to_string(), "Space");
311
312 let key4 = KeyEvent {
313 code: KeyCode::F(12),
314 mods: KeyMods {
315 ctrl: false,
316 alt: false,
317 shift: false,
318 super_key: false,
319 },
320 };
321 assert_eq!(key4.to_formatted_string(false), "F12");
322 assert_eq!(key4.to_formatted_string(true), "f12");
323 assert_eq!(key4.to_string(), "F12");
324 }
325
326 #[test]
327 fn test_key_event_matching_helpers_and_mod_constants() {
328 let plain_enter = KeyEvent {
329 code: KeyCode::Enter,
330 mods: KeyMods::NONE,
331 };
332 assert!(plain_enter.is(KeyCode::Enter));
333 assert!(plain_enter.is_with(KeyCode::Enter, KeyMods::NONE));
334
335 let shift_enter = KeyEvent {
336 code: KeyCode::Enter,
337 mods: KeyMods::SHIFT,
338 };
339 assert!(!shift_enter.is(KeyCode::Enter));
340 assert!(shift_enter.is_with(KeyCode::Enter, KeyMods::SHIFT));
341 assert!(!shift_enter.is_with(KeyCode::Enter, KeyMods::NONE));
342
343 assert!(KeyMods::NONE.is_empty());
344 assert!(!KeyMods::SHIFT.is_empty());
345 }
346}