1use std::cell::{Cell, RefCell};
4use std::io::Result as IOResult;
5use std::marker::PhantomData;
6use std::mem;
7use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
8use std::rc::Rc;
9use std::sync::atomic::Ordering;
10use std::sync::{Arc, Mutex};
11use std::time::{Duration, Instant};
12
13use sctk::reexports::calloop::Error as CalloopError;
14use sctk::reexports::calloop_wayland_source::WaylandSource;
15use sctk::reexports::client::{globals, Connection, QueueHandle};
16
17use crate::cursor::OnlyCursorImage;
18use crate::dpi::LogicalSize;
19use crate::error::{EventLoopError, OsError as RootOsError};
20use crate::event::{Event, InnerSizeWriter, StartCause, WindowEvent};
21use crate::event_loop::{ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents};
22use crate::platform::pump_events::PumpStatus;
23use crate::platform_impl::platform::min_timeout;
24use crate::platform_impl::{
25 ActiveEventLoop as PlatformActiveEventLoop, OsError, PlatformCustomCursor,
26};
27use crate::window::{CustomCursor as RootCustomCursor, CustomCursorSource};
28
29mod proxy;
30pub mod sink;
31
32pub use proxy::EventLoopProxy;
33use sink::EventSink;
34
35use super::state::{WindowCompositorUpdate, WinitState};
36use super::window::state::FrameCallbackState;
37use super::{logical_to_physical_rounded, DeviceId, WaylandError, WindowId};
38
39type WaylandDispatcher = calloop::Dispatcher<'static, WaylandSource<WinitState>, WinitState>;
40
41pub struct EventLoop<T: 'static> {
43 loop_running: bool,
45
46 buffer_sink: EventSink,
47 compositor_updates: Vec<WindowCompositorUpdate>,
48 window_ids: Vec<WindowId>,
49
50 user_events_sender: calloop::channel::Sender<T>,
52
53 pending_user_events: Rc<RefCell<Vec<T>>>,
57
58 wayland_dispatcher: WaylandDispatcher,
61
62 connection: Connection,
64
65 window_target: RootActiveEventLoop,
67
68 event_loop: calloop::EventLoop<'static, WinitState>,
71}
72
73impl<T: 'static> EventLoop<T> {
74 pub fn new() -> Result<EventLoop<T>, EventLoopError> {
75 macro_rules! map_err {
76 ($e:expr, $err:expr) => {
77 $e.map_err(|error| os_error!($err(error).into()))
78 };
79 }
80
81 let connection = map_err!(Connection::connect_to_env(), WaylandError::Connection)?;
82
83 let (globals, mut event_queue) =
84 map_err!(globals::registry_queue_init(&connection), WaylandError::Global)?;
85 let queue_handle = event_queue.handle();
86
87 let event_loop =
88 map_err!(calloop::EventLoop::<WinitState>::try_new(), WaylandError::Calloop)?;
89
90 let mut winit_state = WinitState::new(&globals, &queue_handle, event_loop.handle())
91 .map_err(|error| os_error!(error))?;
92
93 map_err!(event_queue.roundtrip(&mut winit_state), WaylandError::Dispatch)?;
96
97 let wayland_source = WaylandSource::new(connection.clone(), event_queue);
99 let wayland_dispatcher =
100 calloop::Dispatcher::new(wayland_source, |_, queue, winit_state: &mut WinitState| {
101 let result = queue.dispatch_pending(winit_state);
102 if result.is_ok()
103 && (!winit_state.events_sink.is_empty()
104 || !winit_state.window_compositor_updates.is_empty())
105 {
106 winit_state.dispatched_events = true;
107 }
108 result
109 });
110
111 map_err!(
112 event_loop.handle().register_dispatcher(wayland_dispatcher.clone()),
113 WaylandError::Calloop
114 )?;
115
116 let pending_user_events = Rc::new(RefCell::new(Vec::new()));
118 let pending_user_events_clone = pending_user_events.clone();
119 let (user_events_sender, user_events_channel) = calloop::channel::channel();
120 let result = event_loop
121 .handle()
122 .insert_source(user_events_channel, move |event, _, winit_state: &mut WinitState| {
123 if let calloop::channel::Event::Msg(msg) = event {
124 winit_state.dispatched_events = true;
125 pending_user_events_clone.borrow_mut().push(msg);
126 }
127 })
128 .map_err(|error| error.error);
129 map_err!(result, WaylandError::Calloop)?;
130
131 let (event_loop_awakener, event_loop_awakener_source) = map_err!(
133 calloop::ping::make_ping()
134 .map_err(|error| CalloopError::OtherError(Box::new(error).into())),
135 WaylandError::Calloop
136 )?;
137
138 let result = event_loop
139 .handle()
140 .insert_source(event_loop_awakener_source, move |_, _, winit_state: &mut WinitState| {
141 winit_state.dispatched_events = true;
143 })
144 .map_err(|error| error.error);
145 map_err!(result, WaylandError::Calloop)?;
146
147 let window_target = ActiveEventLoop {
148 connection: connection.clone(),
149 wayland_dispatcher: wayland_dispatcher.clone(),
150 event_loop_awakener,
151 queue_handle,
152 control_flow: Cell::new(ControlFlow::default()),
153 exit: Cell::new(None),
154 state: RefCell::new(winit_state),
155 };
156
157 let event_loop = Self {
158 loop_running: false,
159 compositor_updates: Vec::new(),
160 buffer_sink: EventSink::default(),
161 window_ids: Vec::new(),
162 connection,
163 wayland_dispatcher,
164 user_events_sender,
165 pending_user_events,
166 event_loop,
167 window_target: RootActiveEventLoop {
168 p: PlatformActiveEventLoop::Wayland(window_target),
169 _marker: PhantomData,
170 },
171 };
172
173 Ok(event_loop)
174 }
175
176 pub fn run_on_demand<F>(&mut self, mut event_handler: F) -> Result<(), EventLoopError>
177 where
178 F: FnMut(Event<T>, &RootActiveEventLoop),
179 {
180 let exit = loop {
181 match self.pump_events(None, &mut event_handler) {
182 PumpStatus::Exit(0) => {
183 break Ok(());
184 },
185 PumpStatus::Exit(code) => {
186 break Err(EventLoopError::ExitFailure(code));
187 },
188 _ => {
189 continue;
190 },
191 }
192 };
193
194 let _ = self.roundtrip().map_err(EventLoopError::Os);
199
200 exit
201 }
202
203 pub fn pump_events<F>(&mut self, timeout: Option<Duration>, mut callback: F) -> PumpStatus
204 where
205 F: FnMut(Event<T>, &RootActiveEventLoop),
206 {
207 if !self.loop_running {
208 self.loop_running = true;
209
210 self.single_iteration(&mut callback, StartCause::Init);
212 }
213
214 if !self.exiting() {
217 self.poll_events_with_timeout(timeout, &mut callback);
218 }
219 if let Some(code) = self.exit_code() {
220 self.loop_running = false;
221
222 callback(Event::LoopExiting, self.window_target());
223
224 PumpStatus::Exit(code)
225 } else {
226 PumpStatus::Continue
227 }
228 }
229
230 pub fn poll_events_with_timeout<F>(&mut self, mut timeout: Option<Duration>, mut callback: F)
231 where
232 F: FnMut(Event<T>, &RootActiveEventLoop),
233 {
234 let cause = loop {
235 let start = Instant::now();
236
237 timeout = {
238 let control_flow_timeout = match self.control_flow() {
239 ControlFlow::Wait => None,
240 ControlFlow::Poll => Some(Duration::ZERO),
241 ControlFlow::WaitUntil(wait_deadline) => {
242 Some(wait_deadline.saturating_duration_since(start))
243 },
244 };
245 min_timeout(control_flow_timeout, timeout)
246 };
247
248 if self.connection.flush().is_err() {
255 self.set_exit_code(1);
256 return;
257 }
258
259 if let Err(error) = self.loop_dispatch(timeout) {
260 let exit_code = error.raw_os_error().unwrap_or(1);
268 self.set_exit_code(exit_code);
269 return;
270 }
271
272 let cause = match self.control_flow() {
275 ControlFlow::Poll => StartCause::Poll,
276 ControlFlow::Wait => StartCause::WaitCancelled { start, requested_resume: None },
277 ControlFlow::WaitUntil(deadline) => {
278 if Instant::now() < deadline {
279 StartCause::WaitCancelled { start, requested_resume: Some(deadline) }
280 } else {
281 StartCause::ResumeTimeReached { start, requested_resume: deadline }
282 }
283 },
284 };
285
286 let dispatched_events = self.with_state(|state| state.dispatched_events);
288 if matches!(cause, StartCause::WaitCancelled { .. }) && !dispatched_events {
289 continue;
290 }
291
292 break cause;
293 };
294
295 self.single_iteration(&mut callback, cause);
296 }
297
298 fn single_iteration<F>(&mut self, callback: &mut F, cause: StartCause)
299 where
300 F: FnMut(Event<T>, &RootActiveEventLoop),
301 {
302 let mut compositor_updates = std::mem::take(&mut self.compositor_updates);
309 let mut buffer_sink = std::mem::take(&mut self.buffer_sink);
310 let mut window_ids = std::mem::take(&mut self.window_ids);
311
312 callback(Event::NewEvents(cause), &self.window_target);
313
314 if cause == StartCause::Init {
317 callback(Event::Resumed, &self.window_target);
318 }
319
320 for user_event in self.pending_user_events.borrow_mut().drain(..) {
323 callback(Event::UserEvent(user_event), &self.window_target);
324 }
325
326 self.with_state(|state| compositor_updates.append(&mut state.window_compositor_updates));
328
329 for mut compositor_update in compositor_updates.drain(..) {
330 let window_id = compositor_update.window_id;
331 if compositor_update.scale_changed {
332 let (physical_size, scale_factor) = self.with_state(|state| {
333 let windows = state.windows.get_mut();
334 let window = windows.get(&window_id).unwrap().lock().unwrap();
335 let scale_factor = window.scale_factor();
336 let size = logical_to_physical_rounded(window.inner_size(), scale_factor);
337 (size, scale_factor)
338 });
339
340 let old_physical_size = physical_size;
342
343 let new_inner_size = Arc::new(Mutex::new(physical_size));
344 callback(
345 Event::WindowEvent {
346 window_id: crate::window::WindowId(window_id),
347 event: WindowEvent::ScaleFactorChanged {
348 scale_factor,
349 inner_size_writer: InnerSizeWriter::new(Arc::downgrade(
350 &new_inner_size,
351 )),
352 },
353 },
354 &self.window_target,
355 );
356
357 let physical_size = *new_inner_size.lock().unwrap();
358 drop(new_inner_size);
359
360 if old_physical_size != physical_size {
362 self.with_state(|state| {
363 let windows = state.windows.get_mut();
364 let mut window = windows.get(&window_id).unwrap().lock().unwrap();
365
366 let new_logical_size: LogicalSize<f64> =
367 physical_size.to_logical(scale_factor);
368 window.request_inner_size(new_logical_size.into());
369 });
370
371 compositor_update.resized = true;
373 }
374 }
375
376 if compositor_update.resized || compositor_update.scale_changed {
379 let physical_size = self.with_state(|state| {
380 let windows = state.windows.get_mut();
381 let window = windows.get(&window_id).unwrap().lock().unwrap();
382
383 let scale_factor = window.scale_factor();
384 let size = logical_to_physical_rounded(window.inner_size(), scale_factor);
385
386 state
388 .window_requests
389 .get_mut()
390 .get_mut(&window_id)
391 .unwrap()
392 .redraw_requested
393 .store(true, Ordering::Relaxed);
394
395 size
396 });
397
398 callback(
399 Event::WindowEvent {
400 window_id: crate::window::WindowId(window_id),
401 event: WindowEvent::Resized(physical_size),
402 },
403 &self.window_target,
404 );
405 }
406
407 if compositor_update.close_window {
408 callback(
409 Event::WindowEvent {
410 window_id: crate::window::WindowId(window_id),
411 event: WindowEvent::CloseRequested,
412 },
413 &self.window_target,
414 );
415 }
416 }
417
418 self.with_state(|state| {
420 buffer_sink.append(&mut state.window_events_sink.lock().unwrap());
421 });
422 for event in buffer_sink.drain() {
423 let event = event.map_nonuser_event().unwrap();
424 callback(event, &self.window_target);
425 }
426
427 self.with_state(|state| {
429 buffer_sink.append(&mut state.events_sink);
430 });
431 for event in buffer_sink.drain() {
432 let event = event.map_nonuser_event().unwrap();
433 callback(event, &self.window_target);
434 }
435
436 self.with_state(|state| {
438 window_ids.extend(state.window_requests.get_mut().keys());
439 });
440
441 for window_id in window_ids.iter() {
442 let event = self.with_state(|state| {
443 let window_requests = state.window_requests.get_mut();
444 if window_requests.get(window_id).unwrap().take_closed() {
445 mem::drop(window_requests.remove(window_id));
446 mem::drop(state.windows.get_mut().remove(window_id));
447 return Some(WindowEvent::Destroyed);
448 }
449
450 let mut window =
451 state.windows.get_mut().get_mut(window_id).unwrap().lock().unwrap();
452
453 if window.frame_callback_state() == FrameCallbackState::Requested {
454 return None;
455 }
456
457 window.frame_callback_reset();
459 let mut redraw_requested =
460 window_requests.get(window_id).unwrap().take_redraw_requested();
461
462 redraw_requested |= window.refresh_frame();
464
465 redraw_requested.then_some(WindowEvent::RedrawRequested)
466 });
467
468 if let Some(event) = event {
469 callback(
470 Event::WindowEvent { window_id: crate::window::WindowId(*window_id), event },
471 &self.window_target,
472 );
473 }
474 }
475
476 self.with_state(|state| {
478 state.dispatched_events = false;
479 });
480
481 callback(Event::AboutToWait, &self.window_target);
483
484 let mut wake_up = false;
486 for window_id in window_ids.drain(..) {
487 wake_up |= self.with_state(|state| match state.windows.get_mut().get_mut(&window_id) {
488 Some(window) => {
489 let refresh = window.lock().unwrap().refresh_frame();
490 if refresh {
491 state
492 .window_requests
493 .get_mut()
494 .get_mut(&window_id)
495 .unwrap()
496 .redraw_requested
497 .store(true, Ordering::Relaxed);
498 }
499
500 refresh
501 },
502 None => false,
503 });
504 }
505
506 if wake_up {
511 match &self.window_target.p {
512 PlatformActiveEventLoop::Wayland(window_target) => {
513 window_target.event_loop_awakener.ping();
514 },
515 #[cfg(x11_platform)]
516 PlatformActiveEventLoop::X(_) => unreachable!(),
517 }
518 }
519
520 std::mem::swap(&mut self.compositor_updates, &mut compositor_updates);
521 std::mem::swap(&mut self.buffer_sink, &mut buffer_sink);
522 std::mem::swap(&mut self.window_ids, &mut window_ids);
523 }
524
525 #[inline]
526 pub fn create_proxy(&self) -> EventLoopProxy<T> {
527 EventLoopProxy::new(self.user_events_sender.clone())
528 }
529
530 #[inline]
531 pub fn window_target(&self) -> &RootActiveEventLoop {
532 &self.window_target
533 }
534
535 fn with_state<'a, U: 'a, F: FnOnce(&'a mut WinitState) -> U>(&'a mut self, callback: F) -> U {
536 let state = match &mut self.window_target.p {
537 PlatformActiveEventLoop::Wayland(window_target) => window_target.state.get_mut(),
538 #[cfg(x11_platform)]
539 _ => unreachable!(),
540 };
541
542 callback(state)
543 }
544
545 fn loop_dispatch<D: Into<Option<std::time::Duration>>>(&mut self, timeout: D) -> IOResult<()> {
546 let state = match &mut self.window_target.p {
547 PlatformActiveEventLoop::Wayland(window_target) => window_target.state.get_mut(),
548 #[cfg(feature = "x11")]
549 _ => unreachable!(),
550 };
551
552 self.event_loop.dispatch(timeout, state).map_err(|error| {
553 tracing::error!("Error dispatching event loop: {}", error);
554 error.into()
555 })
556 }
557
558 fn roundtrip(&mut self) -> Result<usize, RootOsError> {
559 let state = match &mut self.window_target.p {
560 PlatformActiveEventLoop::Wayland(window_target) => window_target.state.get_mut(),
561 #[cfg(feature = "x11")]
562 _ => unreachable!(),
563 };
564
565 let mut wayland_source = self.wayland_dispatcher.as_source_mut();
566 let event_queue = wayland_source.queue();
567 event_queue.roundtrip(state).map_err(|error| {
568 os_error!(OsError::WaylandError(Arc::new(WaylandError::Dispatch(error))))
569 })
570 }
571
572 fn control_flow(&self) -> ControlFlow {
573 self.window_target.p.control_flow()
574 }
575
576 fn exiting(&self) -> bool {
577 self.window_target.p.exiting()
578 }
579
580 fn set_exit_code(&self, code: i32) {
581 self.window_target.p.set_exit_code(code)
582 }
583
584 fn exit_code(&self) -> Option<i32> {
585 self.window_target.p.exit_code()
586 }
587}
588
589impl<T> AsFd for EventLoop<T> {
590 fn as_fd(&self) -> BorrowedFd<'_> {
591 self.event_loop.as_fd()
592 }
593}
594
595impl<T> AsRawFd for EventLoop<T> {
596 fn as_raw_fd(&self) -> RawFd {
597 self.event_loop.as_raw_fd()
598 }
599}
600
601pub struct ActiveEventLoop {
602 pub event_loop_awakener: calloop::ping::Ping,
604
605 pub queue_handle: QueueHandle<WinitState>,
607
608 pub(crate) control_flow: Cell<ControlFlow>,
610
611 pub(crate) exit: Cell<Option<i32>>,
613
614 pub state: RefCell<WinitState>,
617
618 pub wayland_dispatcher: WaylandDispatcher,
620
621 pub connection: Connection,
623}
624
625impl ActiveEventLoop {
626 pub(crate) fn set_control_flow(&self, control_flow: ControlFlow) {
627 self.control_flow.set(control_flow)
628 }
629
630 pub(crate) fn control_flow(&self) -> ControlFlow {
631 self.control_flow.get()
632 }
633
634 pub(crate) fn exit(&self) {
635 self.exit.set(Some(0))
636 }
637
638 pub(crate) fn clear_exit(&self) {
639 self.exit.set(None)
640 }
641
642 pub(crate) fn exiting(&self) -> bool {
643 self.exit.get().is_some()
644 }
645
646 pub(crate) fn set_exit_code(&self, code: i32) {
647 self.exit.set(Some(code))
648 }
649
650 pub(crate) fn exit_code(&self) -> Option<i32> {
651 self.exit.get()
652 }
653
654 #[inline]
655 pub fn listen_device_events(&self, _allowed: DeviceEvents) {}
656
657 pub(crate) fn create_custom_cursor(&self, cursor: CustomCursorSource) -> RootCustomCursor {
658 RootCustomCursor {
659 inner: PlatformCustomCursor::Wayland(OnlyCursorImage(Arc::from(cursor.inner.0))),
660 }
661 }
662
663 #[cfg(feature = "rwh_05")]
664 #[inline]
665 pub fn raw_display_handle_rwh_05(&self) -> rwh_05::RawDisplayHandle {
666 use sctk::reexports::client::Proxy;
667
668 let mut display_handle = rwh_05::WaylandDisplayHandle::empty();
669 display_handle.display = self.connection.display().id().as_ptr() as *mut _;
670 rwh_05::RawDisplayHandle::Wayland(display_handle)
671 }
672
673 #[cfg(feature = "rwh_06")]
674 #[inline]
675 pub fn raw_display_handle_rwh_06(
676 &self,
677 ) -> Result<rwh_06::RawDisplayHandle, rwh_06::HandleError> {
678 use sctk::reexports::client::Proxy;
679
680 Ok(rwh_06::WaylandDisplayHandle::new({
681 let ptr = self.connection.display().id().as_ptr();
682 std::ptr::NonNull::new(ptr as *mut _).expect("wl_display should never be null")
683 })
684 .into())
685 }
686}