rich_sdl2_rust/
event.rs

1//! SDL2 event system and handlers.
2//!
3//! Most event structures are defined in these sub modules, but [`crate::audio::event::AudioDeviceEvent`] is defined in the external module.
4
5use static_assertions::assert_not_impl_all;
6use std::marker::PhantomData;
7
8use self::{
9    app::QuitEvent,
10    drop::DropEvent,
11    game_controller::event::ControllerEvent,
12    joystick::event::JoystickEvent,
13    keyboard::KeyboardEvent,
14    mouse::{MouseButtonEvent, MouseEvent, MouseMotionEvent, MouseWheelEvent},
15    text::{TextEditingEvent, TextInputEvent},
16    touch::gesture::GestureEvent,
17    window::WindowEvent,
18};
19
20use crate::{audio::event::AudioDeviceEvent, bind, EnumInt, Sdl, Video};
21
22pub mod app;
23pub mod drop;
24pub mod game_controller;
25pub mod joystick;
26pub mod keyboard;
27pub mod mouse;
28pub mod sensor;
29pub mod text;
30pub mod touch;
31pub mod window;
32
33/// An event handler to receive some event structure,
34pub type EventHandler<'video, T> = Box<dyn Fn(&T) + 'video>;
35
36struct EventHandlers<'video, T>(Vec<EventHandler<'video, T>>);
37
38impl<T> Default for EventHandlers<'_, T> {
39    fn default() -> Self {
40        Self(vec![])
41    }
42}
43
44impl<'video, T> EventHandlers<'video, T> {
45    fn push(&mut self, handler: EventHandler<'video, T>) {
46        self.0.push(handler);
47    }
48
49    fn call_handlers(&self, event: &T) {
50        self.0.iter().for_each(|handler| handler(event));
51    }
52}
53
54/// It takes the closure of handler to register, and delivers events to your event handlers by polling.
55pub struct EventBox<'video> {
56    quit_event_handlers: EventHandlers<'video, QuitEvent>,
57    window_event_handlers: EventHandlers<'video, WindowEvent>,
58    keyboard_event_handlers: EventHandlers<'video, KeyboardEvent>,
59    input_event_handlers: EventHandlers<'video, TextInputEvent>,
60    editing_event_handlers: EventHandlers<'video, TextEditingEvent>,
61    mouse_event_handlers: EventHandlers<'video, MouseEvent>,
62    controller_event_handlers: EventHandlers<'video, ControllerEvent<'video>>,
63    joystick_event_handlers: EventHandlers<'video, JoystickEvent<'video>>,
64    audio_device_event_handlers: EventHandlers<'video, AudioDeviceEvent>,
65    drop_event_handlers: EventHandlers<'video, DropEvent>,
66    gesture_event_handlers: EventHandlers<'video, GestureEvent>,
67    _phantom: PhantomData<&'video ()>,
68}
69
70assert_not_impl_all!(EventBox: Send, Sync);
71
72impl<'video> EventBox<'video> {
73    /// Constructs an event box from the video system.
74    #[must_use]
75    pub fn new(_: &'video Video) -> Self {
76        let ret = unsafe { bind::SDL_InitSubSystem(bind::SDL_INIT_EVENTS) };
77        if ret != 0 {
78            Sdl::error_then_panic("Sdl event")
79        }
80        Self {
81            quit_event_handlers: EventHandlers::default(),
82            window_event_handlers: EventHandlers::default(),
83            keyboard_event_handlers: EventHandlers::default(),
84            input_event_handlers: EventHandlers::default(),
85            editing_event_handlers: EventHandlers::default(),
86            mouse_event_handlers: EventHandlers::default(),
87            controller_event_handlers: EventHandlers::default(),
88            joystick_event_handlers: EventHandlers::default(),
89            audio_device_event_handlers: EventHandlers::default(),
90            drop_event_handlers: EventHandlers::default(),
91            gesture_event_handlers: EventHandlers::default(),
92            _phantom: PhantomData,
93        }
94    }
95
96    /// Registers the handler to handle [`QuitEvent`].
97    pub fn handle_quit(&mut self, handler: EventHandler<'video, QuitEvent>) {
98        self.quit_event_handlers.push(handler);
99    }
100
101    /// Registers the handler to handle [`WindowEvent`].
102    pub fn handle_window(&mut self, handler: EventHandler<'video, WindowEvent>) {
103        self.window_event_handlers.push(handler);
104    }
105
106    /// Registers the handler to handle [`KeyboardEvent`].
107    pub fn handle_keyboard(&mut self, handler: EventHandler<'video, KeyboardEvent>) {
108        self.keyboard_event_handlers.push(handler);
109    }
110
111    /// Registers the handler to handle [`TextInputEvent`].
112    pub fn handle_input(&mut self, handler: EventHandler<'video, TextInputEvent>) {
113        self.input_event_handlers.push(handler);
114    }
115
116    /// Registers the handler to handle [`TextEditingEvent`].
117    pub fn handle_editing(&mut self, handler: EventHandler<'video, TextEditingEvent>) {
118        self.editing_event_handlers.push(handler);
119    }
120
121    /// Registers the handler to handle [`MouseEvent`].
122    pub fn handle_mouse(&mut self, handler: EventHandler<'video, MouseEvent>) {
123        self.mouse_event_handlers.push(handler);
124    }
125
126    /// Registers the handler to handle [`ControllerEvent`].
127    pub fn handle_controller(&mut self, handler: EventHandler<'video, ControllerEvent<'video>>) {
128        self.controller_event_handlers.push(handler);
129    }
130
131    /// Registers the handler to handle [`JoystickEvent`].
132    pub fn handle_joystick(&mut self, handler: EventHandler<'video, JoystickEvent<'video>>) {
133        self.joystick_event_handlers.push(handler);
134    }
135
136    /// Registers the handler to handle [`AudioDeviceEvent`].
137    pub fn handle_audio_device(&mut self, handler: EventHandler<'video, AudioDeviceEvent>) {
138        self.audio_device_event_handlers.push(handler);
139    }
140
141    /// Registers the handler to handle [`DropEvent`].
142    pub fn handle_drop(&mut self, handler: EventHandler<'video, DropEvent>) {
143        self.drop_event_handlers.push(handler);
144    }
145
146    /// Registers the handler to handle [`GestureEvent`].
147    pub fn handle_gesture(&mut self, handler: EventHandler<'video, GestureEvent>) {
148        self.gesture_event_handlers.push(handler);
149    }
150
151    fn handle_event(&self, event: bind::SDL_Event) {
152        let ty = unsafe { event.type_ };
153        match ty as EnumInt {
154            bind::SDL_QUIT => {
155                let quit: QuitEvent = unsafe { event.quit }.into();
156                self.quit_event_handlers.call_handlers(&quit);
157            }
158            bind::SDL_WINDOWEVENT => {
159                let window: WindowEvent = unsafe { event.window }.into();
160                self.window_event_handlers.call_handlers(&window);
161            }
162            bind::SDL_KEYDOWN | bind::SDL_KEYUP => {
163                let keyboard: KeyboardEvent = unsafe { event.key }.into();
164                self.keyboard_event_handlers.call_handlers(&keyboard);
165            }
166            bind::SDL_TEXTINPUT => {
167                let input: TextInputEvent = unsafe { event.text }.into();
168                self.input_event_handlers.call_handlers(&input);
169            }
170            bind::SDL_TEXTEDITING => {
171                let editing: TextEditingEvent = unsafe { event.edit }.into();
172                self.editing_event_handlers.call_handlers(&editing);
173            }
174            bind::SDL_MOUSEMOTION => {
175                let motion: MouseMotionEvent = unsafe { event.motion }.into();
176                let mouse = MouseEvent::Motion(motion);
177                self.mouse_event_handlers.call_handlers(&mouse);
178            }
179            bind::SDL_MOUSEBUTTONDOWN | bind::SDL_MOUSEBUTTONUP => {
180                let button: MouseButtonEvent = unsafe { event.button }.into();
181                let mouse = MouseEvent::Button(button);
182                self.mouse_event_handlers.call_handlers(&mouse);
183            }
184            bind::SDL_MOUSEWHEEL => {
185                let wheel: MouseWheelEvent = unsafe { event.wheel }.into();
186                let mouse = MouseEvent::Wheel(wheel);
187                self.mouse_event_handlers.call_handlers(&mouse);
188            }
189            bind::SDL_CONTROLLERAXISMOTION => {
190                let con: ControllerEvent = unsafe { event.caxis }.into();
191                self.controller_event_handlers.call_handlers(&con);
192            }
193            bind::SDL_CONTROLLERBUTTONDOWN | bind::SDL_CONTROLLERBUTTONUP => {
194                let con: ControllerEvent = unsafe { event.cbutton }.into();
195                self.controller_event_handlers.call_handlers(&con);
196            }
197            bind::SDL_CONTROLLERDEVICEADDED
198            | bind::SDL_CONTROLLERDEVICEREMOVED
199            | bind::SDL_CONTROLLERDEVICEREMAPPED => {
200                let con: ControllerEvent = unsafe { event.cdevice }.into();
201                self.controller_event_handlers.call_handlers(&con);
202            }
203            bind::SDL_JOYAXISMOTION => {
204                let joy: JoystickEvent = unsafe { event.jaxis }.into();
205                self.joystick_event_handlers.call_handlers(&joy);
206            }
207            bind::SDL_JOYBALLMOTION => {
208                let joy: JoystickEvent = unsafe { event.jball }.into();
209                self.joystick_event_handlers.call_handlers(&joy);
210            }
211            bind::SDL_JOYBUTTONDOWN | bind::SDL_JOYBUTTONUP => {
212                let joy: JoystickEvent = unsafe { event.jbutton }.into();
213                self.joystick_event_handlers.call_handlers(&joy);
214            }
215            bind::SDL_JOYDEVICEADDED | bind::SDL_JOYDEVICEREMOVED => {
216                let joy: JoystickEvent = unsafe { event.jdevice }.into();
217                self.joystick_event_handlers.call_handlers(&joy);
218            }
219            bind::SDL_JOYHATMOTION => {
220                let joy: JoystickEvent = unsafe { event.jhat }.into();
221                self.joystick_event_handlers.call_handlers(&joy);
222            }
223            bind::SDL_AUDIODEVICEADDED | bind::SDL_AUDIODEVICEREMOVED => {
224                let audio = unsafe { event.adevice }.into();
225                self.audio_device_event_handlers.call_handlers(&audio);
226            }
227            bind::SDL_DROPFILE
228            | bind::SDL_DROPTEXT
229            | bind::SDL_DROPBEGIN
230            | bind::SDL_DROPCOMPLETE => {
231                let drop = unsafe { event.drop }.into();
232                self.drop_event_handlers.call_handlers(&drop);
233            }
234            bind::SDL_MULTIGESTURE => {
235                let gesture = unsafe { event.mgesture }.into();
236                self.gesture_event_handlers.call_handlers(&gesture);
237            }
238            bind::SDL_DOLLARGESTURE => {
239                let gesture = unsafe { event.dgesture }.into();
240                self.gesture_event_handlers.call_handlers(&gesture);
241            }
242            _ => {}
243        }
244    }
245
246    /// Polling the events and triggers the event handlers.
247    pub fn poll(&self) {
248        use std::mem::MaybeUninit;
249        let mut event = MaybeUninit::uninit();
250        let remaining_events = unsafe { bind::SDL_PollEvent(event.as_mut_ptr()) };
251        let event = unsafe { event.assume_init() };
252        if remaining_events == 0 {
253            return;
254        }
255        self.handle_event(event);
256    }
257
258    /// Waits until the next event occurs, but unlock with timeout seconds.
259    pub fn wait_next_event_with(&self, timeout_ms: u32) {
260        use std::mem::MaybeUninit;
261        let mut event = MaybeUninit::uninit();
262        let ret = unsafe { bind::SDL_WaitEventTimeout(event.as_mut_ptr(), timeout_ms as i32) };
263        if ret == 0 {
264            return;
265        }
266        let event = unsafe { event.assume_init() };
267        self.handle_event(event);
268    }
269}
270
271impl<'video> Drop for EventBox<'video> {
272    fn drop(&mut self) {
273        unsafe { bind::SDL_QuitSubSystem(bind::SDL_INIT_EVENTS) }
274    }
275}