est_render/
runner.rs

1use std::{
2    collections::HashMap, hash::{Hash, Hasher}, io::Read, sync::{atomic::{AtomicBool, AtomicUsize}, Arc, Mutex}, thread::ThreadId, time::Duration
3};
4
5use crate::{input::{self, InputInner}, math::{Point2, Timing}, utils::{ArcMut, ArcRef}, window::{Window, WindowBuilder, WindowInner}};
6
7use smol_str::SmolStr;
8use wgpu::rwh::HasWindowHandle;
9use winit::{
10    application::ApplicationHandler, dpi::{PhysicalPosition, PhysicalSize}, event, event_loop::{ActiveEventLoop, EventLoop, EventLoopProxy}, keyboard::{Key, NamedKey, NativeKey}, platform::pump_events::{EventLoopExtPumpEvents, PumpStatus}, window::{Cursor, CustomCursor, CustomCursorSource, Window as WinitWindow, WindowAttributes, WindowId}
11};
12
13#[cfg(target_os = "windows")]
14use winit::platform::windows::EventLoopBuilderExtWindows;
15
16#[cfg(all(not(feature = "x11"), target_os = "linux"))]
17use winit::platform::wayland::EventLoopBuilderExtWayland;
18
19#[cfg(all(feature = "x11", target_os = "linux"))]
20use winit::platform::x11::EventLoopBuilderExtX11;
21
22/// Create a [Runner] instance, required for creating one or more windows.
23///
24/// **NOTE:** When calling this function, the thread will be made the main thread,
25/// future calls to this function will panic if called from a different thread.
26pub fn new() -> Result<Runner, RunnerError> {
27    Runner::new()
28}
29
30// This is the most laziest workaround to able construct multiple event loops
31// in the same process, but only one at a time.
32//
33// However, this will lock the event loop to the thread that created it, and
34// will panic if called from a different thread after the first call.
35lazy_static::lazy_static! {
36    static ref CURRENT_LOOP_THREAD_ID: Mutex<Option<ThreadId>> = Mutex::new(None);
37    static ref CURRENT_LOOP: Mutex<Option<EventLoopWrapper>> = Mutex::new(None);
38    static ref CURRENT_WINDOW_ID: AtomicUsize = AtomicUsize::new(0);
39}
40
41pub(crate) struct EventLoopWrapper {
42    pub event_loop: ArcRef<EventLoop<WindowEvent>>,
43}
44
45// This needed for global access to the event loop
46// But the actual uses, still limit it to the callers thread
47// This is a workaround for the fact that winit's EventLoop is not Send or Sync
48unsafe impl Sync for EventLoopWrapper {}
49unsafe impl Send for EventLoopWrapper {}
50
51/// Provide almost cross-platform event loop for the application.
52///
53/// This wrap winit's [EventLoop] and provides a way to create windows and handle events.
54/// But with some limitations:
55/// - No support for iOS and WASM platforms.
56/// - macOS platform have to use [PollMode::WaitDraw] or drawing at event [Event::RedrawRequested] because
57/// how winit setup the window drawing on macOS.
58#[allow(dead_code)]
59pub struct Runner {
60    pub(crate) app_runner: RunnerInner,
61    pub(crate) event_loop: ArcRef<EventLoop<WindowEvent>>,
62    pub(crate) event_loop_proxy: EventLoopProxy<WindowEvent>,
63    pub(crate) window_events_attributes: Vec<ArcRef<WindowInner>>,
64    pub(crate) input_events_attributes: Vec<ArcRef<InputInner>>,
65    pub(crate) rate_timing: Timing,
66    pub(crate) pending_events: Vec<Event>,
67}
68
69impl Runner {
70    pub(crate) fn new() -> Result<Self, RunnerError> {
71        let thread_id = std::thread::current().id();
72
73        if CURRENT_LOOP_THREAD_ID.lock().unwrap().is_none() {
74            *CURRENT_LOOP_THREAD_ID.lock().unwrap() = Some(thread_id);
75        } else if CURRENT_LOOP_THREAD_ID.lock().unwrap().as_ref() != Some(&thread_id) {
76            return Err(RunnerError::ThreadMissmatch);
77        }
78
79        let event_loop = if let Some(current_loop) = CURRENT_LOOP.lock().unwrap().as_ref() {
80            current_loop.event_loop.clone()
81        } else {
82            let event_loop_result = std::panic::catch_unwind(|| {
83                let mut event_loop_builder = EventLoop::<WindowEvent>::with_user_event();
84
85                #[cfg(any(target_os = "windows", target_os = "linux"))]
86                {
87                    event_loop_builder.with_any_thread(true);
88                }
89
90                event_loop_builder.build()
91            });
92
93            // Winit panic if the event loop is already created in another? thread.
94            if event_loop_result.is_err() {
95                *CURRENT_LOOP_THREAD_ID.lock().unwrap() = None;
96
97                return Err(RunnerError::WinitEventLoopPanic);
98            }
99
100            // If the event loop creation failed, we return an error.
101            let event_loop_result = event_loop_result.unwrap();
102            if event_loop_result.is_err() {
103                *CURRENT_LOOP_THREAD_ID.lock().unwrap() = None;
104
105                return Err(RunnerError::WinitEventLoopFailed);
106            }
107
108            let event_loop_result = ArcRef::new(event_loop_result.unwrap());
109            *CURRENT_LOOP.lock().unwrap() = Some(EventLoopWrapper {
110                event_loop: event_loop_result.clone(),
111            });
112
113            event_loop_result
114        };
115
116        let event_loop_proxy = {
117            let event_loop = event_loop.wait_borrow_mut();
118            event_loop.create_proxy()
119        };
120
121        Ok(Self {
122            app_runner: RunnerInner::new(),
123            event_loop,
124            event_loop_proxy,
125            window_events_attributes: Vec::new(),
126            input_events_attributes: Vec::new(),
127            rate_timing: Timing::new(0),
128            pending_events: Vec::new(),
129        })
130    }
131
132    /// Returns the pending events that have been processed by the event loop in [Runner::pump_events].
133    pub fn get_events(&self) -> &Vec<Event> {
134        &self.pending_events
135    }
136
137    /// Creates a new [WindowBuilder] instance to build a new window.
138    pub fn create_window(&mut self, title: &str, size: Point2) -> WindowBuilder {
139        WindowBuilder::new(self, title, size)
140    }
141
142    /// Creates a new [Input] instance for handling input events.
143    /// 
144    /// You can pass an optional [Window] reference to associate the input with a specific window.
145    /// If no window is provided, the input will be global and not associated with any specific window.
146    /// 
147    /// You still need a [Window] created with [Runner::create_window] to receive input events.
148    pub fn create_input(&mut self, window_id: Option<&Window>) -> input::Input {
149        let window_id = window_id.map(|w| w.id());
150
151        input::Input::new(self, window_id)
152    }
153
154    /// This called from [WindowBuilder] to create a new window.
155    pub(crate) fn internal_new_window(
156        &mut self,
157        parent: Option<usize>,
158        title: String,
159        size: Point2,
160        pos: Option<Point2>,
161    ) -> Result<(usize, EventLoopProxy<WindowEvent>), RunnerError> {
162        let mut event_loop = self.event_loop.wait_borrow_mut();
163        let event_loop_proxy = event_loop.create_proxy();
164
165        let window_id = CURRENT_WINDOW_ID.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
166        if window_id >= 1000 {
167            // return Err("Maximum window reached!".to_string());
168            return Err(RunnerError::MaximumWindowReached);
169        }
170
171        let res = event_loop_proxy.send_event(WindowEvent::Create {
172            ref_id: window_id,
173            parent_ref_id: parent,
174            title,
175            size,
176            pos,
177        });
178
179        if res.is_err() {
180            let err = self
181                .app_runner
182                .last_error
183                .clone()
184                .unwrap_or_else(|| "Failed to create window!".to_string());
185
186            return Err(RunnerError::FailedToCreateWindow(err));
187        }
188
189        event_loop.pump_app_events(Some(Duration::ZERO), &mut self.app_runner);
190
191        let mut found = false;
192        for (_id, handle) in self.app_runner.handles.iter() {
193            if handle.ref_id == window_id {
194                found = true;
195                break;
196            }
197        }
198
199        if !found {
200            let err = self
201                .app_runner
202                .last_error
203                .clone()
204                .unwrap_or_else(|| "Failed to create window!".to_string());
205
206            return Err(RunnerError::FailedToCreateWindow(err));
207        }
208
209        Ok((window_id, event_loop_proxy))
210    }
211
212    /// Pump the event loop and process events.
213    ///
214    /// This method will block based on the provided `mode`.
215    /// - [PollMode::Poll] will return immediately if there are no events.
216    /// - [PollMode::Wait] will block until an event is available.
217    /// - [PollMode::WaitDraw] will block until a redraw is requested (Recommended for MacOS platform).
218    ///
219    /// You can also pass [None] to use the default behavior, which is equivalent to `PollMode::Poll`.
220    ///
221    /// After calling this method, you can access the processed events using the [Runner::get_events] method.
222    ///
223    /// # Incompatible platforms
224    /// - iOS: This method is not supported on iOS due to platform limitations.
225    /// - WASM: This method is not supported on WASM due to how the browser handles events, unless
226    /// you using the emscripten event loop.
227    pub fn pump_events<T>(&mut self, mode: T) -> bool
228    where
229        T: Into<Option<PumpMode>>,
230    {
231        let mut event_loop = self.event_loop.wait_borrow_mut();
232        let mode = mode.into();
233
234        let duration = match mode {
235            Some(PumpMode::Poll) => Some(Duration::ZERO),
236            Some(PumpMode::Wait) => None,
237            Some(PumpMode::WaitDraw) => None,
238            None => Some(Duration::ZERO),
239        };
240
241        let wait_for_redraw = match mode {
242            Some(PumpMode::WaitDraw) => true,
243            _ => false,
244        };
245
246        self.pending_events.clear();
247
248        loop {
249            match event_loop.pump_app_events(duration, &mut self.app_runner) {
250                PumpStatus::Continue => {
251                    for window in self.window_events_attributes.iter() {
252                        if let Some(mut window) = window.try_borrow_mut() {
253                            window.process_event();
254
255                            {
256                                let window_events = window.window_events.wait_borrow_mut();
257                                for event in window_events.iter() {
258                                    match event {
259                                        event::WindowEvent::CloseRequested => {
260                                            self.pending_events.push(Event::WindowClosed {
261                                                window_id: window.window_id,
262                                            });
263                                        }
264                                        event::WindowEvent::Resized(size) => {
265                                            self.pending_events.push(Event::WindowResized {
266                                                window_id: window.window_id,
267                                                size: Point2::new(size.width, size.height),
268                                            });
269                                        }
270                                        event::WindowEvent::Moved(pos) => {
271                                            self.pending_events.push(Event::WindowMoved {
272                                                window_id: window.window_id,
273                                                pos: Point2::new(pos.x, pos.y),
274                                            });
275                                        }
276                                        event::WindowEvent::RedrawRequested => {
277                                            self.pending_events.push(Event::RedrawRequested {
278                                                window_id: window.window_id,
279                                            });
280                                        }
281                                        event::WindowEvent::KeyboardInput {
282                                            event,
283                                            is_synthetic,
284                                            ..
285                                        } => {
286                                            if *is_synthetic {
287                                                continue;
288                                            }
289
290                                            let is_pressed =
291                                                event.state == event::ElementState::Pressed;
292
293                                            match event.logical_key {
294                                                Key::Character(ref smol_str) => {
295                                                    let smol_key = smol_str.clone();
296
297                                                    self.pending_events.push(Event::KeyboardInput {
298                                                        window_id: window.window_id,
299                                                        key: smol_key,
300                                                        pressed: is_pressed,
301                                                    });
302                                                }
303                                                Key::Named(ref named_key) => {
304                                                    let smol_key = named_key_to_str(named_key);
305                                                    if smol_key.is_none() {
306                                                        continue;
307                                                    }
308
309                                                    let smol_key = smol_key.unwrap();
310
311                                                    self.pending_events.push(Event::KeyboardInput {
312                                                        window_id: window.window_id,
313                                                        key: smol_key,
314                                                        pressed: is_pressed,
315                                                    });
316                                                }
317                                                Key::Unidentified(NativeKey::Windows(virtual_key)) => {
318                                                    let fmt = format!("virtual-key:{:?}", virtual_key);
319                                                    let smol_key = SmolStr::new(fmt);
320
321                                                    self.pending_events.push(Event::KeyboardInput {
322                                                        window_id: window.window_id,
323                                                        key: smol_key,
324                                                        pressed: is_pressed,
325                                                    });
326                                                }
327                                                _ => {
328                                                    // ignore
329                                                }
330                                            }
331                                        }
332                                        event::WindowEvent::MouseWheel {
333                                            delta, phase: _, ..
334                                        } => {
335                                            let delta = match delta {
336                                                event::MouseScrollDelta::LineDelta(
337                                                    delta_x,
338                                                    delta_y,
339                                                ) => MouseScrollDelta::LineDelta {
340                                                    delta_x: *delta_x,
341                                                    delta_y: *delta_y,
342                                                },
343                                                event::MouseScrollDelta::PixelDelta(delta_pos) => {
344                                                    MouseScrollDelta::PixelDelta {
345                                                        delta_x: delta_pos.x as f32,
346                                                        delta_y: delta_pos.y as f32,
347                                                    }
348                                                }
349                                            };
350
351                                            self.pending_events.push(Event::MouseWheel {
352                                                window_id: window.window_id,
353                                                delta,
354                                            });
355                                        }
356                                        event::WindowEvent::MouseInput {
357                                            device_id: _,
358                                            state,
359                                            button,
360                                        } => {
361                                            let is_pressed = *state == event::ElementState::Pressed;
362                                            let smoll_str = match button {
363                                                event::MouseButton::Left => SmolStr::new("Left"),
364                                                event::MouseButton::Right => SmolStr::new("Right"),
365                                                event::MouseButton::Middle => SmolStr::new("Middle"),
366                                                event::MouseButton::Back => SmolStr::new("Back"),
367                                                event::MouseButton::Forward => SmolStr::new("Forward"),
368                                                event::MouseButton::Other(_) => continue, // Ignore other buttons
369                                            };
370
371                                            self.pending_events.push(Event::MouseInput {
372                                                window_id: window.window_id,
373                                                button: smoll_str,
374                                                pressed: is_pressed,
375                                            });
376                                        }
377                                        event::WindowEvent::CursorEntered { device_id: _ } => {
378                                            self.pending_events.push(Event::CursorEntered {
379                                                window_id: window.window_id,
380                                            });
381                                        }
382                                        event::WindowEvent::CursorLeft { device_id: _ } => {
383                                            self.pending_events.push(Event::CursorLeft {
384                                                window_id: window.window_id,
385                                            });
386                                        }
387                                        event::WindowEvent::CursorMoved {
388                                            device_id: _,
389                                            position,
390                                        } => {
391                                            self.pending_events.push(Event::CursorMoved {
392                                                window_id: window.window_id,
393                                                pos: Point2::new(position.x, position.y),
394                                            });
395                                        }
396                                        event::WindowEvent::Focused(focused) => {
397                                            self.pending_events.push(Event::WindowFocused {
398                                                window_id: window.window_id,
399                                                focused: *focused,
400                                            });
401                                        }
402                                        _ => {}
403                                    }
404                                }
405                            }
406
407                            window.cycle();
408                        }
409                    }
410                }
411                PumpStatus::Exit(_code) => {
412                    // Exit the event loop
413                    crate::dbg_log!("Event loop exited with code: {}", _code);
414
415                    return false;
416                }
417            }
418
419            for window in self.window_events_attributes.iter() {
420                window.wait_borrow().window_events.wait_borrow_mut().clear();
421            }
422
423            if self.input_events_attributes.len() > 0 {
424                for event in self.pending_events.iter() {
425                    for input in self.input_events_attributes.iter() {
426                        if let Some(mut input) = input.try_borrow_mut() {
427                            input.process_event(event);
428                        }
429                    }
430                }
431            }
432
433            if wait_for_redraw {
434                if self
435                    .app_runner
436                    .has_redraw_requested
437                    .load(std::sync::atomic::Ordering::SeqCst)
438                {
439                    break;
440                }
441            } else {
442                break;
443            }
444        }
445
446        drop(event_loop);
447
448        self.rate_timing.sleep();
449
450        true
451    }
452
453    /// Set the rate (frame rate) for the event loop.
454    ///
455    /// This only useful if you want to control the frame rate of the event loop.
456    /// Not effective if you use `PollMode::Wait` or `PollMode::WaitDraw`, or multi
457    /// window mode, or multiple threads.
458    pub fn set_rate(&mut self, rate: Option<Duration>) {
459        let rate = {
460            if let Some(rate) = rate {
461                1.0 / (rate.as_secs_f64() * 1000.0)
462            } else {
463                0.0
464            }
465        };
466
467        self.rate_timing.set_fps(rate as u32);
468    }
469
470    /// Set the target frames per second (FPS) for the event loop.
471    ///
472    /// This only useful if you want to control the frame rate of the event loop.
473    /// Not effective if you use `PollMode::Wait` or `PollMode::WaitDraw`, or multi
474    /// window mode, or multiple threads.
475    pub fn set_target_fps(&mut self, fps: u32) {
476        self.rate_timing.set_fps(fps);
477    }
478
479    /// Get the current frame rate (FPS) of the event loop.
480    ///
481    /// This only useful if you want to control the frame rate of the event loop.
482    /// Not effective if you use `PollMode::Wait` or `PollMode::WaitDraw`, or multi
483    /// window mode, or multiple threads.
484    pub fn get_target_fps(&self) -> u32 {
485        self.rate_timing.get_fps()
486    }
487
488    /// Get the time taken for each frame in milliseconds.
489    ///
490    /// This only useful if you want to control the frame rate of the event loop.
491    /// Not effective if you use `PollMode::Wait` or `PollMode::WaitDraw`, or multi
492    /// window mode, or multiple threads.
493    pub fn get_frame_time(&self) -> f64 {
494        self.rate_timing.get_frame_time()
495    }
496
497    pub(crate) fn get_events_pointer(
498        &self,
499        window_id: usize,
500    ) -> Option<ArcRef<Vec<event::WindowEvent>>> {
501        self.app_runner.get_window_events_by_ref(window_id)
502    }
503
504    pub(crate) fn get_window_pointer(&self, window_id: usize) -> Option<ArcMut<Handle>> {
505        self.app_runner.get_window_handle_by_ref(window_id)
506    }
507}
508
509#[derive(Clone, Debug)]
510pub(crate) struct Handle {
511    pub window: Option<Arc<WinitWindow>>,
512    pub is_closed: bool,
513    pub is_pinned: bool,
514}
515
516#[allow(dead_code)]
517impl Handle {
518    pub fn new(window: Arc<WinitWindow>) -> Self {
519        Self {
520            window: Some(window),
521            is_closed: false,
522            is_pinned: false,
523        }
524    }
525
526    pub fn is_closed(&self) -> bool {
527        self.is_closed
528    }
529
530    pub fn close(&mut self) {
531        self.window = None;
532        self.is_closed = true;
533    }
534
535    pub fn set_window(&mut self, window: Option<Arc<WinitWindow>>) {
536        self.window = window;
537    }
538
539    pub fn get_window(&self) -> &Arc<WinitWindow> {
540        if self.is_closed {
541            panic!("Window is closed");
542        }
543
544        self.window.as_ref().unwrap()
545    }
546
547    pub fn get_window_id(&self) -> WindowId {
548        if self.is_closed {
549            panic!("Window is closed");
550        }
551
552        self.window.as_ref().unwrap().id()
553    }
554
555    pub fn is_pinned(&self) -> bool {
556        self.is_pinned
557    }
558
559    pub fn set_pinned(&mut self, pinned: bool) {
560        self.is_pinned = pinned;
561    }
562}
563
564pub(crate) struct WindowHandle {
565    pub window: ArcMut<Handle>,
566    pub events: ArcRef<Vec<event::WindowEvent>>,
567
568    pub ref_id: usize,
569}
570
571impl Drop for WindowHandle {
572    fn drop(&mut self) {
573        crate::dbg_log!("WindowHandle dropped: {:?}", self.ref_id);
574    }
575}
576
577pub(crate) struct RunnerInner {
578    pub handles: HashMap<WindowId, WindowHandle>,
579    pub last_error: Option<String>,
580    pub has_redraw_requested: AtomicBool,
581    pub cursor_cache: HashMap<u64, CustomCursor>,
582}
583
584impl RunnerInner {
585    pub fn new() -> Self {
586        Self {
587            handles: HashMap::new(),
588            last_error: None,
589            has_redraw_requested: AtomicBool::new(false),
590            cursor_cache: HashMap::new(),
591        }
592    }
593
594    pub fn get_window_handle_by_ref(&self, ref_id: usize) -> Option<ArcMut<Handle>> {
595        self.handles
596            .iter()
597            .find(|(_, handle)| handle.ref_id == ref_id)
598            .map(|(_, handle)| handle.window.clone())
599    }
600
601    pub fn get_window_events_by_ref(
602        &self,
603        ref_id: usize,
604    ) -> Option<ArcRef<Vec<event::WindowEvent>>> {
605        self.handles
606            .iter()
607            .find(|(_, handle)| handle.ref_id == ref_id)
608            .map(|(_, handle)| handle.events.clone())
609    }
610}
611
612impl ApplicationHandler<WindowEvent> for RunnerInner {
613    fn resumed(&mut self, _event_loop: &ActiveEventLoop) {}
614
615    fn window_event(
616        &mut self,
617        event_loop: &ActiveEventLoop,
618        window_id: WindowId,
619        event: event::WindowEvent,
620    ) {
621        if self.handles.is_empty() {
622            return;
623        }
624
625        let mut to_remove = None;
626
627        if let Some((_ref_id, _)) = self
628            .handles
629            .iter()
630            .find(|(ref_id, _)| **ref_id == window_id)
631        {
632            match event {
633                event::WindowEvent::CloseRequested => {
634                    if self.handles.is_empty() {
635                        event_loop.exit();
636                        return;
637                    }
638
639                    to_remove = Some(window_id);
640                }
641                event::WindowEvent::RedrawRequested => {
642                    self.has_redraw_requested
643                        .store(true, std::sync::atomic::Ordering::SeqCst);
644                }
645                _ => {}
646            }
647
648            if let Some(handle) = self.handles.get_mut(&window_id) {
649                handle.events.borrow_mut().push(event.clone());
650            }
651        }
652
653        if let Some(window_id) = to_remove {
654            self.handles.remove(&window_id);
655            if self.handles.is_empty() {
656                event_loop.exit();
657            }
658        }
659    }
660
661    #[allow(unused_variables, unreachable_patterns)]
662    fn user_event(&mut self, event_loop: &ActiveEventLoop, event: WindowEvent) {
663        match event {
664            WindowEvent::Create {
665                ref_id,
666                parent_ref_id,
667                title,
668                size,
669                pos,
670            } => {
671                let size: PhysicalSize<u32> = PhysicalSize::new(size.x as u32, size.y as u32);
672                let mut window_attributes = WindowAttributes::default()
673                    .with_title(title)
674                    .with_visible(true)
675                    .with_inner_size(size)
676                    .with_resizable(false)
677                    .with_max_inner_size(size)
678                    .with_min_inner_size(size);
679
680                #[cfg(target_os = "windows")]
681                {
682                    use winit::platform::windows::{CornerPreference, WindowAttributesExtWindows};
683
684                    window_attributes =
685                        window_attributes.with_corner_preference(CornerPreference::DoNotRound);
686                }
687
688                if let Some(pos) = pos {
689                    let pos: PhysicalPosition<i32> =
690                        PhysicalPosition::new(pos.x as i32, pos.y as i32);
691                    window_attributes = window_attributes.with_position(pos);
692                }
693
694                if let Some(parent_ref_id) = parent_ref_id {
695                    if let Some(parent_window) = self.get_window_handle_by_ref(parent_ref_id) {
696                        let parent_window = parent_window.lock();
697
698                        // SAFETY: We are using the `window_handle` method to get the raw window handle,
699                        // which is safe as long as the window is valid and not dropped.
700                        unsafe {
701                            if parent_window.is_closed() {
702                                self.last_error = Some(format!(
703                                    "Parent window is None for ref_id: {}",
704                                    parent_ref_id
705                                ));
706                                return;
707                            }
708
709                            let parent_window = parent_window.get_window().window_handle();
710
711                            if let Err(e) = parent_window {
712                                self.last_error =
713                                    Some(format!("Failed to set parent window: {:?}", e));
714
715                                return;
716                            }
717
718                            let parent_window_handle = parent_window.unwrap().as_raw();
719                            window_attributes =
720                                window_attributes.with_parent_window(Some(parent_window_handle));
721                        }
722                    }
723                }
724
725                let window = event_loop.create_window(window_attributes);
726
727                if let Ok(window) = window {
728                    let window_id = window.id();
729                    let handle = Handle::new(Arc::new(window));
730
731                    let window_handle = WindowHandle {
732                        window: ArcMut::new(handle),
733                        events: ArcRef::new(Vec::new()),
734                        ref_id,
735                    };
736
737                    crate::dbg_log!("Window {} created", ref_id);
738                    self.handles.insert(window_id, window_handle);
739                } else {
740                    crate::dbg_log!("Failed to create window: {:?}", window);
741                    self.last_error = Some(format!("Failed to create window: {:?}", window));
742                }
743            }
744            WindowEvent::Close { ref_id } => {
745                if self.handles.is_empty() {
746                    event_loop.exit();
747
748                    return;
749                }
750
751                let mut to_remove = None;
752
753                for (window_id, handle) in &self.handles {
754                    if handle.ref_id == ref_id {
755                        to_remove = Some(*window_id);
756                        break;
757                    }
758                }
759
760                if let Some(window_id) = to_remove {
761                    if let Some(handle) = self.handles.get_mut(&window_id) {
762                        handle.window.lock().close();
763                    }
764
765                    crate::dbg_log!("Window {} closed", ref_id);
766                    self.handles.remove(&window_id);
767                }
768
769                if self.handles.is_empty() {
770                    crate::dbg_log!("All windows closed, exiting event loop");
771                    event_loop.exit();
772                }
773            }
774            WindowEvent::Title { ref_id, title } => {
775                if let Some(handle) = self.get_window_handle_by_ref(ref_id) {
776                    let window = handle.lock();
777                    let window = window.get_window();
778
779                    crate::dbg_log!("Window {} title: {}", ref_id, title);
780
781                    window.set_title(title.as_str());
782                }
783            }
784            WindowEvent::Size { ref_id, size } => {
785                if let Some(handle) = self.get_window_handle_by_ref(ref_id) {
786                    let size: PhysicalSize<u32> = size.into();
787
788                    let handle_ref = handle.lock();
789                    let window = handle_ref.get_window();
790
791                    crate::dbg_log!("Window {} size: {:?}", ref_id, size);
792
793                    window.set_max_inner_size(Some(size));
794                    window.set_min_inner_size(Some(size));
795                    _ = window.request_inner_size(size);
796                }
797            }
798            WindowEvent::Position { ref_id, pos } => {
799                if let Some(handle) = self.get_window_handle_by_ref(ref_id) {
800                    let pos = PhysicalPosition::new(pos.x as i32, pos.y as i32);
801
802                    let handle_ref = handle.lock();
803                    let window = handle_ref.get_window();
804
805                    crate::dbg_log!("Window {} position: {:?}", ref_id, pos);
806                    window.set_outer_position(pos);
807                }
808            }
809            WindowEvent::Visible { ref_id, visible } => {
810                if let Some(handle) = self.get_window_handle_by_ref(ref_id) {
811                    let handle_ref = handle.lock();
812                    let window = handle_ref.get_window();
813
814                    crate::dbg_log!("Window {} visible: {}", ref_id, visible);
815                    window.set_visible(visible);
816                }
817            }
818            WindowEvent::Redraw { ref_id } => {
819                if let Some(handle) = self.get_window_handle_by_ref(ref_id) {
820                    let handle_ref = handle.lock();
821                    let window = handle_ref.get_window();
822
823                    window.request_redraw();
824                }
825            }
826            WindowEvent::Cursor { ref_id, cursor } => {
827                if let Some(CursorIcon::Custom(cursor)) = cursor {
828                    let mut hash = std::collections::hash_map::DefaultHasher::new();
829                    cursor.hash(&mut hash);
830                    let hash = hash.finish();
831
832                    if let Some(cached_cursor) = self.cursor_cache.get(&hash).cloned() {
833                        if let Some(handle) = self.get_window_handle_by_ref(ref_id) {
834                            let handle_ref = handle.lock();
835                            let window = handle_ref.get_window();
836
837                            window.set_cursor(cached_cursor.clone());
838                        }
839                        return;
840                    }
841
842                    let cursor = decode_cursor(cursor);
843                    if let Err(e) = cursor {
844                        self.last_error = Some(format!("Failed to decode cursor: {:?}", e));
845                        return;
846                    }
847
848                    let cursor_src = cursor.unwrap();
849                    let cursor = event_loop.create_custom_cursor(cursor_src);
850
851                    self.cursor_cache.insert(hash, cursor.clone());
852
853                    if let Some(handle) = self.get_window_handle_by_ref(ref_id) {
854                        let handle_ref = handle.lock();
855                        let window = handle_ref.get_window();
856
857                        window.set_cursor(cursor.clone());
858                    }
859                } else {
860                    if let Some(handle) = self.get_window_handle_by_ref(ref_id) {
861                        let handle_ref = handle.lock();
862                        let window = handle_ref.get_window();
863
864                        window.set_cursor(cursor.clone().unwrap());
865                    }
866                }
867            }
868            _ => {
869                println!("Unhandled event: {:?}", event);
870            }
871        }
872    }
873}
874
875fn decode_cursor(cursor: CustomCursorItem) -> Result<CustomCursorSource, String> {
876    let image_src = match cursor {
877        CustomCursorItem::Path(s) => {
878            let file = std::fs::File::open(s).unwrap();
879            let mut reader = std::io::BufReader::new(file);
880            let mut buffer = Vec::new();
881            let result = reader.read_to_end(&mut buffer);
882            if let Err(e) = result {
883                return Err(format!("Failed to read cursor file: {:?}", e));
884            }
885
886            buffer
887        }
888        CustomCursorItem::Image(b) => b,
889    };
890
891    let image = image::load_from_memory(&image_src);
892    if let Err(e) = image {
893        return Err(format!("Failed to load image: {:?}", e));
894    }
895
896    let image = image.unwrap();
897    let image = image.to_rgba8();
898    let (width, height) = image.dimensions();
899    let w = width as u16;
900    let h = height as u16;
901
902    let result = CustomCursor::from_rgba(image.into_raw(), w, h, w / 2, h / 2);
903
904    if let Err(e) = result {
905        return Err(format!("Failed to create custom cursor: {:?}", e));
906    }
907
908    let cursor = result.unwrap();
909    Ok(cursor)
910}
911
912pub(crate) fn named_key_to_str(key: &NamedKey) -> Option<SmolStr> {
913    match key {
914        NamedKey::Alt => Some(SmolStr::new("Alt")),
915        NamedKey::AltGraph => Some(SmolStr::new("AltGraph")),
916        NamedKey::CapsLock => Some(SmolStr::new("CapsLock")),
917        NamedKey::Control => Some(SmolStr::new("Control")),
918        NamedKey::Fn => Some(SmolStr::new("Fn")),
919        NamedKey::FnLock => Some(SmolStr::new("FnLock")),
920        NamedKey::NumLock => Some(SmolStr::new("NumLock")),
921        NamedKey::ScrollLock => Some(SmolStr::new("ScrollLock")),
922        NamedKey::Shift => Some(SmolStr::new("Shift")),
923        NamedKey::Symbol => Some(SmolStr::new("Symbol")),
924        NamedKey::SymbolLock => Some(SmolStr::new("SymbolLock")),
925        NamedKey::Meta => Some(SmolStr::new("Meta")),
926        NamedKey::Hyper => Some(SmolStr::new("Hyper")),
927        NamedKey::Super => Some(SmolStr::new("Super")),
928        NamedKey::Enter => Some(SmolStr::new("Enter")),
929        NamedKey::Tab => Some(SmolStr::new("Tab")),
930        NamedKey::Space => Some(SmolStr::new("Space")),
931        NamedKey::ArrowDown => Some(SmolStr::new("ArrowDown")),
932        NamedKey::ArrowLeft => Some(SmolStr::new("ArrowLeft")),
933        NamedKey::ArrowRight => Some(SmolStr::new("ArrowRight")),
934        NamedKey::ArrowUp => Some(SmolStr::new("ArrowUp")),
935        NamedKey::End => Some(SmolStr::new("End")),
936        NamedKey::Home => Some(SmolStr::new("Home")),
937        NamedKey::PageDown => Some(SmolStr::new("PageDown")),
938        NamedKey::PageUp => Some(SmolStr::new("PageUp")),
939        NamedKey::Backspace => Some(SmolStr::new("Backspace")),
940        NamedKey::Clear => Some(SmolStr::new("Clear")),
941        NamedKey::Delete => Some(SmolStr::new("Delete")),
942        NamedKey::Insert => Some(SmolStr::new("Insert")),
943        NamedKey::Escape => Some(SmolStr::new("Escape")),
944        NamedKey::Pause => Some(SmolStr::new("Pause")),
945        NamedKey::F1 => Some(SmolStr::new("F1")),
946        NamedKey::F2 => Some(SmolStr::new("F2")),
947        NamedKey::F3 => Some(SmolStr::new("F3")),
948        NamedKey::F4 => Some(SmolStr::new("F4")),
949        NamedKey::F5 => Some(SmolStr::new("F5")),
950        NamedKey::F6 => Some(SmolStr::new("F6")),
951        NamedKey::F7 => Some(SmolStr::new("F7")),
952        NamedKey::F8 => Some(SmolStr::new("F8")),
953        NamedKey::F9 => Some(SmolStr::new("F9")),
954        NamedKey::F10 => Some(SmolStr::new("F10")),
955        NamedKey::F11 => Some(SmolStr::new("F11")),
956        NamedKey::F12 => Some(SmolStr::new("F12")),
957        _ => None,
958    }
959}
960
961#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
962pub enum PumpMode {
963    /// The event loop will poll for events and return immediately.
964    Poll,
965    /// The event loop will wait for events and return when an event is available.
966    Wait,
967    /// The event loop will wait for events and return when the window needs to be redrawn.
968    /// Unless calling the [Window::request_redraw] method.
969    WaitDraw,
970}
971
972#[derive(Debug, Clone, Copy)]
973pub enum MouseScrollDelta {
974    LineDelta { delta_x: f32, delta_y: f32 },
975    PixelDelta { delta_x: f32, delta_y: f32 },
976}
977
978impl PartialEq for MouseScrollDelta {
979    fn eq(&self, other: &Self) -> bool {
980        // use near equality for floating point comparison
981
982        match (self, other) {
983            (
984                MouseScrollDelta::LineDelta { delta_x, delta_y },
985                MouseScrollDelta::LineDelta {
986                    delta_x: other_x,
987                    delta_y: other_y,
988                },
989            ) => {
990                (delta_x - other_x).abs() < f32::EPSILON && (delta_y - other_y).abs() < f32::EPSILON
991            }
992            (
993                MouseScrollDelta::PixelDelta { delta_x, delta_y },
994                MouseScrollDelta::PixelDelta {
995                    delta_x: other_x,
996                    delta_y: other_y,
997                },
998            ) => {
999                (delta_x - other_x).abs() < f32::EPSILON && (delta_y - other_y).abs() < f32::EPSILON
1000            }
1001            _ => false,
1002        }
1003    }
1004}
1005
1006impl PartialOrd for MouseScrollDelta {
1007    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
1008        match (self, other) {
1009            (
1010                MouseScrollDelta::LineDelta { delta_x, delta_y },
1011                MouseScrollDelta::LineDelta {
1012                    delta_x: other_x,
1013                    delta_y: other_y,
1014                },
1015            ) => Some(
1016                delta_x
1017                    .partial_cmp(other_x)?
1018                    .then(delta_y.partial_cmp(other_y)?),
1019            ),
1020            (
1021                MouseScrollDelta::PixelDelta { delta_x, delta_y },
1022                MouseScrollDelta::PixelDelta {
1023                    delta_x: other_x,
1024                    delta_y: other_y,
1025                },
1026            ) => Some(
1027                delta_x
1028                    .partial_cmp(other_x)?
1029                    .then(delta_y.partial_cmp(other_y)?),
1030            ),
1031            _ => None,
1032        }
1033    }
1034}
1035
1036impl Ord for MouseScrollDelta {
1037    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
1038        match (self, other) {
1039            (
1040                MouseScrollDelta::LineDelta { delta_x, delta_y },
1041                MouseScrollDelta::LineDelta {
1042                    delta_x: other_x,
1043                    delta_y: other_y,
1044                },
1045            ) => delta_x
1046                .partial_cmp(other_x)
1047                .unwrap_or(std::cmp::Ordering::Equal)
1048                .then(
1049                    delta_y
1050                        .partial_cmp(other_y)
1051                        .unwrap_or(std::cmp::Ordering::Equal),
1052                ),
1053            (
1054                MouseScrollDelta::PixelDelta { delta_x, delta_y },
1055                MouseScrollDelta::PixelDelta {
1056                    delta_x: other_x,
1057                    delta_y: other_y,
1058                },
1059            ) => delta_x
1060                .partial_cmp(other_x)
1061                .unwrap_or(std::cmp::Ordering::Equal)
1062                .then(
1063                    delta_y
1064                        .partial_cmp(other_y)
1065                        .unwrap_or(std::cmp::Ordering::Equal),
1066                ),
1067            _ => std::cmp::Ordering::Equal,
1068        }
1069    }
1070}
1071
1072impl Eq for MouseScrollDelta {}
1073
1074#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
1075pub enum DragAndDropEvent {
1076    /// Occured when a drag enter the window.
1077    Dragleft,
1078    /// Occured when a drag is moved over the window.
1079    DragEntered,
1080    /// Occured when a drag is moved over the window.
1081    DragMoved,
1082    /// Occured when a drag dropped on the window.
1083    DragDropped(Vec<String>), // List of file paths
1084}
1085
1086#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
1087pub enum Event {
1088    /// Happen when the window is closed, either by user action (such clicking X button on window) or programmatically.
1089    WindowClosed {
1090        /// The ID of the window that was closed, which can be used to identify the window in the application.
1091        ///
1092        /// The window ID can be obtained from the [Window] instance using the [Window::id] method.
1093        window_id: usize,
1094    },
1095    /// Happen when a new window is created.
1096    WindowCreated {
1097        /// The ID of the window that was closed, which can be used to identify the window in the application.
1098        ///
1099        /// The window ID can be obtained from the [Window] instance using the [Window::id] method.
1100        window_id: usize,
1101        /// The ID of the parent window, if any. will be [None] if the window is a top-level window.
1102        ///
1103        /// This can be achived when creating a new window using the [WindowBuilder::with_parent_window] method.
1104        parent_ref_id: Option<usize>,
1105        /// The title of the window.
1106        title: String,
1107        /// The size of the window in pixels.
1108        size: Point2,
1109        /// The position of the window in pixels, if specified.
1110        pos: Option<Point2>,
1111    },
1112    /// Happen when the window is focused or unfocused.
1113    WindowFocused {
1114        /// The ID of the window that was closed, which can be used to identify the window in the application.
1115        ///
1116        /// The window ID can be obtained from the [Window] instance using the [Window::id] method.
1117        window_id: usize,
1118        /// Focused state of the window.
1119        focused: bool,
1120    },
1121    /// Happen when the window is resized.
1122    WindowResized {
1123        /// The ID of the window that was closed, which can be used to identify the window in the application.
1124        ///
1125        /// The window ID can be obtained from the [Window] instance using the [Window::id] method.
1126        window_id: usize,
1127        /// The new size of the window in pixels.
1128        size: Point2,
1129    },
1130    /// Happen when the window is moved.
1131    WindowMoved {
1132        /// The ID of the window that was closed, which can be used to identify the window in the application.
1133        ///
1134        /// The window ID can be obtained from the [Window] instance using the [Window::id] method.
1135        window_id: usize,
1136        /// The new position of the window in pixels.
1137        pos: Point2,
1138    },
1139    /// Happen when the cursor enters the window.
1140    CursorEntered {
1141        /// The ID of the window that was closed, which can be used to identify the window in the application.
1142        ///
1143        /// The window ID can be obtained from the [Window] instance using the [Window::id] method.
1144        window_id: usize,
1145    },
1146    /// Happen when the cursor leaves the window.
1147    CursorLeft {
1148        /// The ID of the window that was closed, which can be used to identify the window in the application.
1149        ///
1150        /// The window ID can be obtained from the [Window] instance using the [Window::id] method.
1151        window_id: usize,
1152    },
1153    /// Happen when the cursor is moved within the window.
1154    CursorMoved {
1155        /// The ID of the window that was closed, which can be used to identify the window in the application.
1156        ///
1157        /// The window ID can be obtained from the [Window] instance using the [Window::id] method.
1158        window_id: usize,
1159        /// The new position of the cursor in pixels.
1160        pos: Point2, // Position in pixels
1161    },
1162    /// Happen when the mouse wheel is scrolled.
1163    MouseWheel {
1164        /// The ID of the window that was closed, which can be used to identify the window in the application.
1165        ///
1166        /// The window ID can be obtained from the [Window] instance using the [Window::id] method.
1167        window_id: usize,
1168        /// The delta of the mouse wheel scroll.
1169        delta: MouseScrollDelta,
1170    },
1171    /// Happen when a mouse button is pressed or released.
1172    MouseInput {
1173        /// The ID of the window that was closed, which can be used to identify the window in the application.
1174        ///
1175        /// The window ID can be obtained from the [Window] instance using the [Window::id] method.
1176        window_id: usize,
1177        /// The button that was pressed or released.
1178        ///
1179        /// Either "Left", "Right", "Middle", "Back", or "Forward".
1180        button: SmolStr, // "Left", "Right", "Middle", "Back", "Forward"
1181        /// Whether the button was pressed or released.
1182        pressed: bool, // true if pressed, false if released
1183    },
1184    /// Happen when the window requests a redraw.
1185    ///
1186    /// Can be manually invoked by calling [Window::request_redraw] method.
1187    RedrawRequested {
1188        /// The ID of the window that was closed, which can be used to identify the window in the application.
1189        ///
1190        /// The window ID can be obtained from the [Window] instance using the [Window::id] method.
1191        window_id: usize,
1192    },
1193    /// Happen when a keyboard key is pressed or released.
1194    KeyboardInput {
1195        /// The ID of the window that was closed, which can be used to identify the window in the application.
1196        ///
1197        /// The window ID can be obtained from the [Window] instance using the [Window::id] method.
1198        window_id: usize,
1199        /// The key that was pressed or released.
1200        ///
1201        /// The key string can be modifier keys like "Alt", "Control", "Shift", etc.
1202        /// Which where the cases like `a` can be `A`.
1203        key: SmolStr,
1204        /// Whether the key was pressed or released.
1205        pressed: bool, // true if pressed, false if released
1206    },
1207    /// Happen when a drag and drop event occurs in the window.
1208    DragAndDrop {
1209        /// The ID of the window that was closed, which can be used to identify the window in the application.
1210        ///
1211        /// The window ID can be obtained from the [Window] instance using the [Window::id] method.
1212        window_id: usize,
1213        /// The drag and drop event that occurred.
1214        event: DragAndDropEvent,
1215    },
1216}
1217
1218#[allow(dead_code)]
1219#[derive(Clone, Debug)]
1220pub(crate) enum WindowEvent {
1221    Create {
1222        ref_id: usize,
1223        parent_ref_id: Option<usize>,
1224        title: String,
1225        size: Point2,
1226        pos: Option<Point2>,
1227    },
1228    Close {
1229        ref_id: usize,
1230    },
1231    Title {
1232        ref_id: usize,
1233        title: String,
1234    },
1235    Cursor {
1236        ref_id: usize,
1237        cursor: Option<CursorIcon>,
1238    },
1239    Size {
1240        ref_id: usize,
1241        size: Point2,
1242    },
1243    Position {
1244        ref_id: usize,
1245        pos: Point2,
1246    },
1247    Visible {
1248        ref_id: usize,
1249        visible: bool,
1250    },
1251    Redraw {
1252        ref_id: usize,
1253    },
1254}
1255
1256// #[derive(Clone, Debug, Hash)]
1257// pub enum CursorSource {
1258//     String(&'static str),
1259//     Buffer(Vec<u8>),
1260// }
1261
1262#[derive(Clone, Debug, Eq, Hash, PartialEq)]
1263pub enum CursorIcon {
1264    Default,
1265    ContextMenu,
1266    Help,
1267    Pointer,
1268    Progress,
1269    Wait,
1270    Cell,
1271    Crosshair,
1272    Text,
1273    VerticalText,
1274    Alias,
1275    Copy,
1276    Move,
1277    NoDrop,
1278    NotAllowed,
1279    Grab,
1280    Grabbing,
1281    EResize,
1282    NResize,
1283    NeResize,
1284    NwResize,
1285    SResize,
1286    SeResize,
1287    SwResize,
1288    WResize,
1289    EwResize,
1290    NsResize,
1291    NeswResize,
1292    NwseResize,
1293    ColResize,
1294    RowResize,
1295    AllScroll,
1296    ZoomIn,
1297    ZoomOut,
1298
1299    Custom(CustomCursorItem),
1300}
1301
1302#[derive(Clone, Debug, Eq, Hash, PartialEq)]
1303pub enum CustomCursorItem {
1304    Path(String),
1305    Image(Vec<u8>),
1306}
1307
1308impl Into<Cursor> for CursorIcon {
1309    fn into(self) -> Cursor {
1310        match self {
1311            CursorIcon::Default => Cursor::Icon(winit::window::CursorIcon::Default),
1312            CursorIcon::ContextMenu => Cursor::Icon(winit::window::CursorIcon::ContextMenu),
1313            CursorIcon::Help => Cursor::Icon(winit::window::CursorIcon::Help),
1314            CursorIcon::Pointer => Cursor::Icon(winit::window::CursorIcon::Pointer),
1315            CursorIcon::Progress => Cursor::Icon(winit::window::CursorIcon::Progress),
1316            CursorIcon::Wait => Cursor::Icon(winit::window::CursorIcon::Wait),
1317            CursorIcon::Cell => Cursor::Icon(winit::window::CursorIcon::Cell),
1318            CursorIcon::Crosshair => Cursor::Icon(winit::window::CursorIcon::Crosshair),
1319            CursorIcon::Text => Cursor::Icon(winit::window::CursorIcon::Text),
1320            CursorIcon::VerticalText => Cursor::Icon(winit::window::CursorIcon::VerticalText),
1321            CursorIcon::Alias => Cursor::Icon(winit::window::CursorIcon::Alias),
1322            CursorIcon::Copy => Cursor::Icon(winit::window::CursorIcon::Copy),
1323            CursorIcon::Move => Cursor::Icon(winit::window::CursorIcon::Move),
1324            CursorIcon::NoDrop => Cursor::Icon(winit::window::CursorIcon::NoDrop),
1325            CursorIcon::NotAllowed => Cursor::Icon(winit::window::CursorIcon::NotAllowed),
1326            CursorIcon::Grab => Cursor::Icon(winit::window::CursorIcon::Grab),
1327            CursorIcon::Grabbing => Cursor::Icon(winit::window::CursorIcon::Grabbing),
1328            CursorIcon::EResize => Cursor::Icon(winit::window::CursorIcon::EResize),
1329            CursorIcon::NResize => Cursor::Icon(winit::window::CursorIcon::NResize),
1330            CursorIcon::NeResize => Cursor::Icon(winit::window::CursorIcon::NeResize),
1331            CursorIcon::NwResize => Cursor::Icon(winit::window::CursorIcon::NwResize),
1332            CursorIcon::SResize => Cursor::Icon(winit::window::CursorIcon::SResize),
1333            CursorIcon::SeResize => Cursor::Icon(winit::window::CursorIcon::SeResize),
1334            CursorIcon::SwResize => Cursor::Icon(winit::window::CursorIcon::SwResize),
1335            CursorIcon::WResize => Cursor::Icon(winit::window::CursorIcon::WResize),
1336            CursorIcon::EwResize => Cursor::Icon(winit::window::CursorIcon::EwResize),
1337            CursorIcon::NsResize => Cursor::Icon(winit::window::CursorIcon::NsResize),
1338            CursorIcon::NeswResize => Cursor::Icon(winit::window::CursorIcon::NeswResize),
1339            CursorIcon::NwseResize => Cursor::Icon(winit::window::CursorIcon::NwseResize),
1340            CursorIcon::ColResize => Cursor::Icon(winit::window::CursorIcon::ColResize),
1341            CursorIcon::RowResize => Cursor::Icon(winit::window::CursorIcon::RowResize),
1342            CursorIcon::AllScroll => Cursor::Icon(winit::window::CursorIcon::AllScroll),
1343            CursorIcon::ZoomIn => Cursor::Icon(winit::window::CursorIcon::ZoomIn),
1344            CursorIcon::ZoomOut => Cursor::Icon(winit::window::CursorIcon::ZoomOut),
1345            CursorIcon::Custom(_) => panic!("This should not handled here!"),
1346        }
1347    }
1348}
1349
1350#[derive(Clone, Debug, Eq, Hash, PartialEq)]
1351pub enum RunnerError {
1352    ThreadMissmatch,
1353    WinitEventLoopPanic,
1354    WinitEventLoopFailed,
1355    MaximumWindowReached,
1356    FailedToCreateWindow(String),
1357}