1//! Implementations of the Wayland backends using the system `libwayland`
2
3use crate::protocol::ArgumentType;
4use wayland_sys::common::{wl_argument, wl_array};
5
6#[cfg(any(test, feature = "client_system"))]
7mod client_impl;
8#[cfg(any(test, feature = "server_system"))]
9mod server_impl;
10
11/// Magic static for wayland objects managed by wayland-client or wayland-server
12///
13/// This static serves no purpose other than existing at a stable address.
14static RUST_MANAGED: u8 = 42;
15
16unsafe fn free_arrays(signature: &[ArgumentType], arglist: &[wl_argument]) {
17 for (typ: &ArgumentType, arg: &wl_argument) in signature.iter().zip(arglist.iter()) {
18 if let ArgumentType::Array = typ {
19 // Safety: the arglist provided arglist must be valid for associated signature
20 // and contains pointers to boxed arrays as appropriate
21 let _ = unsafe { Box::from_raw(arg.a as *mut wl_array) };
22 }
23 }
24}
25
26/// Client-side implementation of a Wayland protocol backend using `libwayland`
27///
28/// Entrypoints are:
29/// - [`Backend::connect`](client::Backend::connect) method if you're creating the Wayland connection
30/// - [`Backend::from_foreign_display`](client::Backend::from_foreign_display) if you're interacting with an
31/// already existing Wayland connection through FFI.
32#[cfg(any(test, feature = "client_system"))]
33#[path = "../client_api.rs"]
34pub mod client;
35
36// API complements for FFI
37
38#[cfg(any(test, feature = "client_system"))]
39impl client::ObjectId {
40 /// Creates an object id from a libwayland-client pointer.
41 ///
42 /// # Errors
43 ///
44 /// This function returns an [`InvalidId`](client::InvalidId) error if the interface of the proxy does
45 /// not match the provided interface.
46 ///
47 /// # Safety
48 ///
49 /// The provided pointer must be a valid pointer to a `wl_resource` and remain valid for as
50 /// long as the retrieved `ObjectId` is used.
51 pub unsafe fn from_ptr(
52 interface: &'static crate::protocol::Interface,
53 ptr: *mut wayland_sys::client::wl_proxy,
54 ) -> Result<Self, client::InvalidId> {
55 Ok(Self { id: unsafe { client_impl::InnerObjectId::from_ptr(interface, ptr) }? })
56 }
57
58 /// Get the underlying libwayland pointer for this object
59 pub fn as_ptr(&self) -> *mut wayland_sys::client::wl_proxy {
60 self.id.as_ptr()
61 }
62}
63
64#[cfg(any(test, feature = "client_system"))]
65impl client::Backend {
66 /// Creates a Backend from a foreign `*mut wl_display`.
67 ///
68 /// This is useful if you are writing a library that is expected to plug itself into an existing
69 /// Wayland connection.
70 ///
71 /// This will initialize the [`Backend`](client::Backend) in "guest" mode, meaning it will not close the
72 /// connection on drop. After the [`Backend`](client::Backend) is dropped, if the server sends an event
73 /// to an object that was created from it, that event will be silently discarded. This may lead to
74 /// protocol errors if the server expects an answer to that event, as such you should make sure to
75 /// cleanup your Wayland state before dropping the [`Backend`](client::Backend).
76 ///
77 /// # Safety
78 ///
79 /// You need to ensure the `*mut wl_display` remains live as long as the [`Backend`](client::Backend)
80 /// (or its clones) exist.
81 pub unsafe fn from_foreign_display(display: *mut wayland_sys::client::wl_display) -> Self {
82 Self { backend: unsafe { client_impl::InnerBackend::from_foreign_display(display) } }
83 }
84
85 /// Returns the underlying `wl_display` pointer to this backend.
86 ///
87 /// This pointer is needed to interface with EGL, Vulkan and other C libraries.
88 ///
89 /// This pointer is only valid for the lifetime of the backend.
90 pub fn display_ptr(&self) -> *mut wayland_sys::client::wl_display {
91 self.backend.display_ptr()
92 }
93}
94
95// SAFETY:
96// - The display_ptr will not change for the lifetime of the backend.
97// - The display_ptr will be valid, either because we have created the pointer or the caller which created the
98// backend has ensured the pointer is valid when `Backend::from_foreign_display` was called.
99#[cfg(feature = "raw-window-handle")]
100unsafe impl raw_window_handle::HasRawDisplayHandle for client::Backend {
101 fn raw_display_handle(&self) -> raw_window_handle::RawDisplayHandle {
102 let mut handle = raw_window_handle::WaylandDisplayHandle::empty();
103 handle.display = self.display_ptr().cast();
104 raw_window_handle::RawDisplayHandle::Wayland(handle)
105 }
106}
107
108/// Server-side implementation of a Wayland protocol backend using `libwayland`
109///
110/// The main entrypoint is the [`Backend::new`](server::Backend::new) method.
111#[cfg(any(test, feature = "server_system"))]
112#[path = "../server_api.rs"]
113pub mod server;
114
115#[cfg(any(test, feature = "server_system"))]
116impl server::ObjectId {
117 /// Creates an object from a C pointer.
118 ///
119 /// # Errors
120 ///
121 /// This function returns an [`InvalidId`](server::InvalidId) error if the interface of the
122 /// resource does not match the provided interface.
123 ///
124 /// # Safety
125 ///
126 /// The provided pointer must be a valid pointer to a `wl_resource` and remain valid for as
127 /// long as the retrieved `ObjectId` is used.
128 pub unsafe fn from_ptr(
129 interface: &'static crate::protocol::Interface,
130 ptr: *mut wayland_sys::server::wl_resource,
131 ) -> Result<Self, server::InvalidId> {
132 Ok(Self { id: unsafe { server_impl::InnerObjectId::from_ptr(Some(interface), ptr) }? })
133 }
134
135 /// Returns the pointer that represents this object.
136 ///
137 /// The pointer may be used to interoperate with libwayland.
138 pub fn as_ptr(&self) -> *mut wayland_sys::server::wl_resource {
139 self.id.as_ptr()
140 }
141}
142
143#[cfg(any(test, feature = "server_system"))]
144impl server::Handle {
145 /// Access the underlying `*mut wl_display` pointer
146 pub fn display_ptr(&self) -> *mut wayland_sys::server::wl_display {
147 self.handle.display_ptr()
148 }
149}
150