1use std::borrow::ToOwned;
4use std::collections::HashMap;
5use std::convert::TryFrom;
6use std::ffi::CStr;
7use std::iter::FromIterator;
8use std::marker::PhantomData;
9use std::mem;
10use std::mem::transmute;
11use std::ptr;
12use std::sync::Mutex;
13
14use libc::c_int;
15use libc::c_void;
16
17use crate::controller;
18use crate::controller::{Axis, Button};
19use crate::get_error;
20use crate::joystick;
21use crate::joystick::HatState;
22use crate::keyboard;
23use crate::keyboard::Keycode;
24use crate::keyboard::Mod;
25use crate::keyboard::Scancode;
26use crate::mouse;
27use crate::mouse::{MouseButton, MouseState, MouseWheelDirection};
28use crate::sys;
29use crate::sys::SDL_EventFilter;
30use crate::sys::SDL_EventType;
31use crate::video::Orientation;
32
33struct CustomEventTypeMaps {
34 sdl_id_to_type_id: HashMap<u32, ::std::any::TypeId>,
35 type_id_to_sdl_id: HashMap<::std::any::TypeId, u32>,
36}
37
38impl CustomEventTypeMaps {
39 fn new() -> Self {
40 CustomEventTypeMaps {
41 sdl_id_to_type_id: HashMap::new(),
42 type_id_to_sdl_id: HashMap::new(),
43 }
44 }
45}
46
47lazy_static! {
48 static ref CUSTOM_EVENT_TYPES: Mutex<CustomEventTypeMaps> =
49 Mutex::new(CustomEventTypeMaps::new());
50}
51
52impl crate::EventSubsystem {
53 #[doc(alias = "SDL_FlushEvent")]
55 pub fn flush_event(&self, event_type: EventType) {
56 unsafe { sys::SDL_FlushEvent(event_type as u32) };
57 }
58
59 #[doc(alias = "SDL_FlushEvents")]
61 pub fn flush_events(&self, min_type: u32, max_type: u32) {
62 unsafe { sys::SDL_FlushEvents(min_type, max_type) };
63 }
64
65 #[doc(alias = "SDL_PeepEvents")]
86 pub fn peek_events<B>(&self, max_amount: u32) -> B
87 where
88 B: FromIterator<Event>,
89 {
90 unsafe {
91 let mut events = Vec::with_capacity(max_amount as usize);
92
93 let result = {
94 let events_ptr = events.as_mut_ptr();
95
96 sys::SDL_PeepEvents(
97 events_ptr,
98 max_amount as c_int,
99 sys::SDL_eventaction::SDL_PEEKEVENT,
100 SDL_EventType::SDL_FIRSTEVENT as u32,
101 SDL_EventType::SDL_LASTEVENT as u32,
102 )
103 };
104
105 if result < 0 {
106 panic!("{}", get_error());
108 } else {
109 events.set_len(result as usize);
110
111 events.into_iter().map(Event::from_ll).collect()
112 }
113 }
114 }
115
116 pub fn push_event(&self, event: Event) -> Result<(), String> {
118 self.event_sender().push_event(event)
119 }
120
121 #[inline(always)]
149 pub unsafe fn register_event(&self) -> Result<u32, String> {
150 Ok(*self.register_events(1)?.first().unwrap())
151 }
152
153 pub unsafe fn register_events(&self, nr: u32) -> Result<Vec<u32>, String> {
157 let result = sys::SDL_RegisterEvents(nr as ::libc::c_int);
158 const ERR_NR: u32 = u32::MAX - 1;
159
160 match result {
161 ERR_NR => Err("No more user events can be created; SDL_LASTEVENT reached".to_owned()),
162 _ => {
163 let event_ids = (result..(result + nr)).collect();
164 Ok(event_ids)
165 }
166 }
167 }
168
169 #[inline(always)]
176 pub fn register_custom_event<T: ::std::any::Any>(&self) -> Result<(), String> {
177 use std::any::TypeId;
178 let event_id = *(unsafe { self.register_events(1) })?.first().unwrap();
179 let mut cet = CUSTOM_EVENT_TYPES.lock().unwrap();
180 let type_id = TypeId::of::<Box<T>>();
181
182 if cet.type_id_to_sdl_id.contains_key(&type_id) {
183 return Err("The same event type can not be registered twice!".to_owned());
184 }
185
186 cet.sdl_id_to_type_id.insert(event_id, type_id);
187 cet.type_id_to_sdl_id.insert(type_id, event_id);
188
189 Ok(())
190 }
191
192 pub fn push_custom_event<T: ::std::any::Any>(&self, event: T) -> Result<(), String> {
221 self.event_sender().push_custom_event(event)
222 }
223
224 pub fn event_sender(&self) -> EventSender {
229 EventSender { _priv: () }
230 }
231
232 pub fn add_event_watch<'a, CB: EventWatchCallback + 'a>(
250 &self,
251 callback: CB,
252 ) -> EventWatch<'a, CB> {
253 EventWatch::add(callback)
254 }
255}
256
257#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
259#[repr(u32)]
260pub enum EventType {
261 First = SDL_EventType::SDL_FIRSTEVENT as u32,
262
263 Quit = SDL_EventType::SDL_QUIT as u32,
264 AppTerminating = SDL_EventType::SDL_APP_TERMINATING as u32,
265 AppLowMemory = SDL_EventType::SDL_APP_LOWMEMORY as u32,
266 AppWillEnterBackground = SDL_EventType::SDL_APP_WILLENTERBACKGROUND as u32,
267 AppDidEnterBackground = SDL_EventType::SDL_APP_DIDENTERBACKGROUND as u32,
268 AppWillEnterForeground = SDL_EventType::SDL_APP_WILLENTERFOREGROUND as u32,
269 AppDidEnterForeground = SDL_EventType::SDL_APP_DIDENTERFOREGROUND as u32,
270
271 Display = SDL_EventType::SDL_DISPLAYEVENT as u32,
272 Window = SDL_EventType::SDL_WINDOWEVENT as u32,
273 KeyDown = SDL_EventType::SDL_KEYDOWN as u32,
275 KeyUp = SDL_EventType::SDL_KEYUP as u32,
276 TextEditing = SDL_EventType::SDL_TEXTEDITING as u32,
277 TextInput = SDL_EventType::SDL_TEXTINPUT as u32,
278
279 MouseMotion = SDL_EventType::SDL_MOUSEMOTION as u32,
280 MouseButtonDown = SDL_EventType::SDL_MOUSEBUTTONDOWN as u32,
281 MouseButtonUp = SDL_EventType::SDL_MOUSEBUTTONUP as u32,
282 MouseWheel = SDL_EventType::SDL_MOUSEWHEEL as u32,
283
284 JoyAxisMotion = SDL_EventType::SDL_JOYAXISMOTION as u32,
285 JoyBallMotion = SDL_EventType::SDL_JOYBALLMOTION as u32,
286 JoyHatMotion = SDL_EventType::SDL_JOYHATMOTION as u32,
287 JoyButtonDown = SDL_EventType::SDL_JOYBUTTONDOWN as u32,
288 JoyButtonUp = SDL_EventType::SDL_JOYBUTTONUP as u32,
289 JoyDeviceAdded = SDL_EventType::SDL_JOYDEVICEADDED as u32,
290 JoyDeviceRemoved = SDL_EventType::SDL_JOYDEVICEREMOVED as u32,
291
292 ControllerAxisMotion = SDL_EventType::SDL_CONTROLLERAXISMOTION as u32,
293 ControllerButtonDown = SDL_EventType::SDL_CONTROLLERBUTTONDOWN as u32,
294 ControllerButtonUp = SDL_EventType::SDL_CONTROLLERBUTTONUP as u32,
295 ControllerDeviceAdded = SDL_EventType::SDL_CONTROLLERDEVICEADDED as u32,
296 ControllerDeviceRemoved = SDL_EventType::SDL_CONTROLLERDEVICEREMOVED as u32,
297 ControllerDeviceRemapped = SDL_EventType::SDL_CONTROLLERDEVICEREMAPPED as u32,
298 ControllerTouchpadDown = SDL_EventType::SDL_CONTROLLERTOUCHPADDOWN as u32,
299 ControllerTouchpadMotion = SDL_EventType::SDL_CONTROLLERTOUCHPADMOTION as u32,
300 ControllerTouchpadUp = SDL_EventType::SDL_CONTROLLERTOUCHPADUP as u32,
301 #[cfg(feature = "hidapi")]
302 ControllerSensorUpdated = SDL_EventType::SDL_CONTROLLERSENSORUPDATE as u32,
303
304 FingerDown = SDL_EventType::SDL_FINGERDOWN as u32,
305 FingerUp = SDL_EventType::SDL_FINGERUP as u32,
306 FingerMotion = SDL_EventType::SDL_FINGERMOTION as u32,
307 DollarGesture = SDL_EventType::SDL_DOLLARGESTURE as u32,
308 DollarRecord = SDL_EventType::SDL_DOLLARRECORD as u32,
309 MultiGesture = SDL_EventType::SDL_MULTIGESTURE as u32,
310
311 ClipboardUpdate = SDL_EventType::SDL_CLIPBOARDUPDATE as u32,
312 DropFile = SDL_EventType::SDL_DROPFILE as u32,
313 DropText = SDL_EventType::SDL_DROPTEXT as u32,
314 DropBegin = SDL_EventType::SDL_DROPBEGIN as u32,
315 DropComplete = SDL_EventType::SDL_DROPCOMPLETE as u32,
316
317 AudioDeviceAdded = SDL_EventType::SDL_AUDIODEVICEADDED as u32,
318 AudioDeviceRemoved = SDL_EventType::SDL_AUDIODEVICEREMOVED as u32,
319
320 RenderTargetsReset = SDL_EventType::SDL_RENDER_TARGETS_RESET as u32,
321 RenderDeviceReset = SDL_EventType::SDL_RENDER_DEVICE_RESET as u32,
322
323 LocaleChanged = SDL_EventType::SDL_LOCALECHANGED 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 match n {
337 x if x == SDL_FIRSTEVENT as u32 => Ok(First),
338
339 x if x == SDL_QUIT as u32 => Ok(Quit),
340 x if x == SDL_APP_TERMINATING as u32 => Ok(AppTerminating),
341 x if x == SDL_APP_LOWMEMORY as u32 => Ok(AppLowMemory),
342 x if x == SDL_APP_WILLENTERBACKGROUND as u32 => Ok(AppWillEnterBackground),
343 x if x == SDL_APP_DIDENTERBACKGROUND as u32 => Ok(AppDidEnterBackground),
344 x if x == SDL_APP_WILLENTERFOREGROUND as u32 => Ok(AppWillEnterForeground),
345 x if x == SDL_APP_DIDENTERFOREGROUND as u32 => Ok(AppDidEnterForeground),
346
347 x if x == SDL_DISPLAYEVENT as u32 => Ok(Display),
348 x if x == SDL_WINDOWEVENT as u32 => Ok(Window),
349
350 x if x == SDL_KEYDOWN as u32 => Ok(KeyDown),
351 x if x == SDL_KEYUP as u32 => Ok(KeyUp),
352 x if x == SDL_TEXTEDITING as u32 => Ok(TextEditing),
353 x if x == SDL_TEXTINPUT as u32 => Ok(TextInput),
354
355 x if x == SDL_MOUSEMOTION as u32 => Ok(MouseMotion),
356 x if x == SDL_MOUSEBUTTONDOWN as u32 => Ok(MouseButtonDown),
357 x if x == SDL_MOUSEBUTTONUP as u32 => Ok(MouseButtonUp),
358 x if x == SDL_MOUSEWHEEL as u32 => Ok(MouseWheel),
359
360 x if x == SDL_JOYAXISMOTION as u32 => Ok(JoyAxisMotion),
361 x if x == SDL_JOYBALLMOTION as u32 => Ok(JoyBallMotion),
362 x if x == SDL_JOYHATMOTION as u32 => Ok(JoyHatMotion),
363 x if x == SDL_JOYBUTTONDOWN as u32 => Ok(JoyButtonDown),
364 x if x == SDL_JOYBUTTONUP as u32 => Ok(JoyButtonUp),
365 x if x == SDL_JOYDEVICEADDED as u32 => Ok(JoyDeviceAdded),
366 x if x == SDL_JOYDEVICEREMOVED as u32 => Ok(JoyDeviceRemoved),
367
368 x if x == SDL_CONTROLLERAXISMOTION as u32 => Ok(ControllerAxisMotion),
369 x if x == SDL_CONTROLLERBUTTONDOWN as u32 => Ok(ControllerButtonDown),
370 x if x == SDL_CONTROLLERBUTTONUP as u32 => Ok(ControllerButtonUp),
371 x if x == SDL_CONTROLLERDEVICEADDED as u32 => Ok(ControllerDeviceAdded),
372 x if x == SDL_CONTROLLERDEVICEREMOVED as u32 => Ok(ControllerDeviceRemoved),
373 x if x == SDL_CONTROLLERDEVICEREMAPPED as u32 => Ok(ControllerDeviceRemapped),
374 x if x == SDL_CONTROLLERTOUCHPADDOWN as u32 => Ok(ControllerTouchpadDown),
375 x if x == SDL_CONTROLLERTOUCHPADMOTION as u32 => Ok(ControllerTouchpadMotion),
376 x if x == SDL_CONTROLLERTOUCHPADUP as u32 => Ok(ControllerTouchpadUp),
377 #[cfg(feature = "hidapi")]
378 x if x == SDL_CONTROLLERSENSORUPDATE as u32 => Ok(ControllerSensorUpdated),
379
380 x if x == SDL_FINGERDOWN as u32 => Ok(FingerDown),
381 x if x == SDL_FINGERUP as u32 => Ok(FingerUp),
382 x if x == SDL_FINGERMOTION as u32 => Ok(FingerMotion),
383 x if x == SDL_DOLLARGESTURE as u32 => Ok(DollarGesture),
384 x if x == SDL_DOLLARRECORD as u32 => Ok(DollarRecord),
385 x if x == SDL_MULTIGESTURE as u32 => Ok(MultiGesture),
386
387 x if x == SDL_CLIPBOARDUPDATE as u32 => Ok(ClipboardUpdate),
388 x if x == SDL_DROPFILE as u32 => Ok(DropFile),
389 x if x == SDL_DROPTEXT as u32 => Ok(DropText),
390 x if x == SDL_DROPBEGIN as u32 => Ok(DropBegin),
391 x if x == SDL_DROPCOMPLETE as u32 => Ok(DropComplete),
392
393 x if x == SDL_AUDIODEVICEADDED as u32 => Ok(AudioDeviceAdded),
394 x if x == SDL_AUDIODEVICEREMOVED as u32 => Ok(AudioDeviceRemoved),
395
396 x if x == SDL_RENDER_TARGETS_RESET as u32 => Ok(RenderTargetsReset),
397 x if x == SDL_RENDER_DEVICE_RESET as u32 => Ok(RenderDeviceReset),
398
399 x if x == SDL_USEREVENT as u32 => Ok(User),
400 x if x == SDL_LASTEVENT as u32 => Ok(Last),
401
402 _ => 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 LocaleChanged {
903 timestamp: u32,
904 },
905
906 User {
907 timestamp: u32,
908 window_id: u32,
909 type_: u32,
910 code: i32,
911 data1: *mut c_void,
912 data2: *mut c_void,
913 },
914
915 Unknown {
916 timestamp: u32,
917 type_: u32,
918 },
919}
920
921unsafe impl Send for Event {}
925
926unsafe impl Sync for Event {}
930
931#[doc(alias = "SDL_Keysym")]
934fn mk_keysym<S, K>(scancode: S, keycode: K, keymod: Mod) -> sys::SDL_Keysym
935where
936 S: Into<Option<Scancode>>,
937 K: Into<Option<Keycode>>,
938{
939 let scancode = scancode
940 .into()
941 .map(|sc| unsafe { transmute::<u32, sys::SDL_Scancode>(sc as u32) })
942 .unwrap_or(sys::SDL_Scancode::SDL_SCANCODE_UNKNOWN);
943 let keycode = keycode
944 .into()
945 .map(|kc| kc.into())
946 .unwrap_or(sys::SDL_KeyCode::SDLK_UNKNOWN as i32);
947 let keymod = keymod.bits();
948 sys::SDL_Keysym {
949 scancode,
950 sym: keycode,
951 mod_: keymod,
952 unused: 0,
953 }
954}
955
956impl Event {
960 fn to_ll(&self) -> Option<sys::SDL_Event> {
961 let mut ret = mem::MaybeUninit::uninit();
962 match *self {
963 Event::User {
964 window_id,
965 type_,
966 code,
967 data1,
968 data2,
969 timestamp,
970 } => {
971 let event = sys::SDL_UserEvent {
972 type_,
973 timestamp,
974 windowID: window_id,
975 code,
976 data1,
977 data2,
978 };
979 unsafe {
980 ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_UserEvent, 1);
981 Some(ret.assume_init())
982 }
983 }
984
985 Event::Quit { timestamp } => {
986 let event = sys::SDL_QuitEvent {
987 type_: SDL_EventType::SDL_QUIT as u32,
988 timestamp,
989 };
990 unsafe {
991 ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_QuitEvent, 1);
992 Some(ret.assume_init())
993 }
994 }
995
996 Event::Display {
997 timestamp,
998 display_index,
999 display_event,
1000 } => {
1001 let (display_event_id, data1) = display_event.to_ll();
1002 let event = sys::SDL_DisplayEvent {
1003 type_: SDL_EventType::SDL_DISPLAYEVENT as u32,
1004 timestamp,
1005 display: display_index as u32,
1006 event: display_event_id,
1007 padding1: 0,
1008 padding2: 0,
1009 padding3: 0,
1010 data1,
1011 };
1012 unsafe {
1013 ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_DisplayEvent, 1);
1014 Some(ret.assume_init())
1015 }
1016 }
1017
1018 Event::Window {
1019 timestamp,
1020 window_id,
1021 win_event,
1022 } => {
1023 let (win_event_id, data1, data2) = win_event.to_ll();
1024 let event = sys::SDL_WindowEvent {
1025 type_: SDL_EventType::SDL_WINDOWEVENT as u32,
1026 timestamp,
1027 windowID: window_id,
1028 event: win_event_id,
1029 padding1: 0,
1030 padding2: 0,
1031 padding3: 0,
1032 data1,
1033 data2,
1034 };
1035 unsafe {
1036 ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_WindowEvent, 1);
1037 Some(ret.assume_init())
1038 }
1039 }
1040
1041 Event::KeyDown {
1042 timestamp,
1043 window_id,
1044 keycode,
1045 scancode,
1046 keymod,
1047 repeat,
1048 } => {
1049 let keysym = mk_keysym(scancode, keycode, keymod);
1050 let event = sys::SDL_KeyboardEvent {
1051 type_: SDL_EventType::SDL_KEYDOWN as u32,
1052 timestamp,
1053 windowID: window_id,
1054 state: sys::SDL_PRESSED as u8,
1055 repeat: repeat as u8,
1056 padding2: 0,
1057 padding3: 0,
1058 keysym,
1059 };
1060 unsafe {
1061 ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_KeyboardEvent, 1);
1062 Some(ret.assume_init())
1063 }
1064 }
1065 Event::KeyUp {
1066 timestamp,
1067 window_id,
1068 keycode,
1069 scancode,
1070 keymod,
1071 repeat,
1072 } => {
1073 let keysym = mk_keysym(scancode, keycode, keymod);
1074 let event = sys::SDL_KeyboardEvent {
1075 type_: SDL_EventType::SDL_KEYUP as u32,
1076 timestamp,
1077 windowID: window_id,
1078 state: sys::SDL_RELEASED as u8,
1079 repeat: repeat as u8,
1080 padding2: 0,
1081 padding3: 0,
1082 keysym,
1083 };
1084 unsafe {
1085 ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_KeyboardEvent, 1);
1086 Some(ret.assume_init())
1087 }
1088 }
1089 Event::MouseMotion {
1090 timestamp,
1091 window_id,
1092 which,
1093 mousestate,
1094 x,
1095 y,
1096 xrel,
1097 yrel,
1098 } => {
1099 let state = mousestate.to_sdl_state();
1100 let event = sys::SDL_MouseMotionEvent {
1101 type_: SDL_EventType::SDL_MOUSEMOTION as u32,
1102 timestamp,
1103 windowID: window_id,
1104 which,
1105 state,
1106 x,
1107 y,
1108 xrel,
1109 yrel,
1110 };
1111 unsafe {
1112 ptr::copy(
1113 &event,
1114 ret.as_mut_ptr() as *mut sys::SDL_MouseMotionEvent,
1115 1,
1116 );
1117 Some(ret.assume_init())
1118 }
1119 }
1120 Event::MouseButtonDown {
1121 timestamp,
1122 window_id,
1123 which,
1124 mouse_btn,
1125 clicks,
1126 x,
1127 y,
1128 } => {
1129 let event = sys::SDL_MouseButtonEvent {
1130 type_: SDL_EventType::SDL_MOUSEBUTTONDOWN as u32,
1131 timestamp,
1132 windowID: window_id,
1133 which,
1134 button: mouse_btn as u8,
1135 state: sys::SDL_PRESSED as u8,
1136 clicks,
1137 padding1: 0,
1138 x,
1139 y,
1140 };
1141 unsafe {
1142 ptr::copy(
1143 &event,
1144 ret.as_mut_ptr() as *mut sys::SDL_MouseButtonEvent,
1145 1,
1146 );
1147 Some(ret.assume_init())
1148 }
1149 }
1150 Event::MouseButtonUp {
1151 timestamp,
1152 window_id,
1153 which,
1154 mouse_btn,
1155 clicks,
1156 x,
1157 y,
1158 } => {
1159 let event = sys::SDL_MouseButtonEvent {
1160 type_: SDL_EventType::SDL_MOUSEBUTTONUP as u32,
1161 timestamp,
1162 windowID: window_id,
1163 which,
1164 button: mouse_btn as u8,
1165 state: sys::SDL_RELEASED as u8,
1166 clicks,
1167 padding1: 0,
1168 x,
1169 y,
1170 };
1171 unsafe {
1172 ptr::copy(
1173 &event,
1174 ret.as_mut_ptr() as *mut sys::SDL_MouseButtonEvent,
1175 1,
1176 );
1177 Some(ret.assume_init())
1178 }
1179 }
1180
1181 Event::MouseWheel {
1182 timestamp,
1183 window_id,
1184 which,
1185 x,
1186 y,
1187 direction,
1188 precise_x,
1189 precise_y,
1190 mouse_x,
1191 mouse_y,
1192 } => {
1193 let event = sys::SDL_MouseWheelEvent {
1194 type_: SDL_EventType::SDL_MOUSEWHEEL as u32,
1195 timestamp,
1196 windowID: window_id,
1197 which,
1198 x,
1199 y,
1200 direction: direction.to_ll(),
1201 preciseX: precise_x,
1202 preciseY: precise_y,
1203 mouseX: mouse_x,
1204 mouseY: mouse_y,
1205 };
1206 unsafe {
1207 ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_MouseWheelEvent, 1);
1208 Some(ret.assume_init())
1209 }
1210 }
1211 Event::JoyAxisMotion {
1212 timestamp,
1213 which,
1214 axis_idx,
1215 value,
1216 } => {
1217 let event = sys::SDL_JoyAxisEvent {
1218 type_: SDL_EventType::SDL_JOYAXISMOTION as u32,
1219 timestamp,
1220 which: which as i32,
1221 axis: axis_idx,
1222 value,
1223 padding1: 0,
1224 padding2: 0,
1225 padding3: 0,
1226 padding4: 0,
1227 };
1228 unsafe {
1229 ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_JoyAxisEvent, 1);
1230 Some(ret.assume_init())
1231 }
1232 }
1233 Event::JoyBallMotion {
1234 timestamp,
1235 which,
1236 ball_idx,
1237 xrel,
1238 yrel,
1239 } => {
1240 let event = sys::SDL_JoyBallEvent {
1241 type_: SDL_EventType::SDL_JOYBALLMOTION as u32,
1242 timestamp,
1243 which: which as i32,
1244 ball: ball_idx,
1245 xrel,
1246 yrel,
1247 padding1: 0,
1248 padding2: 0,
1249 padding3: 0,
1250 };
1251 unsafe {
1252 ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_JoyBallEvent, 1);
1253 Some(ret.assume_init())
1254 }
1255 }
1256 Event::JoyHatMotion {
1257 timestamp,
1258 which,
1259 hat_idx,
1260 state,
1261 } => {
1262 let hatvalue = state.to_raw();
1263 let event = sys::SDL_JoyHatEvent {
1264 type_: SDL_EventType::SDL_JOYHATMOTION as u32,
1265 timestamp,
1266 which: which as i32,
1267 hat: hat_idx,
1268 value: hatvalue,
1269 padding1: 0,
1270 padding2: 0,
1271 };
1272 unsafe {
1273 ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_JoyHatEvent, 1);
1274 Some(ret.assume_init())
1275 }
1276 }
1277 Event::JoyButtonDown {
1278 timestamp,
1279 which,
1280 button_idx,
1281 } => {
1282 let event = sys::SDL_JoyButtonEvent {
1283 type_: SDL_EventType::SDL_JOYBUTTONDOWN as u32,
1284 timestamp,
1285 which: which as i32,
1286 button: button_idx,
1287 state: sys::SDL_PRESSED as u8,
1288 padding1: 0,
1289 padding2: 0,
1290 };
1291 unsafe {
1292 ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_JoyButtonEvent, 1);
1293 Some(ret.assume_init())
1294 }
1295 }
1296
1297 Event::JoyButtonUp {
1298 timestamp,
1299 which,
1300 button_idx,
1301 } => {
1302 let event = sys::SDL_JoyButtonEvent {
1303 type_: SDL_EventType::SDL_JOYBUTTONUP as u32,
1304 timestamp,
1305 which: which as i32,
1306 button: button_idx,
1307 state: sys::SDL_RELEASED as u8,
1308 padding1: 0,
1309 padding2: 0,
1310 };
1311 unsafe {
1312 ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_JoyButtonEvent, 1);
1313 Some(ret.assume_init())
1314 }
1315 }
1316
1317 Event::JoyDeviceAdded { timestamp, which } => {
1318 let event = sys::SDL_JoyDeviceEvent {
1319 type_: SDL_EventType::SDL_JOYDEVICEADDED as u32,
1320 timestamp,
1321 which: which as i32,
1322 };
1323 unsafe {
1324 ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_JoyDeviceEvent, 1);
1325 Some(ret.assume_init())
1326 }
1327 }
1328
1329 Event::JoyDeviceRemoved { timestamp, which } => {
1330 let event = sys::SDL_JoyDeviceEvent {
1331 type_: SDL_EventType::SDL_JOYDEVICEREMOVED as u32,
1332 timestamp,
1333 which: which as i32,
1334 };
1335 unsafe {
1336 ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_JoyDeviceEvent, 1);
1337 Some(ret.assume_init())
1338 }
1339 }
1340 Event::ControllerAxisMotion {
1341 timestamp,
1342 which,
1343 axis,
1344 value,
1345 } => {
1346 let axisval = axis.to_ll();
1347 let event = sys::SDL_ControllerAxisEvent {
1348 type_: SDL_EventType::SDL_CONTROLLERAXISMOTION as u32,
1349 timestamp,
1350 which: which as i32,
1351 axis: axisval as u8,
1352 value,
1353 padding1: 0,
1354 padding2: 0,
1355 padding3: 0,
1356 padding4: 0,
1357 };
1358 unsafe {
1359 ptr::copy(
1360 &event,
1361 ret.as_mut_ptr() as *mut sys::SDL_ControllerAxisEvent,
1362 1,
1363 );
1364 Some(ret.assume_init())
1365 }
1366 }
1367 Event::ControllerButtonDown {
1368 timestamp,
1369 which,
1370 button,
1371 } => {
1372 let buttonval = button.to_ll();
1373 let event = sys::SDL_ControllerButtonEvent {
1374 type_: SDL_EventType::SDL_CONTROLLERBUTTONDOWN as u32,
1375 timestamp,
1376 which: which as i32,
1377 button: buttonval as u8,
1380 state: sys::SDL_PRESSED as u8,
1381 padding1: 0,
1382 padding2: 0,
1383 };
1384 unsafe {
1385 ptr::copy(
1386 &event,
1387 ret.as_mut_ptr() as *mut sys::SDL_ControllerButtonEvent,
1388 1,
1389 );
1390 Some(ret.assume_init())
1391 }
1392 }
1393
1394 Event::ControllerButtonUp {
1395 timestamp,
1396 which,
1397 button,
1398 } => {
1399 let buttonval = button.to_ll();
1400 let event = sys::SDL_ControllerButtonEvent {
1401 type_: SDL_EventType::SDL_CONTROLLERBUTTONUP as u32,
1402 timestamp,
1403 which: which as i32,
1404 button: buttonval as u8,
1405 state: sys::SDL_RELEASED as u8,
1406 padding1: 0,
1407 padding2: 0,
1408 };
1409 unsafe {
1410 ptr::copy(
1411 &event,
1412 ret.as_mut_ptr() as *mut sys::SDL_ControllerButtonEvent,
1413 1,
1414 );
1415 Some(ret.assume_init())
1416 }
1417 }
1418
1419 Event::ControllerDeviceAdded { timestamp, which } => {
1420 let event = sys::SDL_ControllerDeviceEvent {
1421 type_: SDL_EventType::SDL_CONTROLLERDEVICEADDED as u32,
1422 timestamp,
1423 which: which as i32,
1424 };
1425 unsafe {
1426 ptr::copy(
1427 &event,
1428 ret.as_mut_ptr() as *mut sys::SDL_ControllerDeviceEvent,
1429 1,
1430 );
1431 Some(ret.assume_init())
1432 }
1433 }
1434
1435 Event::ControllerDeviceRemoved { timestamp, which } => {
1436 let event = sys::SDL_ControllerDeviceEvent {
1437 type_: SDL_EventType::SDL_CONTROLLERDEVICEREMOVED as u32,
1438 timestamp,
1439 which: which as i32,
1440 };
1441 unsafe {
1442 ptr::copy(
1443 &event,
1444 ret.as_mut_ptr() as *mut sys::SDL_ControllerDeviceEvent,
1445 1,
1446 );
1447 Some(ret.assume_init())
1448 }
1449 }
1450
1451 Event::ControllerDeviceRemapped { timestamp, which } => {
1452 let event = sys::SDL_ControllerDeviceEvent {
1453 type_: SDL_EventType::SDL_CONTROLLERDEVICEREMAPPED as u32,
1454 timestamp,
1455 which: which as i32,
1456 };
1457 unsafe {
1458 ptr::copy(
1459 &event,
1460 ret.as_mut_ptr() as *mut sys::SDL_ControllerDeviceEvent,
1461 1,
1462 );
1463 Some(ret.assume_init())
1464 }
1465 }
1466
1467 Event::FingerDown { .. }
1468 | Event::FingerUp { .. }
1469 | Event::FingerMotion { .. }
1470 | Event::DollarGesture { .. }
1471 | Event::DollarRecord { .. }
1472 | Event::MultiGesture { .. }
1473 | Event::ClipboardUpdate { .. }
1474 | Event::DropFile { .. }
1475 | Event::TextEditing { .. }
1476 | Event::TextInput { .. }
1477 | Event::Unknown { .. }
1478 | _ => {
1479 None
1481 }
1482 }
1483 }
1484
1485 pub fn from_ll(raw: sys::SDL_Event) -> Event {
1486 let raw_type = unsafe { raw.type_ };
1487
1488 let event_type: EventType = EventType::try_from(raw_type).unwrap_or(EventType::User);
1490 unsafe {
1491 match event_type {
1492 EventType::Quit => {
1493 let event = raw.quit;
1494 Event::Quit {
1495 timestamp: event.timestamp,
1496 }
1497 }
1498 EventType::AppTerminating => {
1499 let event = raw.common;
1500 Event::AppTerminating {
1501 timestamp: event.timestamp,
1502 }
1503 }
1504 EventType::AppLowMemory => {
1505 let event = raw.common;
1506 Event::AppLowMemory {
1507 timestamp: event.timestamp,
1508 }
1509 }
1510 EventType::AppWillEnterBackground => {
1511 let event = raw.common;
1512 Event::AppWillEnterBackground {
1513 timestamp: event.timestamp,
1514 }
1515 }
1516 EventType::AppDidEnterBackground => {
1517 let event = raw.common;
1518 Event::AppDidEnterBackground {
1519 timestamp: event.timestamp,
1520 }
1521 }
1522 EventType::AppWillEnterForeground => {
1523 let event = raw.common;
1524 Event::AppWillEnterForeground {
1525 timestamp: event.timestamp,
1526 }
1527 }
1528 EventType::AppDidEnterForeground => {
1529 let event = raw.common;
1530 Event::AppDidEnterForeground {
1531 timestamp: event.timestamp,
1532 }
1533 }
1534
1535 EventType::Display => {
1536 let event = raw.display;
1537
1538 Event::Display {
1539 timestamp: event.timestamp,
1540 display_index: event.display as i32,
1541 display_event: DisplayEvent::from_ll(event.event, event.data1),
1542 }
1543 }
1544 EventType::Window => {
1545 let event = raw.window;
1546
1547 Event::Window {
1548 timestamp: event.timestamp,
1549 window_id: event.windowID,
1550 win_event: WindowEvent::from_ll(event.event, event.data1, event.data2),
1551 }
1552 }
1553 EventType::KeyDown => {
1555 let event = raw.key;
1556
1557 Event::KeyDown {
1558 timestamp: event.timestamp,
1559 window_id: event.windowID,
1560 keycode: Keycode::from_i32(event.keysym.sym),
1561 scancode: Scancode::from_i32(event.keysym.scancode as i32),
1562 keymod: keyboard::Mod::from_bits_truncate(event.keysym.mod_),
1563 repeat: event.repeat != 0,
1564 }
1565 }
1566 EventType::KeyUp => {
1567 let event = raw.key;
1568
1569 Event::KeyUp {
1570 timestamp: event.timestamp,
1571 window_id: event.windowID,
1572 keycode: Keycode::from_i32(event.keysym.sym),
1573 scancode: Scancode::from_i32(event.keysym.scancode as i32),
1574 keymod: keyboard::Mod::from_bits_truncate(event.keysym.mod_),
1575 repeat: event.repeat != 0,
1576 }
1577 }
1578 EventType::TextEditing => {
1579 let event = raw.edit;
1580
1581 let text = String::from_utf8(
1582 event
1583 .text
1584 .iter()
1585 .take_while(|&b| (*b) != 0)
1586 .map(|&b| b as u8)
1587 .collect::<Vec<u8>>(),
1588 )
1589 .expect("Invalid TextEditing string");
1590 Event::TextEditing {
1591 timestamp: event.timestamp,
1592 window_id: event.windowID,
1593 text,
1594 start: event.start,
1595 length: event.length,
1596 }
1597 }
1598 EventType::TextInput => {
1599 let event = raw.text;
1600
1601 let text = String::from_utf8(
1602 event
1603 .text
1604 .iter()
1605 .take_while(|&b| (*b) != 0)
1606 .map(|&b| b as u8)
1607 .collect::<Vec<u8>>(),
1608 )
1609 .expect("Invalid TextInput string");
1610 Event::TextInput {
1611 timestamp: event.timestamp,
1612 window_id: event.windowID,
1613 text,
1614 }
1615 }
1616
1617 EventType::MouseMotion => {
1618 let event = raw.motion;
1619
1620 Event::MouseMotion {
1621 timestamp: event.timestamp,
1622 window_id: event.windowID,
1623 which: event.which,
1624 mousestate: mouse::MouseState::from_sdl_state(event.state),
1625 x: event.x,
1626 y: event.y,
1627 xrel: event.xrel,
1628 yrel: event.yrel,
1629 }
1630 }
1631 EventType::MouseButtonDown => {
1632 let event = raw.button;
1633
1634 Event::MouseButtonDown {
1635 timestamp: event.timestamp,
1636 window_id: event.windowID,
1637 which: event.which,
1638 mouse_btn: mouse::MouseButton::from_ll(event.button),
1639 clicks: event.clicks,
1640 x: event.x,
1641 y: event.y,
1642 }
1643 }
1644 EventType::MouseButtonUp => {
1645 let event = raw.button;
1646
1647 Event::MouseButtonUp {
1648 timestamp: event.timestamp,
1649 window_id: event.windowID,
1650 which: event.which,
1651 mouse_btn: mouse::MouseButton::from_ll(event.button),
1652 clicks: event.clicks,
1653 x: event.x,
1654 y: event.y,
1655 }
1656 }
1657 EventType::MouseWheel => {
1658 let event = raw.wheel;
1659
1660 Event::MouseWheel {
1661 timestamp: event.timestamp,
1662 window_id: event.windowID,
1663 which: event.which,
1664 x: event.x,
1665 y: event.y,
1666 direction: mouse::MouseWheelDirection::from_ll(event.direction),
1667 precise_x: event.preciseX,
1668 precise_y: event.preciseY,
1669 mouse_x: event.mouseX,
1670 mouse_y: event.mouseY,
1671 }
1672 }
1673
1674 EventType::JoyAxisMotion => {
1675 let event = raw.jaxis;
1676 Event::JoyAxisMotion {
1677 timestamp: event.timestamp,
1678 which: event.which as u32,
1679 axis_idx: event.axis,
1680 value: event.value,
1681 }
1682 }
1683 EventType::JoyBallMotion => {
1684 let event = raw.jball;
1685 Event::JoyBallMotion {
1686 timestamp: event.timestamp,
1687 which: event.which as u32,
1688 ball_idx: event.ball,
1689 xrel: event.xrel,
1690 yrel: event.yrel,
1691 }
1692 }
1693 EventType::JoyHatMotion => {
1694 let event = raw.jhat;
1695 Event::JoyHatMotion {
1696 timestamp: event.timestamp,
1697 which: event.which as u32,
1698 hat_idx: event.hat,
1699 state: joystick::HatState::from_raw(event.value),
1700 }
1701 }
1702 EventType::JoyButtonDown => {
1703 let event = raw.jbutton;
1704 Event::JoyButtonDown {
1705 timestamp: event.timestamp,
1706 which: event.which as u32,
1707 button_idx: event.button,
1708 }
1709 }
1710 EventType::JoyButtonUp => {
1711 let event = raw.jbutton;
1712 Event::JoyButtonUp {
1713 timestamp: event.timestamp,
1714 which: event.which as u32,
1715 button_idx: event.button,
1716 }
1717 }
1718 EventType::JoyDeviceAdded => {
1719 let event = raw.jdevice;
1720 Event::JoyDeviceAdded {
1721 timestamp: event.timestamp,
1722 which: event.which as u32,
1723 }
1724 }
1725 EventType::JoyDeviceRemoved => {
1726 let event = raw.jdevice;
1727 Event::JoyDeviceRemoved {
1728 timestamp: event.timestamp,
1729 which: event.which as u32,
1730 }
1731 }
1732
1733 EventType::ControllerAxisMotion => {
1734 let event = raw.caxis;
1735 let axis = controller::Axis::from_ll(transmute(event.axis as i32)).unwrap();
1736
1737 Event::ControllerAxisMotion {
1738 timestamp: event.timestamp,
1739 which: event.which as u32,
1740 axis,
1741 value: event.value,
1742 }
1743 }
1744 EventType::ControllerButtonDown => {
1745 let event = raw.cbutton;
1746 let button =
1747 controller::Button::from_ll(transmute(event.button as i32)).unwrap();
1748
1749 Event::ControllerButtonDown {
1750 timestamp: event.timestamp,
1751 which: event.which as u32,
1752 button,
1753 }
1754 }
1755 EventType::ControllerButtonUp => {
1756 let event = raw.cbutton;
1757 let button =
1758 controller::Button::from_ll(transmute(event.button as i32)).unwrap();
1759
1760 Event::ControllerButtonUp {
1761 timestamp: event.timestamp,
1762 which: event.which as u32,
1763 button,
1764 }
1765 }
1766 EventType::ControllerDeviceAdded => {
1767 let event = raw.cdevice;
1768 Event::ControllerDeviceAdded {
1769 timestamp: event.timestamp,
1770 which: event.which as u32,
1771 }
1772 }
1773 EventType::ControllerDeviceRemoved => {
1774 let event = raw.cdevice;
1775 Event::ControllerDeviceRemoved {
1776 timestamp: event.timestamp,
1777 which: event.which as u32,
1778 }
1779 }
1780 EventType::ControllerDeviceRemapped => {
1781 let event = raw.cdevice;
1782 Event::ControllerDeviceRemapped {
1783 timestamp: event.timestamp,
1784 which: event.which as u32,
1785 }
1786 }
1787 EventType::ControllerTouchpadDown => {
1788 let event = raw.ctouchpad;
1789 Event::ControllerTouchpadDown {
1790 timestamp: event.timestamp,
1791 which: event.which as u32,
1792 touchpad: event.touchpad as u32,
1793 finger: event.finger as u32,
1794 x: event.x,
1795 y: event.y,
1796 pressure: event.pressure,
1797 }
1798 }
1799 EventType::ControllerTouchpadMotion => {
1800 let event = raw.ctouchpad;
1801 Event::ControllerTouchpadMotion {
1802 timestamp: event.timestamp,
1803 which: event.which as u32,
1804 touchpad: event.touchpad as u32,
1805 finger: event.finger as u32,
1806 x: event.x,
1807 y: event.y,
1808 pressure: event.pressure,
1809 }
1810 }
1811 EventType::ControllerTouchpadUp => {
1812 let event = raw.ctouchpad;
1813 Event::ControllerTouchpadUp {
1814 timestamp: event.timestamp,
1815 which: event.which as u32,
1816 touchpad: event.touchpad as u32,
1817 finger: event.finger as u32,
1818 x: event.x,
1819 y: event.y,
1820 pressure: event.pressure,
1821 }
1822 }
1823 #[cfg(feature = "hidapi")]
1824 EventType::ControllerSensorUpdated => {
1825 let event = raw.csensor;
1826 Event::ControllerSensorUpdated {
1827 timestamp: event.timestamp,
1828 which: event.which as u32,
1829 sensor: crate::sensor::SensorType::from_ll(event.sensor),
1830 data: event.data,
1831 }
1832 }
1833
1834 EventType::FingerDown => {
1835 let event = raw.tfinger;
1836 Event::FingerDown {
1837 timestamp: event.timestamp,
1838 touch_id: event.touchId,
1839 finger_id: event.fingerId,
1840 x: event.x,
1841 y: event.y,
1842 dx: event.dx,
1843 dy: event.dy,
1844 pressure: event.pressure,
1845 }
1846 }
1847 EventType::FingerUp => {
1848 let event = raw.tfinger;
1849 Event::FingerUp {
1850 timestamp: event.timestamp,
1851 touch_id: event.touchId,
1852 finger_id: event.fingerId,
1853 x: event.x,
1854 y: event.y,
1855 dx: event.dx,
1856 dy: event.dy,
1857 pressure: event.pressure,
1858 }
1859 }
1860 EventType::FingerMotion => {
1861 let event = raw.tfinger;
1862 Event::FingerMotion {
1863 timestamp: event.timestamp,
1864 touch_id: event.touchId,
1865 finger_id: event.fingerId,
1866 x: event.x,
1867 y: event.y,
1868 dx: event.dx,
1869 dy: event.dy,
1870 pressure: event.pressure,
1871 }
1872 }
1873 EventType::DollarGesture => {
1874 let event = raw.dgesture;
1875 Event::DollarGesture {
1876 timestamp: event.timestamp,
1877 touch_id: event.touchId,
1878 gesture_id: event.gestureId,
1879 num_fingers: event.numFingers,
1880 error: event.error,
1881 x: event.x,
1882 y: event.y,
1883 }
1884 }
1885 EventType::DollarRecord => {
1886 let event = raw.dgesture;
1887 Event::DollarRecord {
1888 timestamp: event.timestamp,
1889 touch_id: event.touchId,
1890 gesture_id: event.gestureId,
1891 num_fingers: event.numFingers,
1892 error: event.error,
1893 x: event.x,
1894 y: event.y,
1895 }
1896 }
1897 EventType::MultiGesture => {
1898 let event = raw.mgesture;
1899 Event::MultiGesture {
1900 timestamp: event.timestamp,
1901 touch_id: event.touchId,
1902 d_theta: event.dTheta,
1903 d_dist: event.dDist,
1904 x: event.x,
1905 y: event.y,
1906 num_fingers: event.numFingers,
1907 }
1908 }
1909
1910 EventType::ClipboardUpdate => {
1911 let event = raw.common;
1912 Event::ClipboardUpdate {
1913 timestamp: event.timestamp,
1914 }
1915 }
1916 EventType::DropFile => {
1917 let event = raw.drop;
1918
1919 let buf = CStr::from_ptr(event.file as *const _).to_bytes();
1920 let text = String::from_utf8_lossy(buf).to_string();
1921 sys::SDL_free(event.file as *mut c_void);
1922
1923 Event::DropFile {
1924 timestamp: event.timestamp,
1925 window_id: event.windowID,
1926 filename: text,
1927 }
1928 }
1929 EventType::DropText => {
1930 let event = raw.drop;
1931
1932 let buf = CStr::from_ptr(event.file as *const _).to_bytes();
1933 let text = String::from_utf8_lossy(buf).to_string();
1934 sys::SDL_free(event.file as *mut c_void);
1935
1936 Event::DropText {
1937 timestamp: event.timestamp,
1938 window_id: event.windowID,
1939 filename: text,
1940 }
1941 }
1942 EventType::DropBegin => {
1943 let event = raw.drop;
1944
1945 Event::DropBegin {
1946 timestamp: event.timestamp,
1947 window_id: event.windowID,
1948 }
1949 }
1950 EventType::DropComplete => {
1951 let event = raw.drop;
1952
1953 Event::DropComplete {
1954 timestamp: event.timestamp,
1955 window_id: event.windowID,
1956 }
1957 }
1958 EventType::AudioDeviceAdded => {
1959 let event = raw.adevice;
1960 Event::AudioDeviceAdded {
1961 timestamp: event.timestamp,
1962 which: event.which,
1963 iscapture: event.iscapture != 0,
1965 }
1966 }
1967 EventType::AudioDeviceRemoved => {
1968 let event = raw.adevice;
1969 Event::AudioDeviceRemoved {
1970 timestamp: event.timestamp,
1971 which: event.which,
1972 iscapture: event.iscapture != 0,
1974 }
1975 }
1976
1977 EventType::RenderTargetsReset => Event::RenderTargetsReset {
1978 timestamp: raw.common.timestamp,
1979 },
1980 EventType::RenderDeviceReset => Event::RenderDeviceReset {
1981 timestamp: raw.common.timestamp,
1982 },
1983
1984 EventType::LocaleChanged => Event::LocaleChanged {
1985 timestamp: raw.common.timestamp,
1986 },
1987
1988 EventType::First => panic!("Unused event, EventType::First, was encountered"),
1989 EventType::Last => panic!("Unusable event, EventType::Last, was encountered"),
1990
1991 EventType::User => {
1994 if raw_type < 32_768 {
1995 let event = raw.common;
1998
1999 Event::Unknown {
2000 timestamp: event.timestamp,
2001 type_: event.type_,
2002 }
2003 } else {
2004 let event = raw.user;
2005
2006 Event::User {
2007 timestamp: event.timestamp,
2008 window_id: event.windowID,
2009 type_: raw_type,
2010 code: event.code,
2011 data1: event.data1,
2012 data2: event.data2,
2013 }
2014 }
2015 }
2016 }
2017 } }
2019
2020 pub fn is_user_event(&self) -> bool {
2021 matches!(self, Event::User { .. })
2022 }
2023
2024 pub fn as_user_event_type<T: ::std::any::Any>(&self) -> Option<T> {
2025 use std::any::TypeId;
2026 let type_id = TypeId::of::<Box<T>>();
2027
2028 let (event_id, event_box_ptr) = match *self {
2029 Event::User { type_, data1, .. } => (type_, data1),
2030 _ => return None,
2031 };
2032
2033 let cet = CUSTOM_EVENT_TYPES.lock().unwrap();
2034
2035 let event_type_id = match cet.sdl_id_to_type_id.get(&event_id) {
2036 Some(id) => id,
2037 None => {
2038 panic!("internal error; could not find typeid")
2039 }
2040 };
2041
2042 if &type_id != event_type_id {
2043 return None;
2044 }
2045
2046 let event_box: Box<T> = unsafe { Box::from_raw(event_box_ptr as *mut T) };
2047
2048 Some(*event_box)
2049 }
2050
2051 pub fn is_same_kind_as(&self, other: &Event) -> bool {
2073 match (self, other) {
2074 (Self::Quit { .. }, Self::Quit { .. })
2075 | (Self::AppTerminating { .. }, Self::AppTerminating { .. })
2076 | (Self::AppLowMemory { .. }, Self::AppLowMemory { .. })
2077 | (Self::AppWillEnterBackground { .. }, Self::AppWillEnterBackground { .. })
2078 | (Self::AppDidEnterBackground { .. }, Self::AppDidEnterBackground { .. })
2079 | (Self::AppWillEnterForeground { .. }, Self::AppWillEnterForeground { .. })
2080 | (Self::AppDidEnterForeground { .. }, Self::AppDidEnterForeground { .. })
2081 | (Self::Display { .. }, Self::Display { .. })
2082 | (Self::Window { .. }, Self::Window { .. })
2083 | (Self::KeyDown { .. }, Self::KeyDown { .. })
2084 | (Self::KeyUp { .. }, Self::KeyUp { .. })
2085 | (Self::TextEditing { .. }, Self::TextEditing { .. })
2086 | (Self::TextInput { .. }, Self::TextInput { .. })
2087 | (Self::MouseMotion { .. }, Self::MouseMotion { .. })
2088 | (Self::MouseButtonDown { .. }, Self::MouseButtonDown { .. })
2089 | (Self::MouseButtonUp { .. }, Self::MouseButtonUp { .. })
2090 | (Self::MouseWheel { .. }, Self::MouseWheel { .. })
2091 | (Self::JoyAxisMotion { .. }, Self::JoyAxisMotion { .. })
2092 | (Self::JoyBallMotion { .. }, Self::JoyBallMotion { .. })
2093 | (Self::JoyHatMotion { .. }, Self::JoyHatMotion { .. })
2094 | (Self::JoyButtonDown { .. }, Self::JoyButtonDown { .. })
2095 | (Self::JoyButtonUp { .. }, Self::JoyButtonUp { .. })
2096 | (Self::JoyDeviceAdded { .. }, Self::JoyDeviceAdded { .. })
2097 | (Self::JoyDeviceRemoved { .. }, Self::JoyDeviceRemoved { .. })
2098 | (Self::ControllerAxisMotion { .. }, Self::ControllerAxisMotion { .. })
2099 | (Self::ControllerButtonDown { .. }, Self::ControllerButtonDown { .. })
2100 | (Self::ControllerButtonUp { .. }, Self::ControllerButtonUp { .. })
2101 | (Self::ControllerDeviceAdded { .. }, Self::ControllerDeviceAdded { .. })
2102 | (Self::ControllerDeviceRemoved { .. }, Self::ControllerDeviceRemoved { .. })
2103 | (Self::ControllerDeviceRemapped { .. }, Self::ControllerDeviceRemapped { .. })
2104 | (Self::FingerDown { .. }, Self::FingerDown { .. })
2105 | (Self::FingerUp { .. }, Self::FingerUp { .. })
2106 | (Self::FingerMotion { .. }, Self::FingerMotion { .. })
2107 | (Self::DollarGesture { .. }, Self::DollarGesture { .. })
2108 | (Self::DollarRecord { .. }, Self::DollarRecord { .. })
2109 | (Self::MultiGesture { .. }, Self::MultiGesture { .. })
2110 | (Self::ClipboardUpdate { .. }, Self::ClipboardUpdate { .. })
2111 | (Self::DropFile { .. }, Self::DropFile { .. })
2112 | (Self::DropText { .. }, Self::DropText { .. })
2113 | (Self::DropBegin { .. }, Self::DropBegin { .. })
2114 | (Self::DropComplete { .. }, Self::DropComplete { .. })
2115 | (Self::AudioDeviceAdded { .. }, Self::AudioDeviceAdded { .. })
2116 | (Self::AudioDeviceRemoved { .. }, Self::AudioDeviceRemoved { .. })
2117 | (Self::RenderTargetsReset { .. }, Self::RenderTargetsReset { .. })
2118 | (Self::RenderDeviceReset { .. }, Self::RenderDeviceReset { .. })
2119 | (Self::User { .. }, Self::User { .. })
2120 | (Self::Unknown { .. }, Self::Unknown { .. }) => true,
2121 #[cfg(feature = "hidapi")]
2122 (Self::ControllerSensorUpdated { .. }, Self::ControllerSensorUpdated { .. }) => true,
2123 _ => false,
2124 }
2125 }
2126
2127 pub fn get_timestamp(&self) -> u32 {
2142 *match self {
2143 Self::Quit { timestamp, .. } => timestamp,
2144 Self::AppTerminating { timestamp, .. } => timestamp,
2145 Self::AppLowMemory { timestamp, .. } => timestamp,
2146 Self::AppWillEnterBackground { timestamp, .. } => timestamp,
2147 Self::AppDidEnterBackground { timestamp, .. } => timestamp,
2148 Self::AppWillEnterForeground { timestamp, .. } => timestamp,
2149 Self::AppDidEnterForeground { timestamp, .. } => timestamp,
2150 Self::Display { timestamp, .. } => timestamp,
2151 Self::Window { timestamp, .. } => timestamp,
2152 Self::KeyDown { timestamp, .. } => timestamp,
2153 Self::KeyUp { timestamp, .. } => timestamp,
2154 Self::TextEditing { timestamp, .. } => timestamp,
2155 Self::TextInput { timestamp, .. } => timestamp,
2156 Self::MouseMotion { timestamp, .. } => timestamp,
2157 Self::MouseButtonDown { timestamp, .. } => timestamp,
2158 Self::MouseButtonUp { timestamp, .. } => timestamp,
2159 Self::MouseWheel { timestamp, .. } => timestamp,
2160 Self::JoyAxisMotion { timestamp, .. } => timestamp,
2161 Self::JoyBallMotion { timestamp, .. } => timestamp,
2162 Self::JoyHatMotion { timestamp, .. } => timestamp,
2163 Self::JoyButtonDown { timestamp, .. } => timestamp,
2164 Self::JoyButtonUp { timestamp, .. } => timestamp,
2165 Self::JoyDeviceAdded { timestamp, .. } => timestamp,
2166 Self::JoyDeviceRemoved { timestamp, .. } => timestamp,
2167 Self::ControllerAxisMotion { timestamp, .. } => timestamp,
2168 Self::ControllerButtonDown { timestamp, .. } => timestamp,
2169 Self::ControllerButtonUp { timestamp, .. } => timestamp,
2170 Self::ControllerDeviceAdded { timestamp, .. } => timestamp,
2171 Self::ControllerDeviceRemoved { timestamp, .. } => timestamp,
2172 Self::ControllerDeviceRemapped { timestamp, .. } => timestamp,
2173 Self::ControllerTouchpadDown { timestamp, .. } => timestamp,
2174 Self::ControllerTouchpadMotion { timestamp, .. } => timestamp,
2175 Self::ControllerTouchpadUp { timestamp, .. } => timestamp,
2176 #[cfg(feature = "hidapi")]
2177 Self::ControllerSensorUpdated { timestamp, .. } => timestamp,
2178 Self::FingerDown { timestamp, .. } => timestamp,
2179 Self::FingerUp { timestamp, .. } => timestamp,
2180 Self::FingerMotion { timestamp, .. } => timestamp,
2181 Self::DollarGesture { timestamp, .. } => timestamp,
2182 Self::DollarRecord { timestamp, .. } => timestamp,
2183 Self::MultiGesture { timestamp, .. } => timestamp,
2184 Self::ClipboardUpdate { timestamp, .. } => timestamp,
2185 Self::DropFile { timestamp, .. } => timestamp,
2186 Self::DropText { timestamp, .. } => timestamp,
2187 Self::DropBegin { timestamp, .. } => timestamp,
2188 Self::DropComplete { timestamp, .. } => timestamp,
2189 Self::AudioDeviceAdded { timestamp, .. } => timestamp,
2190 Self::AudioDeviceRemoved { timestamp, .. } => timestamp,
2191 Self::RenderTargetsReset { timestamp, .. } => timestamp,
2192 Self::RenderDeviceReset { timestamp, .. } => timestamp,
2193 Self::LocaleChanged { timestamp, .. } => timestamp,
2194 Self::User { timestamp, .. } => timestamp,
2195 Self::Unknown { timestamp, .. } => timestamp,
2196 }
2197 }
2198
2199 pub fn get_window_id(&self) -> Option<u32> {
2220 match self {
2221 Self::Window { window_id, .. } => Some(*window_id),
2222 Self::KeyDown { window_id, .. } => Some(*window_id),
2223 Self::KeyUp { window_id, .. } => Some(*window_id),
2224 Self::TextEditing { window_id, .. } => Some(*window_id),
2225 Self::TextInput { window_id, .. } => Some(*window_id),
2226 Self::MouseMotion { window_id, .. } => Some(*window_id),
2227 Self::MouseButtonDown { window_id, .. } => Some(*window_id),
2228 Self::MouseButtonUp { window_id, .. } => Some(*window_id),
2229 Self::MouseWheel { window_id, .. } => Some(*window_id),
2230 Self::DropFile { window_id, .. } => Some(*window_id),
2231 Self::DropText { window_id, .. } => Some(*window_id),
2232 Self::DropBegin { window_id, .. } => Some(*window_id),
2233 Self::DropComplete { window_id, .. } => Some(*window_id),
2234 Self::User { window_id, .. } => Some(*window_id),
2235 _ => None,
2236 }
2237 }
2238
2239 pub fn is_window(&self) -> bool {
2264 matches!(
2265 self,
2266 Self::Quit { .. }
2267 | Self::AppTerminating { .. }
2268 | Self::AppLowMemory { .. }
2269 | Self::AppWillEnterBackground { .. }
2270 | Self::AppDidEnterBackground { .. }
2271 | Self::AppWillEnterForeground { .. }
2272 | Self::AppDidEnterForeground { .. }
2273 | Self::Window { .. }
2274 )
2275 }
2276
2277 pub fn is_keyboard(&self) -> bool {
2301 matches!(self, Self::KeyDown { .. } | Self::KeyUp { .. })
2302 }
2303
2304 pub fn is_text(&self) -> bool {
2324 matches!(self, Self::TextEditing { .. } | Self::TextInput { .. })
2325 }
2326
2327 pub fn is_mouse(&self) -> bool {
2355 matches!(
2356 self,
2357 Self::MouseMotion { .. }
2358 | Self::MouseButtonDown { .. }
2359 | Self::MouseButtonUp { .. }
2360 | Self::MouseWheel { .. }
2361 )
2362 }
2363
2364 pub fn is_touch(&self) -> bool {
2368 const SDL_TOUCH_MOUSEID: u32 = 0xFFFFFFFF;
2370
2371 matches!(
2372 self,
2373 Self::MouseMotion {
2374 which: SDL_TOUCH_MOUSEID,
2375 ..
2376 } | Self::MouseButtonDown {
2377 which: SDL_TOUCH_MOUSEID,
2378 ..
2379 } | Self::MouseButtonUp {
2380 which: SDL_TOUCH_MOUSEID,
2381 ..
2382 } | Self::MouseWheel {
2383 which: SDL_TOUCH_MOUSEID,
2384 ..
2385 }
2386 )
2387 }
2388
2389 pub fn is_controller(&self) -> bool {
2408 matches!(
2409 self,
2410 Self::ControllerAxisMotion { .. }
2411 | Self::ControllerButtonDown { .. }
2412 | Self::ControllerButtonUp { .. }
2413 | Self::ControllerDeviceAdded { .. }
2414 | Self::ControllerDeviceRemoved { .. }
2415 | Self::ControllerDeviceRemapped { .. }
2416 )
2417 }
2418
2419 pub fn is_joy(&self) -> bool {
2439 matches!(
2440 self,
2441 Self::JoyAxisMotion { .. }
2442 | Self::JoyBallMotion { .. }
2443 | Self::JoyHatMotion { .. }
2444 | Self::JoyButtonDown { .. }
2445 | Self::JoyButtonUp { .. }
2446 | Self::JoyDeviceAdded { .. }
2447 | Self::JoyDeviceRemoved { .. }
2448 )
2449 }
2450
2451 pub fn is_finger(&self) -> bool {
2476 matches!(
2477 self,
2478 Self::FingerDown { .. } | Self::FingerUp { .. } | Self::FingerMotion { .. }
2479 )
2480 }
2481
2482 pub fn is_dollar(&self) -> bool {
2506 matches!(self, Self::DollarGesture { .. } | Self::DollarRecord { .. })
2507 }
2508
2509 pub fn is_drop(&self) -> bool {
2528 matches!(
2529 self,
2530 Self::DropFile { .. }
2531 | Self::DropText { .. }
2532 | Self::DropBegin { .. }
2533 | Self::DropComplete { .. }
2534 )
2535 }
2536
2537 pub fn is_audio(&self) -> bool {
2557 matches!(
2558 self,
2559 Self::AudioDeviceAdded { .. } | Self::AudioDeviceRemoved { .. }
2560 )
2561 }
2562
2563 pub fn is_render(&self) -> bool {
2581 matches!(
2582 self,
2583 Self::RenderTargetsReset { .. } | Self::RenderDeviceReset { .. }
2584 )
2585 }
2586
2587 pub fn is_locale(&self) -> bool {
2605 matches!(self, Self::LocaleChanged { .. })
2606 }
2607
2608 pub fn is_user(&self) -> bool {
2631 matches!(self, Self::User { .. })
2632 }
2633
2634 pub fn is_unknown(&self) -> bool {
2653 matches!(self, Self::Unknown { .. })
2654 }
2655}
2656
2657unsafe fn poll_event() -> Option<Event> {
2658 let mut raw = mem::MaybeUninit::uninit();
2659 let has_pending = sys::SDL_PollEvent(raw.as_mut_ptr()) == 1;
2660
2661 if has_pending {
2662 Some(Event::from_ll(raw.assume_init()))
2663 } else {
2664 None
2665 }
2666}
2667
2668unsafe fn wait_event() -> Event {
2669 let mut raw = mem::MaybeUninit::uninit();
2670 let success = sys::SDL_WaitEvent(raw.as_mut_ptr()) == 1;
2671
2672 if success {
2673 Event::from_ll(raw.assume_init())
2674 } else {
2675 panic!("{}", get_error())
2676 }
2677}
2678
2679unsafe fn wait_event_timeout(timeout: u32) -> Option<Event> {
2680 let mut raw = mem::MaybeUninit::uninit();
2681 let success = sys::SDL_WaitEventTimeout(raw.as_mut_ptr(), timeout as c_int) == 1;
2682
2683 if success {
2684 Some(Event::from_ll(raw.assume_init()))
2685 } else {
2686 None
2687 }
2688}
2689
2690impl crate::EventPump {
2691 #[doc(alias = "SDL_EventState")]
2693 pub fn is_event_enabled(&self, event_type: EventType) -> bool {
2694 let result = unsafe { sys::SDL_EventState(event_type as u32, sys::SDL_QUERY) };
2695
2696 result != sys::SDL_DISABLE as u8
2697 }
2698
2699 #[doc(alias = "SDL_EventState")]
2701 pub fn enable_event(&mut self, event_type: EventType) -> bool {
2702 let result = unsafe { sys::SDL_EventState(event_type as u32, sys::SDL_ENABLE as c_int) };
2703
2704 result != sys::SDL_DISABLE as u8
2705 }
2706
2707 #[doc(alias = "SDL_EventState")]
2709 pub fn disable_event(&mut self, event_type: EventType) -> bool {
2710 let result = unsafe { sys::SDL_EventState(event_type as u32, sys::SDL_DISABLE as c_int) };
2711
2712 result != sys::SDL_DISABLE as u8
2713 }
2714
2715 pub fn poll_event(&mut self) -> Option<Event> {
2719 unsafe { poll_event() }
2720 }
2721
2722 pub fn poll_iter(&mut self) -> EventPollIterator {
2739 EventPollIterator {
2740 _marker: PhantomData,
2741 }
2742 }
2743
2744 #[doc(alias = "SDL_PumpEvents")]
2746 pub fn pump_events(&mut self) {
2747 unsafe {
2748 sys::SDL_PumpEvents();
2749 };
2750 }
2751
2752 pub fn wait_event(&mut self) -> Event {
2754 unsafe { wait_event() }
2755 }
2756
2757 pub fn wait_event_timeout(&mut self, timeout: u32) -> Option<Event> {
2759 unsafe { wait_event_timeout(timeout) }
2760 }
2761
2762 pub fn wait_iter(&mut self) -> EventWaitIterator {
2766 EventWaitIterator {
2767 _marker: PhantomData,
2768 }
2769 }
2770
2771 pub fn wait_timeout_iter(&mut self, timeout: u32) -> EventWaitTimeoutIterator {
2776 EventWaitTimeoutIterator {
2777 _marker: PhantomData,
2778 timeout,
2779 }
2780 }
2781
2782 #[inline]
2783 pub fn keyboard_state(&self) -> crate::keyboard::KeyboardState {
2784 crate::keyboard::KeyboardState::new(self)
2785 }
2786
2787 #[inline]
2788 pub fn mouse_state(&self) -> crate::mouse::MouseState {
2789 crate::mouse::MouseState::new(self)
2790 }
2791
2792 #[inline]
2793 pub fn relative_mouse_state(&self) -> crate::mouse::RelativeMouseState {
2794 crate::mouse::RelativeMouseState::new(self)
2795 }
2796}
2797
2798#[must_use = "iterators are lazy and do nothing unless consumed"]
2800pub struct EventPollIterator<'a> {
2801 _marker: PhantomData<&'a ()>,
2802}
2803
2804impl<'a> Iterator for EventPollIterator<'a> {
2805 type Item = Event;
2806
2807 fn next(&mut self) -> Option<Event> {
2808 unsafe { poll_event() }
2809 }
2810}
2811
2812#[must_use = "iterators are lazy and do nothing unless consumed"]
2814pub struct EventWaitIterator<'a> {
2815 _marker: PhantomData<&'a ()>,
2816}
2817
2818impl<'a> Iterator for EventWaitIterator<'a> {
2819 type Item = Event;
2820 fn next(&mut self) -> Option<Event> {
2821 unsafe { Some(wait_event()) }
2822 }
2823}
2824
2825#[must_use = "iterators are lazy and do nothing unless consumed"]
2827pub struct EventWaitTimeoutIterator<'a> {
2828 _marker: PhantomData<&'a ()>,
2829 timeout: u32,
2830}
2831
2832impl<'a> Iterator for EventWaitTimeoutIterator<'a> {
2833 type Item = Event;
2834 fn next(&mut self) -> Option<Event> {
2835 unsafe { wait_event_timeout(self.timeout) }
2836 }
2837}
2838
2839pub struct EventSender {
2841 _priv: (),
2842}
2843
2844impl EventSender {
2845 #[doc(alias = "SDL_PushEvent")]
2847 pub fn push_event(&self, event: Event) -> Result<(), String> {
2848 match event.to_ll() {
2849 Some(mut raw_event) => {
2850 let ok = unsafe { sys::SDL_PushEvent(&mut raw_event) == 1 };
2851 if ok {
2852 Ok(())
2853 } else {
2854 Err(get_error())
2855 }
2856 }
2857 None => Err("Cannot push unsupported event type to the queue".to_owned()),
2858 }
2859 }
2860
2861 pub fn push_custom_event<T: ::std::any::Any>(&self, event: T) -> Result<(), String> {
2891 use std::any::TypeId;
2892 let cet = CUSTOM_EVENT_TYPES.lock().unwrap();
2893 let type_id = TypeId::of::<Box<T>>();
2894
2895 let user_event_id = *match cet.type_id_to_sdl_id.get(&type_id) {
2896 Some(id) => id,
2897 None => {
2898 return Err("Type is not registered as a custom event type!".to_owned());
2899 }
2900 };
2901
2902 let event_box = Box::new(event);
2903 let event = Event::User {
2904 timestamp: 0,
2905 window_id: 0,
2906 type_: user_event_id,
2907 code: 0,
2908 data1: Box::into_raw(event_box) as *mut c_void,
2909 data2: ::std::ptr::null_mut(),
2910 };
2911 drop(cet);
2912
2913 self.push_event(event)?;
2914
2915 Ok(())
2916 }
2917}
2918
2919pub trait EventWatchCallback {
2921 fn callback(&mut self, event: Event);
2922}
2923
2924pub struct EventWatch<'a, CB: EventWatchCallback + 'a> {
2928 activated: bool,
2929 callback: Box<CB>,
2930 _phantom: PhantomData<&'a CB>,
2931}
2932
2933impl<'a, CB: EventWatchCallback + 'a> EventWatch<'a, CB> {
2934 fn add(callback: CB) -> EventWatch<'a, CB> {
2935 let f = Box::new(callback);
2936 let mut watch = EventWatch {
2937 activated: false,
2938 callback: f,
2939 _phantom: PhantomData,
2940 };
2941 watch.activate();
2942 watch
2943 }
2944
2945 pub fn activate(&mut self) {
2948 if !self.activated {
2949 self.activated = true;
2950 unsafe { sys::SDL_AddEventWatch(self.filter(), self.callback()) };
2951 }
2952 }
2953
2954 pub fn deactivate(&mut self) {
2957 if self.activated {
2958 self.activated = false;
2959 unsafe { sys::SDL_DelEventWatch(self.filter(), self.callback()) };
2960 }
2961 }
2962
2963 pub fn activated(&self) -> bool {
2965 self.activated
2966 }
2967
2968 pub fn set_activated(&mut self, activate: bool) {
2970 if activate {
2971 self.activate();
2972 } else {
2973 self.deactivate();
2974 }
2975 }
2976
2977 fn filter(&self) -> SDL_EventFilter {
2978 Some(event_callback_marshall::<CB> as _)
2979 }
2980
2981 fn callback(&mut self) -> *mut c_void {
2982 &mut *self.callback as *mut _ as *mut c_void
2983 }
2984}
2985
2986impl<'a, CB: EventWatchCallback + 'a> Drop for EventWatch<'a, CB> {
2987 fn drop(&mut self) {
2988 self.deactivate();
2989 }
2990}
2991
2992extern "C" fn event_callback_marshall<CB: EventWatchCallback>(
2993 user_data: *mut c_void,
2994 event: *mut sdl2_sys::SDL_Event,
2995) -> i32 {
2996 let f: &mut CB = unsafe { &mut *(user_data as *mut _) };
2997 let event = Event::from_ll(unsafe { *event });
2998 f.callback(event);
2999 0
3000}
3001
3002impl<F: FnMut(Event)> EventWatchCallback for F {
3003 fn callback(&mut self, event: Event) {
3004 self(event)
3005 }
3006}
3007
3008#[cfg(test)]
3009mod test {
3010 use super::super::controller::{Axis, Button};
3011 use super::super::joystick::HatState;
3012 use super::super::keyboard::{Keycode, Mod, Scancode};
3013 use super::super::mouse::{MouseButton, MouseState, MouseWheelDirection};
3014 use super::super::video::Orientation;
3015 use super::DisplayEvent;
3016 use super::Event;
3017 use super::WindowEvent;
3018
3019 #[test]
3022 fn test_to_from_ll() {
3023 {
3024 let e = Event::Quit { timestamp: 0 };
3025 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3026 assert_eq!(e, e2);
3027 }
3028 {
3029 let e = Event::Display {
3030 timestamp: 0,
3031 display_index: 1,
3032 display_event: DisplayEvent::Orientation(Orientation::LandscapeFlipped),
3033 };
3034 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3035 assert_eq!(e, e2);
3036 }
3037 {
3038 let e = Event::Window {
3039 timestamp: 0,
3040 window_id: 0,
3041 win_event: WindowEvent::Resized(1, 2),
3042 };
3043 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3044 assert_eq!(e, e2);
3045 }
3046 {
3047 let e = Event::KeyDown {
3048 timestamp: 0,
3049 window_id: 1,
3050 keycode: None,
3051 scancode: Some(Scancode::Q),
3052 keymod: Mod::all(),
3053 repeat: false,
3054 };
3055 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3056 assert_eq!(e, e2);
3057 }
3058 {
3059 let e = Event::KeyUp {
3060 timestamp: 123,
3061 window_id: 0,
3062 keycode: Some(Keycode::R),
3063 scancode: Some(Scancode::R),
3064 keymod: Mod::empty(),
3065 repeat: true,
3066 };
3067 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3068 assert_eq!(e, e2);
3069 }
3070 {
3071 let e = Event::MouseMotion {
3072 timestamp: 0,
3073 window_id: 0,
3074 which: 1,
3075 mousestate: MouseState::from_sdl_state(1),
3076 x: 3,
3077 y: 91,
3078 xrel: -1,
3079 yrel: 43,
3080 };
3081 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3082 assert_eq!(e, e2);
3083 }
3084 {
3085 let e = Event::MouseButtonDown {
3086 timestamp: 5634,
3087 window_id: 2,
3088 which: 0,
3089 mouse_btn: MouseButton::Left,
3090 clicks: 1,
3091 x: 543,
3092 y: 345,
3093 };
3094 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3095 assert_eq!(e, e2);
3096 }
3097 {
3098 let e = Event::MouseButtonUp {
3099 timestamp: 0,
3100 window_id: 2,
3101 which: 0,
3102 mouse_btn: MouseButton::Left,
3103 clicks: 1,
3104 x: 543,
3105 y: 345,
3106 };
3107 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3108 assert_eq!(e, e2);
3109 }
3110 {
3111 let e = Event::MouseWheel {
3112 timestamp: 1,
3113 window_id: 0,
3114 which: 32,
3115 x: 23,
3116 y: 91,
3117 direction: MouseWheelDirection::Flipped,
3118 precise_x: 1.6,
3119 precise_y: 2.7,
3120 mouse_x: 0,
3121 mouse_y: 5,
3122 };
3123 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3124 assert_eq!(e, e2);
3125 }
3126 {
3127 let e = Event::JoyAxisMotion {
3128 timestamp: 0,
3129 which: 1,
3130 axis_idx: 1,
3131 value: 12,
3132 };
3133 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3134 assert_eq!(e, e2);
3135 }
3136 {
3137 let e = Event::JoyBallMotion {
3138 timestamp: 0,
3139 which: 0,
3140 ball_idx: 1,
3141 xrel: 123,
3142 yrel: 321,
3143 };
3144 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3145 assert_eq!(e, e2);
3146 }
3147 {
3148 let e = Event::JoyHatMotion {
3149 timestamp: 0,
3150 which: 3,
3151 hat_idx: 1,
3152 state: HatState::Left,
3153 };
3154 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3155 assert_eq!(e, e2);
3156 }
3157 {
3158 let e = Event::JoyButtonDown {
3159 timestamp: 0,
3160 which: 0,
3161 button_idx: 3,
3162 };
3163 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3164 assert_eq!(e, e2);
3165 }
3166 {
3167 let e = Event::JoyButtonUp {
3168 timestamp: 9876,
3169 which: 1,
3170 button_idx: 2,
3171 };
3172 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3173 assert_eq!(e, e2);
3174 }
3175 {
3176 let e = Event::JoyDeviceAdded {
3177 timestamp: 0,
3178 which: 1,
3179 };
3180 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3181 assert_eq!(e, e2);
3182 }
3183 {
3184 let e = Event::JoyDeviceRemoved {
3185 timestamp: 0,
3186 which: 2,
3187 };
3188 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3189 assert_eq!(e, e2);
3190 }
3191 {
3192 let e = Event::ControllerAxisMotion {
3193 timestamp: 53,
3194 which: 0,
3195 axis: Axis::LeftX,
3196 value: 3,
3197 };
3198 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3199 assert_eq!(e, e2);
3200 }
3201 {
3202 let e = Event::ControllerButtonDown {
3203 timestamp: 0,
3204 which: 1,
3205 button: Button::Guide,
3206 };
3207 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3208 assert_eq!(e, e2);
3209 }
3210 {
3211 let e = Event::ControllerButtonUp {
3212 timestamp: 654214,
3213 which: 0,
3214 button: Button::DPadRight,
3215 };
3216 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3217 assert_eq!(e, e2);
3218 }
3219 {
3220 let e = Event::ControllerDeviceAdded {
3221 timestamp: 543,
3222 which: 3,
3223 };
3224 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3225 assert_eq!(e, e2);
3226 }
3227 {
3228 let e = Event::ControllerDeviceRemoved {
3229 timestamp: 555,
3230 which: 3,
3231 };
3232 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3233 assert_eq!(e, e2);
3234 }
3235 {
3236 let e = Event::ControllerDeviceRemapped {
3237 timestamp: 654,
3238 which: 0,
3239 };
3240 let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3241 assert_eq!(e, e2);
3242 }
3243 }
3244
3245 #[test]
3246 fn test_from_ll_keymod_keydown_unknown_bits() {
3247 let mut raw_event = Event::KeyDown {
3248 timestamp: 0,
3249 window_id: 1,
3250 keycode: None,
3251 scancode: Some(Scancode::Q),
3252 keymod: Mod::empty(),
3253 repeat: false,
3254 }
3255 .to_ll()
3256 .unwrap();
3257
3258 raw_event.key.keysym.mod_ = 0xffff;
3260
3261 if let Event::KeyDown { keymod, .. } = Event::from_ll(raw_event) {
3262 assert_eq!(keymod, Mod::all());
3263 } else {
3264 panic!()
3265 }
3266 }
3267
3268 #[test]
3269 fn test_from_ll_keymod_keyup_unknown_bits() {
3270 let mut raw_event = Event::KeyUp {
3271 timestamp: 0,
3272 window_id: 1,
3273 keycode: None,
3274 scancode: Some(Scancode::Q),
3275 keymod: Mod::empty(),
3276 repeat: false,
3277 }
3278 .to_ll()
3279 .unwrap();
3280
3281 raw_event.key.keysym.mod_ = 0xffff;
3283
3284 if let Event::KeyUp { keymod, .. } = Event::from_ll(raw_event) {
3285 assert_eq!(keymod, Mod::all());
3286 } else {
3287 panic!()
3288 }
3289 }
3290}