[go: up one dir, main page]

sdl2/
event.rs

1/*!
2Event Handling
3 */
4
5use std::borrow::ToOwned;
6use std::collections::HashMap;
7use std::convert::TryFrom;
8use std::ffi::CStr;
9use std::iter::FromIterator;
10use std::marker::PhantomData;
11use std::mem;
12use std::mem::transmute;
13use std::ptr;
14use std::sync::Mutex;
15
16use libc::c_int;
17use libc::c_void;
18
19use crate::controller;
20use crate::controller::{Axis, Button};
21use crate::get_error;
22use crate::joystick;
23use crate::joystick::HatState;
24use crate::keyboard;
25use crate::keyboard::Keycode;
26use crate::keyboard::Mod;
27use crate::keyboard::Scancode;
28use crate::mouse;
29use crate::mouse::{MouseButton, MouseState, MouseWheelDirection};
30use crate::sys;
31use crate::sys::SDL_EventFilter;
32use crate::sys::SDL_EventType;
33use crate::video::Orientation;
34
35struct CustomEventTypeMaps {
36    sdl_id_to_type_id: HashMap<u32, ::std::any::TypeId>,
37    type_id_to_sdl_id: HashMap<::std::any::TypeId, u32>,
38}
39
40impl CustomEventTypeMaps {
41    fn new() -> Self {
42        CustomEventTypeMaps {
43            sdl_id_to_type_id: HashMap::new(),
44            type_id_to_sdl_id: HashMap::new(),
45        }
46    }
47}
48
49lazy_static! {
50    static ref CUSTOM_EVENT_TYPES: Mutex<CustomEventTypeMaps> =
51        Mutex::new(CustomEventTypeMaps::new());
52}
53
54impl crate::EventSubsystem {
55    /// Removes all events in the event queue that match the specified event type.
56    #[doc(alias = "SDL_FlushEvent")]
57    pub fn flush_event(&self, event_type: EventType) {
58        unsafe { sys::SDL_FlushEvent(event_type as u32) };
59    }
60
61    /// Removes all events in the event queue that match the specified type range.
62    #[doc(alias = "SDL_FlushEvents")]
63    pub fn flush_events(&self, min_type: u32, max_type: u32) {
64        unsafe { sys::SDL_FlushEvents(min_type, max_type) };
65    }
66
67    /// Reads the events at the front of the event queue, until the maximum amount
68    /// of events is read.
69    ///
70    /// The events will _not_ be removed from the queue.
71    ///
72    /// # Example
73    /// ```no_run
74    /// use sdl2::event::Event;
75    ///
76    /// let sdl_context = sdl2::init().unwrap();
77    /// let event_subsystem = sdl_context.event().unwrap();
78    ///
79    /// // Read up to 1024 events
80    /// let events: Vec<Event> = event_subsystem.peek_events(1024);
81    ///
82    /// // Print each one
83    /// for event in events {
84    ///     println!("{:?}", event);
85    /// }
86    /// ```
87    #[doc(alias = "SDL_PeepEvents")]
88    pub fn peek_events<B>(&self, max_amount: u32) -> B
89    where
90        B: FromIterator<Event>,
91    {
92        unsafe {
93            let mut events = Vec::with_capacity(max_amount as usize);
94
95            let result = {
96                let events_ptr = events.as_mut_ptr();
97
98                sys::SDL_PeepEvents(
99                    events_ptr,
100                    max_amount as c_int,
101                    sys::SDL_eventaction::SDL_PEEKEVENT,
102                    SDL_EventType::SDL_FIRSTEVENT as u32,
103                    SDL_EventType::SDL_LASTEVENT as u32,
104                )
105            };
106
107            if result < 0 {
108                // The only error possible is "Couldn't lock event queue"
109                panic!("{}", get_error());
110            } else {
111                events.set_len(result as usize);
112
113                events.into_iter().map(Event::from_ll).collect()
114            }
115        }
116    }
117
118    /// Pushes an event to the event queue.
119    pub fn push_event(&self, event: Event) -> Result<(), String> {
120        self.event_sender().push_event(event)
121    }
122
123    /// Register a custom SDL event.
124    ///
125    /// When pushing a user event, you must make sure that the ``type_`` field is set to a
126    /// registered SDL event number.
127    ///
128    /// The ``code``, ``data1``,  and ``data2`` fields can be used to store user defined data.
129    ///
130    /// See the [SDL documentation](https://wiki.libsdl.org/SDL_UserEvent) for more information.
131    ///
132    /// # Example
133    /// ```
134    /// let sdl = sdl2::init().unwrap();
135    /// let ev = sdl.event().unwrap();
136    ///
137    /// let custom_event_type_id = unsafe { ev.register_event().unwrap() };
138    /// let event = sdl2::event::Event::User {
139    ///    timestamp: 0,
140    ///    window_id: 0,
141    ///    type_: custom_event_type_id,
142    ///    code: 456,
143    ///    data1: 0x1234 as *mut libc::c_void,
144    ///    data2: 0x5678 as *mut libc::c_void,
145    /// };
146    ///
147    /// ev.push_event(event);
148    ///
149    /// ```
150    #[inline(always)]
151    pub unsafe fn register_event(&self) -> Result<u32, String> {
152        Ok(*self.register_events(1)?.first().unwrap())
153    }
154
155    /// Registers custom SDL events.
156    ///
157    /// Returns an error, if no more user events can be created.
158    pub unsafe fn register_events(&self, nr: u32) -> Result<Vec<u32>, String> {
159        let result = sys::SDL_RegisterEvents(nr as ::libc::c_int);
160        const ERR_NR: u32 = u32::MAX - 1;
161
162        match result {
163            ERR_NR => Err("No more user events can be created; SDL_LASTEVENT reached".to_owned()),
164            _ => {
165                let event_ids = (result..(result + nr)).collect();
166                Ok(event_ids)
167            }
168        }
169    }
170
171    /// Register a custom event
172    ///
173    /// It returns an error when the same type is registered twice.
174    ///
175    /// # Example
176    /// See [push_custom_event](#method.push_custom_event)
177    #[inline(always)]
178    pub fn register_custom_event<T: ::std::any::Any>(&self) -> Result<(), String> {
179        use std::any::TypeId;
180        let event_id = *(unsafe { self.register_events(1) })?.first().unwrap();
181        let mut cet = CUSTOM_EVENT_TYPES.lock().unwrap();
182        let type_id = TypeId::of::<Box<T>>();
183
184        if cet.type_id_to_sdl_id.contains_key(&type_id) {
185            return Err("The same event type can not be registered twice!".to_owned());
186        }
187
188        cet.sdl_id_to_type_id.insert(event_id, type_id);
189        cet.type_id_to_sdl_id.insert(type_id, event_id);
190
191        Ok(())
192    }
193
194    /// Push a custom event
195    ///
196    /// If the event type ``T`` was not registered using
197    /// [register_custom_event](#method.register_custom_event),
198    /// this method will panic.
199    ///
200    /// # Example: pushing and receiving a custom event
201    /// ```
202    /// struct SomeCustomEvent {
203    ///     a: i32
204    /// }
205    ///
206    /// let sdl = sdl2::init().unwrap();
207    /// let ev = sdl.event().unwrap();
208    /// let mut ep = sdl.event_pump().unwrap();
209    ///
210    /// ev.register_custom_event::<SomeCustomEvent>().unwrap();
211    ///
212    /// let event = SomeCustomEvent { a: 42 };
213    ///
214    /// ev.push_custom_event(event);
215    ///
216    /// let received = ep.poll_event().unwrap(); // or within a for event in ep.poll_iter()
217    /// if received.is_user_event() {
218    ///     let e2 = received.as_user_event_type::<SomeCustomEvent>().unwrap();
219    ///     assert_eq!(e2.a, 42);
220    /// }
221    /// ```
222    pub fn push_custom_event<T: ::std::any::Any>(&self, event: T) -> Result<(), String> {
223        self.event_sender().push_custom_event(event)
224    }
225
226    /// Create an event sender that can be sent to other threads.
227    ///
228    /// An `EventSender` will not keep the event subsystem alive. If the event subsystem is
229    /// shut down calls to `push_event` and `push_custom_event` will return errors.
230    pub fn event_sender(&self) -> EventSender {
231        EventSender { _priv: () }
232    }
233
234    /// Create an event watcher which is called every time an event is added to event queue.
235    ///
236    /// The watcher is disabled when the return value is dropped.
237    /// Just calling this function without binding to a variable immediately disables the watcher.
238    /// In order to make it persistent, you have to bind in a variable and keep it until it's no
239    /// longer needed.
240    ///
241    /// # Example: dump every event to stderr
242    /// ```
243    /// let sdl = sdl2::init().unwrap();
244    /// let ev = sdl.event().unwrap();
245    ///
246    /// // `let _ = ...` is insufficient, as it is dropped immediately.
247    /// let _event_watch = ev.add_event_watch(|event| {
248    ///     dbg!(event);
249    /// });
250    /// ```
251    pub fn add_event_watch<'a, CB: EventWatchCallback + 'a>(
252        &self,
253        callback: CB,
254    ) -> EventWatch<'a, CB> {
255        EventWatch::add(callback)
256    }
257}
258
259/// Types of events that can be delivered.
260#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
261#[repr(u32)]
262pub enum EventType {
263    First = SDL_EventType::SDL_FIRSTEVENT as u32,
264
265    Quit = SDL_EventType::SDL_QUIT as u32,
266    AppTerminating = SDL_EventType::SDL_APP_TERMINATING as u32,
267    AppLowMemory = SDL_EventType::SDL_APP_LOWMEMORY as u32,
268    AppWillEnterBackground = SDL_EventType::SDL_APP_WILLENTERBACKGROUND as u32,
269    AppDidEnterBackground = SDL_EventType::SDL_APP_DIDENTERBACKGROUND as u32,
270    AppWillEnterForeground = SDL_EventType::SDL_APP_WILLENTERFOREGROUND as u32,
271    AppDidEnterForeground = SDL_EventType::SDL_APP_DIDENTERFOREGROUND as u32,
272
273    Display = SDL_EventType::SDL_DISPLAYEVENT as u32,
274    Window = SDL_EventType::SDL_WINDOWEVENT as u32,
275    // TODO: SysWM = sys::SDL_SYSWMEVENT as u32,
276    KeyDown = SDL_EventType::SDL_KEYDOWN as u32,
277    KeyUp = SDL_EventType::SDL_KEYUP as u32,
278    TextEditing = SDL_EventType::SDL_TEXTEDITING as u32,
279    TextInput = SDL_EventType::SDL_TEXTINPUT as u32,
280
281    MouseMotion = SDL_EventType::SDL_MOUSEMOTION as u32,
282    MouseButtonDown = SDL_EventType::SDL_MOUSEBUTTONDOWN as u32,
283    MouseButtonUp = SDL_EventType::SDL_MOUSEBUTTONUP as u32,
284    MouseWheel = SDL_EventType::SDL_MOUSEWHEEL as u32,
285
286    JoyAxisMotion = SDL_EventType::SDL_JOYAXISMOTION as u32,
287    JoyBallMotion = SDL_EventType::SDL_JOYBALLMOTION as u32,
288    JoyHatMotion = SDL_EventType::SDL_JOYHATMOTION as u32,
289    JoyButtonDown = SDL_EventType::SDL_JOYBUTTONDOWN as u32,
290    JoyButtonUp = SDL_EventType::SDL_JOYBUTTONUP as u32,
291    JoyDeviceAdded = SDL_EventType::SDL_JOYDEVICEADDED as u32,
292    JoyDeviceRemoved = SDL_EventType::SDL_JOYDEVICEREMOVED as u32,
293
294    ControllerAxisMotion = SDL_EventType::SDL_CONTROLLERAXISMOTION as u32,
295    ControllerButtonDown = SDL_EventType::SDL_CONTROLLERBUTTONDOWN as u32,
296    ControllerButtonUp = SDL_EventType::SDL_CONTROLLERBUTTONUP as u32,
297    ControllerDeviceAdded = SDL_EventType::SDL_CONTROLLERDEVICEADDED as u32,
298    ControllerDeviceRemoved = SDL_EventType::SDL_CONTROLLERDEVICEREMOVED as u32,
299    ControllerDeviceRemapped = SDL_EventType::SDL_CONTROLLERDEVICEREMAPPED as u32,
300    ControllerTouchpadDown = SDL_EventType::SDL_CONTROLLERTOUCHPADDOWN as u32,
301    ControllerTouchpadMotion = SDL_EventType::SDL_CONTROLLERTOUCHPADMOTION as u32,
302    ControllerTouchpadUp = SDL_EventType::SDL_CONTROLLERTOUCHPADUP as u32,
303    #[cfg(feature = "hidapi")]
304    ControllerSensorUpdated = SDL_EventType::SDL_CONTROLLERSENSORUPDATE as u32,
305
306    FingerDown = SDL_EventType::SDL_FINGERDOWN as u32,
307    FingerUp = SDL_EventType::SDL_FINGERUP as u32,
308    FingerMotion = SDL_EventType::SDL_FINGERMOTION as u32,
309    DollarGesture = SDL_EventType::SDL_DOLLARGESTURE as u32,
310    DollarRecord = SDL_EventType::SDL_DOLLARRECORD as u32,
311    MultiGesture = SDL_EventType::SDL_MULTIGESTURE as u32,
312
313    ClipboardUpdate = SDL_EventType::SDL_CLIPBOARDUPDATE as u32,
314    DropFile = SDL_EventType::SDL_DROPFILE as u32,
315    DropText = SDL_EventType::SDL_DROPTEXT as u32,
316    DropBegin = SDL_EventType::SDL_DROPBEGIN as u32,
317    DropComplete = SDL_EventType::SDL_DROPCOMPLETE as u32,
318
319    AudioDeviceAdded = SDL_EventType::SDL_AUDIODEVICEADDED as u32,
320    AudioDeviceRemoved = SDL_EventType::SDL_AUDIODEVICEREMOVED as u32,
321
322    RenderTargetsReset = SDL_EventType::SDL_RENDER_TARGETS_RESET as u32,
323    RenderDeviceReset = SDL_EventType::SDL_RENDER_DEVICE_RESET as u32,
324
325    User = SDL_EventType::SDL_USEREVENT as u32,
326    Last = SDL_EventType::SDL_LASTEVENT as u32,
327}
328
329impl TryFrom<u32> for EventType {
330    type Error = ();
331
332    fn try_from(n: u32) -> Result<Self, Self::Error> {
333        use self::EventType::*;
334        use crate::sys::SDL_EventType::*;
335
336        Ok(match unsafe { transmute(n) } {
337            SDL_FIRSTEVENT => First,
338
339            SDL_QUIT => Quit,
340            SDL_APP_TERMINATING => AppTerminating,
341            SDL_APP_LOWMEMORY => AppLowMemory,
342            SDL_APP_WILLENTERBACKGROUND => AppWillEnterBackground,
343            SDL_APP_DIDENTERBACKGROUND => AppDidEnterBackground,
344            SDL_APP_WILLENTERFOREGROUND => AppWillEnterForeground,
345            SDL_APP_DIDENTERFOREGROUND => AppDidEnterForeground,
346
347            SDL_DISPLAYEVENT => Display,
348            SDL_WINDOWEVENT => Window,
349
350            SDL_KEYDOWN => KeyDown,
351            SDL_KEYUP => KeyUp,
352            SDL_TEXTEDITING => TextEditing,
353            SDL_TEXTINPUT => TextInput,
354
355            SDL_MOUSEMOTION => MouseMotion,
356            SDL_MOUSEBUTTONDOWN => MouseButtonDown,
357            SDL_MOUSEBUTTONUP => MouseButtonUp,
358            SDL_MOUSEWHEEL => MouseWheel,
359
360            SDL_JOYAXISMOTION => JoyAxisMotion,
361            SDL_JOYBALLMOTION => JoyBallMotion,
362            SDL_JOYHATMOTION => JoyHatMotion,
363            SDL_JOYBUTTONDOWN => JoyButtonDown,
364            SDL_JOYBUTTONUP => JoyButtonUp,
365            SDL_JOYDEVICEADDED => JoyDeviceAdded,
366            SDL_JOYDEVICEREMOVED => JoyDeviceRemoved,
367
368            SDL_CONTROLLERAXISMOTION => ControllerAxisMotion,
369            SDL_CONTROLLERBUTTONDOWN => ControllerButtonDown,
370            SDL_CONTROLLERBUTTONUP => ControllerButtonUp,
371            SDL_CONTROLLERDEVICEADDED => ControllerDeviceAdded,
372            SDL_CONTROLLERDEVICEREMOVED => ControllerDeviceRemoved,
373            SDL_CONTROLLERDEVICEREMAPPED => ControllerDeviceRemapped,
374            SDL_CONTROLLERTOUCHPADDOWN => ControllerTouchpadDown,
375            SDL_CONTROLLERTOUCHPADMOTION => ControllerTouchpadMotion,
376            SDL_CONTROLLERTOUCHPADUP => ControllerTouchpadUp,
377            #[cfg(feature = "hidapi")]
378            SDL_CONTROLLERSENSORUPDATE => ControllerSensorUpdated,
379
380            SDL_FINGERDOWN => FingerDown,
381            SDL_FINGERUP => FingerUp,
382            SDL_FINGERMOTION => FingerMotion,
383            SDL_DOLLARGESTURE => DollarGesture,
384            SDL_DOLLARRECORD => DollarRecord,
385            SDL_MULTIGESTURE => MultiGesture,
386
387            SDL_CLIPBOARDUPDATE => ClipboardUpdate,
388            SDL_DROPFILE => DropFile,
389            SDL_DROPTEXT => DropText,
390            SDL_DROPBEGIN => DropBegin,
391            SDL_DROPCOMPLETE => DropComplete,
392
393            SDL_AUDIODEVICEADDED => AudioDeviceAdded,
394            SDL_AUDIODEVICEREMOVED => AudioDeviceRemoved,
395
396            SDL_RENDER_TARGETS_RESET => RenderTargetsReset,
397            SDL_RENDER_DEVICE_RESET => RenderDeviceReset,
398
399            SDL_USEREVENT => User,
400            SDL_LASTEVENT => Last,
401
402            _ => return Err(()),
403        })
404    }
405}
406
407#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
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    User {
903        timestamp: u32,
904        window_id: u32,
905        type_: u32,
906        code: i32,
907        data1: *mut c_void,
908        data2: *mut c_void,
909    },
910
911    Unknown {
912        timestamp: u32,
913        type_: u32,
914    },
915}
916
917/// This does not auto-derive because `User`'s `data` fields can be used to
918/// store pointers to types that are `!Send`. Dereferencing these as pointers
919/// requires using `unsafe` and ensuring your own safety guarantees.
920unsafe impl Send for Event {}
921
922/// This does not auto-derive because `User`'s `data` fields can be used to
923/// store pointers to types that are `!Sync`. Dereferencing these as pointers
924/// requires using `unsafe` and ensuring your own safety guarantees.
925unsafe impl Sync for Event {}
926
927/// Helper function to make converting scancodes
928/// and keycodes to primitive `SDL_Keysym` types.
929#[doc(alias = "SDL_Keysym")]
930fn mk_keysym<S, K>(scancode: S, keycode: K, keymod: Mod) -> sys::SDL_Keysym
931where
932    S: Into<Option<Scancode>>,
933    K: Into<Option<Keycode>>,
934{
935    let scancode = scancode
936        .into()
937        .map(|sc| unsafe { transmute::<u32, sys::SDL_Scancode>(sc as u32) })
938        .unwrap_or(sys::SDL_Scancode::SDL_SCANCODE_UNKNOWN);
939    let keycode = keycode
940        .into()
941        .map(|kc| kc.into())
942        .unwrap_or(sys::SDL_KeyCode::SDLK_UNKNOWN as i32);
943    let keymod = keymod.bits();
944    sys::SDL_Keysym {
945        scancode,
946        sym: keycode,
947        mod_: keymod,
948        unused: 0,
949    }
950}
951
952// TODO: Remove this when from_utf8 is updated in Rust
953// This would honestly be nice if it took &self instead of self,
954// but Event::User's raw pointers kind of removes that possibility.
955impl Event {
956    fn to_ll(&self) -> Option<sys::SDL_Event> {
957        let mut ret = mem::MaybeUninit::uninit();
958        match *self {
959            Event::User {
960                window_id,
961                type_,
962                code,
963                data1,
964                data2,
965                timestamp,
966            } => {
967                let event = sys::SDL_UserEvent {
968                    type_,
969                    timestamp,
970                    windowID: window_id,
971                    code,
972                    data1,
973                    data2,
974                };
975                unsafe {
976                    ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_UserEvent, 1);
977                    Some(ret.assume_init())
978                }
979            }
980
981            Event::Quit { timestamp } => {
982                let event = sys::SDL_QuitEvent {
983                    type_: SDL_EventType::SDL_QUIT as u32,
984                    timestamp,
985                };
986                unsafe {
987                    ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_QuitEvent, 1);
988                    Some(ret.assume_init())
989                }
990            }
991
992            Event::Display {
993                timestamp,
994                display_index,
995                display_event,
996            } => {
997                let (display_event_id, data1) = display_event.to_ll();
998                let event = sys::SDL_DisplayEvent {
999                    type_: SDL_EventType::SDL_DISPLAYEVENT as u32,
1000                    timestamp,
1001                    display: display_index as u32,
1002                    event: display_event_id,
1003                    padding1: 0,
1004                    padding2: 0,
1005                    padding3: 0,
1006                    data1,
1007                };
1008                unsafe {
1009                    ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_DisplayEvent, 1);
1010                    Some(ret.assume_init())
1011                }
1012            }
1013
1014            Event::Window {
1015                timestamp,
1016                window_id,
1017                win_event,
1018            } => {
1019                let (win_event_id, data1, data2) = win_event.to_ll();
1020                let event = sys::SDL_WindowEvent {
1021                    type_: SDL_EventType::SDL_WINDOWEVENT as u32,
1022                    timestamp,
1023                    windowID: window_id,
1024                    event: win_event_id,
1025                    padding1: 0,
1026                    padding2: 0,
1027                    padding3: 0,
1028                    data1,
1029                    data2,
1030                };
1031                unsafe {
1032                    ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_WindowEvent, 1);
1033                    Some(ret.assume_init())
1034                }
1035            }
1036
1037            Event::KeyDown {
1038                timestamp,
1039                window_id,
1040                keycode,
1041                scancode,
1042                keymod,
1043                repeat,
1044            } => {
1045                let keysym = mk_keysym(scancode, keycode, keymod);
1046                let event = sys::SDL_KeyboardEvent {
1047                    type_: SDL_EventType::SDL_KEYDOWN as u32,
1048                    timestamp,
1049                    windowID: window_id,
1050                    state: sys::SDL_PRESSED as u8,
1051                    repeat: repeat as u8,
1052                    padding2: 0,
1053                    padding3: 0,
1054                    keysym,
1055                };
1056                unsafe {
1057                    ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_KeyboardEvent, 1);
1058                    Some(ret.assume_init())
1059                }
1060            }
1061            Event::KeyUp {
1062                timestamp,
1063                window_id,
1064                keycode,
1065                scancode,
1066                keymod,
1067                repeat,
1068            } => {
1069                let keysym = mk_keysym(scancode, keycode, keymod);
1070                let event = sys::SDL_KeyboardEvent {
1071                    type_: SDL_EventType::SDL_KEYUP as u32,
1072                    timestamp,
1073                    windowID: window_id,
1074                    state: sys::SDL_RELEASED as u8,
1075                    repeat: repeat as u8,
1076                    padding2: 0,
1077                    padding3: 0,
1078                    keysym,
1079                };
1080                unsafe {
1081                    ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_KeyboardEvent, 1);
1082                    Some(ret.assume_init())
1083                }
1084            }
1085            Event::MouseMotion {
1086                timestamp,
1087                window_id,
1088                which,
1089                mousestate,
1090                x,
1091                y,
1092                xrel,
1093                yrel,
1094            } => {
1095                let state = mousestate.to_sdl_state();
1096                let event = sys::SDL_MouseMotionEvent {
1097                    type_: SDL_EventType::SDL_MOUSEMOTION as u32,
1098                    timestamp,
1099                    windowID: window_id,
1100                    which,
1101                    state,
1102                    x,
1103                    y,
1104                    xrel,
1105                    yrel,
1106                };
1107                unsafe {
1108                    ptr::copy(
1109                        &event,
1110                        ret.as_mut_ptr() as *mut sys::SDL_MouseMotionEvent,
1111                        1,
1112                    );
1113                    Some(ret.assume_init())
1114                }
1115            }
1116            Event::MouseButtonDown {
1117                timestamp,
1118                window_id,
1119                which,
1120                mouse_btn,
1121                clicks,
1122                x,
1123                y,
1124            } => {
1125                let event = sys::SDL_MouseButtonEvent {
1126                    type_: SDL_EventType::SDL_MOUSEBUTTONDOWN as u32,
1127                    timestamp,
1128                    windowID: window_id,
1129                    which,
1130                    button: mouse_btn as u8,
1131                    state: sys::SDL_PRESSED as u8,
1132                    clicks,
1133                    padding1: 0,
1134                    x,
1135                    y,
1136                };
1137                unsafe {
1138                    ptr::copy(
1139                        &event,
1140                        ret.as_mut_ptr() as *mut sys::SDL_MouseButtonEvent,
1141                        1,
1142                    );
1143                    Some(ret.assume_init())
1144                }
1145            }
1146            Event::MouseButtonUp {
1147                timestamp,
1148                window_id,
1149                which,
1150                mouse_btn,
1151                clicks,
1152                x,
1153                y,
1154            } => {
1155                let event = sys::SDL_MouseButtonEvent {
1156                    type_: SDL_EventType::SDL_MOUSEBUTTONUP as u32,
1157                    timestamp,
1158                    windowID: window_id,
1159                    which,
1160                    button: mouse_btn as u8,
1161                    state: sys::SDL_RELEASED as u8,
1162                    clicks,
1163                    padding1: 0,
1164                    x,
1165                    y,
1166                };
1167                unsafe {
1168                    ptr::copy(
1169                        &event,
1170                        ret.as_mut_ptr() as *mut sys::SDL_MouseButtonEvent,
1171                        1,
1172                    );
1173                    Some(ret.assume_init())
1174                }
1175            }
1176
1177            Event::MouseWheel {
1178                timestamp,
1179                window_id,
1180                which,
1181                x,
1182                y,
1183                direction,
1184                precise_x,
1185                precise_y,
1186                mouse_x,
1187                mouse_y,
1188            } => {
1189                let event = sys::SDL_MouseWheelEvent {
1190                    type_: SDL_EventType::SDL_MOUSEWHEEL as u32,
1191                    timestamp,
1192                    windowID: window_id,
1193                    which,
1194                    x,
1195                    y,
1196                    direction: direction.to_ll(),
1197                    preciseX: precise_x,
1198                    preciseY: precise_y,
1199                    mouseX: mouse_x,
1200                    mouseY: mouse_y,
1201                };
1202                unsafe {
1203                    ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_MouseWheelEvent, 1);
1204                    Some(ret.assume_init())
1205                }
1206            }
1207            Event::JoyAxisMotion {
1208                timestamp,
1209                which,
1210                axis_idx,
1211                value,
1212            } => {
1213                let event = sys::SDL_JoyAxisEvent {
1214                    type_: SDL_EventType::SDL_JOYAXISMOTION as u32,
1215                    timestamp,
1216                    which: which as i32,
1217                    axis: axis_idx,
1218                    value,
1219                    padding1: 0,
1220                    padding2: 0,
1221                    padding3: 0,
1222                    padding4: 0,
1223                };
1224                unsafe {
1225                    ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_JoyAxisEvent, 1);
1226                    Some(ret.assume_init())
1227                }
1228            }
1229            Event::JoyBallMotion {
1230                timestamp,
1231                which,
1232                ball_idx,
1233                xrel,
1234                yrel,
1235            } => {
1236                let event = sys::SDL_JoyBallEvent {
1237                    type_: SDL_EventType::SDL_JOYBALLMOTION as u32,
1238                    timestamp,
1239                    which: which as i32,
1240                    ball: ball_idx,
1241                    xrel,
1242                    yrel,
1243                    padding1: 0,
1244                    padding2: 0,
1245                    padding3: 0,
1246                };
1247                unsafe {
1248                    ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_JoyBallEvent, 1);
1249                    Some(ret.assume_init())
1250                }
1251            }
1252            Event::JoyHatMotion {
1253                timestamp,
1254                which,
1255                hat_idx,
1256                state,
1257            } => {
1258                let hatvalue = state.to_raw();
1259                let event = sys::SDL_JoyHatEvent {
1260                    type_: SDL_EventType::SDL_JOYHATMOTION as u32,
1261                    timestamp,
1262                    which: which as i32,
1263                    hat: hat_idx,
1264                    value: hatvalue,
1265                    padding1: 0,
1266                    padding2: 0,
1267                };
1268                unsafe {
1269                    ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_JoyHatEvent, 1);
1270                    Some(ret.assume_init())
1271                }
1272            }
1273            Event::JoyButtonDown {
1274                timestamp,
1275                which,
1276                button_idx,
1277            } => {
1278                let event = sys::SDL_JoyButtonEvent {
1279                    type_: SDL_EventType::SDL_JOYBUTTONDOWN as u32,
1280                    timestamp,
1281                    which: which as i32,
1282                    button: button_idx,
1283                    state: sys::SDL_PRESSED as u8,
1284                    padding1: 0,
1285                    padding2: 0,
1286                };
1287                unsafe {
1288                    ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_JoyButtonEvent, 1);
1289                    Some(ret.assume_init())
1290                }
1291            }
1292
1293            Event::JoyButtonUp {
1294                timestamp,
1295                which,
1296                button_idx,
1297            } => {
1298                let event = sys::SDL_JoyButtonEvent {
1299                    type_: SDL_EventType::SDL_JOYBUTTONUP as u32,
1300                    timestamp,
1301                    which: which as i32,
1302                    button: button_idx,
1303                    state: sys::SDL_RELEASED as u8,
1304                    padding1: 0,
1305                    padding2: 0,
1306                };
1307                unsafe {
1308                    ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_JoyButtonEvent, 1);
1309                    Some(ret.assume_init())
1310                }
1311            }
1312
1313            Event::JoyDeviceAdded { timestamp, which } => {
1314                let event = sys::SDL_JoyDeviceEvent {
1315                    type_: SDL_EventType::SDL_JOYDEVICEADDED as u32,
1316                    timestamp,
1317                    which: which as i32,
1318                };
1319                unsafe {
1320                    ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_JoyDeviceEvent, 1);
1321                    Some(ret.assume_init())
1322                }
1323            }
1324
1325            Event::JoyDeviceRemoved { timestamp, which } => {
1326                let event = sys::SDL_JoyDeviceEvent {
1327                    type_: SDL_EventType::SDL_JOYDEVICEREMOVED as u32,
1328                    timestamp,
1329                    which: which as i32,
1330                };
1331                unsafe {
1332                    ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_JoyDeviceEvent, 1);
1333                    Some(ret.assume_init())
1334                }
1335            }
1336            Event::ControllerAxisMotion {
1337                timestamp,
1338                which,
1339                axis,
1340                value,
1341            } => {
1342                let axisval = axis.to_ll();
1343                let event = sys::SDL_ControllerAxisEvent {
1344                    type_: SDL_EventType::SDL_CONTROLLERAXISMOTION as u32,
1345                    timestamp,
1346                    which: which as i32,
1347                    axis: axisval as u8,
1348                    value,
1349                    padding1: 0,
1350                    padding2: 0,
1351                    padding3: 0,
1352                    padding4: 0,
1353                };
1354                unsafe {
1355                    ptr::copy(
1356                        &event,
1357                        ret.as_mut_ptr() as *mut sys::SDL_ControllerAxisEvent,
1358                        1,
1359                    );
1360                    Some(ret.assume_init())
1361                }
1362            }
1363            Event::ControllerButtonDown {
1364                timestamp,
1365                which,
1366                button,
1367            } => {
1368                let buttonval = button.to_ll();
1369                let event = sys::SDL_ControllerButtonEvent {
1370                    type_: SDL_EventType::SDL_CONTROLLERBUTTONDOWN as u32,
1371                    timestamp,
1372                    which: which as i32,
1373                    // This conversion turns an i32 into a u8; signed-to-unsigned conversions
1374                    // are a bit of a code smell, but that appears to be how SDL defines it.
1375                    button: buttonval as u8,
1376                    state: sys::SDL_PRESSED as u8,
1377                    padding1: 0,
1378                    padding2: 0,
1379                };
1380                unsafe {
1381                    ptr::copy(
1382                        &event,
1383                        ret.as_mut_ptr() as *mut sys::SDL_ControllerButtonEvent,
1384                        1,
1385                    );
1386                    Some(ret.assume_init())
1387                }
1388            }
1389
1390            Event::ControllerButtonUp {
1391                timestamp,
1392                which,
1393                button,
1394            } => {
1395                let buttonval = button.to_ll();
1396                let event = sys::SDL_ControllerButtonEvent {
1397                    type_: SDL_EventType::SDL_CONTROLLERBUTTONUP as u32,
1398                    timestamp,
1399                    which: which as i32,
1400                    button: buttonval as u8,
1401                    state: sys::SDL_RELEASED as u8,
1402                    padding1: 0,
1403                    padding2: 0,
1404                };
1405                unsafe {
1406                    ptr::copy(
1407                        &event,
1408                        ret.as_mut_ptr() as *mut sys::SDL_ControllerButtonEvent,
1409                        1,
1410                    );
1411                    Some(ret.assume_init())
1412                }
1413            }
1414
1415            Event::ControllerDeviceAdded { timestamp, which } => {
1416                let event = sys::SDL_ControllerDeviceEvent {
1417                    type_: SDL_EventType::SDL_CONTROLLERDEVICEADDED as u32,
1418                    timestamp,
1419                    which: which as i32,
1420                };
1421                unsafe {
1422                    ptr::copy(
1423                        &event,
1424                        ret.as_mut_ptr() as *mut sys::SDL_ControllerDeviceEvent,
1425                        1,
1426                    );
1427                    Some(ret.assume_init())
1428                }
1429            }
1430
1431            Event::ControllerDeviceRemoved { timestamp, which } => {
1432                let event = sys::SDL_ControllerDeviceEvent {
1433                    type_: SDL_EventType::SDL_CONTROLLERDEVICEREMOVED as u32,
1434                    timestamp,
1435                    which: which as i32,
1436                };
1437                unsafe {
1438                    ptr::copy(
1439                        &event,
1440                        ret.as_mut_ptr() as *mut sys::SDL_ControllerDeviceEvent,
1441                        1,
1442                    );
1443                    Some(ret.assume_init())
1444                }
1445            }
1446
1447            Event::ControllerDeviceRemapped { timestamp, which } => {
1448                let event = sys::SDL_ControllerDeviceEvent {
1449                    type_: SDL_EventType::SDL_CONTROLLERDEVICEREMAPPED as u32,
1450                    timestamp,
1451                    which: which as i32,
1452                };
1453                unsafe {
1454                    ptr::copy(
1455                        &event,
1456                        ret.as_mut_ptr() as *mut sys::SDL_ControllerDeviceEvent,
1457                        1,
1458                    );
1459                    Some(ret.assume_init())
1460                }
1461            }
1462
1463            Event::FingerDown { .. }
1464            | Event::FingerUp { .. }
1465            | Event::FingerMotion { .. }
1466            | Event::DollarGesture { .. }
1467            | Event::DollarRecord { .. }
1468            | Event::MultiGesture { .. }
1469            | Event::ClipboardUpdate { .. }
1470            | Event::DropFile { .. }
1471            | Event::TextEditing { .. }
1472            | Event::TextInput { .. }
1473            | Event::Unknown { .. }
1474            | _ => {
1475                // don't know how to convert!
1476                None
1477            }
1478        }
1479    }
1480
1481    pub fn from_ll(raw: sys::SDL_Event) -> Event {
1482        let raw_type = unsafe { raw.type_ };
1483
1484        // if event type has not been defined, treat it as a UserEvent
1485        let event_type: EventType = EventType::try_from(raw_type).unwrap_or(EventType::User);
1486        unsafe {
1487            match event_type {
1488                EventType::Quit => {
1489                    let event = raw.quit;
1490                    Event::Quit {
1491                        timestamp: event.timestamp,
1492                    }
1493                }
1494                EventType::AppTerminating => {
1495                    let event = raw.common;
1496                    Event::AppTerminating {
1497                        timestamp: event.timestamp,
1498                    }
1499                }
1500                EventType::AppLowMemory => {
1501                    let event = raw.common;
1502                    Event::AppLowMemory {
1503                        timestamp: event.timestamp,
1504                    }
1505                }
1506                EventType::AppWillEnterBackground => {
1507                    let event = raw.common;
1508                    Event::AppWillEnterBackground {
1509                        timestamp: event.timestamp,
1510                    }
1511                }
1512                EventType::AppDidEnterBackground => {
1513                    let event = raw.common;
1514                    Event::AppDidEnterBackground {
1515                        timestamp: event.timestamp,
1516                    }
1517                }
1518                EventType::AppWillEnterForeground => {
1519                    let event = raw.common;
1520                    Event::AppWillEnterForeground {
1521                        timestamp: event.timestamp,
1522                    }
1523                }
1524                EventType::AppDidEnterForeground => {
1525                    let event = raw.common;
1526                    Event::AppDidEnterForeground {
1527                        timestamp: event.timestamp,
1528                    }
1529                }
1530
1531                EventType::Display => {
1532                    let event = raw.display;
1533
1534                    Event::Display {
1535                        timestamp: event.timestamp,
1536                        display_index: event.display as i32,
1537                        display_event: DisplayEvent::from_ll(event.event, event.data1),
1538                    }
1539                }
1540                EventType::Window => {
1541                    let event = raw.window;
1542
1543                    Event::Window {
1544                        timestamp: event.timestamp,
1545                        window_id: event.windowID,
1546                        win_event: WindowEvent::from_ll(event.event, event.data1, event.data2),
1547                    }
1548                }
1549                // TODO: SysWMEventType
1550                EventType::KeyDown => {
1551                    let event = raw.key;
1552
1553                    Event::KeyDown {
1554                        timestamp: event.timestamp,
1555                        window_id: event.windowID,
1556                        keycode: Keycode::from_i32(event.keysym.sym),
1557                        scancode: Scancode::from_i32(event.keysym.scancode as i32),
1558                        keymod: keyboard::Mod::from_bits_truncate(event.keysym.mod_),
1559                        repeat: event.repeat != 0,
1560                    }
1561                }
1562                EventType::KeyUp => {
1563                    let event = raw.key;
1564
1565                    Event::KeyUp {
1566                        timestamp: event.timestamp,
1567                        window_id: event.windowID,
1568                        keycode: Keycode::from_i32(event.keysym.sym),
1569                        scancode: Scancode::from_i32(event.keysym.scancode as i32),
1570                        keymod: keyboard::Mod::from_bits_truncate(event.keysym.mod_),
1571                        repeat: event.repeat != 0,
1572                    }
1573                }
1574                EventType::TextEditing => {
1575                    let event = raw.edit;
1576
1577                    let text = String::from_utf8(
1578                        event
1579                            .text
1580                            .iter()
1581                            .take_while(|&b| (*b) != 0)
1582                            .map(|&b| b as u8)
1583                            .collect::<Vec<u8>>(),
1584                    )
1585                    .expect("Invalid TextEditing string");
1586                    Event::TextEditing {
1587                        timestamp: event.timestamp,
1588                        window_id: event.windowID,
1589                        text,
1590                        start: event.start,
1591                        length: event.length,
1592                    }
1593                }
1594                EventType::TextInput => {
1595                    let event = raw.text;
1596
1597                    let text = String::from_utf8(
1598                        event
1599                            .text
1600                            .iter()
1601                            .take_while(|&b| (*b) != 0)
1602                            .map(|&b| b as u8)
1603                            .collect::<Vec<u8>>(),
1604                    )
1605                    .expect("Invalid TextInput string");
1606                    Event::TextInput {
1607                        timestamp: event.timestamp,
1608                        window_id: event.windowID,
1609                        text,
1610                    }
1611                }
1612
1613                EventType::MouseMotion => {
1614                    let event = raw.motion;
1615
1616                    Event::MouseMotion {
1617                        timestamp: event.timestamp,
1618                        window_id: event.windowID,
1619                        which: event.which,
1620                        mousestate: mouse::MouseState::from_sdl_state(event.state),
1621                        x: event.x,
1622                        y: event.y,
1623                        xrel: event.xrel,
1624                        yrel: event.yrel,
1625                    }
1626                }
1627                EventType::MouseButtonDown => {
1628                    let event = raw.button;
1629
1630                    Event::MouseButtonDown {
1631                        timestamp: event.timestamp,
1632                        window_id: event.windowID,
1633                        which: event.which,
1634                        mouse_btn: mouse::MouseButton::from_ll(event.button),
1635                        clicks: event.clicks,
1636                        x: event.x,
1637                        y: event.y,
1638                    }
1639                }
1640                EventType::MouseButtonUp => {
1641                    let event = raw.button;
1642
1643                    Event::MouseButtonUp {
1644                        timestamp: event.timestamp,
1645                        window_id: event.windowID,
1646                        which: event.which,
1647                        mouse_btn: mouse::MouseButton::from_ll(event.button),
1648                        clicks: event.clicks,
1649                        x: event.x,
1650                        y: event.y,
1651                    }
1652                }
1653                EventType::MouseWheel => {
1654                    let event = raw.wheel;
1655
1656                    Event::MouseWheel {
1657                        timestamp: event.timestamp,
1658                        window_id: event.windowID,
1659                        which: event.which,
1660                        x: event.x,
1661                        y: event.y,
1662                        direction: mouse::MouseWheelDirection::from_ll(event.direction),
1663                        precise_x: event.preciseX,
1664                        precise_y: event.preciseY,
1665                        mouse_x: event.mouseX,
1666                        mouse_y: event.mouseY,
1667                    }
1668                }
1669
1670                EventType::JoyAxisMotion => {
1671                    let event = raw.jaxis;
1672                    Event::JoyAxisMotion {
1673                        timestamp: event.timestamp,
1674                        which: event.which as u32,
1675                        axis_idx: event.axis,
1676                        value: event.value,
1677                    }
1678                }
1679                EventType::JoyBallMotion => {
1680                    let event = raw.jball;
1681                    Event::JoyBallMotion {
1682                        timestamp: event.timestamp,
1683                        which: event.which as u32,
1684                        ball_idx: event.ball,
1685                        xrel: event.xrel,
1686                        yrel: event.yrel,
1687                    }
1688                }
1689                EventType::JoyHatMotion => {
1690                    let event = raw.jhat;
1691                    Event::JoyHatMotion {
1692                        timestamp: event.timestamp,
1693                        which: event.which as u32,
1694                        hat_idx: event.hat,
1695                        state: joystick::HatState::from_raw(event.value),
1696                    }
1697                }
1698                EventType::JoyButtonDown => {
1699                    let event = raw.jbutton;
1700                    Event::JoyButtonDown {
1701                        timestamp: event.timestamp,
1702                        which: event.which as u32,
1703                        button_idx: event.button,
1704                    }
1705                }
1706                EventType::JoyButtonUp => {
1707                    let event = raw.jbutton;
1708                    Event::JoyButtonUp {
1709                        timestamp: event.timestamp,
1710                        which: event.which as u32,
1711                        button_idx: event.button,
1712                    }
1713                }
1714                EventType::JoyDeviceAdded => {
1715                    let event = raw.jdevice;
1716                    Event::JoyDeviceAdded {
1717                        timestamp: event.timestamp,
1718                        which: event.which as u32,
1719                    }
1720                }
1721                EventType::JoyDeviceRemoved => {
1722                    let event = raw.jdevice;
1723                    Event::JoyDeviceRemoved {
1724                        timestamp: event.timestamp,
1725                        which: event.which as u32,
1726                    }
1727                }
1728
1729                EventType::ControllerAxisMotion => {
1730                    let event = raw.caxis;
1731                    let axis = controller::Axis::from_ll(transmute(event.axis as i32)).unwrap();
1732
1733                    Event::ControllerAxisMotion {
1734                        timestamp: event.timestamp,
1735                        which: event.which as u32,
1736                        axis,
1737                        value: event.value,
1738                    }
1739                }
1740                EventType::ControllerButtonDown => {
1741                    let event = raw.cbutton;
1742                    let button =
1743                        controller::Button::from_ll(transmute(event.button as i32)).unwrap();
1744
1745                    Event::ControllerButtonDown {
1746                        timestamp: event.timestamp,
1747                        which: event.which as u32,
1748                        button,
1749                    }
1750                }
1751                EventType::ControllerButtonUp => {
1752                    let event = raw.cbutton;
1753                    let button =
1754                        controller::Button::from_ll(transmute(event.button as i32)).unwrap();
1755
1756                    Event::ControllerButtonUp {
1757                        timestamp: event.timestamp,
1758                        which: event.which as u32,
1759                        button,
1760                    }
1761                }
1762                EventType::ControllerDeviceAdded => {
1763                    let event = raw.cdevice;
1764                    Event::ControllerDeviceAdded {
1765                        timestamp: event.timestamp,
1766                        which: event.which as u32,
1767                    }
1768                }
1769                EventType::ControllerDeviceRemoved => {
1770                    let event = raw.cdevice;
1771                    Event::ControllerDeviceRemoved {
1772                        timestamp: event.timestamp,
1773                        which: event.which as u32,
1774                    }
1775                }
1776                EventType::ControllerDeviceRemapped => {
1777                    let event = raw.cdevice;
1778                    Event::ControllerDeviceRemapped {
1779                        timestamp: event.timestamp,
1780                        which: event.which as u32,
1781                    }
1782                }
1783                EventType::ControllerTouchpadDown => {
1784                    let event = raw.ctouchpad;
1785                    Event::ControllerTouchpadDown {
1786                        timestamp: event.timestamp,
1787                        which: event.which as u32,
1788                        touchpad: event.touchpad as u32,
1789                        finger: event.finger as u32,
1790                        x: event.x,
1791                        y: event.y,
1792                        pressure: event.pressure,
1793                    }
1794                }
1795                EventType::ControllerTouchpadMotion => {
1796                    let event = raw.ctouchpad;
1797                    Event::ControllerTouchpadMotion {
1798                        timestamp: event.timestamp,
1799                        which: event.which as u32,
1800                        touchpad: event.touchpad as u32,
1801                        finger: event.finger as u32,
1802                        x: event.x,
1803                        y: event.y,
1804                        pressure: event.pressure,
1805                    }
1806                }
1807                EventType::ControllerTouchpadUp => {
1808                    let event = raw.ctouchpad;
1809                    Event::ControllerTouchpadUp {
1810                        timestamp: event.timestamp,
1811                        which: event.which as u32,
1812                        touchpad: event.touchpad as u32,
1813                        finger: event.finger as u32,
1814                        x: event.x,
1815                        y: event.y,
1816                        pressure: event.pressure,
1817                    }
1818                }
1819                #[cfg(feature = "hidapi")]
1820                EventType::ControllerSensorUpdated => {
1821                    let event = raw.csensor;
1822                    Event::ControllerSensorUpdated {
1823                        timestamp: event.timestamp,
1824                        which: event.which as u32,
1825                        sensor: crate::sensor::SensorType::from_ll(event.sensor),
1826                        data: event.data,
1827                    }
1828                }
1829
1830                EventType::FingerDown => {
1831                    let event = raw.tfinger;
1832                    Event::FingerDown {
1833                        timestamp: event.timestamp,
1834                        touch_id: event.touchId,
1835                        finger_id: event.fingerId,
1836                        x: event.x,
1837                        y: event.y,
1838                        dx: event.dx,
1839                        dy: event.dy,
1840                        pressure: event.pressure,
1841                    }
1842                }
1843                EventType::FingerUp => {
1844                    let event = raw.tfinger;
1845                    Event::FingerUp {
1846                        timestamp: event.timestamp,
1847                        touch_id: event.touchId,
1848                        finger_id: event.fingerId,
1849                        x: event.x,
1850                        y: event.y,
1851                        dx: event.dx,
1852                        dy: event.dy,
1853                        pressure: event.pressure,
1854                    }
1855                }
1856                EventType::FingerMotion => {
1857                    let event = raw.tfinger;
1858                    Event::FingerMotion {
1859                        timestamp: event.timestamp,
1860                        touch_id: event.touchId,
1861                        finger_id: event.fingerId,
1862                        x: event.x,
1863                        y: event.y,
1864                        dx: event.dx,
1865                        dy: event.dy,
1866                        pressure: event.pressure,
1867                    }
1868                }
1869                EventType::DollarGesture => {
1870                    let event = raw.dgesture;
1871                    Event::DollarGesture {
1872                        timestamp: event.timestamp,
1873                        touch_id: event.touchId,
1874                        gesture_id: event.gestureId,
1875                        num_fingers: event.numFingers,
1876                        error: event.error,
1877                        x: event.x,
1878                        y: event.y,
1879                    }
1880                }
1881                EventType::DollarRecord => {
1882                    let event = raw.dgesture;
1883                    Event::DollarRecord {
1884                        timestamp: event.timestamp,
1885                        touch_id: event.touchId,
1886                        gesture_id: event.gestureId,
1887                        num_fingers: event.numFingers,
1888                        error: event.error,
1889                        x: event.x,
1890                        y: event.y,
1891                    }
1892                }
1893                EventType::MultiGesture => {
1894                    let event = raw.mgesture;
1895                    Event::MultiGesture {
1896                        timestamp: event.timestamp,
1897                        touch_id: event.touchId,
1898                        d_theta: event.dTheta,
1899                        d_dist: event.dDist,
1900                        x: event.x,
1901                        y: event.y,
1902                        num_fingers: event.numFingers,
1903                    }
1904                }
1905
1906                EventType::ClipboardUpdate => {
1907                    let event = raw.common;
1908                    Event::ClipboardUpdate {
1909                        timestamp: event.timestamp,
1910                    }
1911                }
1912                EventType::DropFile => {
1913                    let event = raw.drop;
1914
1915                    let buf = CStr::from_ptr(event.file as *const _).to_bytes();
1916                    let text = String::from_utf8_lossy(buf).to_string();
1917                    sys::SDL_free(event.file as *mut c_void);
1918
1919                    Event::DropFile {
1920                        timestamp: event.timestamp,
1921                        window_id: event.windowID,
1922                        filename: text,
1923                    }
1924                }
1925                EventType::DropText => {
1926                    let event = raw.drop;
1927
1928                    let buf = CStr::from_ptr(event.file as *const _).to_bytes();
1929                    let text = String::from_utf8_lossy(buf).to_string();
1930                    sys::SDL_free(event.file as *mut c_void);
1931
1932                    Event::DropText {
1933                        timestamp: event.timestamp,
1934                        window_id: event.windowID,
1935                        filename: text,
1936                    }
1937                }
1938                EventType::DropBegin => {
1939                    let event = raw.drop;
1940
1941                    Event::DropBegin {
1942                        timestamp: event.timestamp,
1943                        window_id: event.windowID,
1944                    }
1945                }
1946                EventType::DropComplete => {
1947                    let event = raw.drop;
1948
1949                    Event::DropComplete {
1950                        timestamp: event.timestamp,
1951                        window_id: event.windowID,
1952                    }
1953                }
1954                EventType::AudioDeviceAdded => {
1955                    let event = raw.adevice;
1956                    Event::AudioDeviceAdded {
1957                        timestamp: event.timestamp,
1958                        which: event.which,
1959                        // zero if an audio output device, non-zero if an audio capture device
1960                        iscapture: event.iscapture != 0,
1961                    }
1962                }
1963                EventType::AudioDeviceRemoved => {
1964                    let event = raw.adevice;
1965                    Event::AudioDeviceRemoved {
1966                        timestamp: event.timestamp,
1967                        which: event.which,
1968                        // zero if an audio output device, non-zero if an audio capture device
1969                        iscapture: event.iscapture != 0,
1970                    }
1971                }
1972
1973                EventType::RenderTargetsReset => Event::RenderTargetsReset {
1974                    timestamp: raw.common.timestamp,
1975                },
1976                EventType::RenderDeviceReset => Event::RenderDeviceReset {
1977                    timestamp: raw.common.timestamp,
1978                },
1979
1980                EventType::First => panic!("Unused event, EventType::First, was encountered"),
1981                EventType::Last => panic!("Unusable event, EventType::Last, was encountered"),
1982
1983                // If we have no other match and the event type is >= 32768
1984                // this is a user event
1985                EventType::User => {
1986                    if raw_type < 32_768 {
1987                        // The type is unknown to us.
1988                        // It's a newer SDL2 type.
1989                        let event = raw.common;
1990
1991                        Event::Unknown {
1992                            timestamp: event.timestamp,
1993                            type_: event.type_,
1994                        }
1995                    } else {
1996                        let event = raw.user;
1997
1998                        Event::User {
1999                            timestamp: event.timestamp,
2000                            window_id: event.windowID,
2001                            type_: raw_type,
2002                            code: event.code,
2003                            data1: event.data1,
2004                            data2: event.data2,
2005                        }
2006                    }
2007                }
2008            }
2009        } // close unsafe & match
2010    }
2011
2012    pub fn is_user_event(&self) -> bool {
2013        matches!(self, Event::User { .. })
2014    }
2015
2016    pub fn as_user_event_type<T: ::std::any::Any>(&self) -> Option<T> {
2017        use std::any::TypeId;
2018        let type_id = TypeId::of::<Box<T>>();
2019
2020        let (event_id, event_box_ptr) = match *self {
2021            Event::User { type_, data1, .. } => (type_, data1),
2022            _ => return None,
2023        };
2024
2025        let cet = CUSTOM_EVENT_TYPES.lock().unwrap();
2026
2027        let event_type_id = match cet.sdl_id_to_type_id.get(&event_id) {
2028            Some(id) => id,
2029            None => {
2030                panic!("internal error; could not find typeid")
2031            }
2032        };
2033
2034        if &type_id != event_type_id {
2035            return None;
2036        }
2037
2038        let event_box: Box<T> = unsafe { Box::from_raw(event_box_ptr as *mut T) };
2039
2040        Some(*event_box)
2041    }
2042
2043    /// Returns `true` if they are the same "kind" of events.
2044    ///
2045    /// # Example:
2046    ///
2047    /// ```
2048    /// use sdl2::event::Event;
2049    ///
2050    /// let ev1 = Event::JoyButtonDown {
2051    ///     timestamp: 0,
2052    ///     which: 0,
2053    ///     button_idx: 0,
2054    /// };
2055    /// let ev2 = Event::JoyButtonDown {
2056    ///     timestamp: 1,
2057    ///     which: 1,
2058    ///     button_idx: 1,
2059    /// };
2060    ///
2061    /// assert!(ev1 != ev2); // The events aren't equal (they contain different values).
2062    /// assert!(ev1.is_same_kind_as(&ev2)); // But they are of the same kind!
2063    /// ```
2064    pub fn is_same_kind_as(&self, other: &Event) -> bool {
2065        match (self, other) {
2066            (Self::Quit { .. }, Self::Quit { .. })
2067            | (Self::AppTerminating { .. }, Self::AppTerminating { .. })
2068            | (Self::AppLowMemory { .. }, Self::AppLowMemory { .. })
2069            | (Self::AppWillEnterBackground { .. }, Self::AppWillEnterBackground { .. })
2070            | (Self::AppDidEnterBackground { .. }, Self::AppDidEnterBackground { .. })
2071            | (Self::AppWillEnterForeground { .. }, Self::AppWillEnterForeground { .. })
2072            | (Self::AppDidEnterForeground { .. }, Self::AppDidEnterForeground { .. })
2073            | (Self::Display { .. }, Self::Display { .. })
2074            | (Self::Window { .. }, Self::Window { .. })
2075            | (Self::KeyDown { .. }, Self::KeyDown { .. })
2076            | (Self::KeyUp { .. }, Self::KeyUp { .. })
2077            | (Self::TextEditing { .. }, Self::TextEditing { .. })
2078            | (Self::TextInput { .. }, Self::TextInput { .. })
2079            | (Self::MouseMotion { .. }, Self::MouseMotion { .. })
2080            | (Self::MouseButtonDown { .. }, Self::MouseButtonDown { .. })
2081            | (Self::MouseButtonUp { .. }, Self::MouseButtonUp { .. })
2082            | (Self::MouseWheel { .. }, Self::MouseWheel { .. })
2083            | (Self::JoyAxisMotion { .. }, Self::JoyAxisMotion { .. })
2084            | (Self::JoyBallMotion { .. }, Self::JoyBallMotion { .. })
2085            | (Self::JoyHatMotion { .. }, Self::JoyHatMotion { .. })
2086            | (Self::JoyButtonDown { .. }, Self::JoyButtonDown { .. })
2087            | (Self::JoyButtonUp { .. }, Self::JoyButtonUp { .. })
2088            | (Self::JoyDeviceAdded { .. }, Self::JoyDeviceAdded { .. })
2089            | (Self::JoyDeviceRemoved { .. }, Self::JoyDeviceRemoved { .. })
2090            | (Self::ControllerAxisMotion { .. }, Self::ControllerAxisMotion { .. })
2091            | (Self::ControllerButtonDown { .. }, Self::ControllerButtonDown { .. })
2092            | (Self::ControllerButtonUp { .. }, Self::ControllerButtonUp { .. })
2093            | (Self::ControllerDeviceAdded { .. }, Self::ControllerDeviceAdded { .. })
2094            | (Self::ControllerDeviceRemoved { .. }, Self::ControllerDeviceRemoved { .. })
2095            | (Self::ControllerDeviceRemapped { .. }, Self::ControllerDeviceRemapped { .. })
2096            | (Self::FingerDown { .. }, Self::FingerDown { .. })
2097            | (Self::FingerUp { .. }, Self::FingerUp { .. })
2098            | (Self::FingerMotion { .. }, Self::FingerMotion { .. })
2099            | (Self::DollarGesture { .. }, Self::DollarGesture { .. })
2100            | (Self::DollarRecord { .. }, Self::DollarRecord { .. })
2101            | (Self::MultiGesture { .. }, Self::MultiGesture { .. })
2102            | (Self::ClipboardUpdate { .. }, Self::ClipboardUpdate { .. })
2103            | (Self::DropFile { .. }, Self::DropFile { .. })
2104            | (Self::DropText { .. }, Self::DropText { .. })
2105            | (Self::DropBegin { .. }, Self::DropBegin { .. })
2106            | (Self::DropComplete { .. }, Self::DropComplete { .. })
2107            | (Self::AudioDeviceAdded { .. }, Self::AudioDeviceAdded { .. })
2108            | (Self::AudioDeviceRemoved { .. }, Self::AudioDeviceRemoved { .. })
2109            | (Self::RenderTargetsReset { .. }, Self::RenderTargetsReset { .. })
2110            | (Self::RenderDeviceReset { .. }, Self::RenderDeviceReset { .. })
2111            | (Self::User { .. }, Self::User { .. })
2112            | (Self::Unknown { .. }, Self::Unknown { .. }) => true,
2113            #[cfg(feature = "hidapi")]
2114            (Self::ControllerSensorUpdated { .. }, Self::ControllerSensorUpdated { .. }) => true,
2115            _ => false,
2116        }
2117    }
2118
2119    /// Returns the `timestamp` field of the event.
2120    ///
2121    /// # Example
2122    ///
2123    /// ```
2124    /// use sdl2::event::Event;
2125    ///
2126    /// let ev = Event::JoyButtonDown {
2127    ///     timestamp: 12,
2128    ///     which: 0,
2129    ///     button_idx: 0,
2130    /// };
2131    /// assert!(ev.get_timestamp() == 12);
2132    /// ```
2133    pub fn get_timestamp(&self) -> u32 {
2134        *match self {
2135            Self::Quit { timestamp, .. } => timestamp,
2136            Self::AppTerminating { timestamp, .. } => timestamp,
2137            Self::AppLowMemory { timestamp, .. } => timestamp,
2138            Self::AppWillEnterBackground { timestamp, .. } => timestamp,
2139            Self::AppDidEnterBackground { timestamp, .. } => timestamp,
2140            Self::AppWillEnterForeground { timestamp, .. } => timestamp,
2141            Self::AppDidEnterForeground { timestamp, .. } => timestamp,
2142            Self::Display { timestamp, .. } => timestamp,
2143            Self::Window { timestamp, .. } => timestamp,
2144            Self::KeyDown { timestamp, .. } => timestamp,
2145            Self::KeyUp { timestamp, .. } => timestamp,
2146            Self::TextEditing { timestamp, .. } => timestamp,
2147            Self::TextInput { timestamp, .. } => timestamp,
2148            Self::MouseMotion { timestamp, .. } => timestamp,
2149            Self::MouseButtonDown { timestamp, .. } => timestamp,
2150            Self::MouseButtonUp { timestamp, .. } => timestamp,
2151            Self::MouseWheel { timestamp, .. } => timestamp,
2152            Self::JoyAxisMotion { timestamp, .. } => timestamp,
2153            Self::JoyBallMotion { timestamp, .. } => timestamp,
2154            Self::JoyHatMotion { timestamp, .. } => timestamp,
2155            Self::JoyButtonDown { timestamp, .. } => timestamp,
2156            Self::JoyButtonUp { timestamp, .. } => timestamp,
2157            Self::JoyDeviceAdded { timestamp, .. } => timestamp,
2158            Self::JoyDeviceRemoved { timestamp, .. } => timestamp,
2159            Self::ControllerAxisMotion { timestamp, .. } => timestamp,
2160            Self::ControllerButtonDown { timestamp, .. } => timestamp,
2161            Self::ControllerButtonUp { timestamp, .. } => timestamp,
2162            Self::ControllerDeviceAdded { timestamp, .. } => timestamp,
2163            Self::ControllerDeviceRemoved { timestamp, .. } => timestamp,
2164            Self::ControllerDeviceRemapped { timestamp, .. } => timestamp,
2165            Self::ControllerTouchpadDown { timestamp, .. } => timestamp,
2166            Self::ControllerTouchpadMotion { timestamp, .. } => timestamp,
2167            Self::ControllerTouchpadUp { timestamp, .. } => timestamp,
2168            #[cfg(feature = "hidapi")]
2169            Self::ControllerSensorUpdated { timestamp, .. } => timestamp,
2170            Self::FingerDown { timestamp, .. } => timestamp,
2171            Self::FingerUp { timestamp, .. } => timestamp,
2172            Self::FingerMotion { timestamp, .. } => timestamp,
2173            Self::DollarGesture { timestamp, .. } => timestamp,
2174            Self::DollarRecord { timestamp, .. } => timestamp,
2175            Self::MultiGesture { timestamp, .. } => timestamp,
2176            Self::ClipboardUpdate { timestamp, .. } => timestamp,
2177            Self::DropFile { timestamp, .. } => timestamp,
2178            Self::DropText { timestamp, .. } => timestamp,
2179            Self::DropBegin { timestamp, .. } => timestamp,
2180            Self::DropComplete { timestamp, .. } => timestamp,
2181            Self::AudioDeviceAdded { timestamp, .. } => timestamp,
2182            Self::AudioDeviceRemoved { timestamp, .. } => timestamp,
2183            Self::RenderTargetsReset { timestamp, .. } => timestamp,
2184            Self::RenderDeviceReset { timestamp, .. } => timestamp,
2185            Self::User { timestamp, .. } => timestamp,
2186            Self::Unknown { timestamp, .. } => timestamp,
2187        }
2188    }
2189
2190    /// Returns the `window_id` field of the event if it's present (not all events have it!).
2191    ///
2192    /// # Example
2193    ///
2194    /// ```
2195    /// use sdl2::event::Event;
2196    ///
2197    /// let ev = Event::JoyButtonDown {
2198    ///     timestamp: 0,
2199    ///     which: 0,
2200    ///     button_idx: 0,
2201    /// };
2202    /// assert!(ev.get_window_id() == None);
2203    ///
2204    /// let another_ev = Event::DropBegin {
2205    ///     timestamp: 0,
2206    ///     window_id: 3,
2207    /// };
2208    /// assert!(another_ev.get_window_id() == Some(3));
2209    /// ```
2210    pub fn get_window_id(&self) -> Option<u32> {
2211        match self {
2212            Self::Window { window_id, .. } => Some(*window_id),
2213            Self::KeyDown { window_id, .. } => Some(*window_id),
2214            Self::KeyUp { window_id, .. } => Some(*window_id),
2215            Self::TextEditing { window_id, .. } => Some(*window_id),
2216            Self::TextInput { window_id, .. } => Some(*window_id),
2217            Self::MouseMotion { window_id, .. } => Some(*window_id),
2218            Self::MouseButtonDown { window_id, .. } => Some(*window_id),
2219            Self::MouseButtonUp { window_id, .. } => Some(*window_id),
2220            Self::MouseWheel { window_id, .. } => Some(*window_id),
2221            Self::DropFile { window_id, .. } => Some(*window_id),
2222            Self::DropText { window_id, .. } => Some(*window_id),
2223            Self::DropBegin { window_id, .. } => Some(*window_id),
2224            Self::DropComplete { window_id, .. } => Some(*window_id),
2225            Self::User { window_id, .. } => Some(*window_id),
2226            _ => None,
2227        }
2228    }
2229
2230    /// Returns `true` if this is a window event.
2231    ///
2232    /// # Example
2233    ///
2234    /// ```
2235    /// use sdl2::event::Event;
2236    ///
2237    /// let ev = Event::Quit {
2238    ///     timestamp: 0,
2239    /// };
2240    /// assert!(ev.is_window());
2241    ///
2242    /// let ev = Event::AppLowMemory {
2243    ///     timestamp: 0,
2244    /// };
2245    /// assert!(ev.is_window());
2246    ///
2247    /// let another_ev = Event::TextInput {
2248    ///     timestamp: 0,
2249    ///     window_id: 0,
2250    ///     text: String::new(),
2251    /// };
2252    /// assert!(another_ev.is_window() == false); // Not a window event!
2253    /// ```
2254    pub fn is_window(&self) -> bool {
2255        matches!(
2256            self,
2257            Self::Quit { .. }
2258                | Self::AppTerminating { .. }
2259                | Self::AppLowMemory { .. }
2260                | Self::AppWillEnterBackground { .. }
2261                | Self::AppDidEnterBackground { .. }
2262                | Self::AppWillEnterForeground { .. }
2263                | Self::AppDidEnterForeground { .. }
2264                | Self::Window { .. }
2265        )
2266    }
2267
2268    /// Returns `true` if this is a keyboard event.
2269    ///
2270    /// # Example
2271    ///
2272    /// ```
2273    /// use sdl2::event::Event;
2274    /// use sdl2::keyboard::Mod;
2275    ///
2276    /// let ev = Event::KeyDown {
2277    ///     timestamp: 0,
2278    ///     window_id: 0,
2279    ///     keycode: None,
2280    ///     scancode: None,
2281    ///     keymod: Mod::empty(),
2282    ///     repeat: false,
2283    /// };
2284    /// assert!(ev.is_keyboard());
2285    ///
2286    /// let another_ev = Event::Quit {
2287    ///     timestamp: 0,
2288    /// };
2289    /// assert!(another_ev.is_keyboard() == false); // Not a keyboard event!
2290    /// ```
2291    pub fn is_keyboard(&self) -> bool {
2292        matches!(self, Self::KeyDown { .. } | Self::KeyUp { .. })
2293    }
2294
2295    /// Returns `true` if this is a text event.
2296    ///
2297    /// # Example
2298    ///
2299    /// ```
2300    /// use sdl2::event::Event;
2301    ///
2302    /// let ev = Event::TextInput {
2303    ///     timestamp: 0,
2304    ///     window_id: 0,
2305    ///     text: String::new(),
2306    /// };
2307    /// assert!(ev.is_text());
2308    ///
2309    /// let another_ev = Event::Quit {
2310    ///     timestamp: 0,
2311    /// };
2312    /// assert!(another_ev.is_text() == false); // Not a text event!
2313    /// ```
2314    pub fn is_text(&self) -> bool {
2315        matches!(self, Self::TextEditing { .. } | Self::TextInput { .. })
2316    }
2317
2318    /// Returns `true` if this is a mouse event.
2319    ///
2320    /// # Example
2321    ///
2322    /// ```
2323    /// use sdl2::event::Event;
2324    /// use sdl2::mouse::MouseWheelDirection;
2325    ///
2326    /// let ev = Event::MouseWheel {
2327    ///     timestamp: 0,
2328    ///     window_id: 0,
2329    ///     which: 0,
2330    ///     precise_x: 0.0,
2331    ///     precise_y: 0.0,
2332    ///     x: 0,
2333    ///     y: 0,
2334    ///     mouse_x: 0,
2335    ///     mouse_y: 0,
2336    ///     direction: MouseWheelDirection::Normal,
2337    /// };
2338    /// assert!(ev.is_mouse());
2339    ///
2340    /// let another_ev = Event::Quit {
2341    ///     timestamp: 0,
2342    /// };
2343    /// assert!(another_ev.is_mouse() == false); // Not a mouse event!
2344    /// ```
2345    pub fn is_mouse(&self) -> bool {
2346        matches!(
2347            self,
2348            Self::MouseMotion { .. }
2349                | Self::MouseButtonDown { .. }
2350                | Self::MouseButtonUp { .. }
2351                | Self::MouseWheel { .. }
2352        )
2353    }
2354
2355    /// Returns `true` if this mouse event is coming from touch.
2356    ///
2357    /// If used on any other kind of event, non-mouse related, this returns `false`.
2358    pub fn is_touch(&self) -> bool {
2359        // FIXME: Use a constant from sdl2-sys when bindgen will be fixed (see https://github.com/Rust-SDL2/rust-sdl2/issues/1265)
2360        const SDL_TOUCH_MOUSEID: u32 = 0xFFFFFFFF;
2361
2362        match self {
2363            Self::MouseMotion {
2364                which: SDL_TOUCH_MOUSEID,
2365                ..
2366            }
2367            | Self::MouseButtonDown {
2368                which: SDL_TOUCH_MOUSEID,
2369                ..
2370            }
2371            | Self::MouseButtonUp {
2372                which: SDL_TOUCH_MOUSEID,
2373                ..
2374            }
2375            | Self::MouseWheel {
2376                which: SDL_TOUCH_MOUSEID,
2377                ..
2378            } => true,
2379            _ => false,
2380        }
2381    }
2382
2383    /// Returns `true` if this is a controller event.
2384    ///
2385    /// # Example
2386    ///
2387    /// ```
2388    /// use sdl2::event::Event;
2389    ///
2390    /// let ev = Event::ControllerDeviceAdded {
2391    ///     timestamp: 0,
2392    ///     which: 0,
2393    /// };
2394    /// assert!(ev.is_controller());
2395    ///
2396    /// let another_ev = Event::Quit {
2397    ///     timestamp: 0,
2398    /// };
2399    /// assert!(another_ev.is_controller() == false); // Not a controller event!
2400    /// ```
2401    pub fn is_controller(&self) -> bool {
2402        matches!(
2403            self,
2404            Self::ControllerAxisMotion { .. }
2405                | Self::ControllerButtonDown { .. }
2406                | Self::ControllerButtonUp { .. }
2407                | Self::ControllerDeviceAdded { .. }
2408                | Self::ControllerDeviceRemoved { .. }
2409                | Self::ControllerDeviceRemapped { .. }
2410        )
2411    }
2412
2413    /// Returns `true` if this is a joy event.
2414    ///
2415    /// # Example
2416    ///
2417    /// ```
2418    /// use sdl2::event::Event;
2419    ///
2420    /// let ev = Event::JoyButtonUp {
2421    ///     timestamp: 0,
2422    ///     which: 0,
2423    ///     button_idx: 0,
2424    /// };
2425    /// assert!(ev.is_joy());
2426    ///
2427    /// let another_ev = Event::Quit {
2428    ///     timestamp: 0,
2429    /// };
2430    /// assert!(another_ev.is_joy() == false); // Not a joy event!
2431    /// ```
2432    pub fn is_joy(&self) -> bool {
2433        matches!(
2434            self,
2435            Self::JoyAxisMotion { .. }
2436                | Self::JoyBallMotion { .. }
2437                | Self::JoyHatMotion { .. }
2438                | Self::JoyButtonDown { .. }
2439                | Self::JoyButtonUp { .. }
2440                | Self::JoyDeviceAdded { .. }
2441                | Self::JoyDeviceRemoved { .. }
2442        )
2443    }
2444
2445    /// Returns `true` if this is a finger event.
2446    ///
2447    /// # Example
2448    ///
2449    /// ```
2450    /// use sdl2::event::Event;
2451    ///
2452    /// let ev = Event::FingerMotion {
2453    ///     timestamp: 0,
2454    ///     touch_id: 0,
2455    ///     finger_id: 0,
2456    ///     x: 0.,
2457    ///     y: 0.,
2458    ///     dx: 0.,
2459    ///     dy: 0.,
2460    ///     pressure: 0.,
2461    /// };
2462    /// assert!(ev.is_finger());
2463    ///
2464    /// let another_ev = Event::Quit {
2465    ///     timestamp: 0,
2466    /// };
2467    /// assert!(another_ev.is_finger() == false); // Not a finger event!
2468    /// ```
2469    pub fn is_finger(&self) -> bool {
2470        matches!(
2471            self,
2472            Self::FingerDown { .. } | Self::FingerUp { .. } | Self::FingerMotion { .. }
2473        )
2474    }
2475
2476    /// Returns `true` if this is a dollar event.
2477    ///
2478    /// # Example
2479    ///
2480    /// ```
2481    /// use sdl2::event::Event;
2482    ///
2483    /// let ev = Event::DollarGesture {
2484    ///     timestamp: 0,
2485    ///     touch_id: 0,
2486    ///     gesture_id: 0,
2487    ///     num_fingers: 0,
2488    ///     error: 0.,
2489    ///     x: 0.,
2490    ///     y: 0.,
2491    /// };
2492    /// assert!(ev.is_dollar());
2493    ///
2494    /// let another_ev = Event::Quit {
2495    ///     timestamp: 0,
2496    /// };
2497    /// assert!(another_ev.is_dollar() == false); // Not a dollar event!
2498    /// ```
2499    pub fn is_dollar(&self) -> bool {
2500        matches!(self, Self::DollarGesture { .. } | Self::DollarRecord { .. })
2501    }
2502
2503    /// Returns `true` if this is a drop event.
2504    ///
2505    /// # Example
2506    ///
2507    /// ```
2508    /// use sdl2::event::Event;
2509    ///
2510    /// let ev = Event::DropBegin {
2511    ///     timestamp: 0,
2512    ///     window_id: 3,
2513    /// };
2514    /// assert!(ev.is_drop());
2515    ///
2516    /// let another_ev = Event::Quit {
2517    ///     timestamp: 0,
2518    /// };
2519    /// assert!(another_ev.is_drop() == false); // Not a drop event!
2520    /// ```
2521    pub fn is_drop(&self) -> bool {
2522        matches!(
2523            self,
2524            Self::DropFile { .. }
2525                | Self::DropText { .. }
2526                | Self::DropBegin { .. }
2527                | Self::DropComplete { .. }
2528        )
2529    }
2530
2531    /// Returns `true` if this is an audio event.
2532    ///
2533    /// # Example
2534    ///
2535    /// ```
2536    /// use sdl2::event::Event;
2537    ///
2538    /// let ev = Event::AudioDeviceAdded {
2539    ///     timestamp: 0,
2540    ///     which: 3,
2541    ///     iscapture: false,
2542    /// };
2543    /// assert!(ev.is_audio());
2544    ///
2545    /// let another_ev = Event::Quit {
2546    ///     timestamp: 0,
2547    /// };
2548    /// assert!(another_ev.is_audio() == false); // Not an audio event!
2549    /// ```
2550    pub fn is_audio(&self) -> bool {
2551        matches!(
2552            self,
2553            Self::AudioDeviceAdded { .. } | Self::AudioDeviceRemoved { .. }
2554        )
2555    }
2556
2557    /// Returns `true` if this is a render event.
2558    ///
2559    /// # Example
2560    ///
2561    /// ```
2562    /// use sdl2::event::Event;
2563    ///
2564    /// let ev = Event::RenderTargetsReset {
2565    ///     timestamp: 0,
2566    /// };
2567    /// assert!(ev.is_render());
2568    ///
2569    /// let another_ev = Event::Quit {
2570    ///     timestamp: 0,
2571    /// };
2572    /// assert!(another_ev.is_render() == false); // Not a render event!
2573    /// ```
2574    pub fn is_render(&self) -> bool {
2575        matches!(
2576            self,
2577            Self::RenderTargetsReset { .. } | Self::RenderDeviceReset { .. }
2578        )
2579    }
2580
2581    /// Returns `true` if this is a user event.
2582    ///
2583    /// # Example
2584    ///
2585    /// ```
2586    /// use sdl2::event::Event;
2587    ///
2588    /// let ev = Event::User {
2589    ///     timestamp: 0,
2590    ///     window_id: 0,
2591    ///     type_: 0,
2592    ///     code: 0,
2593    ///     data1: ::std::ptr::null_mut(),
2594    ///     data2: ::std::ptr::null_mut(),
2595    /// };
2596    /// assert!(ev.is_user());
2597    ///
2598    /// let another_ev = Event::Quit {
2599    ///     timestamp: 0,
2600    /// };
2601    /// assert!(another_ev.is_user() == false); // Not a user event!
2602    /// ```
2603    pub fn is_user(&self) -> bool {
2604        matches!(self, Self::User { .. })
2605    }
2606
2607    /// Returns `true` if this is an unknown event.
2608    ///
2609    /// # Example
2610    ///
2611    /// ```
2612    /// use sdl2::event::Event;
2613    ///
2614    /// let ev = Event::Unknown {
2615    ///     timestamp: 0,
2616    ///     type_: 0,
2617    /// };
2618    /// assert!(ev.is_unknown());
2619    ///
2620    /// let another_ev = Event::Quit {
2621    ///     timestamp: 0,
2622    /// };
2623    /// assert!(another_ev.is_unknown() == false); // Not an unknown event!
2624    /// ```
2625    pub fn is_unknown(&self) -> bool {
2626        matches!(self, Self::Unknown { .. })
2627    }
2628}
2629
2630unsafe fn poll_event() -> Option<Event> {
2631    let mut raw = mem::MaybeUninit::uninit();
2632    let has_pending = sys::SDL_PollEvent(raw.as_mut_ptr()) == 1;
2633
2634    if has_pending {
2635        Some(Event::from_ll(raw.assume_init()))
2636    } else {
2637        None
2638    }
2639}
2640
2641unsafe fn wait_event() -> Event {
2642    let mut raw = mem::MaybeUninit::uninit();
2643    let success = sys::SDL_WaitEvent(raw.as_mut_ptr()) == 1;
2644
2645    if success {
2646        Event::from_ll(raw.assume_init())
2647    } else {
2648        panic!("{}", get_error())
2649    }
2650}
2651
2652unsafe fn wait_event_timeout(timeout: u32) -> Option<Event> {
2653    let mut raw = mem::MaybeUninit::uninit();
2654    let success = sys::SDL_WaitEventTimeout(raw.as_mut_ptr(), timeout as c_int) == 1;
2655
2656    if success {
2657        Some(Event::from_ll(raw.assume_init()))
2658    } else {
2659        None
2660    }
2661}
2662
2663impl crate::EventPump {
2664    /// Query if an event type is enabled.
2665    #[doc(alias = "SDL_EventState")]
2666    pub fn is_event_enabled(&self, event_type: EventType) -> bool {
2667        let result = unsafe { sys::SDL_EventState(event_type as u32, sys::SDL_QUERY) };
2668
2669        result != sys::SDL_DISABLE as u8
2670    }
2671
2672    /// Enable an event type. Returns if the event type was enabled before the call.
2673    #[doc(alias = "SDL_EventState")]
2674    pub fn enable_event(&mut self, event_type: EventType) -> bool {
2675        let result = unsafe { sys::SDL_EventState(event_type as u32, sys::SDL_ENABLE as c_int) };
2676
2677        result != sys::SDL_DISABLE as u8
2678    }
2679
2680    /// Disable an event type. Returns if the event type was enabled before the call.
2681    #[doc(alias = "SDL_EventState")]
2682    pub fn disable_event(&mut self, event_type: EventType) -> bool {
2683        let result = unsafe { sys::SDL_EventState(event_type as u32, sys::SDL_DISABLE as c_int) };
2684
2685        result != sys::SDL_DISABLE as u8
2686    }
2687
2688    /// Polls for currently pending events.
2689    ///
2690    /// If no events are pending, `None` is returned.
2691    pub fn poll_event(&mut self) -> Option<Event> {
2692        unsafe { poll_event() }
2693    }
2694
2695    /// Returns a polling iterator that calls `poll_event()`.
2696    /// The iterator will terminate once there are no more pending events.
2697    ///
2698    /// # Example
2699    /// ```no_run
2700    /// let sdl_context = sdl2::init().unwrap();
2701    /// let mut event_pump = sdl_context.event_pump().unwrap();
2702    ///
2703    /// for event in event_pump.poll_iter() {
2704    ///     use sdl2::event::Event;
2705    ///     match event {
2706    ///         Event::KeyDown {..} => { /*...*/ }
2707    ///         _ => ()
2708    ///     }
2709    /// }
2710    /// ```
2711    pub fn poll_iter(&mut self) -> EventPollIterator {
2712        EventPollIterator {
2713            _marker: PhantomData,
2714        }
2715    }
2716
2717    /// Pumps the event loop, gathering events from the input devices.
2718    #[doc(alias = "SDL_PumpEvents")]
2719    pub fn pump_events(&mut self) {
2720        unsafe {
2721            sys::SDL_PumpEvents();
2722        };
2723    }
2724
2725    /// Waits indefinitely for the next available event.
2726    pub fn wait_event(&mut self) -> Event {
2727        unsafe { wait_event() }
2728    }
2729
2730    /// Waits until the specified timeout (in milliseconds) for the next available event.
2731    pub fn wait_event_timeout(&mut self, timeout: u32) -> Option<Event> {
2732        unsafe { wait_event_timeout(timeout) }
2733    }
2734
2735    /// Returns a waiting iterator that calls `wait_event()`.
2736    ///
2737    /// Note: The iterator will never terminate.
2738    pub fn wait_iter(&mut self) -> EventWaitIterator {
2739        EventWaitIterator {
2740            _marker: PhantomData,
2741        }
2742    }
2743
2744    /// Returns a waiting iterator that calls `wait_event_timeout()`.
2745    ///
2746    /// Note: The iterator will never terminate, unless waiting for an event
2747    /// exceeds the specified timeout.
2748    pub fn wait_timeout_iter(&mut self, timeout: u32) -> EventWaitTimeoutIterator {
2749        EventWaitTimeoutIterator {
2750            _marker: PhantomData,
2751            timeout,
2752        }
2753    }
2754
2755    #[inline]
2756    pub fn keyboard_state(&self) -> crate::keyboard::KeyboardState {
2757        crate::keyboard::KeyboardState::new(self)
2758    }
2759
2760    #[inline]
2761    pub fn mouse_state(&self) -> crate::mouse::MouseState {
2762        crate::mouse::MouseState::new(self)
2763    }
2764
2765    #[inline]
2766    pub fn relative_mouse_state(&self) -> crate::mouse::RelativeMouseState {
2767        crate::mouse::RelativeMouseState::new(self)
2768    }
2769}
2770
2771/// An iterator that calls `EventPump::poll_event()`.
2772#[must_use = "iterators are lazy and do nothing unless consumed"]
2773pub struct EventPollIterator<'a> {
2774    _marker: PhantomData<&'a ()>,
2775}
2776
2777impl<'a> Iterator for EventPollIterator<'a> {
2778    type Item = Event;
2779
2780    fn next(&mut self) -> Option<Event> {
2781        unsafe { poll_event() }
2782    }
2783}
2784
2785/// An iterator that calls `EventPump::wait_event()`.
2786#[must_use = "iterators are lazy and do nothing unless consumed"]
2787pub struct EventWaitIterator<'a> {
2788    _marker: PhantomData<&'a ()>,
2789}
2790
2791impl<'a> Iterator for EventWaitIterator<'a> {
2792    type Item = Event;
2793    fn next(&mut self) -> Option<Event> {
2794        unsafe { Some(wait_event()) }
2795    }
2796}
2797
2798/// An iterator that calls `EventPump::wait_event_timeout()`.
2799#[must_use = "iterators are lazy and do nothing unless consumed"]
2800pub struct EventWaitTimeoutIterator<'a> {
2801    _marker: PhantomData<&'a ()>,
2802    timeout: u32,
2803}
2804
2805impl<'a> Iterator for EventWaitTimeoutIterator<'a> {
2806    type Item = Event;
2807    fn next(&mut self) -> Option<Event> {
2808        unsafe { wait_event_timeout(self.timeout) }
2809    }
2810}
2811
2812/// A sendible type that can push events to the event queue.
2813pub struct EventSender {
2814    _priv: (),
2815}
2816
2817impl EventSender {
2818    /// Pushes an event to the event queue.
2819    #[doc(alias = "SDL_PushEvent")]
2820    pub fn push_event(&self, event: Event) -> Result<(), String> {
2821        match event.to_ll() {
2822            Some(mut raw_event) => {
2823                let ok = unsafe { sys::SDL_PushEvent(&mut raw_event) == 1 };
2824                if ok {
2825                    Ok(())
2826                } else {
2827                    Err(get_error())
2828                }
2829            }
2830            None => Err("Cannot push unsupported event type to the queue".to_owned()),
2831        }
2832    }
2833
2834    /// Push a custom event
2835    ///
2836    /// If the event type ``T`` was not registered using
2837    /// [EventSubsystem::register_custom_event]
2838    /// (../struct.EventSubsystem.html#method.register_custom_event),
2839    /// this method will panic.
2840    ///
2841    /// # Example: pushing and receiving a custom event
2842    /// ```
2843    /// struct SomeCustomEvent {
2844    ///     a: i32
2845    /// }
2846    ///
2847    /// let sdl = sdl2::init().unwrap();
2848    /// let ev = sdl.event().unwrap();
2849    /// let mut ep = sdl.event_pump().unwrap();
2850    ///
2851    /// ev.register_custom_event::<SomeCustomEvent>().unwrap();
2852    ///
2853    /// let event = SomeCustomEvent { a: 42 };
2854    ///
2855    /// ev.push_custom_event(event);
2856    ///
2857    /// let received = ep.poll_event().unwrap(); // or within a for event in ep.poll_iter()
2858    /// if received.is_user_event() {
2859    ///     let e2 = received.as_user_event_type::<SomeCustomEvent>().unwrap();
2860    ///     assert_eq!(e2.a, 42);
2861    /// }
2862    /// ```
2863    pub fn push_custom_event<T: ::std::any::Any>(&self, event: T) -> Result<(), String> {
2864        use std::any::TypeId;
2865        let cet = CUSTOM_EVENT_TYPES.lock().unwrap();
2866        let type_id = TypeId::of::<Box<T>>();
2867
2868        let user_event_id = *match cet.type_id_to_sdl_id.get(&type_id) {
2869            Some(id) => id,
2870            None => {
2871                return Err("Type is not registered as a custom event type!".to_owned());
2872            }
2873        };
2874
2875        let event_box = Box::new(event);
2876        let event = Event::User {
2877            timestamp: 0,
2878            window_id: 0,
2879            type_: user_event_id,
2880            code: 0,
2881            data1: Box::into_raw(event_box) as *mut c_void,
2882            data2: ::std::ptr::null_mut(),
2883        };
2884        drop(cet);
2885
2886        self.push_event(event)?;
2887
2888        Ok(())
2889    }
2890}
2891
2892/// A callback trait for [`EventSubsystem::add_event_watch`].
2893pub trait EventWatchCallback {
2894    fn callback(&mut self, event: Event);
2895}
2896
2897/// An handler for the event watch callback.
2898/// One must bind this struct in a variable as long as you want to keep the callback active.
2899/// For further information, see [`EventSubsystem::add_event_watch`].
2900pub struct EventWatch<'a, CB: EventWatchCallback + 'a> {
2901    activated: bool,
2902    callback: Box<CB>,
2903    _phantom: PhantomData<&'a CB>,
2904}
2905
2906impl<'a, CB: EventWatchCallback + 'a> EventWatch<'a, CB> {
2907    fn add(callback: CB) -> EventWatch<'a, CB> {
2908        let f = Box::new(callback);
2909        let mut watch = EventWatch {
2910            activated: false,
2911            callback: f,
2912            _phantom: PhantomData,
2913        };
2914        watch.activate();
2915        watch
2916    }
2917
2918    /// Activates the event watch.
2919    /// Does nothing if it is already activated.
2920    pub fn activate(&mut self) {
2921        if !self.activated {
2922            self.activated = true;
2923            unsafe { sys::SDL_AddEventWatch(self.filter(), self.callback()) };
2924        }
2925    }
2926
2927    /// Deactivates the event watch.
2928    /// Does nothing if it is already activated.
2929    pub fn deactivate(&mut self) {
2930        if self.activated {
2931            self.activated = false;
2932            unsafe { sys::SDL_DelEventWatch(self.filter(), self.callback()) };
2933        }
2934    }
2935
2936    /// Returns if the event watch is activated.
2937    pub fn activated(&self) -> bool {
2938        self.activated
2939    }
2940
2941    /// Set the activation state of the event watch.
2942    pub fn set_activated(&mut self, activate: bool) {
2943        if activate {
2944            self.activate();
2945        } else {
2946            self.deactivate();
2947        }
2948    }
2949
2950    fn filter(&self) -> SDL_EventFilter {
2951        Some(event_callback_marshall::<CB> as _)
2952    }
2953
2954    fn callback(&mut self) -> *mut c_void {
2955        &mut *self.callback as *mut _ as *mut c_void
2956    }
2957}
2958
2959impl<'a, CB: EventWatchCallback + 'a> Drop for EventWatch<'a, CB> {
2960    fn drop(&mut self) {
2961        self.deactivate();
2962    }
2963}
2964
2965extern "C" fn event_callback_marshall<CB: EventWatchCallback>(
2966    user_data: *mut c_void,
2967    event: *mut sdl2_sys::SDL_Event,
2968) -> i32 {
2969    let f: &mut CB = unsafe { &mut *(user_data as *mut _) };
2970    let event = Event::from_ll(unsafe { *event });
2971    f.callback(event);
2972    0
2973}
2974
2975impl<F: FnMut(Event)> EventWatchCallback for F {
2976    fn callback(&mut self, event: Event) {
2977        self(event)
2978    }
2979}
2980
2981#[cfg(test)]
2982mod test {
2983    use super::super::controller::{Axis, Button};
2984    use super::super::joystick::HatState;
2985    use super::super::keyboard::{Keycode, Mod, Scancode};
2986    use super::super::mouse::{MouseButton, MouseState, MouseWheelDirection};
2987    use super::super::video::Orientation;
2988    use super::DisplayEvent;
2989    use super::Event;
2990    use super::WindowEvent;
2991
2992    // Tests a round-trip conversion from an Event type to
2993    // the SDL event type and back, to make sure it's sane.
2994    #[test]
2995    fn test_to_from_ll() {
2996        {
2997            let e = Event::Quit { timestamp: 0 };
2998            let e2 = Event::from_ll(e.clone().to_ll().unwrap());
2999            assert_eq!(e, e2);
3000        }
3001        {
3002            let e = Event::Display {
3003                timestamp: 0,
3004                display_index: 1,
3005                display_event: DisplayEvent::Orientation(Orientation::LandscapeFlipped),
3006            };
3007            let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3008            assert_eq!(e, e2);
3009        }
3010        {
3011            let e = Event::Window {
3012                timestamp: 0,
3013                window_id: 0,
3014                win_event: WindowEvent::Resized(1, 2),
3015            };
3016            let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3017            assert_eq!(e, e2);
3018        }
3019        {
3020            let e = Event::KeyDown {
3021                timestamp: 0,
3022                window_id: 1,
3023                keycode: None,
3024                scancode: Some(Scancode::Q),
3025                keymod: Mod::all(),
3026                repeat: false,
3027            };
3028            let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3029            assert_eq!(e, e2);
3030        }
3031        {
3032            let e = Event::KeyUp {
3033                timestamp: 123,
3034                window_id: 0,
3035                keycode: Some(Keycode::R),
3036                scancode: Some(Scancode::R),
3037                keymod: Mod::empty(),
3038                repeat: true,
3039            };
3040            let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3041            assert_eq!(e, e2);
3042        }
3043        {
3044            let e = Event::MouseMotion {
3045                timestamp: 0,
3046                window_id: 0,
3047                which: 1,
3048                mousestate: MouseState::from_sdl_state(1),
3049                x: 3,
3050                y: 91,
3051                xrel: -1,
3052                yrel: 43,
3053            };
3054            let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3055            assert_eq!(e, e2);
3056        }
3057        {
3058            let e = Event::MouseButtonDown {
3059                timestamp: 5634,
3060                window_id: 2,
3061                which: 0,
3062                mouse_btn: MouseButton::Left,
3063                clicks: 1,
3064                x: 543,
3065                y: 345,
3066            };
3067            let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3068            assert_eq!(e, e2);
3069        }
3070        {
3071            let e = Event::MouseButtonUp {
3072                timestamp: 0,
3073                window_id: 2,
3074                which: 0,
3075                mouse_btn: MouseButton::Left,
3076                clicks: 1,
3077                x: 543,
3078                y: 345,
3079            };
3080            let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3081            assert_eq!(e, e2);
3082        }
3083        {
3084            let e = Event::MouseWheel {
3085                timestamp: 1,
3086                window_id: 0,
3087                which: 32,
3088                x: 23,
3089                y: 91,
3090                direction: MouseWheelDirection::Flipped,
3091                precise_x: 1.6,
3092                precise_y: 2.7,
3093                mouse_x: 0,
3094                mouse_y: 5,
3095            };
3096            let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3097            assert_eq!(e, e2);
3098        }
3099        {
3100            let e = Event::JoyAxisMotion {
3101                timestamp: 0,
3102                which: 1,
3103                axis_idx: 1,
3104                value: 12,
3105            };
3106            let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3107            assert_eq!(e, e2);
3108        }
3109        {
3110            let e = Event::JoyBallMotion {
3111                timestamp: 0,
3112                which: 0,
3113                ball_idx: 1,
3114                xrel: 123,
3115                yrel: 321,
3116            };
3117            let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3118            assert_eq!(e, e2);
3119        }
3120        {
3121            let e = Event::JoyHatMotion {
3122                timestamp: 0,
3123                which: 3,
3124                hat_idx: 1,
3125                state: HatState::Left,
3126            };
3127            let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3128            assert_eq!(e, e2);
3129        }
3130        {
3131            let e = Event::JoyButtonDown {
3132                timestamp: 0,
3133                which: 0,
3134                button_idx: 3,
3135            };
3136            let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3137            assert_eq!(e, e2);
3138        }
3139        {
3140            let e = Event::JoyButtonUp {
3141                timestamp: 9876,
3142                which: 1,
3143                button_idx: 2,
3144            };
3145            let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3146            assert_eq!(e, e2);
3147        }
3148        {
3149            let e = Event::JoyDeviceAdded {
3150                timestamp: 0,
3151                which: 1,
3152            };
3153            let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3154            assert_eq!(e, e2);
3155        }
3156        {
3157            let e = Event::JoyDeviceRemoved {
3158                timestamp: 0,
3159                which: 2,
3160            };
3161            let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3162            assert_eq!(e, e2);
3163        }
3164        {
3165            let e = Event::ControllerAxisMotion {
3166                timestamp: 53,
3167                which: 0,
3168                axis: Axis::LeftX,
3169                value: 3,
3170            };
3171            let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3172            assert_eq!(e, e2);
3173        }
3174        {
3175            let e = Event::ControllerButtonDown {
3176                timestamp: 0,
3177                which: 1,
3178                button: Button::Guide,
3179            };
3180            let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3181            assert_eq!(e, e2);
3182        }
3183        {
3184            let e = Event::ControllerButtonUp {
3185                timestamp: 654214,
3186                which: 0,
3187                button: Button::DPadRight,
3188            };
3189            let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3190            assert_eq!(e, e2);
3191        }
3192        {
3193            let e = Event::ControllerDeviceAdded {
3194                timestamp: 543,
3195                which: 3,
3196            };
3197            let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3198            assert_eq!(e, e2);
3199        }
3200        {
3201            let e = Event::ControllerDeviceRemoved {
3202                timestamp: 555,
3203                which: 3,
3204            };
3205            let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3206            assert_eq!(e, e2);
3207        }
3208        {
3209            let e = Event::ControllerDeviceRemapped {
3210                timestamp: 654,
3211                which: 0,
3212            };
3213            let e2 = Event::from_ll(e.clone().to_ll().unwrap());
3214            assert_eq!(e, e2);
3215        }
3216    }
3217
3218    #[test]
3219    fn test_from_ll_keymod_keydown_unknown_bits() {
3220        let mut raw_event = Event::KeyDown {
3221            timestamp: 0,
3222            window_id: 1,
3223            keycode: None,
3224            scancode: Some(Scancode::Q),
3225            keymod: Mod::empty(),
3226            repeat: false,
3227        }
3228        .to_ll()
3229        .unwrap();
3230
3231        // Simulate SDL setting bits unknown to us, see PR #780
3232        raw_event.key.keysym.mod_ = 0xffff;
3233
3234        if let Event::KeyDown { keymod, .. } = Event::from_ll(raw_event) {
3235            assert_eq!(keymod, Mod::all());
3236        } else {
3237            panic!()
3238        }
3239    }
3240
3241    #[test]
3242    fn test_from_ll_keymod_keyup_unknown_bits() {
3243        let mut raw_event = Event::KeyUp {
3244            timestamp: 0,
3245            window_id: 1,
3246            keycode: None,
3247            scancode: Some(Scancode::Q),
3248            keymod: Mod::empty(),
3249            repeat: false,
3250        }
3251        .to_ll()
3252        .unwrap();
3253
3254        // Simulate SDL setting bits unknown to us, see PR #780
3255        raw_event.key.keysym.mod_ = 0xffff;
3256
3257        if let Event::KeyUp { keymod, .. } = Event::from_ll(raw_event) {
3258            assert_eq!(keymod, Mod::all());
3259        } else {
3260            panic!()
3261        }
3262    }
3263}