wayland_server/lib.rs
1//! Interface for interacting with the Wayland protocol, server-side.
2//!
3//! ## General concepts
4//!
5//! This crate is structured around four main objects: the [`Display`] and [`DisplayHandle`] structs,
6//! resources (objects implementing the [`Resource`] trait), and the [`Dispatch`] trait.
7//!
8//! The [`Display`] is the heart of this crate, it represents the protocol state of your Wayland server, and
9//! takes care of processing messages from clients. You'll need to integrate it in your event loop (see its
10//! documentation for details). From it you can retrieve the [`DisplayHandle`], which is a clonable handle to
11//! the Wayland state and is the type used to actually interact with the protocol.
12//!
13//! Each of the Wayland object you can manipulate is represented by a struct implementing the [`Resource`]
14//! trait. Thos structs are automatically generated from the wayland XML protocol specification. This crate
15//! provides the types generated from the core protocol in the [`protocol`] module. For other standard
16//! protocols, see the `wayland-protocols` crate.
17//!
18//! ## Request dispatching and the [`Dispatch`] trait
19//!
20//! The request dispatching logic provided by this crate is build around the [`Dispatch`] trait. During the
21//! dispatching process (in [`Display::dispatch_clients()`]), all requests sent by clients are read from
22//! their respective process and delivered to your processing logic, by invoking methods on the various
23//! [`Dispatch`] implementations of your `State` struct. In this paradigm, your `State` needs to implement
24//! `Dispatch<O, _>` for every Wayland object `O` it needs to process events for.
25//!
26//! However, implementing all those traits on your own is a lot of (often uninteresting) work. To make this
27//! easier a another library (such as Smithay) can provide generic [`Dispatch`] implementations that you
28//! for a user-data type it defines, so can reuse on your own app. See the documentation of those traits
29//! for details.
30//!
31//! ## Globals
32//!
33//! The entry point of the protocol for clients goes through the protocol globals. Each global represents a
34//! capability of your compositor, a peripheral it has access to, or a protocol extension it supports.
35//! Globals are created by you using [`DisplayHandle::create_global()`], and require your `State` to
36//! implement the [`GlobalDispatch`] trait for the interface associated with that global.
37//!
38//! ## Logging
39//!
40//! This crate can generate some runtime error message (notably when a protocol error occurs). By default
41//! those messages are printed to stderr. If you activate the `log` cargo feature, they will instead be
42//! piped through the `log` crate.
43//!
44//! ## Advanced use
45//!
46//! ### Bypassing [`Dispatch`]
47//!
48//! It may be that for some of your objects, handling them via the [`Dispatch`] trait is impractical. In
49//! those contexts, this crate also provides some escape-hatches to directly interface with the low-level
50//! APIs from `wayland-backend`, allowing you to register callbacks for those objects by directly providing
51//! implementations of the backend [`ObjectData`][backend::ObjectData] trait.
52//! See [`Client::create_resource_from_objdata()`] and [`DataInit::custom_init()`].
53//!
54//! ### Interaction with FFI
55//!
56//! It can happen that you'll need to interact with Wayland states accross FFI, such as for example when
57//! interfacing with the graphics stack for enabling hardware acceleration for clients.
58//!
59//! In this case, you'll need enable the `system` feature to use the `libwayland` backend of
60//! `wayland-backend`.
61//!
62//! Then, you'll generally need:
63//!
64//! - The `*mut wl_display` pointer, that you can retrieve by first retrieving the
65//! [`Backend`][backend::Backend] using [`Display::backend()`], and then invoke
66//! [`.handle()`][backend::Backend::handle()][`.display_ptr()`][backend::Handle::display_ptr()].
67//! - The `*mut wl_resource` pointers for the objects you need to share, by first getting the
68//! [`ObjectId`] using the [`Resource::id()`] method, and then
69//! the [`ObjectId::as_ptr()`] method.
70//!
71//! If you need to receive pointers from FFI, you can make [`ObjectId`]s from the `*mut wl_resource` pointers
72//! using [`ObjectId::from_ptr()`], and then make the resources using [`Resource::from_id()`].
73#![forbid(improper_ctypes, unsafe_op_in_unsafe_fn)]
74// Doc feature labels can be tested locally by running RUSTDOCFLAGS="--cfg=docsrs" cargo +nightly doc -p <crate>
75#![cfg_attr(docsrs, feature(doc_cfg))]
76
77use std::{
78 fmt,
79 hash::{Hash, Hasher},
80};
81use wayland_backend::{
82 protocol::{Interface, Message, OwnedMessage},
83 server::{InvalidId, ObjectId, WeakHandle},
84};
85
86mod client;
87mod dispatch;
88mod display;
89mod global;
90mod socket;
91
92pub use client::Client;
93pub use dispatch::{DataInit, Dispatch, New, ResourceData};
94pub use display::{Display, DisplayHandle};
95pub use global::GlobalDispatch;
96pub use socket::{BindError, ListeningSocket};
97
98/// Backend reexports
99pub mod backend {
100 pub use wayland_backend::protocol;
101 pub use wayland_backend::server::{
102 Backend, ClientData, ClientId, Credentials, DisconnectReason, GlobalHandler, GlobalId,
103 Handle, InitError, InvalidId, ObjectData, ObjectId, WeakHandle,
104 };
105 pub use wayland_backend::smallvec;
106}
107
108/// Generated protocol definitions
109///
110/// This module is automatically generated from the `wayland.xml` protocol specification, and contains the
111/// interface definitions for the core Wayland protocol.
112#[allow(missing_docs)]
113pub mod protocol {
114 use self::__interfaces::*;
115 use crate as wayland_server;
116 pub mod __interfaces {
117 wayland_scanner::generate_interfaces!("wayland.xml");
118 }
119 wayland_scanner::generate_server_code!("wayland.xml");
120}
121
122// internal imports for dispatching logging depending on the `log` feature
123#[cfg(feature = "log")]
124#[allow(unused_imports)]
125use log::{debug as log_debug, error as log_error, info as log_info, warn as log_warn};
126#[cfg(not(feature = "log"))]
127#[allow(unused_imports)]
128use std::{
129 eprintln as log_error, eprintln as log_warn, eprintln as log_info, eprintln as log_debug,
130};
131
132/// Trait representing a Wayland interface
133pub trait Resource: Clone + std::fmt::Debug + Sized + 'static {
134 /// The event enum for this interface
135 type Event<'a>;
136 /// The request enum for this interface
137 type Request;
138
139 /// The interface description
140 fn interface() -> &'static Interface;
141
142 /// The ID of this object
143 fn id(&self) -> &ObjectId;
144
145 /// The client owning this object
146 ///
147 /// Returns [`None`] if the object is no longer alive.
148 fn client(&self) -> Option<Client> {
149 let handle = self.handle().upgrade()?;
150 let client_id = handle.get_client(self.id()).ok()?;
151 let dh = DisplayHandle::from(handle);
152 Client::from_id(&dh, client_id.clone()).ok()
153 }
154
155 /// The version of this object
156 fn version(&self) -> u32;
157
158 /// Checks if the Wayland object associated with this proxy is still alive
159 #[inline]
160 fn is_alive(&self) -> bool {
161 if let Some(handle) = self.handle().upgrade() {
162 handle.object_info(self.id()).is_ok()
163 } else {
164 false
165 }
166 }
167
168 /// Access the user-data associated with this object
169 fn data<U: 'static>(&self) -> Option<&U> {
170 Some(&self.object_data()?.downcast_ref::<ResourceData<Self, U>>()?.udata)
171 }
172
173 /// Access the raw data associated with this object.
174 ///
175 /// It is given to you as a `dyn Any`, and you are responsible for downcasting it.
176 ///
177 /// For objects created using the scanner-generated methods, this will be an instance of the
178 /// [`ResourceData`] type.
179 fn object_data(&self) -> Option<&std::sync::Arc<dyn std::any::Any + Send + Sync>>;
180
181 /// Access the backend handle associated with this object
182 fn handle(&self) -> &backend::WeakHandle;
183
184 /// Create an object resource from its ID
185 ///
186 /// Returns an error this the provided object ID does not correspond to the `Self` interface.
187 ///
188 /// **Note:** This method is mostly meant as an implementation detail to be used by code generated by
189 /// wayland-scanner.
190 fn from_id(dh: &DisplayHandle, id: ObjectId) -> Result<Self, InvalidId>;
191
192 /// Send an event to this object
193 fn send_event(&self, evt: Self::Event<'_>) -> Result<(), InvalidId> {
194 let handle = DisplayHandle::from(self.handle().upgrade().ok_or(InvalidId)?);
195 handle.send_event(self, evt)
196 }
197
198 /// Trigger a protocol error on this object
199 ///
200 /// The `code` is intended to be from the `Error` enum declared alongside that object interface.
201 ///
202 /// A protocol error is fatal to the Wayland connection, and the client will be disconnected.
203 #[inline]
204 fn post_error(&self, code: impl Into<u32>, error: impl Into<String>) {
205 if let Some(dh) = self.handle().upgrade().map(DisplayHandle::from) {
206 dh.post_error(self, code.into(), error.into());
207 }
208 }
209
210 /// Parse a event for this object
211 ///
212 /// **Note:** This method is mostly meant as an implementation detail to be used by code generated by
213 /// wayland-scanner.
214 fn parse_request(
215 dh: &DisplayHandle,
216 msg: OwnedMessage<ObjectId>,
217 ) -> Result<(Self, Self::Request), DispatchError>;
218
219 /// Serialize an event for this object
220 ///
221 /// **Note:** This method is mostly meant as an implementation detail to be used by code generated by
222 /// wayland-scanner.
223 fn write_event<'r, 'a: 'r, 'b: 'r>(
224 &'a self,
225 dh: &DisplayHandle,
226 req: Self::Event<'b>,
227 ) -> Result<Message<'r, ObjectId>, InvalidId>;
228
229 /// Creates a weak handle to this object
230 ///
231 /// This weak handle will not keep the user-data associated with the object alive,
232 /// and can be converted back to a full resource using [`Weak::upgrade()`].
233 ///
234 /// This can be of use if you need to store resources in the used data of other objects and want
235 /// to be sure to avoid reference cycles that would cause memory leaks.
236 #[inline]
237 fn downgrade(&self) -> Weak<Self> {
238 Weak {
239 handle: self.handle().clone(),
240 id: self.id().clone(),
241 _iface: std::marker::PhantomData,
242 }
243 }
244
245 #[doc(hidden)]
246 fn __set_object_data(
247 &mut self,
248 odata: std::sync::Arc<dyn std::any::Any + Send + Sync + 'static>,
249 );
250}
251
252/// An error generated if an illegal request was received from a client
253#[derive(Debug)]
254pub enum DispatchError {
255 /// The received message does not match the specification for the object's interface.
256 BadMessage {
257 /// The id of the target object
258 sender_id: ObjectId,
259 /// The interface of the target object
260 interface: &'static str,
261 /// The opcode number
262 opcode: u16,
263 },
264}
265
266impl std::error::Error for DispatchError {}
267
268impl fmt::Display for DispatchError {
269 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
270 match self {
271 DispatchError::BadMessage { sender_id, interface, opcode } => {
272 write!(f, "Bad message for object {interface}@{sender_id} on opcode {opcode}",)
273 }
274 }
275 }
276}
277
278/// A weak handle to a Wayland object
279///
280/// This handle does not keep the underlying user data alive, and can be converted back to a full resource
281/// using [`Weak::upgrade()`].
282#[derive(Debug, Clone)]
283pub struct Weak<I> {
284 handle: WeakHandle,
285 id: ObjectId,
286 _iface: std::marker::PhantomData<I>,
287}
288
289impl<I: Resource> Weak<I> {
290 /// Try to upgrade with weak handle back into a full resource.
291 ///
292 /// This will fail if either:
293 /// - the object represented by this handle has already been destroyed at the protocol level
294 /// - the Wayland connection has already been closed
295 #[inline]
296 pub fn upgrade(&self) -> Result<I, InvalidId> {
297 let handle = self.handle.upgrade().ok_or(InvalidId)?;
298 // Check if the object has been destroyed
299 handle.object_info(&self.id)?;
300 let d_handle = DisplayHandle::from(handle);
301 I::from_id(&d_handle, self.id.clone())
302 }
303
304 /// Check if this resource is still alive
305 ///
306 /// This will return `false` if either:
307 /// - the object represented by this handle has already been destroyed at the protocol level
308 /// - the Wayland connection has already been closed
309 #[inline]
310 pub fn is_alive(&self) -> bool {
311 let Some(handle) = self.handle.upgrade() else {
312 return false;
313 };
314 handle.object_info(&self.id).is_ok()
315 }
316
317 /// The underlying [`ObjectId`]
318 pub fn id(&self) -> &ObjectId {
319 &self.id
320 }
321}
322
323impl<I> PartialEq for Weak<I> {
324 #[inline]
325 fn eq(&self, other: &Self) -> bool {
326 self.id == other.id
327 }
328}
329
330impl<I> Eq for Weak<I> {}
331
332impl<I> Hash for Weak<I> {
333 #[inline]
334 fn hash<H: Hasher>(&self, state: &mut H) {
335 self.id.hash(state);
336 }
337}
338
339impl<I: Resource> PartialEq<I> for Weak<I> {
340 #[inline]
341 fn eq(&self, other: &I) -> bool {
342 self.id == *other.id()
343 }
344}