orbclient/
event.rs

1// SPDX-License-Identifier: MIT
2
3use core::ops::{Deref, DerefMut};
4use core::{char, mem, slice};
5
6pub const EVENT_NONE: i64 = 0;
7pub const EVENT_KEY: i64 = 1;
8pub const EVENT_MOUSE: i64 = 2;
9pub const EVENT_BUTTON: i64 = 3;
10pub const EVENT_SCROLL: i64 = 4;
11pub const EVENT_QUIT: i64 = 5;
12pub const EVENT_FOCUS: i64 = 6;
13pub const EVENT_MOVE: i64 = 7;
14pub const EVENT_RESIZE: i64 = 8;
15pub const EVENT_SCREEN: i64 = 9;
16pub const EVENT_CLIPBOARD: i64 = 10;
17pub const EVENT_MOUSE_RELATIVE: i64 = 11;
18pub const EVENT_DROP: i64 = 12;
19pub const EVENT_TEXT_INPUT: i64 = 13;
20pub const EVENT_CLIPBOARD_UPDATE: i64 = 14;
21pub const EVENT_HOVER: i64 = 15;
22
23/// An optional event
24#[derive(Copy, Clone, Debug)]
25pub enum EventOption {
26    /// A key event
27    Key(KeyEvent),
28    /// A text input event
29    TextInput(TextInputEvent),
30    /// A mouse event (absolute)
31    Mouse(MouseEvent),
32    /// A mouse event (relative)
33    MouseRelative(MouseRelativeEvent),
34    /// A mouse button event
35    Button(ButtonEvent),
36    /// A mouse scroll event
37    Scroll(ScrollEvent),
38    /// A quit request event
39    Quit(QuitEvent),
40    /// A focus event
41    Focus(FocusEvent),
42    /// A move event
43    Move(MoveEvent),
44    /// A resize event
45    Resize(ResizeEvent),
46    /// A screen report event
47    Screen(ScreenEvent),
48    /// A clipboard event
49    Clipboard(ClipboardEvent),
50    /// A clipboard update event
51    ClipboardUpdate(ClipboardUpdateEvent),
52    /// A drop file / text event (available on linux, windows and macOS)
53    Drop(DropEvent),
54    /// A hover event
55    Hover(HoverEvent),
56    /// An unknown event
57    Unknown(Event),
58    /// No event
59    None,
60}
61
62/// An event
63#[derive(Copy, Clone, Debug)]
64#[repr(packed)]
65pub struct Event {
66    pub code: i64,
67    pub a: i64,
68    pub b: i64,
69}
70
71#[allow(clippy::new_without_default)]
72impl Event {
73    /// Create a null event
74    pub fn new() -> Event {
75        Event {
76            code: 0,
77            a: 0,
78            b: 0,
79        }
80    }
81
82    /// Convert the event ot an optional event
83    // TODO: Consider doing this via a From trait.
84    pub fn to_option(self) -> EventOption {
85        match self.code {
86            EVENT_NONE => EventOption::None,
87            EVENT_KEY => EventOption::Key(KeyEvent::from_event(self)),
88            EVENT_TEXT_INPUT => EventOption::TextInput(TextInputEvent::from_event(self)),
89            EVENT_MOUSE => EventOption::Mouse(MouseEvent::from_event(self)),
90            EVENT_MOUSE_RELATIVE => {
91                EventOption::MouseRelative(MouseRelativeEvent::from_event(self))
92            }
93            EVENT_BUTTON => EventOption::Button(ButtonEvent::from_event(self)),
94            EVENT_SCROLL => EventOption::Scroll(ScrollEvent::from_event(self)),
95            EVENT_QUIT => EventOption::Quit(QuitEvent::from_event(self)),
96            EVENT_FOCUS => EventOption::Focus(FocusEvent::from_event(self)),
97            EVENT_MOVE => EventOption::Move(MoveEvent::from_event(self)),
98            EVENT_RESIZE => EventOption::Resize(ResizeEvent::from_event(self)),
99            EVENT_SCREEN => EventOption::Screen(ScreenEvent::from_event(self)),
100            EVENT_CLIPBOARD => EventOption::Clipboard(ClipboardEvent::from_event(self)),
101            EVENT_CLIPBOARD_UPDATE => {
102                EventOption::ClipboardUpdate(ClipboardUpdateEvent::from_event(self))
103            }
104            EVENT_DROP => EventOption::Drop(DropEvent::from_event(self)),
105            EVENT_HOVER => EventOption::Hover(HoverEvent::from_event(self)),
106            _ => EventOption::Unknown(self),
107        }
108    }
109}
110
111impl Deref for Event {
112    type Target = [u8];
113    fn deref(&self) -> &[u8] {
114        unsafe {
115            slice::from_raw_parts(self as *const Event as *const u8, mem::size_of::<Event>())
116                as &[u8]
117        }
118    }
119}
120
121impl DerefMut for Event {
122    fn deref_mut(&mut self) -> &mut [u8] {
123        unsafe {
124            slice::from_raw_parts_mut(self as *mut Event as *mut u8, mem::size_of::<Event>())
125                as &mut [u8]
126        }
127    }
128}
129
130pub const K_A: u8 = 0x1E;
131pub const K_B: u8 = 0x30;
132pub const K_C: u8 = 0x2E;
133pub const K_D: u8 = 0x20;
134pub const K_E: u8 = 0x12;
135pub const K_F: u8 = 0x21;
136pub const K_G: u8 = 0x22;
137pub const K_H: u8 = 0x23;
138pub const K_I: u8 = 0x17;
139pub const K_J: u8 = 0x24;
140pub const K_K: u8 = 0x25;
141pub const K_L: u8 = 0x26;
142pub const K_M: u8 = 0x32;
143pub const K_N: u8 = 0x31;
144pub const K_O: u8 = 0x18;
145pub const K_P: u8 = 0x19;
146pub const K_Q: u8 = 0x10;
147pub const K_R: u8 = 0x13;
148pub const K_S: u8 = 0x1F;
149pub const K_T: u8 = 0x14;
150pub const K_U: u8 = 0x16;
151pub const K_V: u8 = 0x2F;
152pub const K_W: u8 = 0x11;
153pub const K_X: u8 = 0x2D;
154pub const K_Y: u8 = 0x15;
155pub const K_Z: u8 = 0x2C;
156pub const K_0: u8 = 0x0B;
157pub const K_1: u8 = 0x02;
158pub const K_2: u8 = 0x03;
159pub const K_3: u8 = 0x04;
160pub const K_4: u8 = 0x05;
161pub const K_5: u8 = 0x06;
162pub const K_6: u8 = 0x07;
163pub const K_7: u8 = 0x08;
164pub const K_8: u8 = 0x09;
165pub const K_9: u8 = 0x0A;
166
167// Numpad keys (codes 0x70-0x79)
168pub const K_NUM_0: u8 = 0x70;
169pub const K_NUM_1: u8 = 0x71;
170pub const K_NUM_2: u8 = 0x72;
171pub const K_NUM_3: u8 = 0x73;
172pub const K_NUM_4: u8 = 0x74;
173pub const K_NUM_5: u8 = 0x75;
174pub const K_NUM_6: u8 = 0x76;
175pub const K_NUM_7: u8 = 0x77;
176pub const K_NUM_8: u8 = 0x78;
177pub const K_NUM_9: u8 = 0x79;
178
179/// Tick/tilde key
180pub const K_TICK: u8 = 0x29;
181/// Minus/underline key
182pub const K_MINUS: u8 = 0x0C;
183/// Equals/plus key
184pub const K_EQUALS: u8 = 0x0D;
185/// Backslash/pipe key
186pub const K_BACKSLASH: u8 = 0x2B;
187/// Bracket open key
188pub const K_BRACE_OPEN: u8 = 0x1A;
189/// Bracket close key
190pub const K_BRACE_CLOSE: u8 = 0x1B;
191/// Semicolon key
192pub const K_SEMICOLON: u8 = 0x27;
193/// Quote key
194pub const K_QUOTE: u8 = 0x28;
195/// Comma key
196pub const K_COMMA: u8 = 0x33;
197/// Period key
198pub const K_PERIOD: u8 = 0x34;
199/// Slash key
200pub const K_SLASH: u8 = 0x35;
201/// Backspace key
202pub const K_BKSP: u8 = 0x0E;
203/// Space key
204pub const K_SPACE: u8 = 0x39;
205/// Tab key
206pub const K_TAB: u8 = 0x0F;
207/// Capslock
208pub const K_CAPS: u8 = 0x3A;
209/// Left shift
210pub const K_LEFT_SHIFT: u8 = 0x2A;
211/// Right shift
212pub const K_RIGHT_SHIFT: u8 = 0x36;
213/// Control key
214pub const K_CTRL: u8 = 0x1D;
215/// Alt key
216pub const K_ALT: u8 = 0x38;
217/// AltGr key
218pub const K_ALT_GR: u8 = 0x64;
219/// Enter key
220pub const K_ENTER: u8 = 0x1C;
221/// Escape key
222pub const K_ESC: u8 = 0x01;
223/// F1 key
224pub const K_F1: u8 = 0x3B;
225/// F2 key
226pub const K_F2: u8 = 0x3C;
227/// F3 key
228pub const K_F3: u8 = 0x3D;
229/// F4 key
230pub const K_F4: u8 = 0x3E;
231/// F5 key
232pub const K_F5: u8 = 0x3F;
233/// F6 key
234pub const K_F6: u8 = 0x40;
235/// F7 key
236pub const K_F7: u8 = 0x41;
237/// F8 key
238pub const K_F8: u8 = 0x42;
239/// F9 key
240pub const K_F9: u8 = 0x43;
241/// F10 key
242pub const K_F10: u8 = 0x44;
243/// Home key
244pub const K_HOME: u8 = 0x47;
245/// Up key
246pub const K_UP: u8 = 0x48;
247/// Page up key
248pub const K_PGUP: u8 = 0x49;
249/// Left key
250pub const K_LEFT: u8 = 0x4B;
251/// Right key
252pub const K_RIGHT: u8 = 0x4D;
253/// End key
254pub const K_END: u8 = 0x4F;
255/// Down key
256pub const K_DOWN: u8 = 0x50;
257/// Page down key
258pub const K_PGDN: u8 = 0x51;
259/// Delete key
260pub const K_DEL: u8 = 0x53;
261/// F11 key
262pub const K_F11: u8 = 0x57;
263/// F12 key
264pub const K_F12: u8 = 0x58;
265/// SUPER/META/WIN Key
266pub const K_SUPER: u8 = 0x5B;
267/// Media Key for Volume toggle (mute/unmute)
268pub const K_VOLUME_TOGGLE: u8 = 0x80 + 0x20;
269/// Media Key for Volume Down
270pub const K_VOLUME_DOWN: u8 = 0x80 + 0x2E;
271/// Media Key for Volume Up
272pub const K_VOLUME_UP: u8 = 0x80 + 0x30;
273
274/// A key event (such as a pressed key)
275#[derive(Copy, Clone, Debug)]
276pub struct KeyEvent {
277    /// The character of the key
278    pub character: char,
279    /// The scancode of the key
280    pub scancode: u8,
281    /// Was it pressed?
282    pub pressed: bool,
283}
284
285impl KeyEvent {
286    /// Convert to an `Event`
287    pub fn to_event(&self) -> Event {
288        Event {
289            code: EVENT_KEY,
290            a: self.character as i64,
291            b: self.scancode as i64 | (self.pressed as i64) << 8,
292        }
293    }
294
295    /// Convert from an `Event`
296    pub fn from_event(event: Event) -> KeyEvent {
297        KeyEvent {
298            character: char::from_u32(event.a as u32).unwrap_or('\0'),
299            scancode: event.b as u8,
300            pressed: event.b & 1 << 8 == 1 << 8,
301        }
302    }
303}
304
305#[derive(Copy, Clone, Debug)]
306pub struct TextInputEvent {
307    pub character: char,
308}
309
310impl TextInputEvent {
311    /// Convert to an `Event`
312    pub fn to_event(&self) -> Event {
313        Event {
314            code: EVENT_TEXT_INPUT,
315            a: self.character as i64,
316            b: 0,
317        }
318    }
319
320    /// Convert from an `Event`
321    pub fn from_event(event: Event) -> TextInputEvent {
322        TextInputEvent {
323            character: char::from_u32(event.a as u32).unwrap_or('\0'),
324        }
325    }
326}
327
328/// A event related to the mouse (absolute position)
329#[derive(Copy, Clone, Debug)]
330pub struct MouseEvent {
331    /// The x coordinate of the mouse
332    pub x: i32,
333    /// The y coordinate of the mouse
334    pub y: i32,
335}
336
337impl MouseEvent {
338    /// Convert to an `Event`
339    pub fn to_event(&self) -> Event {
340        Event {
341            code: EVENT_MOUSE,
342            a: self.x as i64,
343            b: self.y as i64,
344        }
345    }
346
347    /// Convert an `Event` to a `MouseEvent`
348    pub fn from_event(event: Event) -> MouseEvent {
349        MouseEvent {
350            x: event.a as i32,
351            y: event.b as i32,
352        }
353    }
354}
355
356/// A event related to the mouse (relative position)
357#[derive(Copy, Clone, Debug)]
358pub struct MouseRelativeEvent {
359    /// The x coordinate of the mouse
360    pub dx: i32,
361    /// The y coordinate of the mouse
362    pub dy: i32,
363}
364
365impl MouseRelativeEvent {
366    /// Convert to an `Event`
367    pub fn to_event(&self) -> Event {
368        Event {
369            code: EVENT_MOUSE_RELATIVE,
370            a: self.dx as i64,
371            b: self.dy as i64,
372        }
373    }
374
375    /// Convert an `Event` to a `MouseRelativeEvent`
376    pub fn from_event(event: Event) -> MouseRelativeEvent {
377        MouseRelativeEvent {
378            dx: event.a as i32,
379            dy: event.b as i32,
380        }
381    }
382}
383
384/// A event for clicking the mouse
385#[derive(Copy, Clone, Debug)]
386pub struct ButtonEvent {
387    /// Was the left button pressed?
388    pub left: bool,
389    /// Was the middle button pressed?
390    pub middle: bool,
391    /// Was the right button pressed?
392    pub right: bool,
393}
394
395impl ButtonEvent {
396    /// Convert to an `Event`
397    pub fn to_event(&self) -> Event {
398        Event {
399            code: EVENT_BUTTON,
400            a: self.left as i64 | (self.middle as i64) << 1 | (self.right as i64) << 2,
401            b: 0,
402        }
403    }
404
405    /// Convert an `Event` to a `ButtonEvent`
406    pub fn from_event(event: Event) -> ButtonEvent {
407        ButtonEvent {
408            left: event.a & 1 == 1,
409            middle: event.a & 2 == 2,
410            right: event.a & 4 == 4,
411        }
412    }
413}
414
415/// A event for scrolling the mouse
416#[derive(Copy, Clone, Debug)]
417pub struct ScrollEvent {
418    /// The x distance of the scroll
419    pub x: i32,
420    /// The y distance of the scroll
421    pub y: i32,
422}
423
424impl ScrollEvent {
425    /// Convert to an `Event`
426    pub fn to_event(&self) -> Event {
427        Event {
428            code: EVENT_SCROLL,
429            a: self.x as i64,
430            b: self.y as i64,
431        }
432    }
433
434    /// Convert an `Event` to a `ScrollEvent`
435    pub fn from_event(event: Event) -> ScrollEvent {
436        ScrollEvent {
437            x: event.a as i32,
438            y: event.b as i32,
439        }
440    }
441}
442
443#[derive(Copy, Clone, Debug)]
444pub struct QuitEvent;
445
446impl QuitEvent {
447    pub fn to_event(&self) -> Event {
448        Event {
449            code: EVENT_QUIT,
450            a: 0,
451            b: 0,
452        }
453    }
454
455    pub fn from_event(_: Event) -> QuitEvent {
456        QuitEvent
457    }
458}
459
460/// A focus event
461#[derive(Copy, Clone, Debug)]
462pub struct FocusEvent {
463    /// True if window has been focused, false if not
464    pub focused: bool,
465}
466
467impl FocusEvent {
468    pub fn to_event(&self) -> Event {
469        Event {
470            code: EVENT_FOCUS,
471            a: self.focused as i64,
472            b: 0,
473        }
474    }
475
476    pub fn from_event(event: Event) -> FocusEvent {
477        FocusEvent {
478            focused: event.a > 0,
479        }
480    }
481}
482
483/// A move event
484#[derive(Copy, Clone, Debug)]
485pub struct MoveEvent {
486    pub x: i32,
487    pub y: i32,
488}
489
490impl MoveEvent {
491    pub fn to_event(&self) -> Event {
492        Event {
493            code: EVENT_MOVE,
494            a: self.x as i64,
495            b: self.y as i64,
496        }
497    }
498
499    pub fn from_event(event: Event) -> MoveEvent {
500        MoveEvent {
501            x: event.a as i32,
502            y: event.b as i32,
503        }
504    }
505}
506
507/// A resize event
508#[derive(Copy, Clone, Debug)]
509pub struct ResizeEvent {
510    pub width: u32,
511    pub height: u32,
512}
513
514impl ResizeEvent {
515    pub fn to_event(&self) -> Event {
516        Event {
517            code: EVENT_RESIZE,
518            a: self.width as i64,
519            b: self.height as i64,
520        }
521    }
522
523    pub fn from_event(event: Event) -> ResizeEvent {
524        ResizeEvent {
525            width: event.a as u32,
526            height: event.b as u32,
527        }
528    }
529}
530
531/// A screen report event
532#[derive(Copy, Clone, Debug)]
533pub struct ScreenEvent {
534    pub width: u32,
535    pub height: u32,
536}
537
538impl ScreenEvent {
539    pub fn to_event(&self) -> Event {
540        Event {
541            code: EVENT_SCREEN,
542            a: self.width as i64,
543            b: self.height as i64,
544        }
545    }
546
547    pub fn from_event(event: Event) -> ScreenEvent {
548        ScreenEvent {
549            width: event.a as u32,
550            height: event.b as u32,
551        }
552    }
553}
554
555pub const CLIPBOARD_COPY: u8 = 0;
556pub const CLIPBOARD_CUT: u8 = 1;
557pub const CLIPBOARD_PASTE: u8 = 2;
558
559/// A clipboard event
560#[derive(Copy, Clone, Debug)]
561pub struct ClipboardUpdateEvent;
562
563impl ClipboardUpdateEvent {
564    pub fn to_event(&self) -> Event {
565        Event {
566            code: EVENT_CLIPBOARD_UPDATE,
567            a: 0,
568            b: 0,
569        }
570    }
571
572    pub fn from_event(_: Event) -> ClipboardUpdateEvent {
573        ClipboardUpdateEvent
574    }
575}
576
577/// A clipboard event
578#[derive(Copy, Clone, Debug)]
579pub struct ClipboardEvent {
580    pub kind: u8,
581    pub size: usize,
582}
583
584impl ClipboardEvent {
585    pub fn to_event(&self) -> Event {
586        Event {
587            code: EVENT_CLIPBOARD,
588            a: self.kind as i64,
589            b: self.size as i64,
590        }
591    }
592
593    pub fn from_event(event: Event) -> ClipboardEvent {
594        ClipboardEvent {
595            kind: event.a as u8,
596            size: event.b as usize,
597        }
598    }
599}
600
601pub const DROP_FILE: u8 = 0;
602pub const DROP_TEXT: u8 = 1;
603
604/// A drop file event.
605#[derive(Copy, Clone, Debug)]
606pub struct DropEvent {
607    pub kind: u8,
608}
609
610impl DropEvent {
611    pub fn to_event(&self) -> Event {
612        Event {
613            code: EVENT_DROP,
614            a: self.kind as i64,
615            b: 0,
616        }
617    }
618
619    pub fn from_event(event: Event) -> DropEvent {
620        DropEvent {
621            kind: event.a as u8,
622        }
623    }
624}
625
626/// A hover event
627#[derive(Copy, Clone, Debug)]
628pub struct HoverEvent {
629    /// True if window has been entered, false if exited
630    pub entered: bool,
631}
632
633impl HoverEvent {
634    pub fn to_event(&self) -> Event {
635        Event {
636            code: EVENT_HOVER,
637            a: self.entered as i64,
638            b: 0,
639        }
640    }
641
642    pub fn from_event(event: Event) -> HoverEvent {
643        HoverEvent {
644            entered: event.a > 0,
645        }
646    }
647}