Skip to main content

wayland_backend/sys/
mod.rs

1//! Implementations of the Wayland backends using the system `libwayland`
2
3use std::sync::Arc;
4
5use wayland_sys::client::wl_proxy;
6use wayland_sys::common::{wl_argument, wl_array};
7
8use crate::protocol::{ArgumentType, Interface};
9
10#[cfg(any(test, feature = "client_system"))]
11mod client_impl;
12#[cfg(any(test, feature = "server_system"))]
13mod server_impl;
14
15/// Magic static for wayland objects managed by wayland-client or wayland-server
16///
17/// This static serves no purpose other than existing at a stable address.
18static RUST_MANAGED: u8 = 42;
19
20unsafe fn free_arrays(signature: &[ArgumentType], arglist: &[wl_argument]) {
21    for (typ, arg) in signature.iter().zip(arglist.iter()) {
22        if let ArgumentType::Array = typ {
23            // Safety: the arglist provided arglist must be valid for associated signature
24            // and contains pointers to boxed arrays as appropriate
25            let _ = unsafe { Box::from_raw(arg.a as *mut wl_array) };
26        }
27    }
28}
29
30/// Client-side implementation of a Wayland protocol backend using `libwayland`
31///
32/// Entrypoints are:
33/// - [`Backend::connect()`][client::Backend::connect()] method if you're creating the Wayland connection
34/// - [`Backend::from_foreign_display()`][client::Backend::from_foreign_display()] if you're interacting with an
35///   already existing Wayland connection through FFI.
36#[cfg(any(test, feature = "client_system"))]
37#[path = "../client_api.rs"]
38pub mod client;
39#[cfg(any(test, feature = "client_system"))]
40use client::{ObjectData, ObjectId};
41
42// API complements for FFI
43
44#[cfg(any(test, feature = "client_system"))]
45impl client::ObjectId {
46    /// Creates an object id from a libwayland-client pointer.
47    ///
48    /// # Errors
49    ///
50    /// This function returns an [`InvalidId`][client::InvalidId] error if the interface of the proxy does
51    /// not match the provided interface.
52    ///
53    /// # Safety
54    ///
55    /// The provided pointer must be a valid pointer to a `wl_resource` and remain valid for as
56    /// long as the retrieved `ObjectId` is used.
57    pub unsafe fn from_ptr(
58        interface: &'static crate::protocol::Interface,
59        ptr: *mut wayland_sys::client::wl_proxy,
60    ) -> Result<Self, client::InvalidId> {
61        Ok(Self { id: unsafe { client_impl::InnerObjectId::from_ptr(interface, ptr) }? })
62    }
63
64    /// Get the underlying libwayland pointer for this object
65    ///
66    /// # Errors
67    ///
68    /// This function returns an [`InvalidId`][client::InvalidId] error if proxy has already
69    /// been destroyed.
70    pub fn as_ptr(
71        &self,
72    ) -> Result<std::ptr::NonNull<wayland_sys::client::wl_proxy>, client::InvalidId> {
73        self.id.as_ptr()
74    }
75
76    /// Get the underlying display pointer for this object.
77    ///
78    /// This pointer is associated with the original display this object
79    /// belongs to.
80    #[cfg(feature = "libwayland_client_1_23")]
81    pub fn display_ptr(
82        &self,
83    ) -> Result<std::ptr::NonNull<wayland_sys::client::wl_display>, crate::types::client::InvalidId>
84    {
85        self.id.display_ptr()
86    }
87}
88
89#[cfg(any(test, feature = "client_system"))]
90impl client::Backend {
91    /// Creates a Backend from a foreign `*mut wl_display`.
92    ///
93    /// This is useful if you are writing a library that is expected to plug itself into an existing
94    /// Wayland connection.
95    ///
96    /// This will initialize the [`Backend`][Self] in "guest" mode, meaning it will not close the
97    /// connection on drop. After the [`Backend`][Self] is dropped, if the server sends an event
98    /// to an object that was created from it, that event will be silently discarded. This may lead to
99    /// protocol errors if the server expects an answer to that event, as such you should make sure to
100    /// cleanup your Wayland state before dropping the [`Backend`][Self].
101    ///
102    /// # Safety
103    ///
104    /// You need to ensure the `*mut wl_display` remains live as long as the  [`Backend`][Self]
105    /// (or its clones) exist.
106    pub unsafe fn from_foreign_display(display: *mut wayland_sys::client::wl_display) -> Self {
107        Self { backend: unsafe { client_impl::InnerBackend::from_foreign_display(display) } }
108    }
109
110    /// Returns the underlying `wl_display` pointer to this backend.
111    ///
112    /// This pointer is needed to interface with EGL, Vulkan and other C libraries.
113    ///
114    /// This pointer is only valid for the lifetime of the backend.
115    pub fn display_ptr(&self) -> *mut wayland_sys::client::wl_display {
116        self.backend.display_ptr()
117    }
118
119    /// Take over handling for a proxy created by a third party.
120    ///
121    /// # Safety
122    ///
123    /// There must never be more than one party managing an object. This is only
124    /// safe to call when a third party gave you ownership of an unmanaged proxy.
125    ///
126    /// The caller is also responsible for making sure the passed interface matches
127    /// the proxy.
128    #[inline]
129    pub unsafe fn manage_object(
130        &self,
131        interface: &'static Interface,
132        proxy: *mut wl_proxy,
133        data: Arc<dyn ObjectData>,
134    ) -> ObjectId {
135        unsafe { self.backend.manage_object(interface, proxy, data) }
136    }
137}
138
139#[cfg(any(test, feature = "client_system"))]
140impl client::ReadEventsGuard {
141    /// The same as [`read`], but doesn't dispatch events.
142    ///
143    /// To dispatch them, use [`dispatch_inner_queue`].
144    ///
145    /// [`read`]: client::ReadEventsGuard::read
146    /// [`dispatch_inner_queue`]: client::Backend::dispatch_inner_queue
147    pub fn read_without_dispatch(mut self) -> Result<(), client::WaylandError> {
148        self.guard.read_non_dispatch()
149    }
150}
151
152#[cfg(all(feature = "rwh_06", feature = "client_system"))]
153impl rwh_06::HasDisplayHandle for client::Backend {
154    fn display_handle(&self) -> Result<rwh_06::DisplayHandle<'_>, rwh_06::HandleError> {
155        use std::ptr::NonNull;
156
157        // SAFETY:
158        // - The display_ptr will be valid, either because we have created the pointer or the caller which created the
159        //   backend has ensured the pointer is valid when `Backend::from_foreign_display` was called.
160        let ptr = unsafe { NonNull::new_unchecked(self.display_ptr().cast()) };
161        let handle = rwh_06::WaylandDisplayHandle::new(ptr);
162        let raw = rwh_06::RawDisplayHandle::Wayland(handle);
163
164        // SAFETY:
165        // - The display_ptr will be valid, either because we have created the pointer or the caller which created the
166        //   backend has ensured the pointer is valid when `Backend::from_foreign_display` was called.
167        // - The lifetime assigned to the DisplayHandle borrows the Backend, ensuring the display pointer
168        //   is valid..
169        // - The display_ptr will not change for the lifetime of the backend.
170        Ok(unsafe { rwh_06::DisplayHandle::borrow_raw(raw) })
171    }
172}
173
174/// Server-side implementation of a Wayland protocol backend using `libwayland`
175///
176/// The main entrypoint is the [`Backend::new()`][server::Backend::new()] method.
177#[cfg(any(test, feature = "server_system"))]
178#[path = "../server_api.rs"]
179pub mod server;
180
181#[cfg(any(test, feature = "server_system"))]
182impl server::ObjectId {
183    /// Creates an object from a C pointer.
184    ///
185    /// # Errors
186    ///
187    /// This function returns an [`InvalidId`][server::InvalidId] error if the interface of the
188    /// resource does not match the provided interface.
189    ///
190    /// # Safety
191    ///
192    /// The provided pointer must be a valid pointer to a `wl_resource` and remain valid for as
193    /// long as the retrieved `ObjectId` is used.
194    pub unsafe fn from_ptr(
195        interface: &'static crate::protocol::Interface,
196        ptr: *mut wayland_sys::server::wl_resource,
197    ) -> Result<Self, server::InvalidId> {
198        Ok(Self { id: unsafe { server_impl::InnerObjectId::from_ptr(Some(interface), ptr) }? })
199    }
200
201    /// Returns the pointer that represents this object.
202    ///
203    /// The pointer may be used to interoperate with libwayland.
204    ///
205    /// # Errors
206    ///
207    /// This function returns an [`InvalidId`][server::InvalidId] error if resource has already
208    /// been destroyed.
209    pub fn as_ptr(
210        &self,
211    ) -> Result<std::ptr::NonNull<wayland_sys::server::wl_resource>, server::InvalidId> {
212        self.id.as_ptr()
213    }
214}
215
216#[cfg(any(test, feature = "server_system"))]
217impl server::Handle {
218    /// Access the underlying `*mut wl_display` pointer
219    pub fn display_ptr(&self) -> *mut wayland_sys::server::wl_display {
220        self.handle.display_ptr()
221    }
222}