1 | //! Implementations of the Wayland backends using the system `libwayland` |
2 | |
3 | use crate::protocol::ArgumentType; |
4 | use wayland_sys::common::{wl_argument, wl_array}; |
5 | |
6 | #[cfg (any(test, feature = "client_system" ))] |
7 | mod client_impl; |
8 | #[cfg (any(test, feature = "server_system" ))] |
9 | mod 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. |
14 | static RUST_MANAGED: u8 = 42; |
15 | |
16 | unsafe 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" ] |
34 | pub mod client; |
35 | |
36 | // API complements for FFI |
37 | |
38 | #[cfg (any(test, feature = "client_system" ))] |
39 | impl 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" ))] |
65 | impl 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" )] |
100 | unsafe 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" ] |
113 | pub mod server; |
114 | |
115 | #[cfg (any(test, feature = "server_system" ))] |
116 | impl 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" ))] |
144 | impl 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 | |