1use std::cell::{Cell, RefCell};
4use std::io::Result as IOResult;
5use std::mem;
6use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
7use std::sync::atomic::Ordering;
8use std::sync::{Arc, Mutex};
9use std::time::{Duration, Instant};
10
11use sctk::reexports::calloop_wayland_source::WaylandSource;
12use sctk::reexports::client::{globals, Connection, QueueHandle};
13
14use crate::application::ApplicationHandler;
15use crate::cursor::OnlyCursorImage;
16use crate::dpi::LogicalSize;
17use crate::error::{EventLoopError, OsError, RequestError};
18use crate::event::{Event, StartCause, SurfaceSizeWriter, WindowEvent};
19use crate::event_loop::{ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents};
20use crate::platform::pump_events::PumpStatus;
21use crate::platform_impl::platform::min_timeout;
22use crate::platform_impl::PlatformCustomCursor;
23use crate::window::{CustomCursor as RootCustomCursor, CustomCursorSource, Theme};
24
25mod proxy;
26pub mod sink;
27
28pub use proxy::EventLoopProxy;
29use sink::EventSink;
30
31use super::state::{WindowCompositorUpdate, WinitState};
32use super::window::state::FrameCallbackState;
33use super::{logical_to_physical_rounded, DeviceId, WindowId};
34
35type WaylandDispatcher = calloop::Dispatcher<'static, WaylandSource<WinitState>, WinitState>;
36
37pub struct EventLoop {
39 loop_running: bool,
41
42 buffer_sink: EventSink,
43 compositor_updates: Vec<WindowCompositorUpdate>,
44 window_ids: Vec<WindowId>,
45
46 wayland_dispatcher: WaylandDispatcher,
49
50 connection: Connection,
52
53 active_event_loop: ActiveEventLoop,
55
56 event_loop: calloop::EventLoop<'static, WinitState>,
59}
60
61impl EventLoop {
62 pub fn new() -> Result<EventLoop, EventLoopError> {
63 let connection = Connection::connect_to_env().map_err(|err| os_error!(err))?;
64
65 let (globals, mut event_queue) =
66 globals::registry_queue_init(&connection).map_err(|err| os_error!(err))?;
67 let queue_handle = event_queue.handle();
68
69 let event_loop =
70 calloop::EventLoop::<WinitState>::try_new().map_err(|err| os_error!(err))?;
71
72 let mut winit_state = WinitState::new(&globals, &queue_handle, event_loop.handle())?;
73
74 event_queue.roundtrip(&mut winit_state).map_err(|err| os_error!(err))?;
77
78 let wayland_source = WaylandSource::new(connection.clone(), event_queue);
80 let wayland_dispatcher =
81 calloop::Dispatcher::new(wayland_source, |_, queue, winit_state: &mut WinitState| {
82 let result = queue.dispatch_pending(winit_state);
83 if result.is_ok()
84 && (!winit_state.events_sink.is_empty()
85 || !winit_state.window_compositor_updates.is_empty())
86 {
87 winit_state.dispatched_events = true;
88 }
89 result
90 });
91
92 event_loop
93 .handle()
94 .register_dispatcher(wayland_dispatcher.clone())
95 .map_err(|err| os_error!(err))?;
96
97 let (ping, ping_source) = calloop::ping::make_ping().unwrap();
99 event_loop
100 .handle()
101 .insert_source(ping_source, move |_, _, winit_state: &mut WinitState| {
102 winit_state.dispatched_events = true;
103 winit_state.proxy_wake_up = true;
104 })
105 .map_err(|err| os_error!(err))?;
106
107 let (event_loop_awakener, event_loop_awakener_source) =
109 calloop::ping::make_ping().map_err(|err| os_error!(err))?;
110
111 event_loop
112 .handle()
113 .insert_source(event_loop_awakener_source, move |_, _, winit_state: &mut WinitState| {
114 winit_state.dispatched_events = true;
116 })
117 .map_err(|err| os_error!(err))?;
118
119 let active_event_loop = ActiveEventLoop {
120 connection: connection.clone(),
121 wayland_dispatcher: wayland_dispatcher.clone(),
122 event_loop_awakener,
123 event_loop_proxy: EventLoopProxy::new(ping),
124 queue_handle,
125 control_flow: Cell::new(ControlFlow::default()),
126 exit: Cell::new(None),
127 state: RefCell::new(winit_state),
128 };
129
130 let event_loop = Self {
131 loop_running: false,
132 compositor_updates: Vec::new(),
133 buffer_sink: EventSink::default(),
134 window_ids: Vec::new(),
135 connection,
136 wayland_dispatcher,
137 event_loop,
138 active_event_loop,
139 };
140
141 Ok(event_loop)
142 }
143
144 pub fn run_app<A: ApplicationHandler>(mut self, app: A) -> Result<(), EventLoopError> {
145 self.run_app_on_demand(app)
146 }
147
148 pub fn run_app_on_demand<A: ApplicationHandler>(
149 &mut self,
150 mut app: A,
151 ) -> Result<(), EventLoopError> {
152 self.active_event_loop.clear_exit();
153 let exit = loop {
154 match self.pump_app_events(None, &mut app) {
155 PumpStatus::Exit(0) => {
156 break Ok(());
157 },
158 PumpStatus::Exit(code) => {
159 break Err(EventLoopError::ExitFailure(code));
160 },
161 _ => {
162 continue;
163 },
164 }
165 };
166
167 let _ = self.roundtrip().map_err(EventLoopError::Os);
172
173 exit
174 }
175
176 pub fn pump_app_events<A: ApplicationHandler>(
177 &mut self,
178 timeout: Option<Duration>,
179 mut app: A,
180 ) -> PumpStatus {
181 if !self.loop_running {
182 self.loop_running = true;
183
184 self.single_iteration(&mut app, StartCause::Init);
186 }
187
188 if !self.exiting() {
191 self.poll_events_with_timeout(timeout, &mut app);
192 }
193 if let Some(code) = self.exit_code() {
194 self.loop_running = false;
195
196 app.exiting(&self.active_event_loop);
197
198 PumpStatus::Exit(code)
199 } else {
200 PumpStatus::Continue
201 }
202 }
203
204 fn poll_events_with_timeout<A: ApplicationHandler>(
205 &mut self,
206 mut timeout: Option<Duration>,
207 app: &mut A,
208 ) {
209 let cause = loop {
210 let start = Instant::now();
211
212 timeout = {
213 let control_flow_timeout = match self.control_flow() {
214 ControlFlow::Wait => None,
215 ControlFlow::Poll => Some(Duration::ZERO),
216 ControlFlow::WaitUntil(wait_deadline) => {
217 Some(wait_deadline.saturating_duration_since(start))
218 },
219 };
220 min_timeout(control_flow_timeout, timeout)
221 };
222
223 if self.connection.flush().is_err() {
230 self.set_exit_code(1);
231 return;
232 }
233
234 if let Err(error) = self.loop_dispatch(timeout) {
235 let exit_code = error.raw_os_error().unwrap_or(1);
243 self.set_exit_code(exit_code);
244 return;
245 }
246
247 let cause = match self.control_flow() {
250 ControlFlow::Poll => StartCause::Poll,
251 ControlFlow::Wait => StartCause::WaitCancelled { start, requested_resume: None },
252 ControlFlow::WaitUntil(deadline) => {
253 if Instant::now() < deadline {
254 StartCause::WaitCancelled { start, requested_resume: Some(deadline) }
255 } else {
256 StartCause::ResumeTimeReached { start, requested_resume: deadline }
257 }
258 },
259 };
260
261 let dispatched_events = self.with_state(|state| state.dispatched_events);
263 if matches!(cause, StartCause::WaitCancelled { .. }) && !dispatched_events {
264 continue;
265 }
266
267 break cause;
268 };
269
270 self.single_iteration(app, cause);
271 }
272
273 fn single_iteration<A: ApplicationHandler>(&mut self, app: &mut A, cause: StartCause) {
274 let mut compositor_updates = std::mem::take(&mut self.compositor_updates);
281 let mut buffer_sink = std::mem::take(&mut self.buffer_sink);
282 let mut window_ids = std::mem::take(&mut self.window_ids);
283
284 app.new_events(&self.active_event_loop, cause);
285
286 if cause == StartCause::Init {
289 app.can_create_surfaces(&self.active_event_loop);
290 }
291
292 if self.with_state(|state| mem::take(&mut state.proxy_wake_up)) {
294 app.proxy_wake_up(&self.active_event_loop);
295 }
296
297 self.with_state(|state| compositor_updates.append(&mut state.window_compositor_updates));
299
300 for mut compositor_update in compositor_updates.drain(..) {
301 let window_id = compositor_update.window_id;
302 if compositor_update.scale_changed {
303 let (physical_size, scale_factor) = self.with_state(|state| {
304 let windows = state.windows.get_mut();
305 let window = windows.get(&window_id).unwrap().lock().unwrap();
306 let scale_factor = window.scale_factor();
307 let size = logical_to_physical_rounded(window.surface_size(), scale_factor);
308 (size, scale_factor)
309 });
310
311 let old_physical_size = physical_size;
313
314 let new_surface_size = Arc::new(Mutex::new(physical_size));
315 let root_window_id = crate::window::WindowId(window_id);
316 let event = WindowEvent::ScaleFactorChanged {
317 scale_factor,
318 surface_size_writer: SurfaceSizeWriter::new(Arc::downgrade(&new_surface_size)),
319 };
320
321 app.window_event(&self.active_event_loop, root_window_id, event);
322
323 let physical_size = *new_surface_size.lock().unwrap();
324 drop(new_surface_size);
325
326 if old_physical_size != physical_size {
328 self.with_state(|state| {
329 let windows = state.windows.get_mut();
330 let mut window = windows.get(&window_id).unwrap().lock().unwrap();
331
332 let new_logical_size: LogicalSize<f64> =
333 physical_size.to_logical(scale_factor);
334 window.request_surface_size(new_logical_size.into());
335 });
336
337 compositor_update.resized = true;
339 }
340 }
341
342 if compositor_update.suggested_bounds {
343 let suggested_bounds = self.with_state(|state| {
344 let windows = state.windows.get_mut();
345 let window = windows.get(&window_id).unwrap().lock().unwrap();
346
347 window
348 .last_configure
349 .as_ref()
350 .and_then(|c| c.suggested_bounds)
351 .map(|b| dpi::LogicalSize::new(b.0, b.1).to_physical(window.scale_factor()))
352 .clone()
353 });
354 let window_id = crate::window::WindowId(window_id);
355 let event = WindowEvent::SuggestedBounds(suggested_bounds);
356 app.window_event(&self.active_event_loop, window_id, event);
357 }
358
359 if compositor_update.resized || compositor_update.scale_changed {
362 let physical_size = self.with_state(|state| {
363 let windows = state.windows.get_mut();
364 let window = windows.get(&window_id).unwrap().lock().unwrap();
365
366 let scale_factor = window.scale_factor();
367 let size = logical_to_physical_rounded(window.surface_size(), scale_factor);
368
369 state
371 .window_requests
372 .get_mut()
373 .get_mut(&window_id)
374 .unwrap()
375 .redraw_requested
376 .store(true, Ordering::Relaxed);
377
378 size
379 });
380
381 let window_id = crate::window::WindowId(window_id);
382 let event = WindowEvent::SurfaceResized(physical_size);
383 app.window_event(&self.active_event_loop, window_id, event);
384 }
385
386 if compositor_update.close_window {
387 let window_id = crate::window::WindowId(window_id);
388 app.window_event(&self.active_event_loop, window_id, WindowEvent::CloseRequested);
389 }
390 }
391
392 self.with_state(|state| {
394 buffer_sink.append(&mut state.window_events_sink.lock().unwrap());
395 });
396 for event in buffer_sink.drain() {
397 match event {
398 Event::WindowEvent { window_id, event } => {
399 app.window_event(&self.active_event_loop, window_id, event)
400 },
401 Event::DeviceEvent { device_id, event } => {
402 app.device_event(&self.active_event_loop, device_id, event)
403 },
404 _ => unreachable!("event which is neither device nor window event."),
405 }
406 }
407
408 self.with_state(|state| {
410 buffer_sink.append(&mut state.events_sink);
411 });
412 for event in buffer_sink.drain() {
413 match event {
414 Event::WindowEvent { window_id, event } => {
415 app.window_event(&self.active_event_loop, window_id, event)
416 },
417 Event::DeviceEvent { device_id, event } => {
418 app.device_event(&self.active_event_loop, device_id, event)
419 },
420 _ => unreachable!("event which is neither device nor window event."),
421 }
422 }
423
424 self.with_state(|state| {
426 window_ids.extend(state.window_requests.get_mut().keys());
427 });
428
429 for window_id in window_ids.iter() {
430 let event = self.with_state(|state| {
431 let window_requests = state.window_requests.get_mut();
432 if window_requests.get(window_id).unwrap().take_closed() {
433 mem::drop(window_requests.remove(window_id));
434 mem::drop(state.windows.get_mut().remove(window_id));
435 return Some(WindowEvent::Destroyed);
436 }
437
438 let mut window =
439 state.windows.get_mut().get_mut(window_id).unwrap().lock().unwrap();
440
441 if window.frame_callback_state() == FrameCallbackState::Requested {
442 return None;
443 }
444
445 window.frame_callback_reset();
447 let mut redraw_requested =
448 window_requests.get(window_id).unwrap().take_redraw_requested();
449
450 redraw_requested |= window.refresh_frame();
452
453 redraw_requested.then_some(WindowEvent::RedrawRequested)
454 });
455
456 if let Some(event) = event {
457 let window_id = crate::window::WindowId(*window_id);
458 app.window_event(&self.active_event_loop, window_id, event);
459 }
460 }
461
462 self.with_state(|state| {
464 state.dispatched_events = false;
465 });
466
467 app.about_to_wait(&self.active_event_loop);
469
470 let mut wake_up = false;
472 for window_id in window_ids.drain(..) {
473 wake_up |= self.with_state(|state| match state.windows.get_mut().get_mut(&window_id) {
474 Some(window) => {
475 let refresh = window.lock().unwrap().refresh_frame();
476 if refresh {
477 state
478 .window_requests
479 .get_mut()
480 .get_mut(&window_id)
481 .unwrap()
482 .redraw_requested
483 .store(true, Ordering::Relaxed);
484 }
485
486 refresh
487 },
488 None => false,
489 });
490 }
491
492 if wake_up {
497 self.active_event_loop.event_loop_awakener.ping();
498 }
499
500 std::mem::swap(&mut self.compositor_updates, &mut compositor_updates);
501 std::mem::swap(&mut self.buffer_sink, &mut buffer_sink);
502 std::mem::swap(&mut self.window_ids, &mut window_ids);
503 }
504
505 #[inline]
506 pub fn window_target(&self) -> &dyn RootActiveEventLoop {
507 &self.active_event_loop
508 }
509
510 fn with_state<'a, U: 'a, F: FnOnce(&'a mut WinitState) -> U>(&'a mut self, callback: F) -> U {
511 let state = self.active_event_loop.state.get_mut();
512 callback(state)
513 }
514
515 fn loop_dispatch<D: Into<Option<std::time::Duration>>>(&mut self, timeout: D) -> IOResult<()> {
516 let state = &mut self.active_event_loop.state.get_mut();
517
518 self.event_loop.dispatch(timeout, state).map_err(|error| {
519 tracing::error!("Error dispatching event loop: {}", error);
520 error.into()
521 })
522 }
523
524 fn roundtrip(&mut self) -> Result<usize, OsError> {
525 let state = &mut self.active_event_loop.state.get_mut();
526
527 let mut wayland_source = self.wayland_dispatcher.as_source_mut();
528 let event_queue = wayland_source.queue();
529 event_queue.roundtrip(state).map_err(|err| os_error!(err))
530 }
531
532 fn control_flow(&self) -> ControlFlow {
533 self.active_event_loop.control_flow()
534 }
535
536 fn exiting(&self) -> bool {
537 self.active_event_loop.exiting()
538 }
539
540 fn set_exit_code(&self, code: i32) {
541 self.active_event_loop.set_exit_code(code)
542 }
543
544 fn exit_code(&self) -> Option<i32> {
545 self.active_event_loop.exit_code()
546 }
547}
548
549impl AsFd for EventLoop {
550 fn as_fd(&self) -> BorrowedFd<'_> {
551 self.event_loop.as_fd()
552 }
553}
554
555impl AsRawFd for EventLoop {
556 fn as_raw_fd(&self) -> RawFd {
557 self.event_loop.as_raw_fd()
558 }
559}
560
561pub struct ActiveEventLoop {
562 event_loop_proxy: EventLoopProxy,
564
565 pub event_loop_awakener: calloop::ping::Ping,
567
568 pub queue_handle: QueueHandle<WinitState>,
570
571 pub(crate) control_flow: Cell<ControlFlow>,
573
574 pub(crate) exit: Cell<Option<i32>>,
576
577 pub state: RefCell<WinitState>,
580
581 pub wayland_dispatcher: WaylandDispatcher,
583
584 pub connection: Connection,
586}
587
588impl RootActiveEventLoop for ActiveEventLoop {
589 fn create_proxy(&self) -> crate::event_loop::EventLoopProxy {
590 crate::event_loop::EventLoopProxy {
591 event_loop_proxy: crate::platform_impl::EventLoopProxy::Wayland(
592 self.event_loop_proxy.clone(),
593 ),
594 }
595 }
596
597 fn set_control_flow(&self, control_flow: ControlFlow) {
598 self.control_flow.set(control_flow)
599 }
600
601 fn control_flow(&self) -> ControlFlow {
602 self.control_flow.get()
603 }
604
605 fn exit(&self) {
606 self.exit.set(Some(0))
607 }
608
609 fn exiting(&self) -> bool {
610 self.exit.get().is_some()
611 }
612
613 #[inline]
614 fn listen_device_events(&self, _allowed: DeviceEvents) {}
615
616 fn create_custom_cursor(
617 &self,
618 cursor: CustomCursorSource,
619 ) -> Result<RootCustomCursor, RequestError> {
620 Ok(RootCustomCursor {
621 inner: PlatformCustomCursor::Wayland(OnlyCursorImage(Arc::from(cursor.inner.0))),
622 })
623 }
624
625 #[inline]
626 fn system_theme(&self) -> Option<Theme> {
627 None
628 }
629
630 fn create_window(
631 &self,
632 window_attributes: crate::window::WindowAttributes,
633 ) -> Result<Box<dyn crate::window::Window>, RequestError> {
634 let window = crate::platform_impl::wayland::Window::new(self, window_attributes)?;
635 Ok(Box::new(window))
636 }
637
638 fn available_monitors(&self) -> Box<dyn Iterator<Item = crate::monitor::MonitorHandle>> {
639 Box::new(
640 self.state
641 .borrow()
642 .output_state
643 .outputs()
644 .map(crate::platform_impl::wayland::output::MonitorHandle::new)
645 .map(crate::platform_impl::MonitorHandle::Wayland)
646 .map(|inner| crate::monitor::MonitorHandle { inner }),
647 )
648 }
649
650 fn primary_monitor(&self) -> Option<crate::monitor::MonitorHandle> {
651 None
653 }
654
655 fn owned_display_handle(&self) -> crate::event_loop::OwnedDisplayHandle {
656 crate::event_loop::OwnedDisplayHandle {
657 platform: crate::platform_impl::OwnedDisplayHandle::Wayland(self.connection.clone()),
658 }
659 }
660
661 #[cfg(feature = "rwh_06")]
662 fn rwh_06_handle(&self) -> &dyn rwh_06::HasDisplayHandle {
663 self
664 }
665}
666
667impl ActiveEventLoop {
668 fn clear_exit(&self) {
669 self.exit.set(None)
670 }
671
672 fn set_exit_code(&self, code: i32) {
673 self.exit.set(Some(code))
674 }
675
676 fn exit_code(&self) -> Option<i32> {
677 self.exit.get()
678 }
679}
680
681#[cfg(feature = "rwh_06")]
682impl rwh_06::HasDisplayHandle for ActiveEventLoop {
683 fn display_handle(&self) -> Result<rwh_06::DisplayHandle<'_>, rwh_06::HandleError> {
684 use sctk::reexports::client::Proxy;
685
686 let raw = rwh_06::WaylandDisplayHandle::new({
687 let ptr = self.connection.display().id().as_ptr();
688 std::ptr::NonNull::new(ptr as *mut _).expect("wl_display should never be null")
689 });
690
691 Ok(unsafe { rwh_06::DisplayHandle::borrow_raw(raw.into()) })
692 }
693}