1 use std::cell::RefCell;
2 use std::collections::HashMap;
3 use std::error::Error;
4 use std::process;
5 use std::rc::Rc;
6 use std::time::{Duration, Instant};
7 
8 use sctk::reexports::client::protocol::wl_compositor::WlCompositor;
9 use sctk::reexports::client::protocol::wl_shm::WlShm;
10 use sctk::reexports::client::Display;
11 
12 use sctk::reexports::calloop;
13 
14 use sctk::environment::Environment;
15 use sctk::seat::pointer::{ThemeManager, ThemeSpec};
16 use sctk::WaylandSource;
17 
18 use crate::event::{Event, StartCause, WindowEvent};
19 use crate::event_loop::{ControlFlow, EventLoopWindowTarget as RootEventLoopWindowTarget};
20 use crate::platform_impl::platform::sticky_exit_callback;
21 
22 use super::env::{WindowingFeatures, WinitEnv};
23 use super::output::OutputManager;
24 use super::seat::SeatManager;
25 use super::window::shim::{self, WindowUpdate};
26 use super::{DeviceId, WindowId};
27 
28 mod proxy;
29 mod sink;
30 mod state;
31 
32 pub use proxy::EventLoopProxy;
33 pub use state::WinitState;
34 
35 use sink::EventSink;
36 
37 pub struct EventLoopWindowTarget<T> {
38     /// Wayland display.
39     pub display: Display,
40 
41     /// Environment to handle object creation, etc.
42     pub env: Environment<WinitEnv>,
43 
44     /// Event loop handle.
45     pub event_loop_handle: calloop::LoopHandle<WinitState>,
46 
47     /// Output manager.
48     pub output_manager: OutputManager,
49 
50     /// State that we share across callbacks.
51     pub state: RefCell<WinitState>,
52 
53     /// Wayland source.
54     pub wayland_source: Rc<calloop::Source<WaylandSource>>,
55 
56     /// A proxy to wake up event loop.
57     pub event_loop_awakener: calloop::ping::Ping,
58 
59     /// The available windowing features.
60     pub windowing_features: WindowingFeatures,
61 
62     /// Theme manager to manage cursors.
63     ///
64     /// It's being shared amoung all windows to avoid loading
65     /// multiple similar themes.
66     pub theme_manager: ThemeManager,
67 
68     _marker: std::marker::PhantomData<T>,
69 }
70 
71 pub struct EventLoop<T: 'static> {
72     /// Event loop.
73     event_loop: calloop::EventLoop<WinitState>,
74 
75     /// Wayland display.
76     display: Display,
77 
78     /// Pending user events.
79     pending_user_events: Rc<RefCell<Vec<T>>>,
80 
81     /// Sender of user events.
82     user_events_sender: calloop::channel::Sender<T>,
83 
84     /// Wayland source of events.
85     wayland_source: Rc<calloop::Source<WaylandSource>>,
86 
87     /// Window target.
88     window_target: RootEventLoopWindowTarget<T>,
89 
90     /// Output manager.
91     _seat_manager: SeatManager,
92 }
93 
94 impl<T: 'static> EventLoop<T> {
new() -> Result<EventLoop<T>, Box<dyn Error>>95     pub fn new() -> Result<EventLoop<T>, Box<dyn Error>> {
96         // Connect to wayland server and setup event queue.
97         let display = Display::connect_to_env()?;
98         let mut event_queue = display.create_event_queue();
99         let display_proxy = display.attach(event_queue.token());
100 
101         // Setup environment.
102         let env = Environment::new(&display_proxy, &mut event_queue, WinitEnv::new())?;
103 
104         // Create event loop.
105         let event_loop = calloop::EventLoop::<WinitState>::new()?;
106         // Build windowing features.
107         let windowing_features = WindowingFeatures::new(&env);
108 
109         // Create a theme manager.
110         let compositor = env.require_global::<WlCompositor>();
111         let shm = env.require_global::<WlShm>();
112         let theme_manager = ThemeManager::init(ThemeSpec::System, compositor, shm);
113 
114         // Setup theme seat and output managers.
115         let seat_manager = SeatManager::new(&env, event_loop.handle(), theme_manager.clone());
116         let output_manager = OutputManager::new(&env);
117 
118         // A source of events that we plug into our event loop.
119         let wayland_source = WaylandSource::new(event_queue).quick_insert(event_loop.handle())?;
120         let wayland_source = Rc::new(wayland_source);
121 
122         // A source of user events.
123         let pending_user_events = Rc::new(RefCell::new(Vec::new()));
124         let pending_user_events_clone = pending_user_events.clone();
125         let (user_events_sender, user_events_channel) = calloop::channel::channel();
126 
127         // User events channel.
128         event_loop
129             .handle()
130             .insert_source(user_events_channel, move |event, _, _| {
131                 if let calloop::channel::Event::Msg(msg) = event {
132                     pending_user_events_clone.borrow_mut().push(msg);
133                 }
134             })?;
135 
136         // An event's loop awakener to wake up for window events from winit's windows.
137         let (event_loop_awakener, event_loop_awakener_source) = calloop::ping::make_ping()?;
138 
139         // Handler of window requests.
140         event_loop.handle().insert_source(
141             event_loop_awakener_source,
142             move |_, _, winit_state| {
143                 shim::handle_window_requests(winit_state);
144             },
145         )?;
146 
147         let event_loop_handle = event_loop.handle();
148         let window_map = HashMap::new();
149         let event_sink = EventSink::new();
150         let window_updates = HashMap::new();
151 
152         // Create event loop window target.
153         let event_loop_window_target = EventLoopWindowTarget {
154             display: display.clone(),
155             env,
156             state: RefCell::new(WinitState {
157                 window_map,
158                 event_sink,
159                 window_updates,
160             }),
161             event_loop_handle,
162             output_manager,
163             event_loop_awakener,
164             wayland_source: wayland_source.clone(),
165             windowing_features,
166             theme_manager,
167             _marker: std::marker::PhantomData,
168         };
169 
170         // Create event loop itself.
171         let event_loop = Self {
172             event_loop,
173             display,
174             pending_user_events,
175             wayland_source,
176             _seat_manager: seat_manager,
177             user_events_sender,
178             window_target: RootEventLoopWindowTarget {
179                 p: crate::platform_impl::EventLoopWindowTarget::Wayland(event_loop_window_target),
180                 _marker: std::marker::PhantomData,
181             },
182         };
183 
184         Ok(event_loop)
185     }
186 
run<F>(mut self, callback: F) -> ! where F: FnMut(Event<'_, T>, &RootEventLoopWindowTarget<T>, &mut ControlFlow) + 'static,187     pub fn run<F>(mut self, callback: F) -> !
188     where
189         F: FnMut(Event<'_, T>, &RootEventLoopWindowTarget<T>, &mut ControlFlow) + 'static,
190     {
191         self.run_return(callback);
192         process::exit(0)
193     }
194 
run_return<F>(&mut self, mut callback: F) where F: FnMut(Event<'_, T>, &RootEventLoopWindowTarget<T>, &mut ControlFlow),195     pub fn run_return<F>(&mut self, mut callback: F)
196     where
197         F: FnMut(Event<'_, T>, &RootEventLoopWindowTarget<T>, &mut ControlFlow),
198     {
199         // Send pending events to the server.
200         let _ = self.display.flush();
201 
202         let mut control_flow = ControlFlow::default();
203 
204         let pending_user_events = self.pending_user_events.clone();
205 
206         callback(
207             Event::NewEvents(StartCause::Init),
208             &self.window_target,
209             &mut control_flow,
210         );
211 
212         let mut window_updates: Vec<(WindowId, WindowUpdate)> = Vec::new();
213         let mut event_sink_back_buffer = Vec::new();
214 
215         // NOTE We break on errors from dispatches, since if we've got protocol error
216         // libwayland-client/wayland-rs will inform us anyway, but crashing downstream is not
217         // really an option. Instead we inform that the event loop got destroyed. We may
218         // communicate an error that something was terminated, but winit doesn't provide us
219         // with an API to do that via some event.
220         loop {
221             // Handle pending user events. We don't need back buffer, since we can't dispatch
222             // user events indirectly via callback to the user.
223             for user_event in pending_user_events.borrow_mut().drain(..) {
224                 sticky_exit_callback(
225                     Event::UserEvent(user_event),
226                     &self.window_target,
227                     &mut control_flow,
228                     &mut callback,
229                 );
230             }
231 
232             // Process 'new' pending updates.
233             self.with_state(|state| {
234                 window_updates.clear();
235                 window_updates.extend(
236                     state
237                         .window_updates
238                         .iter_mut()
239                         .map(|(wid, window_update)| (*wid, window_update.take())),
240                 );
241             });
242 
243             for (window_id, window_update) in window_updates.iter_mut() {
244                 if let Some(scale_factor) = window_update.scale_factor.map(|f| f as f64) {
245                     let mut physical_size = self.with_state(|state| {
246                         let window_handle = state.window_map.get(&window_id).unwrap();
247                         let mut size = window_handle.size.lock().unwrap();
248 
249                         // Update the new logical size if it was changed.
250                         let window_size = window_update.size.unwrap_or(*size);
251                         *size = window_size;
252 
253                         window_size.to_physical(scale_factor)
254                     });
255 
256                     sticky_exit_callback(
257                         Event::WindowEvent {
258                             window_id: crate::window::WindowId(
259                                 crate::platform_impl::WindowId::Wayland(*window_id),
260                             ),
261                             event: WindowEvent::ScaleFactorChanged {
262                                 scale_factor,
263                                 new_inner_size: &mut physical_size,
264                             },
265                         },
266                         &self.window_target,
267                         &mut control_flow,
268                         &mut callback,
269                     );
270 
271                     // We don't update size on a window handle since we'll do that later
272                     // when handling size update.
273                     let new_logical_size = physical_size.to_logical(scale_factor);
274                     window_update.size = Some(new_logical_size);
275                 }
276 
277                 if let Some(size) = window_update.size.take() {
278                     let physical_size = self.with_state(|state| {
279                         let window_handle = state.window_map.get_mut(&window_id).unwrap();
280                         let mut window_size = window_handle.size.lock().unwrap();
281 
282                         // Always issue resize event on scale factor change.
283                         let physical_size =
284                             if window_update.scale_factor.is_none() && *window_size == size {
285                                 // The size hasn't changed, don't inform downstream about that.
286                                 None
287                             } else {
288                                 *window_size = size;
289                                 let scale_factor =
290                                     sctk::get_surface_scale_factor(&window_handle.window.surface());
291                                 let physical_size = size.to_physical(scale_factor as f64);
292                                 Some(physical_size)
293                             };
294 
295                         // We still perform all of those resize related logic even if the size
296                         // hasn't changed, since GNOME relies on `set_geometry` calls after
297                         // configures.
298                         window_handle.window.resize(size.width, size.height);
299                         window_handle.window.refresh();
300 
301                         // Mark that refresh isn't required, since we've done it right now.
302                         window_update.refresh_frame = false;
303 
304                         physical_size
305                     });
306 
307                     if let Some(physical_size) = physical_size {
308                         sticky_exit_callback(
309                             Event::WindowEvent {
310                                 window_id: crate::window::WindowId(
311                                     crate::platform_impl::WindowId::Wayland(*window_id),
312                                 ),
313                                 event: WindowEvent::Resized(physical_size),
314                             },
315                             &self.window_target,
316                             &mut control_flow,
317                             &mut callback,
318                         );
319                     }
320                 }
321 
322                 if window_update.close_window {
323                     sticky_exit_callback(
324                         Event::WindowEvent {
325                             window_id: crate::window::WindowId(
326                                 crate::platform_impl::WindowId::Wayland(*window_id),
327                             ),
328                             event: WindowEvent::CloseRequested,
329                         },
330                         &self.window_target,
331                         &mut control_flow,
332                         &mut callback,
333                     );
334                 }
335             }
336 
337             // The purpose of the back buffer and that swap is to not hold borrow_mut when
338             // we're doing callback to the user, since we can double borrow if the user decides
339             // to create a window in one of those callbacks.
340             self.with_state(|state| {
341                 std::mem::swap(
342                     &mut event_sink_back_buffer,
343                     &mut state.event_sink.window_events,
344                 )
345             });
346 
347             // Handle pending window events.
348             for event in event_sink_back_buffer.drain(..) {
349                 let event = event.map_nonuser_event().unwrap();
350                 sticky_exit_callback(event, &self.window_target, &mut control_flow, &mut callback);
351             }
352 
353             // Send events cleared.
354             sticky_exit_callback(
355                 Event::MainEventsCleared,
356                 &self.window_target,
357                 &mut control_flow,
358                 &mut callback,
359             );
360 
361             // Handle RedrawRequested events.
362             for (window_id, window_update) in window_updates.iter() {
363                 // Handle refresh of the frame.
364                 if window_update.refresh_frame {
365                     self.with_state(|state| {
366                         let window_handle = state.window_map.get_mut(&window_id).unwrap();
367                         window_handle.window.refresh();
368                         if !window_update.redraw_requested {
369                             window_handle.window.surface().commit();
370                         }
371                     });
372                 }
373 
374                 // Handle redraw request.
375                 if window_update.redraw_requested {
376                     sticky_exit_callback(
377                         Event::RedrawRequested(crate::window::WindowId(
378                             crate::platform_impl::WindowId::Wayland(*window_id),
379                         )),
380                         &self.window_target,
381                         &mut control_flow,
382                         &mut callback,
383                     );
384                 }
385             }
386 
387             // Send RedrawEventCleared.
388             sticky_exit_callback(
389                 Event::RedrawEventsCleared,
390                 &self.window_target,
391                 &mut control_flow,
392                 &mut callback,
393             );
394 
395             // Send pending events to the server.
396             let _ = self.display.flush();
397 
398             // During the run of the user callback, some other code monitoring and reading the
399             // Wayland socket may have been run (mesa for example does this with vsync), if that
400             // is the case, some events may have been enqueued in our event queue.
401             //
402             // If some messages are there, the event loop needs to behave as if it was instantly
403             // woken up by messages arriving from the Wayland socket, to avoid delaying the
404             // dispatch of these events until we're woken up again.
405             let instant_wakeup = {
406                 let handle = self.event_loop.handle();
407                 let source = self.wayland_source.clone();
408                 let dispatched = handle.with_source(&source, |wayland_source| {
409                     let queue = wayland_source.queue();
410                     self.with_state(|state| {
411                         queue.dispatch_pending(state, |_, _, _| unimplemented!())
412                     })
413                 });
414 
415                 if let Ok(dispatched) = dispatched {
416                     dispatched > 0
417                 } else {
418                     break;
419                 }
420             };
421 
422             match control_flow {
423                 ControlFlow::Exit => break,
424                 ControlFlow::Poll => {
425                     // Non-blocking dispatch.
426                     let timeout = Duration::from_millis(0);
427                     if self.loop_dispatch(Some(timeout)).is_err() {
428                         break;
429                     }
430 
431                     callback(
432                         Event::NewEvents(StartCause::Poll),
433                         &self.window_target,
434                         &mut control_flow,
435                     );
436                 }
437                 ControlFlow::Wait => {
438                     let timeout = if instant_wakeup {
439                         Some(Duration::from_millis(0))
440                     } else {
441                         None
442                     };
443 
444                     if self.loop_dispatch(timeout).is_err() {
445                         break;
446                     }
447 
448                     callback(
449                         Event::NewEvents(StartCause::WaitCancelled {
450                             start: Instant::now(),
451                             requested_resume: None,
452                         }),
453                         &self.window_target,
454                         &mut control_flow,
455                     );
456                 }
457                 ControlFlow::WaitUntil(deadline) => {
458                     let start = Instant::now();
459 
460                     // Compute the amount of time we'll block for.
461                     let duration = if deadline > start && !instant_wakeup {
462                         deadline - start
463                     } else {
464                         Duration::from_millis(0)
465                     };
466 
467                     if self.loop_dispatch(Some(duration)).is_err() {
468                         break;
469                     }
470 
471                     let now = Instant::now();
472 
473                     if now < deadline {
474                         callback(
475                             Event::NewEvents(StartCause::WaitCancelled {
476                                 start,
477                                 requested_resume: Some(deadline),
478                             }),
479                             &self.window_target,
480                             &mut control_flow,
481                         )
482                     } else {
483                         callback(
484                             Event::NewEvents(StartCause::ResumeTimeReached {
485                                 start,
486                                 requested_resume: deadline,
487                             }),
488                             &self.window_target,
489                             &mut control_flow,
490                         )
491                     }
492                 }
493             }
494         }
495 
496         callback(Event::LoopDestroyed, &self.window_target, &mut control_flow);
497     }
498 
499     #[inline]
create_proxy(&self) -> EventLoopProxy<T>500     pub fn create_proxy(&self) -> EventLoopProxy<T> {
501         EventLoopProxy::new(self.user_events_sender.clone())
502     }
503 
504     #[inline]
window_target(&self) -> &RootEventLoopWindowTarget<T>505     pub fn window_target(&self) -> &RootEventLoopWindowTarget<T> {
506         &self.window_target
507     }
508 
with_state<U, F: FnOnce(&mut WinitState) -> U>(&mut self, f: F) -> U509     fn with_state<U, F: FnOnce(&mut WinitState) -> U>(&mut self, f: F) -> U {
510         let state = match &mut self.window_target.p {
511             crate::platform_impl::EventLoopWindowTarget::Wayland(ref mut window_target) => {
512                 window_target.state.get_mut()
513             }
514             #[cfg(feature = "x11")]
515             _ => unreachable!(),
516         };
517 
518         f(state)
519     }
520 
loop_dispatch<D: Into<Option<std::time::Duration>>>( &mut self, timeout: D, ) -> std::io::Result<()>521     fn loop_dispatch<D: Into<Option<std::time::Duration>>>(
522         &mut self,
523         timeout: D,
524     ) -> std::io::Result<()> {
525         let mut state = match &mut self.window_target.p {
526             crate::platform_impl::EventLoopWindowTarget::Wayland(ref mut window_target) => {
527                 window_target.state.get_mut()
528             }
529             #[cfg(feature = "x11")]
530             _ => unreachable!(),
531         };
532 
533         self.event_loop.dispatch(timeout, &mut state)
534     }
535 }
536