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