[go: up one dir, main page]

sdl2/
event.rs

1//! Event Handling
2
3use 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    /// Removes all events in the event queue that match the specified event type.
54    #[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    /// Removes all events in the event queue that match the specified type range.
60    #[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    /// Reads the events at the front of the event queue, until the maximum amount
66    /// of events is read.
67    ///
68    /// The events will _not_ be removed from the queue.
69    ///
70    /// # Example
71    /// ```no_run
72    /// use sdl2::event::Event;
73    ///
74    /// let sdl_context = sdl2::init().unwrap();
75    /// let event_subsystem = sdl_context.event().unwrap();
76    ///
77    /// // Read up to 1024 events
78    /// let events: Vec<Event> = event_subsystem.peek_events(1024);
79    ///
80    /// // Print each one
81    /// for event in events {
82    ///     println!("{:?}", event);
83    /// }
84    /// ```
85    #[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                // The only error possible is "Couldn't lock event queue"
107                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    /// Pushes an event to the event queue.
117    pub fn push_event(&self, event: Event) -> Result<(), String> {
118        self.event_sender().push_event(event)
119    }
120
121    /// Register a custom SDL event.
122    ///
123    /// When pushing a user event, you must make sure that the ``type_`` field is set to a
124    /// registered SDL event number.
125    ///
126    /// The ``code``, ``data1``,  and ``data2`` fields can be used to store user defined data.
127    ///
128    /// See the [SDL documentation](https://wiki.libsdl.org/SDL_UserEvent) for more information.
129    ///
130    /// # Example
131    /// ```
132    /// let sdl = sdl2::init().unwrap();
133    /// let ev = sdl.event().unwrap();
134    ///
135    /// let custom_event_type_id = unsafe { ev.register_event().unwrap() };
136    /// let event = sdl2::event::Event::User {
137    ///    timestamp: 0,
138    ///    window_id: 0,
139    ///    type_: custom_event_type_id,
140    ///    code: 456,
141    ///    data1: 0x1234 as *mut libc::c_void,
142    ///    data2: 0x5678 as *mut libc::c_void,
143    /// };
144    ///
145    /// ev.push_event(event);
146    ///
147    /// ```
148    #[inline(always)]
149    pub unsafe fn register_event(&self) -> Result<u32, String> {
150        Ok(*self.register_events(1)?.first().unwrap())
151    }
152
153    /// Registers custom SDL events.
154    ///
155    /// Returns an error, if no more user events can be created.
156    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    /// Register a custom event
170    ///
171    /// It returns an error when the same type is registered twice.
172    ///
173    /// # Example
174    /// See [push_custom_event](#method.push_custom_event)
175    #[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    /// Push a custom event
193    ///
194    /// If the event type ``T`` was not registered using
195    /// [register_custom_event](#method.register_custom_event),
196    /// this method will panic.
197    ///
198    /// # Example: pushing and receiving a custom event
199    /// ```
200    /// struct SomeCustomEvent {
201    ///     a: i32
202    /// }
203    ///
204    /// let sdl = sdl2::init().unwrap();
205    /// let ev = sdl.event().unwrap();
206    /// let mut ep = sdl.event_pump().unwrap();
207    ///
208    /// ev.register_custom_event::<SomeCustomEvent>().unwrap();
209    ///
210    /// let event = SomeCustomEvent { a: 42 };
211    ///
212    /// ev.push_custom_event(event);
213    ///
214    /// let received = ep.poll_event().unwrap(); // or within a for event in ep.poll_iter()
215    /// if received.is_user_event() {
216    ///     let e2 = received.as_user_event_type::<SomeCustomEvent>().unwrap();
217    ///     assert_eq!(e2.a, 42);
218    /// }
219    /// ```
220    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    /// Create an event sender that can be sent to other threads.
225    ///
226    /// An `EventSender` will not keep the event subsystem alive. If the event subsystem is
227    /// shut down calls to `push_event` and `push_custom_event` will return errors.
228    pub fn event_sender(&self) -> EventSender {
229        EventSender { _priv: () }
230    }
231
232    /// Create an event watcher which is called every time an event is added to event queue.
233    ///
234    /// The watcher is disabled when the return value is dropped.
235    /// Just calling this function without binding to a variable immediately disables the watcher.
236    /// In order to make it persistent, you have to bind in a variable and keep it until it's no
237    /// longer needed.
238    ///
239    /// # Example: dump every event to stderr
240    /// ```
241    /// let sdl = sdl2::init().unwrap();
242    /// let ev = sdl.event().unwrap();
243    ///
244    /// // `let _ = ...` is insufficient, as it is dropped immediately.
245    /// let _event_watch = ev.add_event_watch(|event| {
246    ///     dbg!(event);
247    /// });
248    /// ```
249    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/// Types of events that can be delivered.
258#[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    // TODO: SysWM = sys::SDL_SYSWMEVENT as u32,
274    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)]
408/// An enum of display events.
409pub 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)]
462/// An enum of window events.
463pub 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)]
542/// Different event types.
543pub 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    // TODO: SysWMEvent
577    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        /// How much did we scroll in X, with integer precision
643        x: i32,
644        /// How much did we scroll in Y, with integer precision
645        y: i32,
646        direction: MouseWheelDirection,
647        /// How much did we scroll in X, with floating precision (added in 2.0.18)
648        precise_x: f32,
649        /// How much did we scroll in Y, with floating precision (added in 2.0.18)
650        precise_y: f32,
651        /// The X position of the mouse from the window's origin
652        mouse_x: i32,
653        /// The X position of the mouse from the window's origin
654        mouse_y: i32,
655    },
656
657    JoyAxisMotion {
658        timestamp: u32,
659        /// The joystick's `id`
660        which: u32,
661        axis_idx: u8,
662        value: i16,
663    },
664
665    JoyBallMotion {
666        timestamp: u32,
667        /// The joystick's `id`
668        which: u32,
669        ball_idx: u8,
670        xrel: i16,
671        yrel: i16,
672    },
673
674    JoyHatMotion {
675        timestamp: u32,
676        /// The joystick's `id`
677        which: u32,
678        hat_idx: u8,
679        state: HatState,
680    },
681
682    JoyButtonDown {
683        timestamp: u32,
684        /// The joystick's `id`
685        which: u32,
686        button_idx: u8,
687    },
688    JoyButtonUp {
689        timestamp: u32,
690        /// The joystick's `id`
691        which: u32,
692        button_idx: u8,
693    },
694
695    JoyDeviceAdded {
696        timestamp: u32,
697        /// The newly added joystick's `joystick_index`
698        which: u32,
699    },
700    JoyDeviceRemoved {
701        timestamp: u32,
702        /// The joystick's `id`
703        which: u32,
704    },
705
706    ControllerAxisMotion {
707        timestamp: u32,
708        /// The controller's joystick `id`
709        which: u32,
710        axis: Axis,
711        value: i16,
712    },
713
714    ControllerButtonDown {
715        timestamp: u32,
716        /// The controller's joystick `id`
717        which: u32,
718        button: Button,
719    },
720    ControllerButtonUp {
721        timestamp: u32,
722        /// The controller's joystick `id`
723        which: u32,
724        button: Button,
725    },
726
727    ControllerDeviceAdded {
728        timestamp: u32,
729        /// The newly added controller's `joystick_index`
730        which: u32,
731    },
732    ControllerDeviceRemoved {
733        timestamp: u32,
734        /// The controller's joystick `id`
735        which: u32,
736    },
737    ControllerDeviceRemapped {
738        timestamp: u32,
739        /// The controller's joystick `id`
740        which: u32,
741    },
742
743    ControllerTouchpadDown {
744        timestamp: u32,
745        /// The joystick instance id
746        which: u32,
747        /// The index of the touchpad
748        touchpad: u32,
749        /// The index of the finger on the touchpad
750        finger: u32,
751        /// Normalized in the range 0...1 with 0 being on the left
752        x: f32,
753        /// Normalized in the range 0...1 with 0 being at the top
754        y: f32,
755        /// Normalized in the range 0...1
756        pressure: f32,
757    },
758    ControllerTouchpadMotion {
759        timestamp: u32,
760        /// The joystick instance id
761        which: u32,
762        /// The index of the touchpad
763        touchpad: u32,
764        /// The index of the finger on the touchpad
765        finger: u32,
766        /// Normalized in the range 0...1 with 0 being on the left
767        x: f32,
768        /// Normalized in the range 0...1 with 0 being at the top
769        y: f32,
770        /// Normalized in the range 0...1
771        pressure: f32,
772    },
773    ControllerTouchpadUp {
774        timestamp: u32,
775        /// The joystick instance id
776        which: u32,
777        /// The index of the touchpad
778        touchpad: u32,
779        /// The index of the finger on the touchpad
780        finger: u32,
781        /// Normalized in the range 0...1 with 0 being on the left
782        x: f32,
783        /// Normalized in the range 0...1 with 0 being at the top
784        y: f32,
785        /// Normalized in the range 0...1
786        pressure: f32,
787    },
788
789    /// Triggered when the gyroscope or accelerometer is updated
790    #[cfg(feature = "hidapi")]
791    ControllerSensorUpdated {
792        timestamp: u32,
793        which: u32,
794        sensor: crate::sensor::SensorType,
795        /// Data from the sensor.
796        ///
797        /// See the `sensor` module for more information.
798        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
921/// This does not auto-derive because `User`'s `data` fields can be used to
922/// store pointers to types that are `!Send`. Dereferencing these as pointers
923/// requires using `unsafe` and ensuring your own safety guarantees.
924unsafe impl Send for Event {}
925
926/// This does not auto-derive because `User`'s `data` fields can be used to
927/// store pointers to types that are `!Sync`. Dereferencing these as pointers
928/// requires using `unsafe` and ensuring your own safety guarantees.
929unsafe impl Sync for Event {}
930
931/// Helper function to make converting scancodes
932/// and keycodes to primitive `SDL_Keysym` types.
933#[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
956// TODO: Remove this when from_utf8 is updated in Rust
957// This would honestly be nice if it took &self instead of self,
958// but Event::User's raw pointers kind of removes that possibility.
959impl 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                    // This conversion turns an i32 into a u8; signed-to-unsigned conversions
1378                    // are a bit of a code smell, but that appears to be how SDL defines it.
1379                    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                // don't know how to convert!
1480                None
1481            }
1482        }
1483    }
1484
1485    pub fn from_ll(raw: sys::SDL_Event) -> Event {
1486        let raw_type = unsafe { raw.type_ };
1487
1488        // if event type has not been defined, treat it as a UserEvent
1489        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                // TODO: SysWMEventType
1554                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                        // zero if an audio output device, non-zero if an audio capture device
1964                        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                        // zero if an audio output device, non-zero if an audio capture device
1973                        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                // If we have no other match and the event type is >= 32768
1992                // this is a user event
1993                EventType::User => {
1994                    if raw_type < 32_768 {
1995                        // The type is unknown to us.
1996                        // It's a newer SDL2 type.
1997                        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        } // close unsafe & match
2018    }
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    /// Returns `true` if they are the same "kind" of events.
2052    ///
2053    /// # Example:
2054    ///
2055    /// ```
2056    /// use sdl2::event::Event;
2057    ///
2058    /// let ev1 = Event::JoyButtonDown {
2059    ///     timestamp: 0,
2060    ///     which: 0,
2061    ///     button_idx: 0,
2062    /// };
2063    /// let ev2 = Event::JoyButtonDown {
2064    ///     timestamp: 1,
2065    ///     which: 1,
2066    ///     button_idx: 1,
2067    /// };
2068    ///
2069    /// assert!(ev1 != ev2); // The events aren't equal (they contain different values).
2070    /// assert!(ev1.is_same_kind_as(&ev2)); // But they are of the same kind!
2071    /// ```
2072    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    /// Returns the `timestamp` field of the event.
2128    ///
2129    /// # Example
2130    ///
2131    /// ```
2132    /// use sdl2::event::Event;
2133    ///
2134    /// let ev = Event::JoyButtonDown {
2135    ///     timestamp: 12,
2136    ///     which: 0,
2137    ///     button_idx: 0,
2138    /// };
2139    /// assert!(ev.get_timestamp() == 12);
2140    /// ```
2141    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    /// Returns the `window_id` field of the event if it's present (not all events have it!).
2200    ///
2201    /// # Example
2202    ///
2203    /// ```
2204    /// use sdl2::event::Event;
2205    ///
2206    /// let ev = Event::JoyButtonDown {
2207    ///     timestamp: 0,
2208    ///     which: 0,
2209    ///     button_idx: 0,
2210    /// };
2211    /// assert!(ev.get_window_id() == None);
2212    ///
2213    /// let another_ev = Event::DropBegin {
2214    ///     timestamp: 0,
2215    ///     window_id: 3,
2216    /// };
2217    /// assert!(another_ev.get_window_id() == Some(3));
2218    /// ```
2219    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    /// Returns `true` if this is a window event.
2240    ///
2241    /// # Example
2242    ///
2243    /// ```
2244    /// use sdl2::event::Event;
2245    ///
2246    /// let ev = Event::Quit {
2247    ///     timestamp: 0,
2248    /// };
2249    /// assert!(ev.is_window());
2250    ///
2251    /// let ev = Event::AppLowMemory {
2252    ///     timestamp: 0,
2253    /// };
2254    /// assert!(ev.is_window());
2255    ///
2256    /// let another_ev = Event::TextInput {
2257    ///     timestamp: 0,
2258    ///     window_id: 0,
2259    ///     text: String::new(),
2260    /// };
2261    /// assert!(another_ev.is_window() == false); // Not a window event!
2262    /// ```
2263    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    /// Returns `true` if this is a keyboard event.
2278    ///
2279    /// # Example
2280    ///
2281    /// ```
2282    /// use sdl2::event::Event;
2283    /// use sdl2::keyboard::Mod;
2284    ///
2285    /// let ev = Event::KeyDown {
2286    ///     timestamp: 0,
2287    ///     window_id: 0,
2288    ///     keycode: None,
2289    ///     scancode: None,
2290    ///     keymod: Mod::empty(),
2291    ///     repeat: false,
2292    /// };
2293    /// assert!(ev.is_keyboard());
2294    ///
2295    /// let another_ev = Event::Quit {
2296    ///     timestamp: 0,
2297    /// };
2298    /// assert!(another_ev.is_keyboard() == false); // Not a keyboard event!
2299    /// ```
2300    pub fn is_keyboard(&self) -> bool {
2301        matches!(self, Self::KeyDown { .. } | Self::KeyUp { .. })
2302    }
2303
2304    /// Returns `true` if this is a text event.
2305    ///
2306    /// # Example
2307    ///
2308    /// ```
2309    /// use sdl2::event::Event;
2310    ///
2311    /// let ev = Event::TextInput {
2312    ///     timestamp: 0,
2313    ///     window_id: 0,
2314    ///     text: String::new(),
2315    /// };
2316    /// assert!(ev.is_text());
2317    ///
2318    /// let another_ev = Event::Quit {
2319    ///     timestamp: 0,
2320    /// };
2321    /// assert!(another_ev.is_text() == false); // Not a text event!
2322    /// ```
2323    pub fn is_text(&self) -> bool {
2324        matches!(self, Self::TextEditing { .. } | Self::TextInput { .. })
2325    }
2326
2327    /// Returns `true` if this is a mouse event.
2328    ///
2329    /// # Example
2330    ///
2331    /// ```
2332    /// use sdl2::event::Event;
2333    /// use sdl2::mouse::MouseWheelDirection;
2334    ///
2335    /// let ev = Event::MouseWheel {
2336    ///     timestamp: 0,
2337    ///     window_id: 0,
2338    ///     which: 0,
2339    ///     precise_x: 0.0,
2340    ///     precise_y: 0.0,
2341    ///     x: 0,
2342    ///     y: 0,
2343    ///     mouse_x: 0,
2344    ///     mouse_y: 0,
2345    ///     direction: MouseWheelDirection::Normal,
2346    /// };
2347    /// assert!(ev.is_mouse());
2348    ///
2349    /// let another_ev = Event::Quit {
2350    ///     timestamp: 0,
2351    /// };
2352    /// assert!(another_ev.is_mouse() == false); // Not a mouse event!
2353    /// ```
2354    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    /// Returns `true` if this mouse event is coming from touch.
2365    ///
2366    /// If used on any other kind of event, non-mouse related, this returns `false`.
2367    pub fn is_touch(&self) -> bool {
2368        // FIXME: Use a constant from sdl2-sys when bindgen will be fixed (see https://github.com/Rust-SDL2/rust-sdl2/issues/1265)
2369        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    /// Returns `true` if this is a controller event.
2390    ///
2391    /// # Example
2392    ///
2393    /// ```
2394    /// use sdl2::event::Event;
2395    ///
2396    /// let ev = Event::ControllerDeviceAdded {
2397    ///     timestamp: 0,
2398    ///     which: 0,
2399    /// };
2400    /// assert!(ev.is_controller());
2401    ///
2402    /// let another_ev = Event::Quit {
2403    ///     timestamp: 0,
2404    /// };
2405    /// assert!(another_ev.is_controller() == false); // Not a controller event!
2406    /// ```
2407    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    /// Returns `true` if this is a joy event.
2420    ///
2421    /// # Example
2422    ///
2423    /// ```
2424    /// use sdl2::event::Event;
2425    ///
2426    /// let ev = Event::JoyButtonUp {
2427    ///     timestamp: 0,
2428    ///     which: 0,
2429    ///     button_idx: 0,
2430    /// };
2431    /// assert!(ev.is_joy());
2432    ///
2433    /// let another_ev = Event::Quit {
2434    ///     timestamp: 0,
2435    /// };
2436    /// assert!(another_ev.is_joy() == false); // Not a joy event!
2437    /// ```
2438    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    /// Returns `true` if this is a finger event.
2452    ///
2453    /// # Example
2454    ///
2455    /// ```
2456    /// use sdl2::event::Event;
2457    ///
2458    /// let ev = Event::FingerMotion {
2459    ///     timestamp: 0,
2460    ///     touch_id: 0,
2461    ///     finger_id: 0,
2462    ///     x: 0.,
2463    ///     y: 0.,
2464    ///     dx: 0.,
2465    ///     dy: 0.,
2466    ///     pressure: 0.,
2467    /// };
2468    /// assert!(ev.is_finger());
2469    ///
2470    /// let another_ev = Event::Quit {
2471    ///     timestamp: 0,
2472    /// };
2473    /// assert!(another_ev.is_finger() == false); // Not a finger event!
2474    /// ```
2475    pub fn is_finger(&self) -> bool {
2476        matches!(
2477            self,
2478            Self::FingerDown { .. } | Self::FingerUp { .. } | Self::FingerMotion { .. }
2479        )
2480    }
2481
2482    /// Returns `true` if this is a dollar event.
2483    ///
2484    /// # Example
2485    ///
2486    /// ```
2487    /// use sdl2::event::Event;
2488    ///
2489    /// let ev = Event::DollarGesture {
2490    ///     timestamp: 0,
2491    ///     touch_id: 0,
2492    ///     gesture_id: 0,
2493    ///     num_fingers: 0,
2494    ///     error: 0.,
2495    ///     x: 0.,
2496    ///     y: 0.,
2497    /// };
2498    /// assert!(ev.is_dollar());
2499    ///
2500    /// let another_ev = Event::Quit {
2501    ///     timestamp: 0,
2502    /// };
2503    /// assert!(another_ev.is_dollar() == false); // Not a dollar event!
2504    /// ```
2505    pub fn is_dollar(&self) -> bool {
2506        matches!(self, Self::DollarGesture { .. } | Self::DollarRecord { .. })
2507    }
2508
2509    /// Returns `true` if this is a drop event.
2510    ///
2511    /// # Example
2512    ///
2513    /// ```
2514    /// use sdl2::event::Event;
2515    ///
2516    /// let ev = Event::DropBegin {
2517    ///     timestamp: 0,
2518    ///     window_id: 3,
2519    /// };
2520    /// assert!(ev.is_drop());
2521    ///
2522    /// let another_ev = Event::Quit {
2523    ///     timestamp: 0,
2524    /// };
2525    /// assert!(another_ev.is_drop() == false); // Not a drop event!
2526    /// ```
2527    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    /// Returns `true` if this is an audio event.
2538    ///
2539    /// # Example
2540    ///
2541    /// ```
2542    /// use sdl2::event::Event;
2543    ///
2544    /// let ev = Event::AudioDeviceAdded {
2545    ///     timestamp: 0,
2546    ///     which: 3,
2547    ///     iscapture: false,
2548    /// };
2549    /// assert!(ev.is_audio());
2550    ///
2551    /// let another_ev = Event::Quit {
2552    ///     timestamp: 0,
2553    /// };
2554    /// assert!(another_ev.is_audio() == false); // Not an audio event!
2555    /// ```
2556    pub fn is_audio(&self) -> bool {
2557        matches!(
2558            self,
2559            Self::AudioDeviceAdded { .. } | Self::AudioDeviceRemoved { .. }
2560        )
2561    }
2562
2563    /// Returns `true` if this is a render event.
2564    ///
2565    /// # Example
2566    ///
2567    /// ```
2568    /// use sdl2::event::Event;
2569    ///
2570    /// let ev = Event::RenderTargetsReset {
2571    ///     timestamp: 0,
2572    /// };
2573    /// assert!(ev.is_render());
2574    ///
2575    /// let another_ev = Event::Quit {
2576    ///     timestamp: 0,
2577    /// };
2578    /// assert!(another_ev.is_render() == false); // Not a render event!
2579    /// ```
2580    pub fn is_render(&self) -> bool {
2581        matches!(
2582            self,
2583            Self::RenderTargetsReset { .. } | Self::RenderDeviceReset { .. }
2584        )
2585    }
2586
2587    /// Returns `true` if this is a locale event.
2588    ///
2589    /// # Example
2590    ///
2591    /// ```
2592    /// use sdl2::event::Event;
2593    ///
2594    /// let ev = Event::LocaleChanged {
2595    ///    timestamp: 0,
2596    /// };
2597    /// assert!(ev.is_locale());
2598    ///
2599    /// let another_ev = Event::Quit {
2600    ///   timestamp: 0,
2601    /// };
2602    /// assert!(another_ev.is_locale() == false); // Not a locale event!
2603    /// ```
2604    pub fn is_locale(&self) -> bool {
2605        matches!(self, Self::LocaleChanged { .. })
2606    }
2607
2608    /// Returns `true` if this is a user event.
2609    ///
2610    /// # Example
2611    ///
2612    /// ```
2613    /// use sdl2::event::Event;
2614    ///
2615    /// let ev = Event::User {
2616    ///     timestamp: 0,
2617    ///     window_id: 0,
2618    ///     type_: 0,
2619    ///     code: 0,
2620    ///     data1: ::std::ptr::null_mut(),
2621    ///     data2: ::std::ptr::null_mut(),
2622    /// };
2623    /// assert!(ev.is_user());
2624    ///
2625    /// let another_ev = Event::Quit {
2626    ///     timestamp: 0,
2627    /// };
2628    /// assert!(another_ev.is_user() == false); // Not a user event!
2629    /// ```
2630    pub fn is_user(&self) -> bool {
2631        matches!(self, Self::User { .. })
2632    }
2633
2634    /// Returns `true` if this is an unknown event.
2635    ///
2636    /// # Example
2637    ///
2638    /// ```
2639    /// use sdl2::event::Event;
2640    ///
2641    /// let ev = Event::Unknown {
2642    ///     timestamp: 0,
2643    ///     type_: 0,
2644    /// };
2645    /// assert!(ev.is_unknown());
2646    ///
2647    /// let another_ev = Event::Quit {
2648    ///     timestamp: 0,
2649    /// };
2650    /// assert!(another_ev.is_unknown() == false); // Not an unknown event!
2651    /// ```
2652    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    /// Query if an event type is enabled.
2692    #[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    /// Enable an event type. Returns if the event type was enabled before the call.
2700    #[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    /// Disable an event type. Returns if the event type was enabled before the call.
2708    #[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    /// Polls for currently pending events.
2716    ///
2717    /// If no events are pending, `None` is returned.
2718    pub fn poll_event(&mut self) -> Option<Event> {
2719        unsafe { poll_event() }
2720    }
2721
2722    /// Returns a polling iterator that calls `poll_event()`.
2723    /// The iterator will terminate once there are no more pending events.
2724    ///
2725    /// # Example
2726    /// ```no_run
2727    /// let sdl_context = sdl2::init().unwrap();
2728    /// let mut event_pump = sdl_context.event_pump().unwrap();
2729    ///
2730    /// for event in event_pump.poll_iter() {
2731    ///     use sdl2::event::Event;
2732    ///     match event {
2733    ///         Event::KeyDown {..} => { /*...*/ }
2734    ///         _ => ()
2735    ///     }
2736    /// }
2737    /// ```
2738    pub fn poll_iter(&mut self) -> EventPollIterator {
2739        EventPollIterator {
2740            _marker: PhantomData,
2741        }
2742    }
2743
2744    /// Pumps the event loop, gathering events from the input devices.
2745    #[doc(alias = "SDL_PumpEvents")]
2746    pub fn pump_events(&mut self) {
2747        unsafe {
2748            sys::SDL_PumpEvents();
2749        };
2750    }
2751
2752    /// Waits indefinitely for the next available event.
2753    pub fn wait_event(&mut self) -> Event {
2754        unsafe { wait_event() }
2755    }
2756
2757    /// Waits until the specified timeout (in milliseconds) for the next available event.
2758    pub fn wait_event_timeout(&mut self, timeout: u32) -> Option<Event> {
2759        unsafe { wait_event_timeout(timeout) }
2760    }
2761
2762    /// Returns a waiting iterator that calls `wait_event()`.
2763    ///
2764    /// Note: The iterator will never terminate.
2765    pub fn wait_iter(&mut self) -> EventWaitIterator {
2766        EventWaitIterator {
2767            _marker: PhantomData,
2768        }
2769    }
2770
2771    /// Returns a waiting iterator that calls `wait_event_timeout()`.
2772    ///
2773    /// Note: The iterator will never terminate, unless waiting for an event
2774    /// exceeds the specified timeout.
2775    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/// An iterator that calls `EventPump::poll_event()`.
2799#[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/// An iterator that calls `EventPump::wait_event()`.
2813#[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/// An iterator that calls `EventPump::wait_event_timeout()`.
2826#[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
2839/// A sendible type that can push events to the event queue.
2840pub struct EventSender {
2841    _priv: (),
2842}
2843
2844impl EventSender {
2845    /// Pushes an event to the event queue.
2846    #[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    /// Push a custom event
2862    ///
2863    /// If the event type ``T`` was not registered using
2864    /// [EventSubsystem::register_custom_event]
2865    /// (../struct.EventSubsystem.html#method.register_custom_event),
2866    /// this method will panic.
2867    ///
2868    /// # Example: pushing and receiving a custom event
2869    /// ```
2870    /// struct SomeCustomEvent {
2871    ///     a: i32
2872    /// }
2873    ///
2874    /// let sdl = sdl2::init().unwrap();
2875    /// let ev = sdl.event().unwrap();
2876    /// let mut ep = sdl.event_pump().unwrap();
2877    ///
2878    /// ev.register_custom_event::<SomeCustomEvent>().unwrap();
2879    ///
2880    /// let event = SomeCustomEvent { a: 42 };
2881    ///
2882    /// ev.push_custom_event(event);
2883    ///
2884    /// let received = ep.poll_event().unwrap(); // or within a for event in ep.poll_iter()
2885    /// if received.is_user_event() {
2886    ///     let e2 = received.as_user_event_type::<SomeCustomEvent>().unwrap();
2887    ///     assert_eq!(e2.a, 42);
2888    /// }
2889    /// ```
2890    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
2919/// A callback trait for [`EventSubsystem::add_event_watch`].
2920pub trait EventWatchCallback {
2921    fn callback(&mut self, event: Event);
2922}
2923
2924/// An handler for the event watch callback.
2925/// One must bind this struct in a variable as long as you want to keep the callback active.
2926/// For further information, see [`EventSubsystem::add_event_watch`].
2927pub 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    /// Activates the event watch.
2946    /// Does nothing if it is already activated.
2947    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    /// Deactivates the event watch.
2955    /// Does nothing if it is already activated.
2956    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    /// Returns if the event watch is activated.
2964    pub fn activated(&self) -> bool {
2965        self.activated
2966    }
2967
2968    /// Set the activation state of the event watch.
2969    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    // Tests a round-trip conversion from an Event type to
3020    // the SDL event type and back, to make sure it's sane.
3021    #[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        // Simulate SDL setting bits unknown to us, see PR #780
3259        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        // Simulate SDL setting bits unknown to us, see PR #780
3282        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}