1use std::ops::Deref;
2use std::sync::{Arc, Mutex, MutexGuard};
3
4use winit::{
5 dpi::PhysicalSize,
6 event::{Event, WindowEvent},
7 event_loop::EventLoop,
8 window::{Window, WindowBuilder},
9};
10use winit_input_helper::WinitInputHelper;
11
12use crate::rendering::window::{PresentableWindow, WindowConfig, WindowProvider, WindowRunner};
13
14#[derive(Clone)]
20pub struct Input(Arc<Mutex<WinitInputHelper>>);
21
22impl Input {
23 fn new() -> Self {
24 Self(Arc::new(Mutex::new(WinitInputHelper::new())))
25 }
26
27 pub fn get(&self) -> InputGuard<'_> {
31 InputGuard(self.0.lock().unwrap())
32 }
33
34 fn update(&self, event: &Event<()>) {
35 self.0.lock().unwrap().update(event);
36 }
37}
38
39pub struct InputGuard<'a>(MutexGuard<'a, WinitInputHelper>);
40
41impl Deref for InputGuard<'_> {
42 type Target = WinitInputHelper;
43 fn deref(&self) -> &Self::Target {
44 &self.0
45 }
46}
47
48pub struct WinitWindow {
49 window: Arc<Window>,
50 event_loop: EventLoop<()>,
51 input: Input,
52}
53
54impl WindowProvider for WinitWindow {
55 type Handle = Arc<Window>;
56 type Exposed = Input;
57
58 fn create(config: &WindowConfig) -> Self {
59 let event_loop = EventLoop::new().unwrap();
60 let window = Arc::new(
61 WindowBuilder::new()
62 .with_title(config.title)
63 .with_inner_size(PhysicalSize::new(config.width, config.height))
64 .build(&event_loop)
65 .unwrap(),
66 );
67
68 Self {
69 window,
70 event_loop,
71 input: Input::new(),
72 }
73 }
74
75 fn size(handle: &Self::Handle) -> (u32, u32) {
76 let s = handle.inner_size();
77 (s.width, s.height)
78 }
79
80 fn exposed(&self) -> Self::Exposed {
81 self.input.clone()
82 }
83
84 fn handle(&self) -> &Self::Handle {
85 &self.window
86 }
87}
88
89impl WindowRunner for WinitWindow {
90 fn run(self, mut on_frame: impl FnMut() + 'static) {
91 let Self {
92 window,
93 event_loop,
94 input,
95 } = self;
96
97 event_loop
98 .run(move |event, elwt| {
99 input.update(&event);
100
101 match &event {
102 Event::WindowEvent {
103 event: WindowEvent::CloseRequested,
104 ..
105 } => elwt.exit(),
106 Event::WindowEvent {
107 event: WindowEvent::RedrawRequested,
108 ..
109 } => on_frame(),
110 Event::AboutToWait => window.request_redraw(),
111 _ => {}
112 }
113 })
114 .unwrap();
115 }
116}
117
118impl PresentableWindow for WinitWindow {}