1use 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
33pub 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
54pub 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 #[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 pub fn handle_quit(&mut self, handler: EventHandler<'video, QuitEvent>) {
98 self.quit_event_handlers.push(handler);
99 }
100
101 pub fn handle_window(&mut self, handler: EventHandler<'video, WindowEvent>) {
103 self.window_event_handlers.push(handler);
104 }
105
106 pub fn handle_keyboard(&mut self, handler: EventHandler<'video, KeyboardEvent>) {
108 self.keyboard_event_handlers.push(handler);
109 }
110
111 pub fn handle_input(&mut self, handler: EventHandler<'video, TextInputEvent>) {
113 self.input_event_handlers.push(handler);
114 }
115
116 pub fn handle_editing(&mut self, handler: EventHandler<'video, TextEditingEvent>) {
118 self.editing_event_handlers.push(handler);
119 }
120
121 pub fn handle_mouse(&mut self, handler: EventHandler<'video, MouseEvent>) {
123 self.mouse_event_handlers.push(handler);
124 }
125
126 pub fn handle_controller(&mut self, handler: EventHandler<'video, ControllerEvent<'video>>) {
128 self.controller_event_handlers.push(handler);
129 }
130
131 pub fn handle_joystick(&mut self, handler: EventHandler<'video, JoystickEvent<'video>>) {
133 self.joystick_event_handlers.push(handler);
134 }
135
136 pub fn handle_audio_device(&mut self, handler: EventHandler<'video, AudioDeviceEvent>) {
138 self.audio_device_event_handlers.push(handler);
139 }
140
141 pub fn handle_drop(&mut self, handler: EventHandler<'video, DropEvent>) {
143 self.drop_event_handlers.push(handler);
144 }
145
146 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 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 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}