1use std::borrow::ToOwned;
6use std::collections::HashMap;
7use std::convert::TryFrom;
8use std::ffi::CStr;
9use std::iter::FromIterator;
10use std::marker::PhantomData;
11use std::mem;
12use std::mem::transmute;
13use std::ptr;
14use std::sync::Mutex;
15
16use libc::c_int;
17use libc::c_void;
18
19use crate::controller;
20use crate::controller::{Axis, Button};
21use crate::get_error;
22use crate::joystick;
23use crate::joystick::HatState;
24use crate::keyboard;
25use crate::keyboard::Keycode;
26use crate::keyboard::Mod;
27use crate::keyboard::Scancode;
28use crate::mouse;
29use crate::mouse::{MouseButton, MouseState, MouseWheelDirection};
30use crate::sys;
31use crate::sys::SDL_EventFilter;
32use crate::sys::SDL_EventType;
33use crate::video::Orientation;
34
35struct CustomEventTypeMaps {
36 sdl_id_to_type_id: HashMap<u32, ::std::any::TypeId>,
37 type_id_to_sdl_id: HashMap<::std::any::TypeId, u32>,
38}
39
40impl CustomEventTypeMaps {
41 fn new() -> Self {
42 CustomEventTypeMaps {
43 sdl_id_to_type_id: HashMap::new(),
44 type_id_to_sdl_id: HashMap::new(),
45 }
46 }
47}
48
49lazy_static! {
50 static ref CUSTOM_EVENT_TYPES: Mutex<CustomEventTypeMaps> =
51 Mutex::new(CustomEventTypeMaps::new());
52}
53
54impl crate::EventSubsystem {
55 #[doc(alias = "SDL_FlushEvent")]
57 pub fn flush_event(&self, event_type: EventType) {
58 unsafe { sys::SDL_FlushEvent(event_type as u32) };
59 }
60
61 #[doc(alias = "SDL_FlushEvents")]
63 pub fn flush_events(&self, min_type: u32, max_type: u32) {
64 unsafe { sys::SDL_FlushEvents(min_type, max_type) };
65 }
66
67 #[doc(alias = "SDL_PeepEvents")]
88 pub fn peek_events<B>(&self, max_amount: u32) -> B
89 where
90 B: FromIterator<Event>,
91 {
92 unsafe {
93 let mut events = Vec::with_capacity(max_amount as usize);
94
95 let result = {
96 let events_ptr = events.as_mut_ptr();
97
98 sys::SDL_PeepEvents(
99 events_ptr,
100 max_amount as c_int,
101 sys::SDL_eventaction::SDL_PEEKEVENT,
102 SDL_EventType::SDL_FIRSTEVENT as u32,
103 SDL_EventType::SDL_LASTEVENT as u32,
104 )
105 };
106
107 if result < 0 {
108 panic!("{}", get_error());
110 } else {
111 events.set_len(result as usize);
112
113 events.into_iter().map(Event::from_ll).collect()
114 }
115 }
116 }
117
118 pub fn push_event(&self, event: Event) -> Result<(), String> {
120 self.event_sender().push_event(event)
121 }
122
123 #[inline(always)]
151 pub unsafe fn register_event(&self) -> Result<u32, String> {
152 Ok(*self.register_events(1)?.first().unwrap())
153 }
154
155 pub unsafe fn register_events(&self, nr: u32) -> Result<Vec<u32>, String> {
159 let result = sys::SDL_RegisterEvents(nr as ::libc::c_int);
160 const ERR_NR: u32 = u32::MAX - 1;
161
162 match result {
163 ERR_NR => Err("No more user events can be created; SDL_LASTEVENT reached".to_owned()),
164 _ => {
165 let event_ids = (result..(result + nr)).collect();
166 Ok(event_ids)
167 }
168 }
169 }
170
171 #[inline(always)]
178 pub fn register_custom_event<T: ::std::any::Any>(&self) -> Result<(), String> {
179 use std::any::TypeId;
180 let event_id = *(unsafe { self.register_events(1) })?.first().unwrap();
181 let mut cet = CUSTOM_EVENT_TYPES.lock().unwrap();
182 let type_id = TypeId::of::<Box<T>>();
183
184 if cet.type_id_to_sdl_id.contains_key(&type_id) {
185 return Err("The same event type can not be registered twice!".to_owned());
186 }
187
188 cet.sdl_id_to_type_id.insert(event_id, type_id);
189 cet.type_id_to_sdl_id.insert(type_id, event_id);
190
191 Ok(())
192 }
193
194 pub fn push_custom_event<T: ::std::any::Any>(&self, event: T) -> Result<(), String> {
223 self.event_sender().push_custom_event(event)
224 }
225
226 pub fn event_sender(&self) -> EventSender {
231 EventSender { _priv: () }
232 }
233
234 pub fn add_event_watch<'a, CB: EventWatchCallback + 'a>(
252 &self,
253 callback: CB,
254 ) -> EventWatch<'a, CB> {
255 EventWatch::add(callback)
256 }
257}
258
259#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
261#[repr(u32)]
262pub enum EventType {
263 First = SDL_EventType::SDL_FIRSTEVENT as u32,
264
265 Quit = SDL_EventType::SDL_QUIT as u32,
266 AppTerminating = SDL_EventType::SDL_APP_TERMINATING as u32,
267 AppLowMemory = SDL_EventType::SDL_APP_LOWMEMORY as u32,
268 AppWillEnterBackground = SDL_EventType::SDL_APP_WILLENTERBACKGROUND as u32,
269 AppDidEnterBackground = SDL_EventType::SDL_APP_DIDENTERBACKGROUND as u32,
270 AppWillEnterForeground = SDL_EventType::SDL_APP_WILLENTERFOREGROUND as u32,
271 AppDidEnterForeground = SDL_EventType::SDL_APP_DIDENTERFOREGROUND as u32,
272
273 Display = SDL_EventType::SDL_DISPLAYEVENT as u32,
274 Window = SDL_EventType::SDL_WINDOWEVENT as u32,
275 KeyDown = SDL_EventType::SDL_KEYDOWN as u32,
277 KeyUp = SDL_EventType::SDL_KEYUP as u32,
278 TextEditing = SDL_EventType::SDL_TEXTEDITING as u32,
279 TextInput = SDL_EventType::SDL_TEXTINPUT as u32,
280
281 MouseMotion = SDL_EventType::SDL_MOUSEMOTION as u32,
282 MouseButtonDown = SDL_EventType::SDL_MOUSEBUTTONDOWN as u32,
283 MouseButtonUp = SDL_EventType::SDL_MOUSEBUTTONUP as u32,
284 MouseWheel = SDL_EventType::SDL_MOUSEWHEEL as u32,
285
286 JoyAxisMotion = SDL_EventType::SDL_JOYAXISMOTION as u32,
287 JoyBallMotion = SDL_EventType::SDL_JOYBALLMOTION as u32,
288 JoyHatMotion = SDL_EventType::SDL_JOYHATMOTION as u32,
289 JoyButtonDown = SDL_EventType::SDL_JOYBUTTONDOWN as u32,
290 JoyButtonUp = SDL_EventType::SDL_JOYBUTTONUP as u32,
291 JoyDeviceAdded = SDL_EventType::SDL_JOYDEVICEADDED as u32,
292 JoyDeviceRemoved = SDL_EventType::SDL_JOYDEVICEREMOVED as u32,
293
294 ControllerAxisMotion = SDL_EventType::SDL_CONTROLLERAXISMOTION as u32,
295 ControllerButtonDown = SDL_EventType::SDL_CONTROLLERBUTTONDOWN as u32,
296 ControllerButtonUp = SDL_EventType::SDL_CONTROLLERBUTTONUP as u32,
297 ControllerDeviceAdded = SDL_EventType::SDL_CONTROLLERDEVICEADDED as u32,
298 ControllerDeviceRemoved = SDL_EventType::SDL_CONTROLLERDEVICEREMOVED as u32,
299 ControllerDeviceRemapped = SDL_EventType::SDL_CONTROLLERDEVICEREMAPPED as u32,
300 ControllerTouchpadDown = SDL_EventType::SDL_CONTROLLERTOUCHPADDOWN as u32,
301 ControllerTouchpadMotion = SDL_EventType::SDL_CONTROLLERTOUCHPADMOTION as u32,
302 ControllerTouchpadUp = SDL_EventType::SDL_CONTROLLERTOUCHPADUP as u32,
303 #[cfg(feature = "hidapi")]
304 ControllerSensorUpdated = SDL_EventType::SDL_CONTROLLERSENSORUPDATE as u32,
305
306 FingerDown = SDL_EventType::SDL_FINGERDOWN as u32,
307 FingerUp = SDL_EventType::SDL_FINGERUP as u32,
308 FingerMotion = SDL_EventType::SDL_FINGERMOTION as u32,
309 DollarGesture = SDL_EventType::SDL_DOLLARGESTURE as u32,
310 DollarRecord = SDL_EventType::SDL_DOLLARRECORD as u32,
311 MultiGesture = SDL_EventType::SDL_MULTIGESTURE as u32,
312
313 ClipboardUpdate = SDL_EventType::SDL_CLIPBOARDUPDATE as u32,
314 DropFile = SDL_EventType::SDL_DROPFILE as u32,
315 DropText = SDL_EventType::SDL_DROPTEXT as u32,
316 DropBegin = SDL_EventType::SDL_DROPBEGIN as u32,
317 DropComplete = SDL_EventType::SDL_DROPCOMPLETE as u32,
318
319 AudioDeviceAdded = SDL_EventType::SDL_AUDIODEVICEADDED as u32,
320 AudioDeviceRemoved = SDL_EventType::SDL_AUDIODEVICEREMOVED as u32,
321
322 RenderTargetsReset = SDL_EventType::SDL_RENDER_TARGETS_RESET as u32,
323 RenderDeviceReset = SDL_EventType::SDL_RENDER_DEVICE_RESET as u32,
324
325 User = SDL_EventType::SDL_USEREVENT as u32,
326 Last = SDL_EventType::SDL_LASTEVENT as u32,
327}
328
329impl TryFrom<u32> for EventType {
330 type Error = ();
331
332 fn try_from(n: u32) -> Result<Self, Self::Error> {
333 use self::EventType::*;
334 use crate::sys::SDL_EventType::*;
335
336 Ok(match unsafe { transmute(n) } {
337 SDL_FIRSTEVENT => First,
338
339 SDL_QUIT => Quit,
340 SDL_APP_TERMINATING => AppTerminating,
341 SDL_APP_LOWMEMORY => AppLowMemory,
342 SDL_APP_WILLENTERBACKGROUND => AppWillEnterBackground,
343 SDL_APP_DIDENTERBACKGROUND => AppDidEnterBackground,
344 SDL_APP_WILLENTERFOREGROUND => AppWillEnterForeground,
345 SDL_APP_DIDENTERFOREGROUND => AppDidEnterForeground,
346
347 SDL_DISPLAYEVENT => Display,
348 SDL_WINDOWEVENT => Window,
349
350 SDL_KEYDOWN => KeyDown,
351 SDL_KEYUP => KeyUp,
352 SDL_TEXTEDITING => TextEditing,
353 SDL_TEXTINPUT => TextInput,
354
355 SDL_MOUSEMOTION => MouseMotion,
356 SDL_MOUSEBUTTONDOWN => MouseButtonDown,
357 SDL_MOUSEBUTTONUP => MouseButtonUp,
358 SDL_MOUSEWHEEL => MouseWheel,
359
360 SDL_JOYAXISMOTION => JoyAxisMotion,
361 SDL_JOYBALLMOTION => JoyBallMotion,
362 SDL_JOYHATMOTION => JoyHatMotion,
363 SDL_JOYBUTTONDOWN => JoyButtonDown,
364 SDL_JOYBUTTONUP => JoyButtonUp,
365 SDL_JOYDEVICEADDED => JoyDeviceAdded,
366 SDL_JOYDEVICEREMOVED => JoyDeviceRemoved,
367
368 SDL_CONTROLLERAXISMOTION => ControllerAxisMotion,
369 SDL_CONTROLLERBUTTONDOWN => ControllerButtonDown,
370 SDL_CONTROLLERBUTTONUP => ControllerButtonUp,
371 SDL_CONTROLLERDEVICEADDED => ControllerDeviceAdded,
372 SDL_CONTROLLERDEVICEREMOVED => ControllerDeviceRemoved,
373 SDL_CONTROLLERDEVICEREMAPPED => ControllerDeviceRemapped,
374 SDL_CONTROLLERTOUCHPADDOWN => ControllerTouchpadDown,
375 SDL_CONTROLLERTOUCHPADMOTION => ControllerTouchpadMotion,
376 SDL_CONTROLLERTOUCHPADUP => ControllerTouchpadUp,
377 #[cfg(feature = "hidapi")]
378 SDL_CONTROLLERSENSORUPDATE => ControllerSensorUpdated,
379
380 SDL_FINGERDOWN => FingerDown,
381 SDL_FINGERUP => FingerUp,
382 SDL_FINGERMOTION => FingerMotion,
383 SDL_DOLLARGESTURE => DollarGesture,
384 SDL_DOLLARRECORD => DollarRecord,
385 SDL_MULTIGESTURE => MultiGesture,
386
387 SDL_CLIPBOARDUPDATE => ClipboardUpdate,
388 SDL_DROPFILE => DropFile,
389 SDL_DROPTEXT => DropText,
390 SDL_DROPBEGIN => DropBegin,
391 SDL_DROPCOMPLETE => DropComplete,
392
393 SDL_AUDIODEVICEADDED => AudioDeviceAdded,
394 SDL_AUDIODEVICEREMOVED => AudioDeviceRemoved,
395
396 SDL_RENDER_TARGETS_RESET => RenderTargetsReset,
397 SDL_RENDER_DEVICE_RESET => RenderDeviceReset,
398
399 SDL_USEREVENT => User,
400 SDL_LASTEVENT => Last,
401
402 _ => return Err(()),
403 })
404 }
405}
406
407#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
408pub enum DisplayEvent {
410 None,
411 Orientation(Orientation),
412 Connected,
413 Disconnected,
414}
415
416impl DisplayEvent {
417 #[allow(clippy::match_same_arms)]
418 fn from_ll(id: u8, data1: i32) -> DisplayEvent {
419 if id > sys::SDL_DisplayEventID::SDL_DISPLAYEVENT_DISCONNECTED as u8 {
420 return DisplayEvent::None;
421 }
422 match unsafe { transmute(id as u32) } {
423 sys::SDL_DisplayEventID::SDL_DISPLAYEVENT_NONE => DisplayEvent::None,
424 sys::SDL_DisplayEventID::SDL_DISPLAYEVENT_ORIENTATION => {
425 let orientation = if data1 as u32
426 > sys::SDL_DisplayOrientation::SDL_ORIENTATION_PORTRAIT_FLIPPED as u32
427 {
428 Orientation::Unknown
429 } else {
430 Orientation::from_ll(unsafe { transmute(data1 as u32) })
431 };
432 DisplayEvent::Orientation(orientation)
433 }
434 sys::SDL_DisplayEventID::SDL_DISPLAYEVENT_CONNECTED => DisplayEvent::Connected,
435 sys::SDL_DisplayEventID::SDL_DISPLAYEVENT_DISCONNECTED => DisplayEvent::Disconnected,
436 }
437 }
438
439 fn to_ll(self) -> (u8, i32) {
440 match self {
441 DisplayEvent::None => (sys::SDL_DisplayEventID::SDL_DISPLAYEVENT_NONE as u8, 0),
442 DisplayEvent::Orientation(orientation) => (
443 sys::SDL_DisplayEventID::SDL_DISPLAYEVENT_ORIENTATION as u8,
444 orientation.to_ll() as i32,
445 ),
446 DisplayEvent::Connected => {
447 (sys::SDL_DisplayEventID::SDL_DISPLAYEVENT_CONNECTED as u8, 0)
448 }
449 DisplayEvent::Disconnected => (
450 sys::SDL_DisplayEventID::SDL_DISPLAYEVENT_DISCONNECTED as u8,
451 0,
452 ),
453 }
454 }
455
456 pub fn is_same_kind_as(&self, other: &DisplayEvent) -> bool {
457 mem::discriminant(self) == mem::discriminant(other)
458 }
459}
460
461#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
462pub enum WindowEvent {
464 None,
465 Shown,
466 Hidden,
467 Exposed,
468 Moved(i32, i32),
469 Resized(i32, i32),
470 SizeChanged(i32, i32),
471 Minimized,
472 Maximized,
473 Restored,
474 Enter,
475 Leave,
476 FocusGained,
477 FocusLost,
478 Close,
479 TakeFocus,
480 HitTest,
481 ICCProfChanged,
482 DisplayChanged(i32),
483}
484
485impl WindowEvent {
486 #[allow(clippy::match_same_arms)]
487 fn from_ll(id: u8, data1: i32, data2: i32) -> WindowEvent {
488 match id {
489 0 => WindowEvent::None,
490 1 => WindowEvent::Shown,
491 2 => WindowEvent::Hidden,
492 3 => WindowEvent::Exposed,
493 4 => WindowEvent::Moved(data1, data2),
494 5 => WindowEvent::Resized(data1, data2),
495 6 => WindowEvent::SizeChanged(data1, data2),
496 7 => WindowEvent::Minimized,
497 8 => WindowEvent::Maximized,
498 9 => WindowEvent::Restored,
499 10 => WindowEvent::Enter,
500 11 => WindowEvent::Leave,
501 12 => WindowEvent::FocusGained,
502 13 => WindowEvent::FocusLost,
503 14 => WindowEvent::Close,
504 15 => WindowEvent::TakeFocus,
505 16 => WindowEvent::HitTest,
506 17 => WindowEvent::ICCProfChanged,
507 18 => WindowEvent::DisplayChanged(data1),
508 _ => WindowEvent::None,
509 }
510 }
511
512 fn to_ll(self) -> (u8, i32, i32) {
513 match self {
514 WindowEvent::None => (0, 0, 0),
515 WindowEvent::Shown => (1, 0, 0),
516 WindowEvent::Hidden => (2, 0, 0),
517 WindowEvent::Exposed => (3, 0, 0),
518 WindowEvent::Moved(d1, d2) => (4, d1, d2),
519 WindowEvent::Resized(d1, d2) => (5, d1, d2),
520 WindowEvent::SizeChanged(d1, d2) => (6, d1, d2),
521 WindowEvent::Minimized => (7, 0, 0),
522 WindowEvent::Maximized => (8, 0, 0),
523 WindowEvent::Restored => (9, 0, 0),
524 WindowEvent::Enter => (10, 0, 0),
525 WindowEvent::Leave => (11, 0, 0),
526 WindowEvent::FocusGained => (12, 0, 0),
527 WindowEvent::FocusLost => (13, 0, 0),
528 WindowEvent::Close => (14, 0, 0),
529 WindowEvent::TakeFocus => (15, 0, 0),
530 WindowEvent::HitTest => (16, 0, 0),
531 WindowEvent::ICCProfChanged => (17, 0, 0),
532 WindowEvent::DisplayChanged(d1) => (18, d1, 0),
533 }
534 }
535
536 pub fn is_same_kind_as(&self, other: &WindowEvent) -> bool {
537 mem::discriminant(self) == mem::discriminant(other)
538 }
539}
540
541#[derive(Clone, PartialEq, Debug)]
542pub enum Event {
544 Quit {
545 timestamp: u32,
546 },
547 AppTerminating {
548 timestamp: u32,
549 },
550 AppLowMemory {
551 timestamp: u32,
552 },
553 AppWillEnterBackground {
554 timestamp: u32,
555 },
556 AppDidEnterBackground {
557 timestamp: u32,
558 },
559 AppWillEnterForeground {
560 timestamp: u32,
561 },
562 AppDidEnterForeground {
563 timestamp: u32,
564 },
565
566 Display {
567 timestamp: u32,
568 display_index: i32,
569 display_event: DisplayEvent,
570 },
571 Window {
572 timestamp: u32,
573 window_id: u32,
574 win_event: WindowEvent,
575 },
576 KeyDown {
578 timestamp: u32,
579 window_id: u32,
580 keycode: Option<Keycode>,
581 scancode: Option<Scancode>,
582 keymod: Mod,
583 repeat: bool,
584 },
585 KeyUp {
586 timestamp: u32,
587 window_id: u32,
588 keycode: Option<Keycode>,
589 scancode: Option<Scancode>,
590 keymod: Mod,
591 repeat: bool,
592 },
593
594 TextEditing {
595 timestamp: u32,
596 window_id: u32,
597 text: String,
598 start: i32,
599 length: i32,
600 },
601
602 TextInput {
603 timestamp: u32,
604 window_id: u32,
605 text: String,
606 },
607
608 MouseMotion {
609 timestamp: u32,
610 window_id: u32,
611 which: u32,
612 mousestate: MouseState,
613 x: i32,
614 y: i32,
615 xrel: i32,
616 yrel: i32,
617 },
618
619 MouseButtonDown {
620 timestamp: u32,
621 window_id: u32,
622 which: u32,
623 mouse_btn: MouseButton,
624 clicks: u8,
625 x: i32,
626 y: i32,
627 },
628 MouseButtonUp {
629 timestamp: u32,
630 window_id: u32,
631 which: u32,
632 mouse_btn: MouseButton,
633 clicks: u8,
634 x: i32,
635 y: i32,
636 },
637
638 MouseWheel {
639 timestamp: u32,
640 window_id: u32,
641 which: u32,
642 x: i32,
644 y: i32,
646 direction: MouseWheelDirection,
647 precise_x: f32,
649 precise_y: f32,
651 mouse_x: i32,
653 mouse_y: i32,
655 },
656
657 JoyAxisMotion {
658 timestamp: u32,
659 which: u32,
661 axis_idx: u8,
662 value: i16,
663 },
664
665 JoyBallMotion {
666 timestamp: u32,
667 which: u32,
669 ball_idx: u8,
670 xrel: i16,
671 yrel: i16,
672 },
673
674 JoyHatMotion {
675 timestamp: u32,
676 which: u32,
678 hat_idx: u8,
679 state: HatState,
680 },
681
682 JoyButtonDown {
683 timestamp: u32,
684 which: u32,
686 button_idx: u8,
687 },
688 JoyButtonUp {
689 timestamp: u32,
690 which: u32,
692 button_idx: u8,
693 },
694
695 JoyDeviceAdded {
696 timestamp: u32,
697 which: u32,
699 },
700 JoyDeviceRemoved {
701 timestamp: u32,
702 which: u32,
704 },
705
706 ControllerAxisMotion {
707 timestamp: u32,
708 which: u32,
710 axis: Axis,
711 value: i16,
712 },
713
714 ControllerButtonDown {
715 timestamp: u32,
716 which: u32,
718 button: Button,
719 },
720 ControllerButtonUp {
721 timestamp: u32,
722 which: u32,
724 button: Button,
725 },
726
727 ControllerDeviceAdded {
728 timestamp: u32,
729 which: u32,
731 },
732 ControllerDeviceRemoved {
733 timestamp: u32,
734 which: u32,
736 },
737 ControllerDeviceRemapped {
738 timestamp: u32,
739 which: u32,
741 },
742
743 ControllerTouchpadDown {
744 timestamp: u32,
745 which: u32,
747 touchpad: u32,
749 finger: u32,
751 x: f32,
753 y: f32,
755 pressure: f32,
757 },
758 ControllerTouchpadMotion {
759 timestamp: u32,
760 which: u32,
762 touchpad: u32,
764 finger: u32,
766 x: f32,
768 y: f32,
770 pressure: f32,
772 },
773 ControllerTouchpadUp {
774 timestamp: u32,
775 which: u32,
777 touchpad: u32,
779 finger: u32,
781 x: f32,
783 y: f32,
785 pressure: f32,
787 },
788
789 #[cfg(feature = "hidapi")]
791 ControllerSensorUpdated {
792 timestamp: u32,
793 which: u32,
794 sensor: crate::sensor::SensorType,
795 data: [f32; 3],
799 },
800
801 FingerDown {
802 timestamp: u32,
803 touch_id: i64,
804 finger_id: i64,
805 x: f32,
806 y: f32,
807 dx: f32,
808 dy: f32,
809 pressure: f32,
810 },
811 FingerUp {
812 timestamp: u32,
813 touch_id: i64,
814 finger_id: i64,
815 x: f32,
816 y: f32,
817 dx: f32,
818 dy: f32,
819 pressure: f32,
820 },
821 FingerMotion {
822 timestamp: u32,
823 touch_id: i64,
824 finger_id: i64,
825 x: f32,
826 y: f32,
827 dx: f32,
828 dy: f32,
829 pressure: f32,
830 },
831
832 DollarGesture {
833 timestamp: u32,
834 touch_id: i64,
835 gesture_id: i64,
836 num_fingers: u32,
837 error: f32,
838 x: f32,
839 y: f32,
840 },
841 DollarRecord {
842 timestamp: u32,
843 touch_id: i64,
844 gesture_id: i64,
845 num_fingers: u32,
846 error: f32,
847 x: f32,
848 y: f32,
849 },
850
851 MultiGesture {
852 timestamp: u32,
853 touch_id: i64,
854 d_theta: f32,
855 d_dist: f32,
856 x: f32,
857 y: f32,
858 num_fingers: u16,
859 },
860
861 ClipboardUpdate {
862 timestamp: u32,
863 },
864
865 DropFile {
866 timestamp: u32,
867 window_id: u32,
868 filename: String,
869 },
870 DropText {
871 timestamp: u32,
872 window_id: u32,
873 filename: String,
874 },
875 DropBegin {
876 timestamp: u32,
877 window_id: u32,
878 },
879 DropComplete {
880 timestamp: u32,
881 window_id: u32,
882 },
883
884 AudioDeviceAdded {
885 timestamp: u32,
886 which: u32,
887 iscapture: bool,
888 },
889 AudioDeviceRemoved {
890 timestamp: u32,
891 which: u32,
892 iscapture: bool,
893 },
894
895 RenderTargetsReset {
896 timestamp: u32,
897 },
898 RenderDeviceReset {
899 timestamp: u32,
900 },
901
902 User {
903 timestamp: u32,
904 window_id: u32,
905 type_: u32,
906 code: i32,
907 data1: *mut c_void,
908 data2: *mut c_void,
909 },
910
911 Unknown {
912 timestamp: u32,
913 type_: u32,
914 },
915}
916
917unsafe impl Send for Event {}
921
922unsafe impl Sync for Event {}
926
927#[doc(alias = "SDL_Keysym")]
930fn mk_keysym<S, K>(scancode: S, keycode: K, keymod: Mod) -> sys::SDL_Keysym
931where
932 S: Into<Option<Scancode>>,
933 K: Into<Option<Keycode>>,
934{
935 let scancode = scancode
936 .into()
937 .map(|sc| unsafe { transmute::<u32, sys::SDL_Scancode>(sc as u32) })
938 .unwrap_or(sys::SDL_Scancode::SDL_SCANCODE_UNKNOWN);
939 let keycode = keycode
940 .into()
941 .map(|kc| kc.into())
942 .unwrap_or(sys::SDL_KeyCode::SDLK_UNKNOWN as i32);
943 let keymod = keymod.bits();
944 sys::SDL_Keysym {
945 scancode,
946 sym: keycode,
947 mod_: keymod,
948 unused: 0,
949 }
950}
951
952impl Event {
956 fn to_ll(&self) -> Option<sys::SDL_Event> {
957 let mut ret = mem::MaybeUninit::uninit();
958 match *self {
959 Event::User {
960 window_id,
961 type_,
962 code,
963 data1,
964 data2,
965 timestamp,
966 } => {
967 let event = sys::SDL_UserEvent {
968 type_,
969 timestamp,
970 windowID: window_id,
971 code,
972 data1,
973 data2,
974 };
975 unsafe {
976 ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_UserEvent, 1);
977 Some(ret.assume_init())
978 }
979 }
980
981 Event::Quit { timestamp } => {
982 let event = sys::SDL_QuitEvent {
983 type_: SDL_EventType::SDL_QUIT as u32,
984 timestamp,
985 };
986 unsafe {
987 ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_QuitEvent, 1);
988 Some(ret.assume_init())
989 }
990 }
991
992 Event::Display {
993 timestamp,
994 display_index,
995 display_event,
996 } => {
997 let (display_event_id, data1) = display_event.to_ll();
998 let event = sys::SDL_DisplayEvent {
999 type_: SDL_EventType::SDL_DISPLAYEVENT as u32,
1000 timestamp,
1001 display: display_index as u32,
1002 event: display_event_id,
1003 padding1: 0,
1004 padding2: 0,
1005 padding3: 0,
1006 data1,
1007 };
1008 unsafe {
1009 ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_DisplayEvent, 1);
1010 Some(ret.assume_init())
1011 }
1012 }
1013
1014 Event::Window {
1015 timestamp,
1016 window_id,
1017 win_event,
1018 } => {
1019 let (win_event_id, data1, data2) = win_event.to_ll();
1020 let event = sys::SDL_WindowEvent {
1021 type_: SDL_EventType::SDL_WINDOWEVENT as u32,
1022 timestamp,
1023 windowID: window_id,
1024 event: win_event_id,
1025 padding1: 0,
1026 padding2: 0,
1027 padding3: 0,
1028 data1,
1029 data2,
1030 };
1031 unsafe {
1032 ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_WindowEvent, 1);
1033 Some(ret.assume_init())
1034 }
1035 }
1036
1037 Event::KeyDown {
1038 timestamp,
1039 window_id,
1040 keycode,
1041 scancode,
1042 keymod,
1043 repeat,
1044 } => {
1045 let keysym = mk_keysym(scancode, keycode, keymod);
1046 let event = sys::SDL_KeyboardEvent {
1047 type_: SDL_EventType::SDL_KEYDOWN as u32,
1048 timestamp,
1049 windowID: window_id,
1050 state: sys::SDL_PRESSED as u8,
1051 repeat: repeat as u8,
1052 padding2: 0,
1053 padding3: 0,
1054 keysym,
1055 };
1056 unsafe {
1057 ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_KeyboardEvent, 1);
1058 Some(ret.assume_init())
1059 }
1060 }
1061 Event::KeyUp {
1062 timestamp,
1063 window_id,
1064 keycode,
1065 scancode,
1066 keymod,
1067 repeat,
1068 } => {
1069 let keysym = mk_keysym(scancode, keycode, keymod);
1070 let event = sys::SDL_KeyboardEvent {
1071 type_: SDL_EventType::SDL_KEYUP as u32,
1072 timestamp,
1073 windowID: window_id,
1074 state: sys::SDL_RELEASED as u8,
1075 repeat: repeat as u8,
1076 padding2: 0,
1077 padding3: 0,
1078 keysym,
1079 };
1080 unsafe {
1081 ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_KeyboardEvent, 1);
1082 Some(ret.assume_init())
1083 }
1084 }
1085 Event::MouseMotion {
1086 timestamp,
1087 window_id,
1088 which,
1089 mousestate,
1090 x,
1091 y,
1092 xrel,
1093 yrel,
1094 } => {
1095 let state = mousestate.to_sdl_state();
1096 let event = sys::SDL_MouseMotionEvent {
1097 type_: SDL_EventType::SDL_MOUSEMOTION as u32,
1098 timestamp,
1099 windowID: window_id,
1100 which,
1101 state,
1102 x,
1103 y,
1104 xrel,
1105 yrel,
1106 };
1107 unsafe {
1108 ptr::copy(
1109 &event,
1110 ret.as_mut_ptr() as *mut sys::SDL_MouseMotionEvent,
1111 1,
1112 );
1113 Some(ret.assume_init())
1114 }
1115 }
1116 Event::MouseButtonDown {
1117 timestamp,
1118 window_id,
1119 which,
1120 mouse_btn,
1121 clicks,
1122 x,
1123 y,
1124 } => {
1125 let event = sys::SDL_MouseButtonEvent {
1126 type_: SDL_EventType::SDL_MOUSEBUTTONDOWN as u32,
1127 timestamp,
1128 windowID: window_id,
1129 which,
1130 button: mouse_btn as u8,
1131 state: sys::SDL_PRESSED as u8,
1132 clicks,
1133 padding1: 0,
1134 x,
1135 y,
1136 };
1137 unsafe {
1138 ptr::copy(
1139 &event,
1140 ret.as_mut_ptr() as *mut sys::SDL_MouseButtonEvent,
1141 1,
1142 );
1143 Some(ret.assume_init())
1144 }
1145 }
1146 Event::MouseButtonUp {
1147 timestamp,
1148 window_id,
1149 which,
1150 mouse_btn,
1151 clicks,
1152 x,
1153 y,
1154 } => {
1155 let event = sys::SDL_MouseButtonEvent {
1156 type_: SDL_EventType::SDL_MOUSEBUTTONUP as u32,
1157 timestamp,
1158 windowID: window_id,
1159 which,
1160 button: mouse_btn as u8,
1161 state: sys::SDL_RELEASED as u8,
1162 clicks,
1163 padding1: 0,
1164 x,
1165 y,
1166 };
1167 unsafe {
1168 ptr::copy(
1169 &event,
1170 ret.as_mut_ptr() as *mut sys::SDL_MouseButtonEvent,
1171 1,
1172 );
1173 Some(ret.assume_init())
1174 }
1175 }
1176
1177 Event::MouseWheel {
1178 timestamp,
1179 window_id,
1180 which,
1181 x,
1182 y,
1183 direction,
1184 precise_x,
1185 precise_y,
1186 mouse_x,
1187 mouse_y,
1188 } => {
1189 let event = sys::SDL_MouseWheelEvent {
1190 type_: SDL_EventType::SDL_MOUSEWHEEL as u32,
1191 timestamp,
1192 windowID: window_id,
1193 which,
1194 x,
1195 y,
1196 direction: direction.to_ll(),
1197 preciseX: precise_x,
1198 preciseY: precise_y,
1199 mouseX: mouse_x,
1200 mouseY: mouse_y,
1201 };
1202 unsafe {
1203 ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_MouseWheelEvent, 1);
1204 Some(ret.assume_init())
1205 }
1206 }
1207 Event::JoyAxisMotion {
1208 timestamp,
1209 which,
1210 axis_idx,
1211 value,
1212 } => {
1213 let event = sys::SDL_JoyAxisEvent {
1214 type_: SDL_EventType::SDL_JOYAXISMOTION as u32,
1215 timestamp,
1216 which: which as i32,
1217 axis: axis_idx,
1218 value,
1219 padding1: 0,
1220 padding2: 0,
1221 padding3: 0,
1222 padding4: 0,
1223 };
1224 unsafe {
1225 ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_JoyAxisEvent, 1);
1226 Some(ret.assume_init())
1227 }
1228 }
1229 Event::JoyBallMotion {
1230 timestamp,
1231 which,
1232 ball_idx,
1233 xrel,
1234 yrel,
1235 } => {
1236 let event = sys::SDL_JoyBallEvent {
1237 type_: SDL_EventType::SDL_JOYBALLMOTION as u32,
1238 timestamp,
1239 which: which as i32,
1240 ball: ball_idx,
1241 xrel,
1242 yrel,
1243 padding1: 0,
1244 padding2: 0,
1245 padding3: 0,
1246 };
1247 unsafe {
1248 ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_JoyBallEvent, 1);
1249 Some(ret.assume_init())
1250 }
1251 }
1252 Event::JoyHatMotion {
1253 timestamp,
1254 which,
1255 hat_idx,
1256 state,
1257 } => {
1258 let hatvalue = state.to_raw();
1259 let event = sys::SDL_JoyHatEvent {
1260 type_: SDL_EventType::SDL_JOYHATMOTION as u32,
1261 timestamp,
1262 which: which as i32,
1263 hat: hat_idx,
1264 value: hatvalue,
1265 padding1: 0,
1266 padding2: 0,
1267 };
1268 unsafe {
1269 ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_JoyHatEvent, 1);
1270 Some(ret.assume_init())
1271 }
1272 }
1273 Event::JoyButtonDown {
1274 timestamp,
1275 which,
1276 button_idx,
1277 } => {
1278 let event = sys::SDL_JoyButtonEvent {
1279 type_: SDL_EventType::SDL_JOYBUTTONDOWN as u32,
1280 timestamp,
1281 which: which as i32,
1282 button: button_idx,
1283 state: sys::SDL_PRESSED as u8,
1284 padding1: 0,
1285 padding2: 0,
1286 };
1287 unsafe {
1288 ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_JoyButtonEvent, 1);
1289 Some(ret.assume_init())
1290 }
1291 }
1292
1293 Event::JoyButtonUp {
1294 timestamp,
1295 which,
1296 button_idx,
1297 } => {
1298 let event = sys::SDL_JoyButtonEvent {
1299 type_: SDL_EventType::SDL_JOYBUTTONUP as u32,
1300 timestamp,
1301 which: which as i32,
1302 button: button_idx,
1303 state: sys::SDL_RELEASED as u8,
1304 padding1: 0,
1305 padding2: 0,
1306 };
1307 unsafe {
1308 ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_JoyButtonEvent, 1);
1309 Some(ret.assume_init())
1310 }
1311 }
1312
1313 Event::JoyDeviceAdded { timestamp, which } => {
1314 let event = sys::SDL_JoyDeviceEvent {
1315 type_: SDL_EventType::SDL_JOYDEVICEADDED as u32,
1316 timestamp,
1317 which: which as i32,
1318 };
1319 unsafe {
1320 ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_JoyDeviceEvent, 1);
1321 Some(ret.assume_init())
1322 }
1323 }
1324
1325 Event::JoyDeviceRemoved { timestamp, which } => {
1326 let event = sys::SDL_JoyDeviceEvent {
1327 type_: SDL_EventType::SDL_JOYDEVICEREMOVED as u32,
1328 timestamp,
1329 which: which as i32,
1330 };
1331 unsafe {
1332 ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_JoyDeviceEvent, 1);
1333 Some(ret.assume_init())
1334 }
1335 }
1336 Event::ControllerAxisMotion {
1337 timestamp,
1338 which,
1339 axis,
1340 value,
1341 } => {
1342 let axisval = axis.to_ll();
1343 let event = sys::SDL_ControllerAxisEvent {
1344 type_: SDL_EventType::SDL_CONTROLLERAXISMOTION as u32,
1345 timestamp,
1346 which: which as i32,
1347 axis: axisval as u8,
1348 value,
1349 padding1: 0,
1350 padding2: 0,
1351 padding3: 0,
1352 padding4: 0,
1353 };
1354 unsafe {
1355 ptr::copy(
1356 &event,
1357 ret.as_mut_ptr() as *mut sys::SDL_ControllerAxisEvent,
1358 1,
1359 );
1360 Some(ret.assume_init())
1361 }
1362 }
1363 Event::ControllerButtonDown {
1364 timestamp,
1365 which,
1366 button,
1367 } => {
1368 let buttonval = button.to_ll();
1369 let event = sys::SDL_ControllerButtonEvent {
1370 type_: SDL_EventType::SDL_CONTROLLERBUTTONDOWN as u32,
1371 timestamp,
1372 which: which as i32,
1373 button: buttonval as u8,
1376 state: sys::SDL_PRESSED as u8,
1377 padding1: 0,
1378 padding2: 0,
1379 };
1380 unsafe {
1381 ptr::copy(
1382 &event,
1383 ret.as_mut_ptr() as *mut sys::SDL_ControllerButtonEvent,
1384 1,
1385 );
1386 Some(ret.assume_init())
1387 }
1388 }
1389
1390 Event::ControllerButtonUp {
1391 timestamp,
1392 which,
1393 button,
1394 } => {
1395 let buttonval = button.to_ll();
1396 let event = sys::SDL_ControllerButtonEvent {
1397 type_: SDL_EventType::SDL_CONTROLLERBUTTONUP as u32,
1398 timestamp,
1399 which: which as i32,
1400 button: buttonval as u8,
1401 state: sys::SDL_RELEASED as u8,
1402 padding1: 0,
1403 padding2: 0,
1404 };
1405 unsafe {
1406 ptr::copy(
1407 &event,
1408 ret.as_mut_ptr() as *mut sys::SDL_ControllerButtonEvent,
1409 1,
1410 );
1411 Some(ret.assume_init())
1412 }
1413 }
1414
1415 Event::ControllerDeviceAdded { timestamp, which } => {
1416 let event = sys::SDL_ControllerDeviceEvent {
1417 type_: SDL_EventType::SDL_CONTROLLERDEVICEADDED as u32,
1418 timestamp,
1419 which: which as i32,
1420 };
1421 unsafe {
1422 ptr::copy(
1423 &event,
1424 ret.as_mut_ptr() as *mut sys::SDL_ControllerDeviceEvent,
1425 1,
1426 );
1427 Some(ret.assume_init())
1428 }
1429 }
1430
1431 Event::ControllerDeviceRemoved { timestamp, which } => {
1432 let event = sys::SDL_ControllerDeviceEvent {
1433 type_: SDL_EventType::SDL_CONTROLLERDEVICEREMOVED as u32,
1434 timestamp,
1435 which: which as i32,
1436 };
1437 unsafe {
1438 ptr::copy(
1439 &event,
1440 ret.as_mut_ptr() as *mut sys::SDL_ControllerDeviceEvent,
1441 1,
1442 );
1443 Some(ret.assume_init())
1444 }
1445 }
1446
1447 Event::ControllerDeviceRemapped { timestamp, which } => {
1448 let event = sys::SDL_ControllerDeviceEvent {
1449 type_: SDL_EventType::SDL_CONTROLLERDEVICEREMAPPED as u32,
1450 timestamp,
1451 which: which as i32,
1452 };
1453 unsafe {
1454 ptr::copy(
1455 &event,
1456 ret.as_mut_ptr() as *mut sys::SDL_ControllerDeviceEvent,
1457 1,
1458 );
1459 Some(ret.assume_init())
1460 }
1461 }
1462
1463 Event::FingerDown { .. }
1464 | Event::FingerUp { .. }
1465 | Event::FingerMotion { .. }
1466 | Event::DollarGesture { .. }
1467 | Event::DollarRecord { .. }
1468 | Event::MultiGesture { .. }
1469 | Event::ClipboardUpdate { .. }
1470 | Event::DropFile { .. }
1471 | Event::TextEditing { .. }
1472 | Event::TextInput { .. }
1473 | Event::Unknown { .. }
1474 | _ => {
1475 None
1477 }
1478 }
1479 }
1480
1481 pub fn from_ll(raw: sys::SDL_Event) -> Event {
1482 let raw_type = unsafe { raw.type_ };
1483
1484 let event_type: EventType = EventType::try_from(raw_type).unwrap_or(EventType::User);
1486 unsafe {
1487 match event_type {
1488 EventType::Quit => {
1489 let event = raw.quit;
1490 Event::Quit {
1491 timestamp: event.timestamp,
1492 }
1493 }
1494 EventType::AppTerminating => {
1495 let event = raw.common;
1496 Event::AppTerminating {
1497 timestamp: event.timestamp,
1498 }
1499 }
1500 EventType::AppLowMemory => {
1501 let event = raw.common;
1502 Event::AppLowMemory {
1503 timestamp: event.timestamp,
1504 }
1505 }
1506 EventType::AppWillEnterBackground => {
1507 let event = raw.common;
1508 Event::AppWillEnterBackground {
1509 timestamp: event.timestamp,
1510 }
1511 }
1512 EventType::AppDidEnterBackground => {
1513 let event = raw.common;
1514 Event::AppDidEnterBackground {
1515 timestamp: event.timestamp,
1516 }
1517 }
1518 EventType::AppWillEnterForeground => {
1519 let event = raw.common;
1520 Event::AppWillEnterForeground {
1521 timestamp: event.timestamp,
1522 }
1523 }
1524 EventType::AppDidEnterForeground => {
1525 let event = raw.common;
1526 Event::AppDidEnterForeground {
1527 timestamp: event.timestamp,
1528 }
1529 }
1530
1531 EventType::Display => {
1532 let event = raw.display;
1533
1534 Event::Display {
1535 timestamp: event.timestamp,
1536 display_index: event.display as i32,
1537 display_event: DisplayEvent::from_ll(event.event, event.data1),
1538 }
1539 }
1540 EventType::Window => {
1541 let event = raw.window;
1542
1543 Event::Window {
1544 timestamp: event.timestamp,
1545 window_id: event.windowID,
1546 win_event: WindowEvent::from_ll(event.event, event.data1, event.data2),
1547 }
1548 }
1549 EventType::KeyDown => {
1551 let event = raw.key;
1552
1553 Event::KeyDown {
1554 timestamp: event.timestamp,
1555 window_id: event.windowID,
1556 keycode: Keycode::from_i32(event.keysym.sym),
1557 scancode: Scancode::from_i32(event.keysym.scancode as i32),
1558 keymod: keyboard::Mod::from_bits_truncate(event.keysym.mod_),
1559 repeat: event.repeat != 0,
1560 }
1561 }
1562 EventType::KeyUp => {
1563 let event = raw.key;
1564
1565 Event::KeyUp {
1566 timestamp: event.timestamp,
1567 window_id: event.windowID,
1568 keycode: Keycode::from_i32(event.keysym.sym),
1569 scancode: Scancode::from_i32(event.keysym.scancode as i32),
1570 keymod: keyboard::Mod::from_bits_truncate(event.keysym.mod_),
1571 repeat: event.repeat != 0,
1572 }
1573 }
1574 EventType::TextEditing => {
1575 let event = raw.edit;
1576
1577 let text = String::from_utf8(
1578 event
1579 .text
1580 .iter()
1581 .take_while(|&b| (*b) != 0)
1582 .map(|&b| b as u8)
1583 .collect::<Vec<u8>>(),
1584 )
1585 .expect("Invalid TextEditing string");
1586 Event::TextEditing {
1587 timestamp: event.timestamp,
1588 window_id: event.windowID,
1589 text,
1590 start: event.start,
1591 length: event.length,
1592 }
1593 }
1594 EventType::TextInput => {
1595 let event = raw.text;
1596
1597 let text = String::from_utf8(
1598 event
1599 .text
1600 .iter()
1601 .take_while(|&b| (*b) != 0)
1602 .map(|&b| b as u8)
1603 .collect::<Vec<u8>>(),
1604 )
1605 .expect("Invalid TextInput string");
1606 Event::TextInput {
1607 timestamp: event.timestamp,
1608 window_id: event.windowID,
1609 text,
1610 }
1611 }
1612
1613 EventType::MouseMotion => {
1614 let event = raw.motion;
1615
1616 Event::MouseMotion {
1617 timestamp: event.timestamp,
1618 window_id: event.windowID,
1619 which: event.which,
1620 mousestate: mouse::MouseState::from_sdl_state(event.state),
1621 x: event.x,
1622 y: event.y,
1623 xrel: event.xrel,
1624 yrel: event.yrel,
1625 }
1626 }
1627 EventType::MouseButtonDown => {
1628 let event = raw.button;
1629
1630 Event::MouseButtonDown {
1631 timestamp: event.timestamp,
1632 window_id: event.windowID,
1633 which: event.which,
1634 mouse_btn: mouse::MouseButton::from_ll(event.button),
1635 clicks: event.clicks,
1636 x: event.x,
1637 y: event.y,
1638 }
1639 }
1640 EventType::MouseButtonUp => {
1641 let event = raw.button;
1642
1643 Event::MouseButtonUp {
1644 timestamp: event.timestamp,
1645 window_id: event.windowID,
1646 which: event.which,
1647 mouse_btn: mouse::MouseButton::from_ll(event.button),
1648 clicks: event.clicks,
1649 x: event.x,
1650 y: event.y,
1651 }
1652 }
1653 EventType::MouseWheel => {
1654 let event = raw.wheel;
1655
1656 Event::MouseWheel {
1657 timestamp: event.timestamp,
1658 window_id: event.windowID,
1659 which: event.which,
1660 x: event.x,
1661 y: event.y,
1662 direction: mouse::MouseWheelDirection::from_ll(event.direction),
1663 precise_x: event.preciseX,
1664 precise_y: event.preciseY,
1665 mouse_x: event.mouseX,
1666 mouse_y: event.mouseY,
1667 }
1668 }
1669
1670 EventType::JoyAxisMotion => {
1671 let event = raw.jaxis;
1672 Event::JoyAxisMotion {
1673 timestamp: event.timestamp,
1674 which: event.which as u32,
1675 axis_idx: event.axis,
1676 value: event.value,
1677 }
1678 }
1679 EventType::JoyBallMotion => {
1680 let event = raw.jball;
1681 Event::JoyBallMotion {
1682 timestamp: event.timestamp,
1683 which: event.which as u32,
1684 ball_idx: event.ball,
1685 xrel: event.xrel,
1686 yrel: event.yrel,
1687 }
1688 }
1689 EventType::JoyHatMotion => {
1690 let event = raw.jhat;
1691 Event::JoyHatMotion {
1692 timestamp: event.timestamp,
1693 which: event.which as u32,
1694 hat_idx: event.hat,
1695 state: joystick::HatState::from_raw(event.value),
1696 }
1697 }
1698 EventType::JoyButtonDown => {
1699 let event = raw.jbutton;
1700 Event::JoyButtonDown {
1701 timestamp: event.timestamp,
1702 which: event.which as u32,
1703 button_idx: event.button,
1704 }
1705 }
1706 EventType::JoyButtonUp => {
1707 let event = raw.jbutton;
1708 Event::JoyButtonUp {
1709 timestamp: event.timestamp,
1710 which: event.which as u32,
1711 button_idx: event.button,
1712 }
1713 }
1714 EventType::JoyDeviceAdded => {
1715 let event = raw.jdevice;
1716 Event::JoyDeviceAdded {
1717 timestamp: event.timestamp,
1718 which: event.which as u32,
1719 }
1720 }
1721 EventType::JoyDeviceRemoved => {
1722 let event = raw.jdevice;
1723 Event::JoyDeviceRemoved {
1724 timestamp: event.timestamp,
1725 which: event.which as u32,
1726 }
1727 }
1728
1729 EventType::ControllerAxisMotion => {
1730 let event = raw.caxis;
1731 let axis = controller::Axis::from_ll(transmute(event.axis as i32)).unwrap();
1732
1733 Event::ControllerAxisMotion {
1734 timestamp: event.timestamp,
1735 which: event.which as u32,
1736 axis,
1737 value: event.value,
1738 }
1739 }
1740 EventType::ControllerButtonDown => {
1741 let event = raw.cbutton;
1742 let button =
1743 controller::Button::from_ll(transmute(event.button as i32)).unwrap();
1744
1745 Event::ControllerButtonDown {
1746 timestamp: event.timestamp,
1747 which: event.which as u32,
1748 button,
1749 }
1750 }
1751 EventType::ControllerButtonUp => {
1752 let event = raw.cbutton;
1753 let button =
1754 controller::Button::from_ll(transmute(event.button as i32)).unwrap();
1755
1756 Event::ControllerButtonUp {
1757 timestamp: event.timestamp,
1758 which: event.which as u32,
1759 button,
1760 }
1761 }
1762 EventType::ControllerDeviceAdded => {
1763 let event = raw.cdevice;
1764 Event::ControllerDeviceAdded {
1765 timestamp: event.timestamp,
1766 which: event.which as u32,
1767 }
1768 }
1769 EventType::ControllerDeviceRemoved => {
1770 let event = raw.cdevice;
1771 Event::ControllerDeviceRemoved {
1772 timestamp: event.timestamp,
1773 which: event.which as u32,
1774 }
1775 }
1776 EventType::ControllerDeviceRemapped => {
1777 let event = raw.cdevice;
1778 Event::ControllerDeviceRemapped {
1779 timestamp: event.timestamp,
1780 which: event.which as u32,
1781 }
1782 }
1783 EventType::ControllerTouchpadDown => {
1784 let event = raw.ctouchpad;
1785 Event::ControllerTouchpadDown {
1786 timestamp: event.timestamp,
1787 which: event.which as u32,
1788 touchpad: event.touchpad as u32,
1789 finger: event.finger as u32,
1790 x: event.x,
1791 y: event.y,
1792 pressure: event.pressure,
1793 }
1794 }
1795 EventType::ControllerTouchpadMotion => {
1796 let event = raw.ctouchpad;
1797 Event::ControllerTouchpadMotion {
1798 timestamp: event.timestamp,
1799 which: event.which as u32,
1800 touchpad: event.touchpad as u32,
1801 finger: event.finger as u32,
1802 x: event.x,
1803 y: event.y,
1804 pressure: event.pressure,
1805 }
1806 }
1807 EventType::ControllerTouchpadUp => {
1808 let event = raw.ctouchpad;
1809 Event::ControllerTouchpadUp {
1810 timestamp: event.timestamp,
1811 which: event.which as u32,
1812 touchpad: event.touchpad as u32,
1813 finger: event.finger as u32,
1814 x: event.x,
1815 y: event.y,
1816 pressure: event.pressure,
1817 }
1818 }
1819 #[cfg(feature = "hidapi")]
1820 EventType::ControllerSensorUpdated => {
1821 let event = raw.csensor;
1822 Event::ControllerSensorUpdated {
1823 timestamp: event.timestamp,
1824 which: event.which as u32,
1825 sensor: crate::sensor::SensorType::from_ll(event.sensor),
1826 data: event.data,
1827 }
1828 }
1829
1830 EventType::FingerDown => {
1831 let event = raw.tfinger;
1832 Event::FingerDown {
1833 timestamp: event.timestamp,
1834 touch_id: event.touchId,
1835 finger_id: event.fingerId,
1836 x: event.x,
1837 y: event.y,
1838 dx: event.dx,
1839 dy: event.dy,
1840 pressure: event.pressure,
1841 }
1842 }
1843 EventType::FingerUp => {
1844 let event = raw.tfinger;
1845 Event::FingerUp {
1846 timestamp: event.timestamp,
1847 touch_id: event.touchId,
1848 finger_id: event.fingerId,
1849 x: event.x,
1850 y: event.y,
1851 dx: event.dx,
1852 dy: event.dy,
1853 pressure: event.pressure,
1854 }
1855 }
1856 EventType::FingerMotion => {
1857 let event = raw.tfinger;
1858 Event::FingerMotion {
1859 timestamp: event.timestamp,
1860 touch_id: event.touchId,
1861 finger_id: event.fingerId,
1862 x: event.x,
1863 y: event.y,
1864 dx: event.dx,
1865 dy: event.dy,
1866 pressure: event.pressure,
1867 }
1868 }
1869 EventType::DollarGesture => {
1870 let event = raw.dgesture;
1871 Event::DollarGesture {
1872 timestamp: event.timestamp,
1873 touch_id: event.touchId,
1874 gesture_id: event.gestureId,
1875 num_fingers: event.numFingers,
1876 error: event.error,
1877 x: event.x,
1878 y: event.y,
1879 }
1880 }
1881 EventType::DollarRecord => {
1882 let event = raw.dgesture;
1883 Event::DollarRecord {
1884 timestamp: event.timestamp,
1885 touch_id: event.touchId,
1886 gesture_id: event.gestureId,
1887 num_fingers: event.numFingers,
1888 error: event.error,
1889 x: event.x,
1890 y: event.y,
1891 }
1892 }
1893 EventType::MultiGesture => {
1894 let event = raw.mgesture;
1895 Event::MultiGesture {
1896 timestamp: event.timestamp,
1897 touch_id: event.touchId,
1898 d_theta: event.dTheta,
1899 d_dist: event.dDist,
1900 x: event.x,
1901 y: event.y,
1902 num_fingers: event.numFingers,
1903 }
1904 }
1905
1906 EventType::ClipboardUpdate => {
1907 let event = raw.common;
1908 Event::ClipboardUpdate {
1909 timestamp: event.timestamp,
1910 }
1911 }
1912 EventType::DropFile => {
1913 let event = raw.drop;
1914
1915 let buf = CStr::from_ptr(event.file as *const _).to_bytes();
1916 let text = String::from_utf8_lossy(buf).to_string();
1917 sys::SDL_free(event.file as *mut c_void);
1918
1919 Event::DropFile {
1920 timestamp: event.timestamp,
1921 window_id: event.windowID,
1922 filename: text,
1923 }
1924 }
1925 EventType::DropText => {
1926 let event = raw.drop;
1927
1928 let buf = CStr::from_ptr(event.file as *const _).to_bytes();
1929 let text = String::from_utf8_lossy(buf).to_string();
1930 sys::SDL_free(event.file as *mut c_void);
1931
1932 Event::DropText {
1933 timestamp: event.timestamp,
1934 window_id: event.windowID,
1935 filename: text,
1936 }
1937 }
1938 EventType::DropBegin => {
1939 let event = raw.drop;
1940
1941 Event::DropBegin {
1942 timestamp: event.timestamp,
1943 window_id: event.windowID,
1944 }
1945 }
1946 EventType::DropComplete => {
1947 let event = raw.drop;
1948
1949 Event::DropComplete {
1950 timestamp: event.timestamp,
1951 window_id: event.windowID,
1952 }
1953 }
1954 EventType::AudioDeviceAdded => {
1955 let event = raw.adevice;
1956 Event::AudioDeviceAdded {
1957 timestamp: event.timestamp,
1958 which: event.which,
1959 iscapture: event.iscapture != 0,
1961 }
1962 }
1963 EventType::AudioDeviceRemoved => {
1964 let event = raw.adevice;
1965 Event::AudioDeviceRemoved {
1966 timestamp: event.timestamp,
1967 which: event.which,
1968 iscapture: event.iscapture != 0,
1970 }
1971 }
1972
1973 EventType::RenderTargetsReset => Event::RenderTargetsReset {
1974 timestamp: raw.common.timestamp,
1975 },
1976 EventType::RenderDeviceReset => Event::RenderDeviceReset {
1977 timestamp: raw.common.timestamp,
1978 },
1979
1980 EventType::First => panic!("Unused event, EventType::First, was encountered"),
1981 EventType::Last => panic!("Unusable event, EventType::Last, was encountered"),
1982
1983 EventType::User => {
1986 if raw_type < 32_768 {
1987 let event = raw.common;
1990
1991 Event::Unknown {
1992 timestamp: event.timestamp,
1993 type_: event.type_,
1994 }
1995 } else {
1996 let event = raw.user;
1997
1998 Event::User {
1999 timestamp: event.timestamp,
2000 window_id: event.windowID,
2001 type_: raw_type,
2002 code: event.code,
2003 data1: event.data1,
2004 data2: event.data2,
2005 }
2006 }
2007 }
2008 }
2009 } }
2011
2012 pub fn is_user_event(&self) -> bool {
2013 matches!(self, Event::User { .. })
2014 }
2015
2016 pub fn as_user_event_type<T: ::std::any::Any>(&self) -> Option<T> {
2017 use std::any::TypeId;
2018 let type_id = TypeId::of::<Box<T>>();
2019
2020 let (event_id, event_box_ptr) = match *self {
2021 Event::User { type_, data1, .. } => (type_, data1),
2022 _ => return None,
2023 };
2024
2025 let cet = CUSTOM_EVENT_TYPES.lock().unwrap();
2026
2027 let event_type_id = match cet.sdl_id_to_type_id.get(&event_id) {
2028 Some(id) => id,
2029 None => {
2030 panic!("internal error; could not find typeid")
2031 }
2032 };
2033
2034 if &type_id != event_type_id {
2035 return None;
2036 }
2037
2038 let event_box: Box<T> = unsafe { Box::from_raw(event_box_ptr as *mut T) };
2039
2040 Some(*event_box)
2041 }
2042
2043 pub fn is_same_kind_as(&self, other: &Event) -> bool {
2065 match (self, other) {
2066 (Self::Quit { .. }, Self::Quit { .. })
2067 | (Self::AppTerminating { .. }, Self::AppTerminating { .. })
2068 | (Self::AppLowMemory { .. }, Self::AppLowMemory { .. })
2069 | (Self::AppWillEnterBackground { .. }, Self::AppWillEnterBackground { .. })
2070 | (Self::AppDidEnterBackground { .. }, Self::AppDidEnterBackground { .. })
2071 | (Self::AppWillEnterForeground { .. }, Self::AppWillEnterForeground { .. })
2072 | (Self::AppDidEnterForeground { .. }, Self::AppDidEnterForeground { .. })
2073 | (Self::Display { .. }, Self::Display { .. })
2074 | (Self::Window { .. }, Self::Window { .. })
2075 | (Self::KeyDown { .. }, Self::KeyDown { .. })
2076 | (Self::KeyUp { .. }, Self::KeyUp { .. })
2077 | (Self::TextEditing { .. }, Self::TextEditing { .. })
2078 | (Self::TextInput { .. }, Self::TextInput { .. })
2079 | (Self::MouseMotion { .. }, Self::MouseMotion { .. })
2080 | (Self::MouseButtonDown { .. }, Self::MouseButtonDown { .. })
2081 | (Self::MouseButtonUp { .. }, Self::MouseButtonUp { .. })
2082 | (Self::MouseWheel { .. }, Self::MouseWheel { .. })
2083 | (Self::JoyAxisMotion { .. }, Self::JoyAxisMotion { .. })
2084 | (Self::JoyBallMotion { .. }, Self::JoyBallMotion { .. })
2085 | (Self::JoyHatMotion { .. }, Self::JoyHatMotion { .. })
2086 | (Self::JoyButtonDown { .. }, Self::JoyButtonDown { .. })
2087 | (Self::JoyButtonUp { .. }, Self::JoyButtonUp { .. })
2088 | (Self::JoyDeviceAdded { .. }, Self::JoyDeviceAdded { .. })
2089 | (Self::JoyDeviceRemoved { .. }, Self::JoyDeviceRemoved { .. })
2090 | (Self::ControllerAxisMotion { .. }, Self::ControllerAxisMotion { .. })
2091 | (Self::ControllerButtonDown { .. }, Self::ControllerButtonDown { .. })
2092 | (Self::ControllerButtonUp { .. }, Self::ControllerButtonUp { .. })
2093 | (Self::ControllerDeviceAdded { .. }, Self::ControllerDeviceAdded { .. })
2094 | (Self::ControllerDeviceRemoved { .. }, Self::ControllerDeviceRemoved { .. })
2095 | (Self::ControllerDeviceRemapped { .. }, Self::ControllerDeviceRemapped { .. })
2096 | (Self::FingerDown { .. }, Self::FingerDown { .. })
2097 | (Self::FingerUp { .. }, Self::FingerUp { .. })
2098 | (Self::FingerMotion { .. }, Self::FingerMotion { .. })
2099 | (Self::DollarGesture { .. }, Self::DollarGesture { .. })
2100 | (Self::DollarRecord { .. }, Self::DollarRecord { .. })
2101 | (Self::MultiGesture { .. }, Self::MultiGesture { .. })
2102 | (Self::ClipboardUpdate { .. }, Self::ClipboardUpdate { .. })
2103 | (Self::DropFile { .. }, Self::DropFile { .. })
2104 | (Self::DropText { .. }, Self::DropText { .. })
2105 | (Self::DropBegin { .. }, Self::DropBegin { .. })
2106 | (Self::DropComplete { .. }, Self::DropComplete { .. })
2107 | (Self::AudioDeviceAdded { .. }, Self::AudioDeviceAdded { .. })
2108 | (Self::AudioDeviceRemoved { .. }, Self::AudioDeviceRemoved { .. })
2109 | (Self::RenderTargetsReset { .. }, Self::RenderTargetsReset { .. })
2110 | (Self::RenderDeviceReset { .. }, Self::RenderDeviceReset { .. })
2111 | (Self::User { .. }, Self::User { .. })
2112 | (Self::Unknown { .. }, Self::Unknown { .. }) => true,
2113 #[cfg(feature = "hidapi")]
2114 (Self::ControllerSensorUpdated { .. }, Self::ControllerSensorUpdated { .. }) => true,
2115 _ => false,
2116 }
2117 }
2118
2119 pub fn get_timestamp(&self) -> u32 {
2134 *match self {
2135 Self::Quit { timestamp, .. } => timestamp,
2136 Self::AppTerminating { timestamp, .. } => timestamp,
2137 Self::AppLowMemory { timestamp, .. } => timestamp,
2138 Self::AppWillEnterBackground { timestamp, .. } => timestamp,
2139 Self::AppDidEnterBackground { timestamp, .. } => timestamp,
2140 Self::AppWillEnterForeground { timestamp, .. } => timestamp,
2141 Self::AppDidEnterForeground { timestamp, .. } => timestamp,
2142 Self::Display { timestamp, .. } => timestamp,
2143 Self::Window { timestamp, .. } => timestamp,
2144 Self::KeyDown { timestamp, .. } => timestamp,
2145 Self::KeyUp { timestamp, .. } => timestamp,
2146 Self::TextEditing { timestamp, .. } => timestamp,
2147 Self::TextInput { timestamp, .. } => timestamp,
2148 Self::MouseMotion { timestamp, .. } => timestamp,
2149 Self::MouseButtonDown { timestamp, .. } => timestamp,
2150 Self::MouseButtonUp { timestamp, .. } => timestamp,
2151 Self::MouseWheel { timestamp, .. } => timestamp,
2152 Self::JoyAxisMotion { timestamp, .. } => timestamp,
2153 Self::JoyBallMotion { timestamp, .. } => timestamp,
2154 Self::JoyHatMotion { timestamp, .. } => timestamp,
2155 Self::JoyButtonDown { timestamp, .. } => timestamp,
2156 Self::JoyButtonUp { timestamp, .. } => timestamp,
2157 Self::JoyDeviceAdded { timestamp, .. } => timestamp,
2158 Self::JoyDeviceRemoved { timestamp, .. } => timestamp,
2159 Self::ControllerAxisMotion { timestamp, .. } => timestamp,
2160 Self::ControllerButtonDown { timestamp, .. } => timestamp,
2161 Self::ControllerButtonUp { timestamp, .. } => timestamp,
2162 Self::ControllerDeviceAdded { timestamp, .. } => timestamp,
2163 Self::ControllerDeviceRemoved { timestamp, .. } => timestamp,
2164 Self::ControllerDeviceRemapped { timestamp, .. } => timestamp,
2165 Self::ControllerTouchpadDown { timestamp, .. } => timestamp,
2166 Self::ControllerTouchpadMotion { timestamp, .. } => timestamp,
2167 Self::ControllerTouchpadUp { timestamp, .. } => timestamp,
2168 #[cfg(feature = "hidapi")]
2169 Self::ControllerSensorUpdated { timestamp, .. } => timestamp,
2170 Self::FingerDown { timestamp, .. } => timestamp,
2171 Self::FingerUp { timestamp, .. } => timestamp,
2172 Self::FingerMotion { timestamp, .. } => timestamp,
2173 Self::DollarGesture { timestamp, .. } => timestamp,
2174 Self::DollarRecord { timestamp, .. } => timestamp,
2175 Self::MultiGesture { timestamp, .. } => timestamp,
2176 Self::ClipboardUpdate { timestamp, .. } => timestamp,
2177 Self::DropFile { timestamp, .. } => timestamp,
2178 Self::DropText { timestamp, .. } => timestamp,
2179 Self::DropBegin { timestamp, .. } => timestamp,
2180 Self::DropComplete { timestamp, .. } => timestamp,
2181 Self::AudioDeviceAdded { timestamp, .. } => timestamp,
2182 Self::AudioDeviceRemoved { timestamp, .. } => timestamp,
2183 Self::RenderTargetsReset { timestamp, .. } => timestamp,
2184 Self::RenderDeviceReset { timestamp, .. } => timestamp,
2185 Self::User { timestamp, .. } => timestamp,
2186 Self::Unknown { timestamp, .. } => timestamp,
2187 }
2188 }
2189
2190 pub fn get_window_id(&self) -> Option<u32> {
2211 match self {
2212 Self::Window { window_id, .. } => Some(*window_id),
2213 Self::KeyDown { window_id, .. } => Some(*window_id),
2214 Self::KeyUp { window_id, .. } => Some(*window_id),
2215 Self::TextEditing { window_id, .. } => Some(*window_id),
2216 Self::TextInput { window_id, .. } => Some(*window_id),
2217 Self::MouseMotion { window_id, .. } => Some(*window_id),
2218 Self::MouseButtonDown { window_id, .. } => Some(*window_id),
2219 Self::MouseButtonUp { window_id, .. } => Some(*window_id),
2220 Self::MouseWheel { window_id, .. } => Some(*window_id),
2221 Self::DropFile { window_id, .. } => Some(*window_id),
2222 Self::DropText { window_id, .. } => Some(*window_id),
2223 Self::DropBegin { window_id, .. } => Some(*window_id),
2224 Self::DropComplete { window_id, .. } => Some(*window_id),
2225 Self::User { window_id, .. } => Some(*window_id),
2226 _ => None,
2227 }
2228 }
2229
2230 pub fn is_window(&self) -> bool {
2255 matches!(
2256 self,
2257 Self::Quit { .. }
2258 | Self::AppTerminating { .. }
2259 | Self::AppLowMemory { .. }
2260 | Self::AppWillEnterBackground { .. }
2261 | Self::AppDidEnterBackground { .. }
2262 | Self::AppWillEnterForeground { .. }
2263 | Self::AppDidEnterForeground { .. }
2264 | Self::Window { .. }
2265 )
2266 }
2267
2268 pub fn is_keyboard(&self) -> bool {
2292 matches!(self, Self::KeyDown { .. } | Self::KeyUp { .. })
2293 }
2294
2295 pub fn is_text(&self) -> bool {
2315 matches!(self, Self::TextEditing { .. } | Self::TextInput { .. })
2316 }
2317
2318 pub fn is_mouse(&self) -> bool {
2346 matches!(
2347 self,
2348 Self::MouseMotion { .. }
2349 | Self::MouseButtonDown { .. }
2350 | Self::MouseButtonUp { .. }
2351 | Self::MouseWheel { .. }
2352 )
2353 }
2354
2355 pub fn is_touch(&self) -> bool {
2359 const SDL_TOUCH_MOUSEID: u32 = 0xFFFFFFFF;
2361
2362 match self {
2363 Self::MouseMotion {
2364 which: SDL_TOUCH_MOUSEID,
2365 ..
2366 }
2367 | Self::MouseButtonDown {
2368 which: SDL_TOUCH_MOUSEID,
2369 ..
2370 }
2371 | Self::MouseButtonUp {
2372 which: SDL_TOUCH_MOUSEID,
2373 ..
2374 }
2375 | Self::MouseWheel {
2376 which: SDL_TOUCH_MOUSEID,
2377 ..
2378 } => true,
2379 _ => false,
2380 }
2381 }
2382
2383 pub fn is_controller(&self) -> bool {
2402 matches!(
2403 self,
2404 Self::ControllerAxisMotion { .. }
2405 | Self::ControllerButtonDown { .. }
2406 | Self::ControllerButtonUp { .. }
2407 | Self::ControllerDeviceAdded { .. }
2408 | Self::ControllerDeviceRemoved { .. }
2409 | Self::ControllerDeviceRemapped { .. }
2410 )
2411 }
2412
2413 pub fn is_joy(&self) -> bool {
2433 matches!(
2434 self,
2435 Self::JoyAxisMotion { .. }
2436 | Self::JoyBallMotion { .. }
2437 | Self::JoyHatMotion { .. }
2438 | Self::JoyButtonDown { .. }
2439 | Self::JoyButtonUp { .. }
2440 | Self::JoyDeviceAdded { .. }
2441 | Self::JoyDeviceRemoved { .. }
2442 )
2443 }
2444
2445 pub fn is_finger(&self) -> bool {
2470 matches!(
2471 self,
2472 Self::FingerDown { .. } | Self::FingerUp { .. } | Self::FingerMotion { .. }
2473 )
2474 }
2475
2476 pub fn is_dollar(&self) -> bool {
2500 matches!(self, Self::DollarGesture { .. } | Self::DollarRecord { .. })
2501 }
2502
2503 pub fn is_drop(&self) -> bool {
2522 matches!(
2523 self,
2524 Self::DropFile { .. }
2525 | Self::DropText { .. }
2526 | Self::DropBegin { .. }
2527 | Self::DropComplete { .. }
2528 )
2529 }
2530
2531 pub fn is_audio(&self) -> bool {
2551 matches!(
2552 self,
2553 Self::AudioDeviceAdded { .. } | Self::AudioDeviceRemoved { .. }
2554 )
2555 }
2556
2557 pub fn is_render(&self) -> bool {
2575 matches!(
2576 self,
2577 Self::RenderTargetsReset { .. } | Self::RenderDeviceReset { .. }
2578 )
2579 }
2580
2581 pub fn is_user(&self) -> bool {
2604 matches!(self, Self::User { .. })
2605 }
2606
2607 pub fn is_unknown(&self) -> bool {
2626 matches!(self, Self::Unknown { .. })
2627 }
2628}
2629
2630unsafe fn poll_event() -> Option<Event> {
2631 let mut raw = mem::MaybeUninit::uninit();
2632 let has_pending = sys::SDL_PollEvent(raw.as_mut_ptr()) == 1;
2633
2634 if has_pending {
2635 Some(Event::from_ll(raw.assume_init()))
2636 } else {
2637 None
2638 }
2639}
2640
2641unsafe fn wait_event() -> Event {
2642 let mut raw = mem::MaybeUninit::uninit();
2643 let success = sys::SDL_WaitEvent(raw.as_mut_ptr()) == 1;
2644
2645 if success {
2646 Event::from_ll(raw.assume_init())
2647 } else {
2648 panic!("{}", get_error())
2649 }
2650}
2651
2652unsafe fn wait_event_timeout(timeout: u32) -> Option<Event> {
2653 let mut raw = mem::MaybeUninit::uninit();
2654 let success = sys::SDL_WaitEventTimeout(raw.as_mut_ptr(), timeout as c_int) == 1;
2655
2656 if success {
2657 Some(Event::from_ll(raw.assume_init()))
2658 } else {
2659 None
2660 }
2661}
2662
2663impl crate::EventPump {
2664 #[doc(alias = "SDL_EventState")]
2666 pub fn is_event_enabled(&self, event_type: EventType) -> bool {
2667 let result = unsafe { sys::SDL_EventState(event_type as u32, sys::SDL_QUERY) };
2668
2669 result != sys::SDL_DISABLE as u8
2670 }
2671
2672 #[doc(alias = "SDL_EventState")]
2674 pub fn enable_event(&mut self, event_type: EventType) -> bool {
2675 let result = unsafe { sys::SDL_EventState(event_type as u32, sys::SDL_ENABLE as c_int) };
2676
2677 result != sys::SDL_DISABLE as u8
2678 }
2679
2680 #[doc(alias = "SDL_EventState")]
2682 pub fn disable_event(&mut self, event_type: EventType) -> bool {
2683 let result = unsafe { sys::SDL_EventState(event_type as u32, sys::SDL_DISABLE as c_int) };
2684
2685 result != sys::SDL_DISABLE as u8
2686 }
2687
2688 pub fn poll_event(&mut self) -> Option<Event> {
2692 unsafe { poll_event() }
2693 }
2694
2695 pub fn poll_iter(&mut self) -> EventPollIterator {
2712 EventPollIterator {
2713 _marker: PhantomData,
2714 }
2715 }
2716
2717 #[doc(alias = "SDL_PumpEvents")]
2719 pub fn pump_events(&mut self) {
2720 unsafe {
2721 sys::SDL_PumpEvents();
2722 };
2723 }
2724
2725 pub fn wait_event(&mut self) -> Event {
2727 unsafe { wait_event() }
2728 }
2729
2730 pub fn wait_event_timeout(&mut self, timeout: u32) -> Option<Event> {
2732 unsafe { wait_event_timeout(timeout) }
2733 }
2734
2735 pub fn wait_iter(&mut self) -> EventWaitIterator {
2739 EventWaitIterator {
2740 _marker: PhantomData,
2741 }
2742 }
2743
2744 pub fn wait_timeout_iter(&mut self, timeout: u32) -> EventWaitTimeoutIterator {
2749 EventWaitTimeoutIterator {
2750 _marker: PhantomData,
2751 timeout,
2752 }
2753 }
2754
2755 #[inline]
2756 pub fn keyboard_state(&self) -> crate::keyboard::KeyboardState {
2757 crate::keyboard::KeyboardState::new(self)
2758 }
2759
2760 #[inline]
2761 pub fn mouse_state(&self) -> crate::mouse::MouseState {
2762 crate::mouse::MouseState::new(self)
2763 }
2764
2765 #[inline]
2766 pub fn relative_mouse_state(&self) -> crate::mouse::RelativeMouseState {
2767 crate::mouse::RelativeMouseState::new(self)
2768 }
2769}
2770
2771#[must_use = "iterators are lazy and do nothing unless consumed"]
2773pub struct EventPollIterator<'a> {
2774 _marker: PhantomData<&'a ()>,
2775}
2776
2777impl<'a> Iterator for EventPollIterator<'a> {
2778 type Item = Event;
2779
2780 fn next(&mut self) -> Option<Event> {
2781 unsafe { poll_event() }
2782 }
2783}
2784
2785#[must_use = "iterators are lazy and do nothing unless consumed"]
2787pub struct EventWaitIterator<'a> {
2788 _marker: PhantomData<&'a ()>,
2789}
2790
2791impl<'a> Iterator for EventWaitIterator<'a> {
2792 type Item = Event;
2793 fn next(&mut self) -> Option<Event> {
2794 unsafe { Some(wait_event()) }
2795 }
2796}
2797
2798#[must_use = "iterators are lazy and do nothing unless consumed"]
2800pub struct EventWaitTimeoutIterator<'a> {
2801 _marker: PhantomData<&'a ()>,
2802 timeout: u32,
2803}
2804
2805impl<'a> Iterator for EventWaitTimeoutIterator<'a> {
2806 type Item = Event;
2807 fn next(&mut self) -> Option<Event> {
2808 unsafe { wait_event_timeout(self.timeout) }
2809 }
2810}
2811
2812pub struct EventSender {
2814 _priv: (),
2815}
2816
2817impl EventSender {
2818 #[doc(alias = "SDL_PushEvent")]
2820 pub fn push_event(&self, event: Event) -> Result<(), String> {
2821 match event.to_ll() {
2822 Some(mut raw_event) => {
2823 let ok = unsafe { sys::SDL_PushEvent(&mut raw_event) == 1 };
2824 if ok {
2825 Ok(())
2826 } else {
2827 Err(get_error())
2828 }
2829 }
2830 None => Err("Cannot push unsupported event type to the queue".to_owned()),
2831 }
2832 }
2833
2834 pub fn push_custom_event<T: ::std::any::Any>(&self, event: T) -> Result<(), String> {
2864 use std::any::TypeId;
2865 let cet = CUSTOM_EVENT_TYPES.lock().unwrap();
2866 let type_id = TypeId::of::<Box<T>>();
2867
2868 let user_event_id = *match cet.type_id_to_sdl_id.get(&type_id) {
2869 Some(id) => id,
2870 None => {
2871 return Err("Type is not registered as a custom event type!".to_owned());
2872 }
2873 };
2874
2875 let event_box = Box::new(event);
2876 let event = Event::User {
2877 timestamp: 0,
2878 window_id: 0,
2879 type_: user_event_id,
2880 code: 0,
2881 data1: Box::into_raw(event_box) as *mut c_void,
2882 data2: ::std::ptr::null_mut(),
2883 };
2884 drop(cet);
2885
2886 self.push_event(event)?;
2887
2888 Ok(())
2889 }
2890}
2891
2892pub trait EventWatchCallback {
2894 fn callback(&mut self, event: Event);
2895}
2896
2897pub struct EventWatch<'a, CB: EventWatchCallback + 'a> {
2901 activated: bool,
2902 callback: Box<CB>,
2903 _phantom: PhantomData<&'a CB>,
2904}
2905
2906impl<'a, CB: EventWatchCallback + 'a> EventWatch<'a, CB> {
2907 fn add(callback: CB) -> EventWatch<'a, CB> {
2908 let f = Box::new(callback);
2909 let mut watch = EventWatch {
2910 activated: false,
2911 callback: f,
2912 _phantom: PhantomData,
2913 };
2914 watch.activate();
2915 watch
2916 }
2917
2918 pub fn activate(&mut self) {
2921 if !self.activated {
2922 self.activated = true;
2923 unsafe { sys::SDL_AddEventWatch(self.filter(), self.callback()) };
2924 }
2925 }
2926
2927 pub fn deactivate(&mut self) {
2930 if self.activated {
2931 self.activated = false;
2932 unsafe { sys::SDL_DelEventWatch(self.filter(), self.callback()) };
2933 }
2934 }
2935
2936 pub fn activated(&self) -> bool {
2938 self.activated
2939 }
2940
2941 pub fn set_activated(&mut self, activate: bool) {
2943 if activate {
2944 self.activate();
2945 } else {
2946 self.deactivate();
2947 }
2948 }
2949
2950 fn filter(&self) -> SDL_EventFilter {
2951 Some(event_callback_marshall::<CB> as _)
2952 }
2953
2954 fn callback(&mut self) -> *mut c_void {
2955 &mut *self.callback as *mut _ as *mut c_void
2956 }
2957}
2958
2959impl<'a, CB: EventWatchCallback + 'a> Drop for EventWatch<'a, CB> {
2960 fn drop(&mut self) {
2961 self.deactivate();
2962 }
2963}
2964
2965extern "C" fn event_callback_marshall<CB: EventWatchCallback>(
2966 user_data: *mut c_void,
2967 event: *mut sdl2_sys::SDL_Event,
2968) -> i32 {
2969 let f: &mut CB = unsafe { &mut *(user_data as *mut _) };
2970 let event = Event::from_ll(unsafe { *event });
2971 f.callback(event);
2972 0
2973}
2974
2975impl<F: FnMut(Event)> EventWatchCallback for F {
2976 fn callback(&mut self, event: Event) {
2977 self(event)
2978 }
2979}
2980
2981#[cfg(test)]
2982mod test {
2983 use super::super::controller::{Axis, Button};
2984 use super::super::joystick::HatState;
2985 use super::super::keyboard::{Keycode, Mod, Scancode};
2986 use super::super::mouse::{MouseButton, MouseState, MouseWheelDirection};
2987 use super::super::video::Orientation;
2988 use super::DisplayEvent;
2989 use super::Event;
2990 use super::WindowEvent;
2991
2992 #[test]
2995 fn test_to_from_ll() {
2996 {
2997 let e = Event::Quit { timestamp: 0 };
2998 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
2999 assert_eq!(e, e2);
3000 }
3001 {
3002 let e = Event::Display {
3003 timestamp: 0,
3004 display_index: 1,
3005 display_event: DisplayEvent::Orientation(Orientation::LandscapeFlipped),
3006 };
3007 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3008 assert_eq!(e, e2);
3009 }
3010 {
3011 let e = Event::Window {
3012 timestamp: 0,
3013 window_id: 0,
3014 win_event: WindowEvent::Resized(1, 2),
3015 };
3016 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3017 assert_eq!(e, e2);
3018 }
3019 {
3020 let e = Event::KeyDown {
3021 timestamp: 0,
3022 window_id: 1,
3023 keycode: None,
3024 scancode: Some(Scancode::Q),
3025 keymod: Mod::all(),
3026 repeat: false,
3027 };
3028 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3029 assert_eq!(e, e2);
3030 }
3031 {
3032 let e = Event::KeyUp {
3033 timestamp: 123,
3034 window_id: 0,
3035 keycode: Some(Keycode::R),
3036 scancode: Some(Scancode::R),
3037 keymod: Mod::empty(),
3038 repeat: true,
3039 };
3040 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3041 assert_eq!(e, e2);
3042 }
3043 {
3044 let e = Event::MouseMotion {
3045 timestamp: 0,
3046 window_id: 0,
3047 which: 1,
3048 mousestate: MouseState::from_sdl_state(1),
3049 x: 3,
3050 y: 91,
3051 xrel: -1,
3052 yrel: 43,
3053 };
3054 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3055 assert_eq!(e, e2);
3056 }
3057 {
3058 let e = Event::MouseButtonDown {
3059 timestamp: 5634,
3060 window_id: 2,
3061 which: 0,
3062 mouse_btn: MouseButton::Left,
3063 clicks: 1,
3064 x: 543,
3065 y: 345,
3066 };
3067 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3068 assert_eq!(e, e2);
3069 }
3070 {
3071 let e = Event::MouseButtonUp {
3072 timestamp: 0,
3073 window_id: 2,
3074 which: 0,
3075 mouse_btn: MouseButton::Left,
3076 clicks: 1,
3077 x: 543,
3078 y: 345,
3079 };
3080 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3081 assert_eq!(e, e2);
3082 }
3083 {
3084 let e = Event::MouseWheel {
3085 timestamp: 1,
3086 window_id: 0,
3087 which: 32,
3088 x: 23,
3089 y: 91,
3090 direction: MouseWheelDirection::Flipped,
3091 precise_x: 1.6,
3092 precise_y: 2.7,
3093 mouse_x: 0,
3094 mouse_y: 5,
3095 };
3096 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3097 assert_eq!(e, e2);
3098 }
3099 {
3100 let e = Event::JoyAxisMotion {
3101 timestamp: 0,
3102 which: 1,
3103 axis_idx: 1,
3104 value: 12,
3105 };
3106 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3107 assert_eq!(e, e2);
3108 }
3109 {
3110 let e = Event::JoyBallMotion {
3111 timestamp: 0,
3112 which: 0,
3113 ball_idx: 1,
3114 xrel: 123,
3115 yrel: 321,
3116 };
3117 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3118 assert_eq!(e, e2);
3119 }
3120 {
3121 let e = Event::JoyHatMotion {
3122 timestamp: 0,
3123 which: 3,
3124 hat_idx: 1,
3125 state: HatState::Left,
3126 };
3127 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3128 assert_eq!(e, e2);
3129 }
3130 {
3131 let e = Event::JoyButtonDown {
3132 timestamp: 0,
3133 which: 0,
3134 button_idx: 3,
3135 };
3136 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3137 assert_eq!(e, e2);
3138 }
3139 {
3140 let e = Event::JoyButtonUp {
3141 timestamp: 9876,
3142 which: 1,
3143 button_idx: 2,
3144 };
3145 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3146 assert_eq!(e, e2);
3147 }
3148 {
3149 let e = Event::JoyDeviceAdded {
3150 timestamp: 0,
3151 which: 1,
3152 };
3153 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3154 assert_eq!(e, e2);
3155 }
3156 {
3157 let e = Event::JoyDeviceRemoved {
3158 timestamp: 0,
3159 which: 2,
3160 };
3161 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3162 assert_eq!(e, e2);
3163 }
3164 {
3165 let e = Event::ControllerAxisMotion {
3166 timestamp: 53,
3167 which: 0,
3168 axis: Axis::LeftX,
3169 value: 3,
3170 };
3171 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3172 assert_eq!(e, e2);
3173 }
3174 {
3175 let e = Event::ControllerButtonDown {
3176 timestamp: 0,
3177 which: 1,
3178 button: Button::Guide,
3179 };
3180 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3181 assert_eq!(e, e2);
3182 }
3183 {
3184 let e = Event::ControllerButtonUp {
3185 timestamp: 654214,
3186 which: 0,
3187 button: Button::DPadRight,
3188 };
3189 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3190 assert_eq!(e, e2);
3191 }
3192 {
3193 let e = Event::ControllerDeviceAdded {
3194 timestamp: 543,
3195 which: 3,
3196 };
3197 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3198 assert_eq!(e, e2);
3199 }
3200 {
3201 let e = Event::ControllerDeviceRemoved {
3202 timestamp: 555,
3203 which: 3,
3204 };
3205 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3206 assert_eq!(e, e2);
3207 }
3208 {
3209 let e = Event::ControllerDeviceRemapped {
3210 timestamp: 654,
3211 which: 0,
3212 };
3213 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3214 assert_eq!(e, e2);
3215 }
3216 }
3217
3218 #[test]
3219 fn test_from_ll_keymod_keydown_unknown_bits() {
3220 let mut raw_event = Event::KeyDown {
3221 timestamp: 0,
3222 window_id: 1,
3223 keycode: None,
3224 scancode: Some(Scancode::Q),
3225 keymod: Mod::empty(),
3226 repeat: false,
3227 }
3228 .to_ll()
3229 .unwrap();
3230
3231 raw_event.key.keysym.mod_ = 0xffff;
3233
3234 if let Event::KeyDown { keymod, .. } = Event::from_ll(raw_event) {
3235 assert_eq!(keymod, Mod::all());
3236 } else {
3237 panic!()
3238 }
3239 }
3240
3241 #[test]
3242 fn test_from_ll_keymod_keyup_unknown_bits() {
3243 let mut raw_event = Event::KeyUp {
3244 timestamp: 0,
3245 window_id: 1,
3246 keycode: None,
3247 scancode: Some(Scancode::Q),
3248 keymod: Mod::empty(),
3249 repeat: false,
3250 }
3251 .to_ll()
3252 .unwrap();
3253
3254 raw_event.key.keysym.mod_ = 0xffff;
3256
3257 if let Event::KeyUp { keymod, .. } = Event::from_ll(raw_event) {
3258 assert_eq!(keymod, Mod::all());
3259 } else {
3260 panic!()
3261 }
3262 }
3263}