From c48116a8fd4c395bb0ea523d4a99d051b5122503 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Sun, 15 Oct 2023 20:31:29 +0400 Subject: [PATCH] Implement `AsFd`/`AsRawFd` for `EventLoop` This should help other crates to integrate winit's event loop into their bigger event loop without adding an extra thread. --- CHANGELOG.md | 1 + src/event_loop.rs | 30 +++++++++++++++++++ src/platform_impl/linux/mod.rs | 13 ++++++++ .../linux/wayland/event_loop/mod.rs | 13 ++++++++ src/platform_impl/linux/x11/mod.rs | 14 ++++++++- 5 files changed, 70 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cc639ecc..67806fcb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ And please only add new entries to the top of this list, right below the `# Unre - On iOS, send events `WindowEvent::Occluded(false)`, `WindowEvent::Occluded(true)` when application enters/leaves foreground. - **Breaking** add `Event::MemoryWarning`; implemented on iOS/Android. - On Wayland, support `Occluded` event with xdg-shell v6 +- Implement `AsFd`/`AsRawFd` for `EventLoop` on X11 and Wayland. # 0.29.1-beta diff --git a/src/event_loop.rs b/src/event_loop.rs index 503bb79e..ac2b6c9d 100644 --- a/src/event_loop.rs +++ b/src/event_loop.rs @@ -9,6 +9,8 @@ //! handle events. use std::marker::PhantomData; use std::ops::Deref; +#[cfg(any(x11_platform, wayland_platform))] +use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd}; use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; use std::{error, fmt}; @@ -262,6 +264,34 @@ unsafe impl rwh_05::HasRawDisplayHandle for EventLoop { } } +#[cfg(any(x11_platform, wayland_platform))] +impl AsFd for EventLoop { + /// Get the underlying [EventLoop]'s `fd` which you can register + /// into other event loop, like [`calloop`] or [`mio`]. When doing so, the + /// loop must be polled with the [`pump_events`] API. + /// + /// [`calloop`]: https://crates.io/crates/calloop + /// [`mio`]: https://crates.io/crates/mio + /// [`pump_events`]: crate::platform::pump_events::EventLoopExtPumpEvents::pump_events + fn as_fd(&self) -> BorrowedFd<'_> { + self.event_loop.as_fd() + } +} + +#[cfg(any(x11_platform, wayland_platform))] +impl AsRawFd for EventLoop { + /// Get the underlying [EventLoop]'s raw `fd` which you can register + /// into other event loop, like [`calloop`] or [`mio`]. When doing so, the + /// loop must be polled with the [`pump_events`] API. + /// + /// [`calloop`]: https://crates.io/crates/calloop + /// [`mio`]: https://crates.io/crates/mio + /// [`pump_events`]: crate::platform::pump_events::EventLoopExtPumpEvents::pump_events + fn as_raw_fd(&self) -> RawFd { + self.event_loop.as_raw_fd() + } +} + impl Deref for EventLoop { type Target = EventLoopWindowTarget; fn deref(&self) -> &EventLoopWindowTarget { diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index a6499bf7..19d1e6a7 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -3,6 +3,7 @@ #[cfg(all(not(x11_platform), not(wayland_platform)))] compile_error!("Please select a feature to build for unix: `x11`, `wayland`"); +use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd}; use std::sync::Arc; use std::time::Duration; use std::{collections::VecDeque, env, fmt}; @@ -827,6 +828,18 @@ impl EventLoop { } } +impl AsFd for EventLoop { + fn as_fd(&self) -> BorrowedFd<'_> { + x11_or_wayland!(match self; EventLoop(evlp) => evlp.as_fd()) + } +} + +impl AsRawFd for EventLoop { + fn as_raw_fd(&self) -> RawFd { + x11_or_wayland!(match self; EventLoop(evlp) => evlp.as_raw_fd()) + } +} + impl EventLoopProxy { pub fn send_event(&self, event: T) -> Result<(), EventLoopClosed> { x11_or_wayland!(match self; EventLoopProxy(proxy) => proxy.send_event(event)) diff --git a/src/platform_impl/linux/wayland/event_loop/mod.rs b/src/platform_impl/linux/wayland/event_loop/mod.rs index 08060ecf..cfdc870a 100644 --- a/src/platform_impl/linux/wayland/event_loop/mod.rs +++ b/src/platform_impl/linux/wayland/event_loop/mod.rs @@ -4,6 +4,7 @@ use std::cell::{Cell, RefCell}; use std::io::Result as IOResult; use std::marker::PhantomData; use std::mem; +use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd}; use std::rc::Rc; use std::sync::atomic::Ordering; use std::sync::{Arc, Mutex}; @@ -589,6 +590,18 @@ impl EventLoop { } } +impl AsFd for EventLoop { + fn as_fd(&self) -> BorrowedFd<'_> { + self.event_loop.as_fd() + } +} + +impl AsRawFd for EventLoop { + fn as_raw_fd(&self) -> RawFd { + self.event_loop.as_raw_fd() + } +} + pub struct EventLoopWindowTarget { /// The event loop wakeup source. pub event_loop_awakener: calloop::ping::Ping, diff --git a/src/platform_impl/linux/x11/mod.rs b/src/platform_impl/linux/x11/mod.rs index 07596c79..26c9fe30 100644 --- a/src/platform_impl/linux/x11/mod.rs +++ b/src/platform_impl/linux/x11/mod.rs @@ -32,7 +32,7 @@ use std::{ ops::Deref, os::{ raw::*, - unix::io::{AsRawFd, BorrowedFd}, + unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd}, }, ptr, rc::Rc, @@ -658,6 +658,18 @@ impl EventLoop { } } +impl AsFd for EventLoop { + fn as_fd(&self) -> BorrowedFd<'_> { + self.event_loop.as_fd() + } +} + +impl AsRawFd for EventLoop { + fn as_raw_fd(&self) -> RawFd { + self.event_loop.as_raw_fd() + } +} + pub(crate) fn get_xtarget(target: &RootELW) -> &EventLoopWindowTarget { match target.p { super::EventLoopWindowTarget::X(ref target) => target,