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 pub fn as_ptr(&self) -> *mut wayland_sys::client::wl_proxy {
66 self.id.as_ptr()
67 }
68
69 /// Get the underlying display pointer for this object.
70 ///
71 /// This pointer is associated with the original display this object
72 /// belongs to.
73 pub fn display_ptr(
74 &self,
75 ) -> Result<std::ptr::NonNull<wayland_sys::client::wl_display>, crate::types::client::InvalidId>
76 {
77 self.id.display_ptr()
78 }
79}
80
81#[cfg(any(test, feature = "client_system"))]
82impl client::Backend {
83 /// Creates a Backend from a foreign `*mut wl_display`.
84 ///
85 /// This is useful if you are writing a library that is expected to plug itself into an existing
86 /// Wayland connection.
87 ///
88 /// This will initialize the [`Backend`][Self] in "guest" mode, meaning it will not close the
89 /// connection on drop. After the [`Backend`][Self] is dropped, if the server sends an event
90 /// to an object that was created from it, that event will be silently discarded. This may lead to
91 /// protocol errors if the server expects an answer to that event, as such you should make sure to
92 /// cleanup your Wayland state before dropping the [`Backend`][Self].
93 ///
94 /// # Safety
95 ///
96 /// You need to ensure the `*mut wl_display` remains live as long as the [`Backend`][Self]
97 /// (or its clones) exist.
98 pub unsafe fn from_foreign_display(display: *mut wayland_sys::client::wl_display) -> Self {
99 Self { backend: unsafe { client_impl::InnerBackend::from_foreign_display(display) } }
100 }
101
102 /// Returns the underlying `wl_display` pointer to this backend.
103 ///
104 /// This pointer is needed to interface with EGL, Vulkan and other C libraries.
105 ///
106 /// This pointer is only valid for the lifetime of the backend.
107 pub fn display_ptr(&self) -> *mut wayland_sys::client::wl_display {
108 self.backend.display_ptr()
109 }
110
111 /// Take over handling for a proxy created by a third party.
112 ///
113 /// # Safety
114 ///
115 /// There must never be more than one party managing an object. This is only
116 /// safe to call when a third party gave you ownership of an unmanaged proxy.
117 ///
118 /// The caller is also responsible for making sure the passed interface matches
119 /// the proxy.
120 #[inline]
121 pub unsafe fn manage_object(
122 &self,
123 interface: &'static Interface,
124 proxy: *mut wl_proxy,
125 data: Arc<dyn ObjectData>,
126 ) -> ObjectId {
127 unsafe { self.backend.manage_object(interface, proxy, data) }
128 }
129}
130
131#[cfg(any(test, feature = "client_system"))]
132impl client::ReadEventsGuard {
133 /// The same as [`read`], but doesn't dispatch events.
134 ///
135 /// To dispatch them, use [`dispatch_inner_queue`].
136 ///
137 /// [`read`]: client::ReadEventsGuard::read
138 /// [`dispatch_inner_queue`]: client::Backend::dispatch_inner_queue
139 pub fn read_without_dispatch(mut self) -> Result<(), client::WaylandError> {
140 self.guard.read_non_dispatch()
141 }
142}
143
144// SAFETY:
145// - The display_ptr will not change for the lifetime of the backend.
146// - The display_ptr will be valid, either because we have created the pointer or the caller which created the
147// backend has ensured the pointer is valid when `Backend::from_foreign_display` was called.
148#[cfg(feature = "raw-window-handle")]
149unsafe impl raw_window_handle::HasRawDisplayHandle for client::Backend {
150 fn raw_display_handle(&self) -> raw_window_handle::RawDisplayHandle {
151 let mut handle = raw_window_handle::WaylandDisplayHandle::empty();
152 handle.display = self.display_ptr().cast();
153 raw_window_handle::RawDisplayHandle::Wayland(handle)
154 }
155}
156
157#[cfg(all(feature = "rwh_06", feature = "client_system"))]
158impl rwh_06::HasDisplayHandle for client::Backend {
159 fn display_handle(&self) -> Result<rwh_06::DisplayHandle<'_>, rwh_06::HandleError> {
160 use std::ptr::NonNull;
161
162 // SAFETY:
163 // - The display_ptr will be valid, either because we have created the pointer or the caller which created the
164 // backend has ensured the pointer is valid when `Backend::from_foreign_display` was called.
165 let ptr = unsafe { NonNull::new_unchecked(self.display_ptr().cast()) };
166 let handle = rwh_06::WaylandDisplayHandle::new(ptr);
167 let raw = rwh_06::RawDisplayHandle::Wayland(handle);
168
169 // SAFETY:
170 // - The display_ptr will be valid, either because we have created the pointer or the caller which created the
171 // backend has ensured the pointer is valid when `Backend::from_foreign_display` was called.
172 // - The lifetime assigned to the DisplayHandle borrows the Backend, ensuring the display pointer
173 // is valid..
174 // - The display_ptr will not change for the lifetime of the backend.
175 Ok(unsafe { rwh_06::DisplayHandle::borrow_raw(raw) })
176 }
177}
178
179/// Server-side implementation of a Wayland protocol backend using `libwayland`
180///
181/// The main entrypoint is the [`Backend::new()`][server::Backend::new()] method.
182#[cfg(any(test, feature = "server_system"))]
183#[path = "../server_api.rs"]
184pub mod server;
185
186#[cfg(any(test, feature = "server_system"))]
187impl server::ObjectId {
188 /// Creates an object from a C pointer.
189 ///
190 /// # Errors
191 ///
192 /// This function returns an [`InvalidId`][server::InvalidId] error if the interface of the
193 /// resource does not match the provided interface.
194 ///
195 /// # Safety
196 ///
197 /// The provided pointer must be a valid pointer to a `wl_resource` and remain valid for as
198 /// long as the retrieved `ObjectId` is used.
199 pub unsafe fn from_ptr(
200 interface: &'static crate::protocol::Interface,
201 ptr: *mut wayland_sys::server::wl_resource,
202 ) -> Result<Self, server::InvalidId> {
203 Ok(Self { id: unsafe { server_impl::InnerObjectId::from_ptr(Some(interface), ptr) }? })
204 }
205
206 /// Returns the pointer that represents this object.
207 ///
208 /// The pointer may be used to interoperate with libwayland.
209 pub fn as_ptr(&self) -> *mut wayland_sys::server::wl_resource {
210 self.id.as_ptr()
211 }
212}
213
214#[cfg(any(test, feature = "server_system"))]
215impl server::Handle {
216 /// Access the underlying `*mut wl_display` pointer
217 pub fn display_ptr(&self) -> *mut wayland_sys::server::wl_display {
218 self.handle.display_ptr()
219 }
220}