Skip to main content

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