| 1 | //! Implementations of the Wayland backends using the system `libwayland` |
| 2 | |
| 3 | use std::sync::Arc; |
| 4 | |
| 5 | use wayland_sys::client::wl_proxy; |
| 6 | use wayland_sys::common::{wl_argument, wl_array}; |
| 7 | |
| 8 | use crate::client::{ObjectData, ObjectId}; |
| 9 | use crate::protocol::{ArgumentType, Interface}; |
| 10 | |
| 11 | #[cfg (any(test, feature = "client_system" ))] |
| 12 | mod client_impl; |
| 13 | #[cfg (any(test, feature = "server_system" ))] |
| 14 | mod 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. |
| 19 | static RUST_MANAGED: u8 = 42; |
| 20 | |
| 21 | unsafe fn free_arrays(signature: &[ArgumentType], arglist: &[wl_argument]) { |
| 22 | for (typ: &ArgumentType, arg: &wl_argument) 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" ] |
| 39 | pub mod client; |
| 40 | |
| 41 | // API complements for FFI |
| 42 | |
| 43 | #[cfg (any(test, feature = "client_system" ))] |
| 44 | impl 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" ))] |
| 70 | impl 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" )] |
| 124 | unsafe 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" ))] |
| 133 | impl 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" ] |
| 159 | pub mod server; |
| 160 | |
| 161 | #[cfg (any(test, feature = "server_system" ))] |
| 162 | impl 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" ))] |
| 190 | impl 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 | } |
| 196 | |