1use sdl3::event::Event;
4use std::time::{Duration, Instant};
5
6use crate::Window;
7
8use sdl3::{
9 keyboard::{Keycode, Mod, Scancode},
10 mouse::{MouseButton, MouseState, MouseWheelDirection},
11};
12
13pub struct KeyboardEvent {
14 pub timestamp: u64,
15 pub window_id: u32,
16 pub keycode: Option<Keycode>,
17 pub scancode: Option<Scancode>,
18 pub keymod: Mod,
19 pub repeat: bool,
20 pub which: u32,
21 pub raw: u16,
22}
23
24pub struct MouseMotionEvent {
25 pub timestamp: u64,
26 pub window_id: u32,
27 pub which: u32,
28 pub mousestate: MouseState,
29 pub x: f32,
30 pub y: f32,
31 pub xrel: f32,
32 pub yrel: f32,
33}
34
35pub struct MouseClickEvent {
36 pub timestamp: u64,
37 pub window_id: u32,
38 pub which: u32,
39 pub mouse_btn: MouseButton,
40 pub clicks: u8,
41 pub x: f32,
42 pub y: f32,
43}
44
45pub struct MouseWheelEvent {
46 pub timestamp: u64,
47 pub window_id: u32,
48 pub which: u32,
49 pub x: f32,
50 pub y: f32,
51 pub direction: MouseWheelDirection,
52 pub mouse_x: f32,
53 pub mouse_y: f32,
54}
55
56#[async_trait::async_trait]
57pub trait WindowEventHandler: Send + Sync {
58 fn update(&self, _window: &mut Window) -> anyhow::Result<()>;
59 fn draw(&mut self, _window: &mut Window) -> anyhow::Result<()>;
60
61 fn key_down_event(&self, _window: &mut Window, _event: KeyboardEvent) -> anyhow::Result<()> {
62 Ok(())
63 }
64 fn key_up_event(&self, _window: &mut Window, _event: KeyboardEvent) -> anyhow::Result<()> {
65 Ok(())
66 }
67 fn mouse_motion_event(
68 &self,
69 _window: &mut Window,
70 _event: MouseMotionEvent,
71 ) -> anyhow::Result<()> {
72 Ok(())
73 }
74 fn mouse_button_down_event(
75 &self,
76 _window: &mut Window,
77 _event: MouseClickEvent,
78 ) -> anyhow::Result<()> {
79 Ok(())
80 }
81 fn mouse_button_up_event(
82 &self,
83 _window: &mut Window,
84 _event: MouseClickEvent,
85 ) -> anyhow::Result<()> {
86 Ok(())
87 }
88 fn mouse_wheel_event(
89 &self,
90 _window: &mut Window,
91 _event: MouseWheelEvent,
92 ) -> anyhow::Result<()> {
93 Ok(())
94 }
95}
96
97pub async fn run(window: &mut Window, state: &'static mut dyn WindowEventHandler) {
114 let mut event_pump = window.graphics.sdl_context.event_pump().unwrap();
115
116 'running: loop {
117 let now = Instant::now();
118
119 for event in event_pump.poll_iter() {
121 match event {
122 Event::Quit { .. } => break 'running,
123 Event::KeyDown {
124 timestamp,
125 window_id,
126 keycode: Some(keycode),
127 scancode: Some(scancode),
128 keymod,
129 repeat,
130 which,
131 raw,
132 } => state
133 .key_down_event(
134 window,
135 KeyboardEvent {
136 timestamp,
137 window_id,
138 keycode: Some(keycode),
139 scancode: Some(scancode),
140 keymod,
141 repeat,
142 which,
143 raw,
144 },
145 )
146 .unwrap(),
147
148 Event::KeyUp {
149 timestamp,
150 window_id,
151 keycode: Some(keycode),
152 scancode: Some(scancode),
153 keymod,
154 repeat,
155 which,
156 raw,
157 } => state
158 .key_up_event(
159 window,
160 KeyboardEvent {
161 timestamp,
162 window_id,
163 keycode: Some(keycode),
164 scancode: Some(scancode),
165 keymod,
166 repeat,
167 which,
168 raw,
169 },
170 )
171 .unwrap(),
172
173 Event::MouseMotion {
174 timestamp,
175 window_id,
176 which,
177 mousestate,
178 x,
179 y,
180 xrel,
181 yrel,
182 } => state
183 .mouse_motion_event(
184 window,
185 MouseMotionEvent {
186 timestamp,
187 window_id,
188 which,
189 mousestate,
190 x,
191 y,
192 xrel,
193 yrel,
194 },
195 )
196 .unwrap(),
197
198 Event::MouseButtonDown {
199 timestamp,
200 window_id,
201 which,
202 mouse_btn,
203 clicks,
204 x,
205 y,
206 } => state
207 .mouse_button_down_event(
208 window,
209 MouseClickEvent {
210 timestamp,
211 window_id,
212 which,
213 mouse_btn,
214 clicks,
215 x,
216 y,
217 },
218 )
219 .unwrap(),
220
221 Event::MouseButtonUp {
222 timestamp,
223 window_id,
224 which,
225 mouse_btn,
226 clicks,
227 x,
228 y,
229 } => state
230 .mouse_button_up_event(
231 window,
232 MouseClickEvent {
233 timestamp,
234 window_id,
235 which,
236 mouse_btn,
237 clicks,
238 x,
239 y,
240 },
241 )
242 .unwrap(),
243
244 Event::MouseWheel {
245 timestamp,
246 window_id,
247 which,
248 x,
249 y,
250 direction,
251 mouse_x,
252 mouse_y,
253 } => state
254 .mouse_wheel_event(
255 window,
256 MouseWheelEvent {
257 timestamp,
258 window_id,
259 which,
260 x,
261 y,
262 direction,
263 mouse_x,
264 mouse_y,
265 },
266 )
267 .unwrap(),
268 _ => {}
269 }
270 }
271 let _ = state.update(window);
273 let _ = state.draw(window);
274
275 let elapsed = Instant::now().duration_since(now).as_nanos() as u64;
277 if elapsed < 999_999 {
278 std::thread::sleep(Duration::from_nanos(999_999 - elapsed));
279 }
280 }
281}