Skip to main content

orbclient/
event.rs

1// SPDX-License-Identifier: MIT
2
3use core::ops::{Deref, DerefMut};
4use core::{char, mem, slice};
5
6use crate::{ClipboardAction, DragAction};
7
8pub const EVENT_NONE: i64 = 0;
9pub const EVENT_KEY: i64 = 1;
10pub const EVENT_MOUSE: i64 = 2;
11pub const EVENT_BUTTON: i64 = 3;
12pub const EVENT_SCROLL: i64 = 4;
13pub const EVENT_QUIT: i64 = 5;
14pub const EVENT_FOCUS: i64 = 6;
15pub const EVENT_MOVE: i64 = 7;
16pub const EVENT_RESIZE: i64 = 8;
17pub const EVENT_SCREEN: i64 = 9;
18pub const EVENT_CLIPBOARD: i64 = 10;
19pub const EVENT_MOUSE_RELATIVE: i64 = 11;
20pub const EVENT_DROP: i64 = 12;
21pub const EVENT_TEXT_INPUT: i64 = 13;
22pub const EVENT_CLIPBOARD_UPDATE: i64 = 14;
23pub const EVENT_HOVER: i64 = 15;
24pub const EVENT_SCALE: i64 = 16;
25pub const EVENT_DRAG_ENTER: i64 = 17;
26pub const EVENT_DRAG_MOVE: i64 = 18;
27pub const EVENT_DRAG_LEAVE: i64 = 19;
28pub const EVENT_CONTROLLER_AXIS: i64 = 20;
29pub const EVENT_CONTROLLER_BUTTON: i64 = 21;
30
31/// An optional event
32#[derive(Copy, Clone, Debug)]
33pub enum EventOption {
34    /// A key event
35    Key(KeyEvent),
36    /// A text input event
37    TextInput(TextInputEvent),
38    /// A mouse event (absolute)
39    Mouse(MouseEvent),
40    /// A mouse event (relative)
41    MouseRelative(MouseRelativeEvent),
42    /// A mouse button event
43    Button(ButtonEvent),
44    /// A mouse scroll event
45    Scroll(ScrollEvent),
46    /// A quit request event
47    Quit(QuitEvent),
48    /// A focus event
49    Focus(FocusEvent),
50    /// A move event
51    Move(MoveEvent),
52    /// A resize event
53    Resize(ResizeEvent),
54    /// A screen report event
55    Screen(ScreenEvent),
56    /// A screen scale event
57    Scale(ScaleEvent),
58    /// A clipboard event
59    Clipboard(ClipboardEvent),
60    /// A clipboard update event
61    ClipboardUpdate(ClipboardUpdateEvent),
62    /// A drag enter event
63    DragEnter(DragEnterEvent),
64    /// A drag move event
65    DragMove(DragMoveEvent),
66    /// A drag leave event
67    DragLeave(DragLeaveEvent),
68    /// A drop event
69    Drop(DropEvent),
70    /// A hover event
71    Hover(HoverEvent),
72    /// A controller axis event
73    ControllerAxis(ControllerAxisEvent),
74    /// A controller button event
75    ControllerButton(ControllerButtonEvent),
76    /// An unknown event
77    Unknown(Event),
78    /// No event
79    None,
80}
81
82/// An event
83#[derive(Copy, Clone, Debug)]
84#[repr(packed)]
85pub struct Event {
86    pub code: i64,
87    pub a: i64,
88    pub b: i64,
89}
90
91#[allow(clippy::new_without_default)]
92impl Event {
93    /// Create a null event
94    pub fn new() -> Event {
95        Event {
96            code: 0,
97            a: 0,
98            b: 0,
99        }
100    }
101
102    /// Convert the event ot an optional event
103    // TODO: Consider doing this via a From trait.
104    pub fn to_option(self) -> EventOption {
105        match self.code {
106            EVENT_NONE => EventOption::None,
107            EVENT_KEY => EventOption::Key(KeyEvent::from_event(self)),
108            EVENT_TEXT_INPUT => EventOption::TextInput(TextInputEvent::from_event(self)),
109            EVENT_MOUSE => EventOption::Mouse(MouseEvent::from_event(self)),
110            EVENT_MOUSE_RELATIVE => {
111                EventOption::MouseRelative(MouseRelativeEvent::from_event(self))
112            }
113            EVENT_BUTTON => EventOption::Button(ButtonEvent::from_event(self)),
114            EVENT_SCROLL => EventOption::Scroll(ScrollEvent::from_event(self)),
115            EVENT_QUIT => EventOption::Quit(QuitEvent::from_event(self)),
116            EVENT_FOCUS => EventOption::Focus(FocusEvent::from_event(self)),
117            EVENT_MOVE => EventOption::Move(MoveEvent::from_event(self)),
118            EVENT_RESIZE => EventOption::Resize(ResizeEvent::from_event(self)),
119            EVENT_SCREEN => EventOption::Screen(ScreenEvent::from_event(self)),
120            EVENT_CLIPBOARD => EventOption::Clipboard(ClipboardEvent::from_event(self)),
121            EVENT_CLIPBOARD_UPDATE => {
122                EventOption::ClipboardUpdate(ClipboardUpdateEvent::from_event(self))
123            }
124            EVENT_DROP => EventOption::Drop(DropEvent::from_event(self)),
125            EVENT_HOVER => EventOption::Hover(HoverEvent::from_event(self)),
126            EVENT_SCALE => EventOption::Scale(ScaleEvent::from_event(self)),
127            EVENT_DRAG_ENTER => EventOption::DragEnter(DragEnterEvent::from_event(self)),
128            EVENT_DRAG_MOVE => EventOption::DragMove(DragMoveEvent::from_event(self)),
129            EVENT_DRAG_LEAVE => EventOption::DragLeave(DragLeaveEvent::from_event(self)),
130            EVENT_CONTROLLER_AXIS => {
131                EventOption::ControllerAxis(ControllerAxisEvent::from_event(self))
132            }
133            EVENT_CONTROLLER_BUTTON => {
134                EventOption::ControllerButton(ControllerButtonEvent::from_event(self))
135            }
136            _ => EventOption::Unknown(self),
137        }
138    }
139}
140
141impl Deref for Event {
142    type Target = [u8];
143    fn deref(&self) -> &[u8] {
144        unsafe {
145            slice::from_raw_parts(self as *const Event as *const u8, mem::size_of::<Event>())
146                as &[u8]
147        }
148    }
149}
150
151impl DerefMut for Event {
152    fn deref_mut(&mut self) -> &mut [u8] {
153        unsafe {
154            slice::from_raw_parts_mut(self as *mut Event as *mut u8, mem::size_of::<Event>())
155                as &mut [u8]
156        }
157    }
158}
159
160// Mapped closely with scancodes from XT keyboard.
161// Unconventional ranges should be in 0x60-0x7F, 0x80 and above are for media keys
162// See https://aeb.win.tue.nl/linux/kbd/scancodes-10.html
163
164pub const K_A: u8 = 0x1E;
165pub const K_B: u8 = 0x30;
166pub const K_C: u8 = 0x2E;
167pub const K_D: u8 = 0x20;
168pub const K_E: u8 = 0x12;
169pub const K_F: u8 = 0x21;
170pub const K_G: u8 = 0x22;
171pub const K_H: u8 = 0x23;
172pub const K_I: u8 = 0x17;
173pub const K_J: u8 = 0x24;
174pub const K_K: u8 = 0x25;
175pub const K_L: u8 = 0x26;
176pub const K_M: u8 = 0x32;
177pub const K_N: u8 = 0x31;
178pub const K_O: u8 = 0x18;
179pub const K_P: u8 = 0x19;
180pub const K_Q: u8 = 0x10;
181pub const K_R: u8 = 0x13;
182pub const K_S: u8 = 0x1F;
183pub const K_T: u8 = 0x14;
184pub const K_U: u8 = 0x16;
185pub const K_V: u8 = 0x2F;
186pub const K_W: u8 = 0x11;
187pub const K_X: u8 = 0x2D;
188pub const K_Y: u8 = 0x15;
189pub const K_Z: u8 = 0x2C;
190pub const K_0: u8 = 0x0B;
191pub const K_1: u8 = 0x02;
192pub const K_2: u8 = 0x03;
193pub const K_3: u8 = 0x04;
194pub const K_4: u8 = 0x05;
195pub const K_5: u8 = 0x06;
196pub const K_6: u8 = 0x07;
197pub const K_7: u8 = 0x08;
198pub const K_8: u8 = 0x09;
199pub const K_9: u8 = 0x0A;
200
201// Numpad keys (codes 0x70-0x7f)
202
203pub const K_NUM_0: u8 = 0x70;
204pub const K_NUM_1: u8 = 0x71;
205pub const K_NUM_2: u8 = 0x72;
206pub const K_NUM_3: u8 = 0x73;
207pub const K_NUM_4: u8 = 0x74;
208pub const K_NUM_5: u8 = 0x75;
209pub const K_NUM_6: u8 = 0x76;
210pub const K_NUM_7: u8 = 0x77;
211pub const K_NUM_8: u8 = 0x78;
212pub const K_NUM_9: u8 = 0x79;
213pub const K_NUM_PERIOD: u8 = 0x7a;
214pub const K_NUM_PLUS: u8 = 0x7c;
215pub const K_NUM_MINUS: u8 = 0x7b;
216pub const K_NUM_ASTERISK: u8 = 0x7d;
217pub const K_NUM_SLASH: u8 = 0x7e;
218pub const K_NUM_ENTER: u8 = 0x7f;
219
220/// Tick/tilde key
221pub const K_TICK: u8 = 0x29;
222/// Minus/underline key
223pub const K_MINUS: u8 = 0x0C;
224/// Equals/plus key
225pub const K_EQUALS: u8 = 0x0D;
226/// Backslash/pipe key
227pub const K_BACKSLASH: u8 = 0x2B;
228/// Bracket open key
229pub const K_BRACE_OPEN: u8 = 0x1A;
230/// Bracket close key
231pub const K_BRACE_CLOSE: u8 = 0x1B;
232/// Semicolon key
233pub const K_SEMICOLON: u8 = 0x27;
234/// Quote key
235pub const K_QUOTE: u8 = 0x28;
236/// Comma key
237pub const K_COMMA: u8 = 0x33;
238/// Period key
239pub const K_PERIOD: u8 = 0x34;
240/// Slash key
241pub const K_SLASH: u8 = 0x35;
242/// Backspace key
243pub const K_BKSP: u8 = 0x0E;
244/// Space key
245pub const K_SPACE: u8 = 0x39;
246/// Tab key
247pub const K_TAB: u8 = 0x0F;
248/// Capslock
249pub const K_CAPS: u8 = 0x3A;
250/// Left shift
251pub const K_LEFT_SHIFT: u8 = 0x2A;
252/// Right shift
253pub const K_RIGHT_SHIFT: u8 = 0x36;
254/// Control key (deprecated)
255pub const K_CTRL: u8 = 0x1D;
256/// Left control key
257pub const K_LEFT_CTRL: u8 = 0x1D;
258/// Right control key
259pub const K_RIGHT_CTRL: u8 = 0x64;
260/// Alt key
261pub const K_ALT: u8 = 0x38;
262/// AltGr key
263pub const K_ALT_GR: u8 = 0x64;
264/// Enter key
265pub const K_ENTER: u8 = 0x1C;
266/// Escape key
267pub const K_ESC: u8 = 0x01;
268/// Print screen key
269pub const K_PRTSC: u8 = 0x37;
270/// F1 key
271pub const K_F1: u8 = 0x3B;
272/// F2 key
273pub const K_F2: u8 = 0x3C;
274/// F3 key
275pub const K_F3: u8 = 0x3D;
276/// F4 key
277pub const K_F4: u8 = 0x3E;
278/// F5 key
279pub const K_F5: u8 = 0x3F;
280/// F6 key
281pub const K_F6: u8 = 0x40;
282/// F7 key
283pub const K_F7: u8 = 0x41;
284/// F8 key
285pub const K_F8: u8 = 0x42;
286/// F9 key
287pub const K_F9: u8 = 0x43;
288/// F10 key
289pub const K_F10: u8 = 0x44;
290/// Num lock key
291pub const K_NUM: u8 = 0x45;
292/// Scroll lock key
293pub const K_SCROLL: u8 = 0x46;
294/// Home key
295pub const K_HOME: u8 = 0x47;
296/// Up key
297pub const K_UP: u8 = 0x48;
298/// Page up key
299pub const K_PGUP: u8 = 0x49;
300/// Left key
301pub const K_LEFT: u8 = 0x4B;
302/// Right key
303pub const K_RIGHT: u8 = 0x4D;
304/// End key
305pub const K_END: u8 = 0x4F;
306/// Down key
307pub const K_DOWN: u8 = 0x50;
308/// Page down key
309pub const K_PGDN: u8 = 0x51;
310/// Insert key (deprecated)
311pub const K_INS: u8 = 0x52;
312/// Insert key
313pub const K_INSERT: u8 = 0x52;
314/// Delete key
315pub const K_DEL: u8 = 0x53;
316/// F11 key
317pub const K_F11: u8 = 0x57;
318/// F12 key
319pub const K_F12: u8 = 0x58;
320/// SUPER/META/WIN Key (deprecated)
321pub const K_SUPER: u8 = 0x5B;
322/// SUPER/META/WIN Left Key
323pub const K_LEFT_SUPER: u8 = 0x5B;
324/// SUPER/META/WIN Right Key
325pub const K_RIGHT_SUPER: u8 = 0x5C;
326/// Application key
327pub const K_APP: u8 = 0x5D;
328/// Power off key
329pub const K_POWER: u8 = 0x5E;
330/// Sleep key
331pub const K_SLEEP: u8 = 0x5F;
332
333// Media keys are derived from MF II keyboards
334// See https://www.scs.stanford.edu/10wi-cs140/pintos/specs/kbd/scancodes-5.html
335
336/// Media Key for Volume toggle (mute/unmute)
337pub const K_VOLUME_TOGGLE: u8 = 0x80 + 0x20;
338/// Media Key for Volume Down
339pub const K_VOLUME_DOWN: u8 = 0x80 + 0x2E;
340/// Media Key for Volume Up
341pub const K_VOLUME_UP: u8 = 0x80 + 0x30;
342/// Media Key for Play/pause
343pub const K_MEDIA_PLAY_PAUSE: u8 = 0x80 + 0x22;
344/// Media Key for Stop
345pub const K_MEDIA_STOP: u8 = 0x80 + 0x24;
346/// Media Key for Fast forward/next track
347pub const K_MEDIA_FAST_FORWARD: u8 = 0x80 + 0x19;
348/// Media Key for Rewind/previous track
349pub const K_MEDIA_REWIND: u8 = 0x80 + 0x10;
350
351/// A key event (such as a pressed key)
352#[derive(Copy, Clone, Debug)]
353pub struct KeyEvent {
354    /// Deprecated, always zero. use TextInputEvent instead
355    pub character: char,
356    /// The scancode of the key
357    pub scancode: u8,
358    /// Was it pressed?
359    pub pressed: bool,
360}
361
362impl KeyEvent {
363    /// Convert to an `Event`
364    pub fn to_event(&self) -> Event {
365        Event {
366            code: EVENT_KEY,
367            a: self.character as i64,
368            b: self.scancode as i64 | (self.pressed as i64) << 8,
369        }
370    }
371
372    /// Convert from an `Event`
373    pub fn from_event(event: Event) -> KeyEvent {
374        KeyEvent {
375            character: char::from_u32(event.a as u32).unwrap_or('\0'),
376            scancode: event.b as u8,
377            pressed: event.b & 1 << 8 == 1 << 8,
378        }
379    }
380}
381
382/// A supplement to KeyEvent that report a character.
383/// Affected by modifier keys and keyboard layout.
384/// Control character (e.g. Backspace and Enter key) does not count as a TextInputEvent.
385#[derive(Copy, Clone, Debug)]
386pub struct TextInputEvent {
387    /// Character being sent.
388    pub character: char,
389}
390
391impl TextInputEvent {
392    /// Convert to an `Event`
393    pub fn to_event(&self) -> Event {
394        Event {
395            code: EVENT_TEXT_INPUT,
396            a: self.character as i64,
397            b: 0,
398        }
399    }
400
401    /// Convert from an `Event`
402    pub fn from_event(event: Event) -> TextInputEvent {
403        TextInputEvent {
404            character: char::from_u32(event.a as u32).unwrap_or('\0'),
405        }
406    }
407}
408
409/// A event related to the mouse (absolute position)
410#[derive(Copy, Clone, Debug)]
411pub struct MouseEvent {
412    /// The x coordinate of the mouse
413    pub x: i32,
414    /// The y coordinate of the mouse
415    pub y: i32,
416}
417
418impl MouseEvent {
419    /// Convert to an `Event`
420    pub fn to_event(&self) -> Event {
421        Event {
422            code: EVENT_MOUSE,
423            a: self.x as i64,
424            b: self.y as i64,
425        }
426    }
427
428    /// Convert an `Event` to a `MouseEvent`
429    pub fn from_event(event: Event) -> MouseEvent {
430        MouseEvent {
431            x: event.a as i32,
432            y: event.b as i32,
433        }
434    }
435}
436
437/// A event related to the mouse (relative position)
438#[derive(Copy, Clone, Debug)]
439pub struct MouseRelativeEvent {
440    /// The x coordinate of the mouse
441    pub dx: i32,
442    /// The y coordinate of the mouse
443    pub dy: i32,
444}
445
446impl MouseRelativeEvent {
447    /// Convert to an `Event`
448    pub fn to_event(&self) -> Event {
449        Event {
450            code: EVENT_MOUSE_RELATIVE,
451            a: self.dx as i64,
452            b: self.dy as i64,
453        }
454    }
455
456    /// Convert an `Event` to a `MouseRelativeEvent`
457    pub fn from_event(event: Event) -> MouseRelativeEvent {
458        MouseRelativeEvent {
459            dx: event.a as i32,
460            dy: event.b as i32,
461        }
462    }
463}
464
465/// A event for clicking the mouse
466#[derive(Copy, Clone, Debug)]
467pub struct ButtonEvent {
468    /// Was the left button pressed?
469    pub left: bool,
470    /// Was the middle button pressed?
471    pub middle: bool,
472    /// Was the right button pressed?
473    pub right: bool,
474}
475
476impl ButtonEvent {
477    /// Convert to an `Event`
478    pub fn to_event(&self) -> Event {
479        Event {
480            code: EVENT_BUTTON,
481            a: self.left as i64 | (self.middle as i64) << 1 | (self.right as i64) << 2,
482            b: 0,
483        }
484    }
485
486    /// Convert an `Event` to a `ButtonEvent`
487    pub fn from_event(event: Event) -> ButtonEvent {
488        ButtonEvent {
489            left: event.a & 1 == 1,
490            middle: event.a & 2 == 2,
491            right: event.a & 4 == 4,
492        }
493    }
494}
495
496/// A event for scrolling the mouse
497#[derive(Copy, Clone, Debug)]
498pub struct ScrollEvent {
499    /// The x distance of the scroll
500    pub x: i32,
501    /// The y distance of the scroll
502    pub y: i32,
503}
504
505impl ScrollEvent {
506    /// Convert to an `Event`
507    pub fn to_event(&self) -> Event {
508        Event {
509            code: EVENT_SCROLL,
510            a: self.x as i64,
511            b: self.y as i64,
512        }
513    }
514
515    /// Convert an `Event` to a `ScrollEvent`
516    pub fn from_event(event: Event) -> ScrollEvent {
517        ScrollEvent {
518            x: event.a as i32,
519            y: event.b as i32,
520        }
521    }
522}
523
524#[derive(Copy, Clone, Debug)]
525pub struct QuitEvent;
526
527impl QuitEvent {
528    pub fn to_event(&self) -> Event {
529        Event {
530            code: EVENT_QUIT,
531            a: 0,
532            b: 0,
533        }
534    }
535
536    pub fn from_event(_: Event) -> QuitEvent {
537        QuitEvent
538    }
539}
540
541/// A focus event
542#[derive(Copy, Clone, Debug)]
543pub struct FocusEvent {
544    /// True if window has been focused, false if not
545    pub focused: bool,
546}
547
548impl FocusEvent {
549    pub fn to_event(&self) -> Event {
550        Event {
551            code: EVENT_FOCUS,
552            a: self.focused as i64,
553            b: 0,
554        }
555    }
556
557    pub fn from_event(event: Event) -> FocusEvent {
558        FocusEvent {
559            focused: event.a > 0,
560        }
561    }
562}
563
564/// A move event
565#[derive(Copy, Clone, Debug)]
566pub struct MoveEvent {
567    /// New window X position
568    pub x: i32,
569    /// New window Y position
570    pub y: i32,
571}
572
573impl MoveEvent {
574    pub fn to_event(&self) -> Event {
575        Event {
576            code: EVENT_MOVE,
577            a: self.x as i64,
578            b: self.y as i64,
579        }
580    }
581
582    pub fn from_event(event: Event) -> MoveEvent {
583        MoveEvent {
584            x: event.a as i32,
585            y: event.b as i32,
586        }
587    }
588}
589
590/// A resize event
591#[derive(Copy, Clone, Debug)]
592pub struct ResizeEvent {
593    /// New window width
594    pub width: u32,
595    /// New window height
596    pub height: u32,
597}
598
599impl ResizeEvent {
600    pub fn to_event(&self) -> Event {
601        Event {
602            code: EVENT_RESIZE,
603            a: self.width as i64,
604            b: self.height as i64,
605        }
606    }
607
608    pub fn from_event(event: Event) -> ResizeEvent {
609        ResizeEvent {
610            width: event.a as u32,
611            height: event.b as u32,
612        }
613    }
614}
615
616/// A screen report event
617#[derive(Copy, Clone, Debug)]
618pub struct ScreenEvent {
619    /// New screen width
620    pub width: u32,
621    /// New screen height
622    pub height: u32,
623}
624
625impl ScreenEvent {
626    pub fn to_event(&self) -> Event {
627        Event {
628            code: EVENT_SCREEN,
629            a: self.width as i64,
630            b: self.height as i64,
631        }
632    }
633
634    pub fn from_event(event: Event) -> ScreenEvent {
635        ScreenEvent {
636            width: event.a as u32,
637            height: event.b as u32,
638        }
639    }
640}
641
642/// Not used
643#[derive(Copy, Clone, Debug)]
644pub struct ClipboardUpdateEvent;
645
646impl ClipboardUpdateEvent {
647    pub fn to_event(&self) -> Event {
648        Event {
649            code: EVENT_CLIPBOARD_UPDATE,
650            a: 0,
651            b: 0,
652        }
653    }
654
655    pub fn from_event(_: Event) -> ClipboardUpdateEvent {
656        ClipboardUpdateEvent
657    }
658}
659
660/// A clipboard event
661#[derive(Copy, Clone, Debug)]
662pub struct ClipboardEvent {
663    pub kind: ClipboardAction,
664    pub size: usize,
665}
666
667impl ClipboardEvent {
668    pub fn to_event(&self) -> Event {
669        Event {
670            code: EVENT_CLIPBOARD,
671            a: self.kind.to_u8() as i64,
672            b: self.size as i64,
673        }
674    }
675
676    pub fn from_event(event: Event) -> ClipboardEvent {
677        ClipboardEvent {
678            kind: ClipboardAction::try_from_u8(event.a as u8).unwrap_or(ClipboardAction::Copy),
679            size: event.b as usize,
680        }
681    }
682}
683
684fn pack_dnd(kind: DragAction, size: usize, x: i32, y: i32) -> (i64, i64) {
685    (
686        (kind.to_u8() as i64) | (size as i64) << 8,
687        (x as i64) | (y as i64) << 32,
688    )
689}
690
691fn unpack_dnd(ev: Event) -> (DragAction, usize, i32, i32) {
692    (
693        DragAction::try_from_u8((ev.a & 0xFF) as u8).unwrap_or(DragAction::Copy),
694        (ev.a >> 8) as usize,
695        ev.b as i32,
696        (ev.b >> 32) as i32,
697    )
698}
699
700/// A drag enter file event.
701/// App must call peek_drop_content to receive DragMoveEvent, DragLeaveEvent, DropEvent.
702/// App can ignore DND by doing nothing or peek_drop_content + pop_drop_content before DropEvent.
703#[derive(Copy, Clone, Debug)]
704pub struct DragEnterEvent {
705    pub kind: DragAction,
706    pub size: usize,
707}
708
709impl DragEnterEvent {
710    pub fn to_event(&self) -> Event {
711        let (a, b) = pack_dnd(self.kind, self.size, 0, 0);
712        Event {
713            code: EVENT_DRAG_ENTER,
714            a,
715            b,
716        }
717    }
718
719    pub fn from_event(event: Event) -> Self {
720        let (kind, size, _, _) = unpack_dnd(event);
721        Self { kind, size }
722    }
723}
724
725/// A DND drag move event.
726#[derive(Copy, Clone, Debug)]
727pub struct DragMoveEvent {
728    pub kind: DragAction,
729    pub size: usize,
730    pub x: i32,
731    pub y: i32,
732}
733
734impl DragMoveEvent {
735    pub fn to_event(&self) -> Event {
736        let (a, b) = pack_dnd(self.kind, self.size, self.x, self.y);
737        Event {
738            code: EVENT_DRAG_MOVE,
739            a,
740            b,
741        }
742    }
743
744    pub fn from_event(event: Event) -> Self {
745        let (kind, size, x, y) = unpack_dnd(event);
746        Self { kind, size, x, y }
747    }
748}
749
750/// A DND drag move event.
751#[derive(Copy, Clone, Debug)]
752pub struct DragLeaveEvent {}
753
754impl DragLeaveEvent {
755    pub fn to_event(&self) -> Event {
756        Event {
757            code: EVENT_DRAG_LEAVE,
758            a: 0,
759            b: 0,
760        }
761    }
762
763    pub fn from_event(_event: Event) -> Self {
764        Self {}
765    }
766}
767
768/// A DND drop event.
769#[derive(Copy, Clone, Debug)]
770pub struct DropEvent {
771    pub kind: DragAction,
772    pub size: usize,
773    pub x: i32,
774    pub y: i32,
775}
776
777impl DropEvent {
778    pub fn to_event(&self) -> Event {
779        let (a, b) = pack_dnd(self.kind, self.size, self.x, self.y);
780        Event {
781            code: EVENT_DROP,
782            a,
783            b,
784        }
785    }
786
787    pub fn from_event(event: Event) -> Self {
788        let (kind, size, x, y) = unpack_dnd(event);
789        Self { kind, size, x, y }
790    }
791}
792
793/// A window hover event
794#[derive(Copy, Clone, Debug)]
795pub struct HoverEvent {
796    /// True if window has been entered, false if exited
797    pub entered: bool,
798}
799
800impl HoverEvent {
801    pub fn to_event(&self) -> Event {
802        Event {
803            code: EVENT_HOVER,
804            a: self.entered as i64,
805            b: 0,
806        }
807    }
808
809    pub fn from_event(event: Event) -> HoverEvent {
810        HoverEvent {
811            entered: event.a > 0,
812        }
813    }
814}
815
816/// A screen scale event
817#[derive(Copy, Clone, Debug)]
818pub struct ScaleEvent {
819    /// Integer scale (premultiplied with baseline)
820    pub scale: i32,
821    /// Baseline of the scale
822    pub baseline: i32,
823}
824
825impl ScaleEvent {
826    pub fn to_event(&self) -> Event {
827        Event {
828            code: EVENT_SCALE,
829            a: self.scale as i64,
830            b: self.baseline as i64,
831        }
832    }
833
834    pub fn from_event(event: Event) -> ScaleEvent {
835        ScaleEvent {
836            scale: event.a as i32,
837            baseline: event.b as i32,
838        }
839    }
840}
841
842// Taken from generic desktop HID definitions
843pub const CONTROLLER_AXIS_X: u16 = 0x30;
844pub const CONTROLLER_AXIS_Y: u16 = 0x31;
845pub const CONTROLLER_AXIS_Z: u16 = 0x32;
846pub const CONTROLLER_AXIS_RX: u16 = 0x33;
847pub const CONTROLLER_AXIS_RY: u16 = 0x34;
848pub const CONTROLLER_AXIS_RZ: u16 = 0x35;
849
850/// A controller axis event
851#[derive(Copy, Clone, Debug)]
852pub struct ControllerAxisEvent {
853    /// Controller ID
854    pub id: u32,
855    pub axis: u16,
856    pub value: i32,
857}
858
859impl ControllerAxisEvent {
860    /// Convert to an `Event`
861    pub fn to_event(&self) -> Event {
862        Event {
863            code: EVENT_CONTROLLER_AXIS,
864            a: self.id as i64 | ((self.axis as i64) << 32),
865            b: self.value as i64,
866        }
867    }
868
869    /// Convert from an `Event`
870    pub fn from_event(event: Event) -> Self {
871        Self {
872            id: event.a as u32,
873            axis: (event.a >> 32) as u16,
874            value: event.b as i32,
875        }
876    }
877}
878
879// Button layout from Xbox controller
880pub const CONTROLLER_A: u16 = 1;
881pub const CONTROLLER_B: u16 = 2;
882pub const CONTROLLER_X: u16 = 3;
883pub const CONTROLLER_Y: u16 = 4;
884pub const CONTROLLER_LB: u16 = 5;
885pub const CONTROLLER_RB: u16 = 6;
886pub const CONTROLLER_BACK: u16 = 7;
887pub const CONTROLLER_START: u16 = 8;
888pub const CONTROLLER_LS: u16 = 9;
889pub const CONTROLLER_RS: u16 = 10;
890pub const CONTROLLER_GUIDE: u16 = 11;
891// Taken from generic desktop page
892pub const CONTROLLER_DPAD_UP: u16 = 0x90;
893pub const CONTROLLER_DPAD_DOWN: u16 = 0x91;
894pub const CONTROLLER_DPAD_RIGHT: u16 = 0x92;
895pub const CONTROLLER_DPAD_LEFT: u16 = 0x93;
896
897/// A controller button event
898#[derive(Copy, Clone, Debug)]
899pub struct ControllerButtonEvent {
900    /// Controller ID
901    pub id: u32,
902    pub button: u16,
903    pub pressed: bool,
904}
905
906impl ControllerButtonEvent {
907    /// Convert to an `Event`
908    pub fn to_event(&self) -> Event {
909        Event {
910            code: EVENT_CONTROLLER_BUTTON,
911            a: self.id as i64 | ((self.button as i64) << 32),
912            b: if self.pressed { 1 } else { 0 },
913        }
914    }
915
916    /// Convert from an `Event`
917    pub fn from_event(event: Event) -> Self {
918        Self {
919            id: event.a as u32,
920            button: (event.a >> 32) as u16,
921            pressed: event.b != 0,
922        }
923    }
924}