Skip to main content

wayland_client/
lib.rs

1//! Interface for interacting with the Wayland protocol, client-side.
2//!
3//! ## General concepts
4//!
5//! This crate is structured around four main objects: the [`Connection`] and [`EventQueue`] structs,
6//! proxies (objects implementing the [`Proxy`] trait), and the [`Dispatch`] trait.
7//!
8//! The [`Connection`] is the heart of this crate. It represents your connection to the Wayland server, and
9//! you'll generally initialize it using the [`Connection::connect_to_env()`] method, which will
10//! attempt to open a Wayland connection following the configuration specified by the ! environment.
11//!
12//! Once you have a [`Connection`], you can create an [`EventQueue`] from it. This [`EventQueue`] will take
13//! care of processing events from the Wayland server and delivering them to your processing logic, in the form
14//! of a state struct with several [`Dispatch`] implementations (see below).
15//!
16//! Each of the Wayland objects you can manipulate is represented by a struct implementing the [`Proxy`]
17//! trait. Those structs are automatically generated from the wayland XML protocol specification. This crate
18//! provides the types generated from the core protocol in the [`protocol`] module. For other standard
19//! protocols, see the `wayland-protocols` crate.
20//!
21//! ## Event dispatching
22//!
23//! The core event dispatching logic provided by this crate is built around the [`EventQueue`] struct. In
24//! this paradigm, receiving and processing events is a two-step process:
25//!
26//! - First, events are read from the Wayland socket. For each event, the backend figures out which [`EventQueue`]
27//!   manages it, and enqueues the event in an internal buffer of that queue.
28//! - Then, the [`EventQueue`] empties its internal buffer by sequentially invoking the appropriate
29//!   [`Dispatch::event()`] method on the `State` value that was provided to it.
30//!
31//! The main goal of this structure is to make your `State` accessible without synchronization to most of
32//! your event-processing logic, to reduce the plumbing costs. See [`EventQueue`]'s documentation for
33//! explanations of how to use it to drive your event loop, and when and how to use multiple
34//! event queues in your app.
35//!
36//! ### The [`Dispatch`] trait and dispatch delegation
37//!
38//! In this paradigm, your `State` needs to implement `Dispatch<O, _>` for every Wayland object `O` it needs to
39//! process events for. This is ensured by the fact that, whenever creating an object using the methods on
40//! an other object, you need to pass a [`QueueHandle<State>`] from the [`EventQueue`] that will be
41//! managing the newly created object.
42//!
43//! However, implementing all those traits on your own is a lot of (often uninteresting) work. To make this
44//! easier another library (such as Smithay's Client Toolkit) can provide generic [`Dispatch`] implementations
45//! for a user-data type it defines, that you can reuse in your own appSee the documentation of those traits
46//! for details.
47//!
48//! ## Getting started example
49//!
50//! As an overview of how this crate is used, here is a commented example of a program that connects to the
51//! Wayland server and lists the globals this server advertised through the `wl_registry`:
52//!
53//! ```rust,no_run
54//! use wayland_client::{protocol::wl_registry, Connection, Dispatch, QueueHandle};
55//! // This struct represents the state of our app. This simple app does not
56//! // need any state, but this type still supports the `Dispatch` implementations.
57//! struct AppData;
58//!
59//! // Implement `Dispatch<WlRegistry, ()> for our state. This provides the logic
60//! // to be able to process events for the wl_registry interface.
61//! //
62//! // The second type parameter is the user-data of our implementation. It is a
63//! // mechanism that allows you to associate a value to each particular Wayland
64//! // object, and allow different dispatching logic depending on the type of the
65//! // associated value.
66//! //
67//! // In this example, we just use () as we don't have any value to associate. See
68//! // the `Dispatch` documentation for more details about this.
69//! impl Dispatch<wl_registry::WlRegistry, AppData> for () {
70//!     fn event(
71//!         &self,
72//!         _state: &mut AppData,
73//!         _: &wl_registry::WlRegistry,
74//!         event: wl_registry::Event,
75//!         _: &Connection,
76//!         _: &QueueHandle<AppData>,
77//!     ) {
78//!         // When receiving events from the wl_registry, we are only interested in the
79//!         // `global` event, which signals a new available global.
80//!         // When receiving this event, we just print its characteristics in this example.
81//!         if let wl_registry::Event::Global { name, interface, version } = event {
82//!             println!("[{}] {} (v{})", name, interface, version);
83//!         }
84//!     }
85//! }
86//!
87//! // The main function of our program
88//! fn main() {
89//!     // Create a Wayland connection by connecting to the server through the
90//!     // environment-provided configuration.
91//!     let conn = unsafe { Connection::connect_to_env() }.unwrap();
92//!
93//!     // Retrieve the WlDisplay Wayland object from the connection. This object is
94//!     // the starting point of any Wayland program, from which all other objects will
95//!     // be created.
96//!     let display = conn.display();
97//!
98//!     // Create an event queue for our event processing
99//!     let mut event_queue = conn.new_event_queue();
100//!     // And get its handle to associate new objects to it
101//!     let qh = event_queue.handle();
102//!
103//!     // Create a wl_registry object by sending the wl_display.get_registry request.
104//!     // This method takes two arguments: a handle to the queue that the newly created
105//!     // wl_registry will be assigned to, and the user-data that should be associated
106//!     // with this registry (here it is () as we don't need user-data).
107//!     let _registry = display.get_registry(&qh, ());
108//!
109//!     // At this point everything is ready, and we just need to wait to receive the events
110//!     // from the wl_registry. Our callback will print the advertised globals.
111//!     println!("Advertised globals:");
112//!
113//!     // To actually receive the events, we invoke the `roundtrip` method. This method
114//!     // is special and you will generally only invoke it during the setup of your program:
115//!     // it will block until the server has received and processed all the messages you've
116//!     // sent up to now.
117//!     //
118//!     // In our case, that means it'll block until the server has received our
119//!     // wl_display.get_registry request, and as a reaction has sent us a batch of
120//!     // wl_registry.global events.
121//!     //
122//!     // `roundtrip` will then empty the internal buffer of the queue it has been invoked
123//!     // on, and thus invoke our `Dispatch` implementation that prints the list of advertised
124//!     // globals.
125//!     event_queue.roundtrip(&mut AppData).unwrap();
126//! }
127//! ```
128//!
129//! ## Advanced use
130//!
131//! ### Bypassing [`Dispatch`]
132//!
133//! It may be that for some of your objects, handling them via the [`EventQueue`] is impractical. For example,
134//! if processing the events from those objects doesn't require accessing some global state, and/or you need to
135//! handle them in a context where cranking an event loop is impractical.
136//!
137//! In those contexts, this crate also provides some escape hatches to directly interface with the low-level
138//! APIs from `wayland-backend`, allowing you to register callbacks for those objects that will be invoked
139//! whenever they receive an event and *any* event queue from the program is being dispatched. Those
140//! callbacks are more constrained: they don't get a `&mut State` reference, and must be threadsafe. See
141//! [`Proxy::send_constructor()`] and [`ObjectData`] for details about how to
142//! assign such callbacks to objects.
143//!
144//! ### Interaction with FFI
145//!
146//! It can happen that you'll need to interact with Wayland states accross FFI. A typical example would be if
147//! you need to use the [`raw-window-handle`](https://docs.rs/raw-window-handle/) crate.
148//!
149//! In this case, you'll need enable the `system` feature to use the `libwayland` backend of
150//! `wayland-backend`.
151//!
152//! - If you need to send pointers to FFI, you can retrive the `*mut wl_proxy` pointers from the proxies by
153//!   first getting the [`ObjectId`] using the [`Proxy::id()`] method, and then
154//!   using the [`ObjectId::as_ptr()`] method.
155//  - If you need to receive pointers from FFI, you need to first create a
156//    [`Backend`][backend::Backend] from the `*mut wl_display` using
157//    [`Backend::from_external_display()`][backend::Backend::from_foreign_display()], and then
158//    make it into a [`Connection`] using [`Connection::from_backend()`]. Similarly, you can make
159//    [`ObjectId`]s from the `*mut wl_proxy` pointers using [`ObjectId::from_ptr()`], and then make
160//    the proxies using [`Proxy::from_id()`].
161
162#![allow(clippy::needless_doctest_main)]
163#![warn(missing_docs, missing_debug_implementations)]
164#![forbid(improper_ctypes, unsafe_op_in_unsafe_fn)]
165#![cfg_attr(unstable_coverage, feature(coverage_attribute))]
166// Doc feature labels can be tested locally by running RUSTDOCFLAGS="--cfg=docsrs" cargo +nightly doc -p <crate>
167#![cfg_attr(docsrs, feature(doc_cfg))]
168
169use std::{
170    fmt,
171    hash::{Hash, Hasher},
172    sync::Arc,
173};
174use wayland_backend::{
175    client::{InvalidId, ObjectData, ObjectId, WaylandError, WeakBackend},
176    protocol::{Interface, Message, OwnedMessage},
177};
178
179mod conn;
180mod event_queue;
181pub mod globals;
182
183/// Backend reexports
184pub mod backend {
185    pub use wayland_backend::client::{
186        Backend, InvalidId, NoWaylandLib, ObjectData, ObjectId, ReadEventsGuard, WaylandError,
187        WeakBackend,
188    };
189    pub use wayland_backend::protocol;
190    pub use wayland_backend::smallvec;
191}
192
193pub use conn::{ConnectError, Connection};
194pub use event_queue::{
195    Dispatch, EventQueue, Noop, NoopIgnore, QueueFreezeGuard, QueueHandle, QueueProxyData,
196};
197
198// internal imports for dispatching logging depending on the `log` feature
199#[cfg(feature = "log")]
200#[allow(unused_imports)]
201use log::{debug as log_debug, error as log_error, info as log_info, warn as log_warn};
202#[cfg(not(feature = "log"))]
203#[allow(unused_imports)]
204use std::{
205    eprintln as log_error, eprintln as log_warn, eprintln as log_info, eprintln as log_debug,
206};
207
208/// Generated protocol definitions
209///
210/// This module is automatically generated from the `wayland.xml` protocol specification,
211/// and contains the interface definitions for the core Wayland protocol.
212#[allow(missing_docs)]
213pub mod protocol {
214    use self::__interfaces::*;
215    use crate as wayland_client;
216    pub mod __interfaces {
217        wayland_scanner::generate_interfaces!("wayland.xml");
218    }
219    wayland_scanner::generate_client_code!("wayland.xml");
220}
221
222/// Trait representing a Wayland interface
223pub trait Proxy: Clone + std::fmt::Debug + Sized + 'static {
224    /// The event enum for this interface
225    type Event;
226    /// The request enum for this interface
227    type Request<'a>;
228
229    /// The interface description
230    fn interface() -> &'static Interface;
231
232    /// The ID of this object
233    fn id(&self) -> &ObjectId;
234
235    /// The version of this object
236    fn version(&self) -> u32;
237
238    /// Checks if the Wayland object associated with this proxy is still alive
239    fn is_alive(&self) -> bool {
240        if let Some(backend) = self.backend().upgrade() {
241            backend.info(self.id()).is_ok()
242        } else {
243            false
244        }
245    }
246
247    /// Access the user-data associated with this object
248    fn data<U: Send + Sync + 'static>(&self) -> Option<&U> {
249        self.object_data()?.data_as_any().downcast_ref::<U>()
250    }
251
252    /// Access the raw data associated with this object.
253    ///
254    /// For objects created using the scanner-generated methods, this will be an instance of the
255    /// [`QueueProxyData`] type.
256    fn object_data(&self) -> Option<&Arc<dyn ObjectData>>;
257
258    /// Access the backend associated with this object
259    fn backend(&self) -> &backend::WeakBackend;
260
261    /// Create an object proxy from its ID
262    ///
263    /// Returns an error this the provided object ID does not correspond to
264    /// the `Self` interface.
265    ///
266    /// **Note:** This method is mostly meant as an implementation detail to be
267    /// used by code generated by wayland-scanner.
268    fn from_id(conn: &Connection, id: ObjectId) -> Result<Self, InvalidId>;
269
270    /// Create an inert object proxy
271    ///
272    /// **Note:** This method is mostly meant as an implementation detail to be
273    /// used by code generated by wayland-scanner.
274    fn inert(backend: backend::WeakBackend) -> Self;
275
276    /// Send a request for this object.
277    ///
278    /// It is an error to use this function on requests that create objects; use
279    /// [`send_constructor()`][Self::send_constructor()] for such requests.
280    fn send_request<'a>(&'a self, req: Self::Request<'a>) -> Result<(), InvalidId> {
281        let conn = Connection::from_backend(self.backend().upgrade().ok_or(InvalidId)?);
282        let id = conn.send_request(self, req, None)?;
283        debug_assert!(id.is_null());
284        Ok(())
285    }
286
287    /// Send a request for this object that creates another object.
288    ///
289    /// It is an error to use this function on requests that do not create objects; use
290    /// [`send_request()`][Self::send_request()] for such requests.
291    fn send_constructor<I: Proxy>(
292        &self,
293        req: Self::Request<'_>,
294        data: Arc<dyn ObjectData>,
295    ) -> Result<I, InvalidId> {
296        let conn = Connection::from_backend(self.backend().upgrade().ok_or(InvalidId)?);
297        let id = conn.send_request(self, req, Some(data))?;
298        Proxy::from_id(&conn, id)
299    }
300
301    /// Parse a event for this object
302    ///
303    /// **Note:** This method is mostly meant as an implementation detail to be
304    /// used by code generated by wayland-scanner.
305    fn parse_event(
306        conn: &Connection,
307        msg: OwnedMessage<ObjectId>,
308    ) -> Result<(Self, Self::Event), DispatchError>;
309
310    /// Serialize a request for this object
311    ///
312    /// **Note:** This method is mostly meant as an implementation detail to be
313    /// used by code generated by wayland-scanner.
314    #[allow(clippy::type_complexity)]
315    fn write_request<'r, 'a: 'r, 'b: 'a>(
316        &'a self,
317        conn: &Connection,
318        req: Self::Request<'b>,
319    ) -> Result<(Message<'r, ObjectId>, Option<(&'static Interface, u32)>), InvalidId>;
320
321    /// Creates a weak handle to this object
322    ///
323    /// This weak handle will not keep the user-data associated with the object alive,
324    /// and can be converted back to a full proxy using [`Weak::upgrade()`].
325    ///
326    /// This can be of use if you need to store proxies in the used data of other objects and want
327    /// to be sure to avoid reference cycles that would cause memory leaks.
328    fn downgrade(&self) -> Weak<Self> {
329        Weak {
330            backend: self.backend().clone(),
331            id: self.id().clone(),
332            _iface: std::marker::PhantomData,
333        }
334    }
335}
336
337/// Wayland dispatching error
338#[derive(Debug)]
339pub enum DispatchError {
340    /// The received message does not match the specification for the object's interface.
341    BadMessage {
342        /// The id of the target object
343        sender_id: ObjectId,
344        /// The interface of the target object
345        interface: &'static str,
346        /// The opcode number
347        opcode: u16,
348    },
349    /// The backend generated an error
350    Backend(WaylandError),
351}
352
353impl std::error::Error for DispatchError {
354    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
355        match self {
356            DispatchError::BadMessage { .. } => Option::None,
357            DispatchError::Backend(source) => Some(source),
358        }
359    }
360}
361
362impl fmt::Display for DispatchError {
363    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
364        match self {
365            DispatchError::BadMessage { sender_id, interface, opcode } => {
366                write!(f, "Bad message for object {interface}@{sender_id} on opcode {opcode}")
367            }
368            DispatchError::Backend(source) => {
369                write!(f, "Backend error: {source}")
370            }
371        }
372    }
373}
374
375impl From<WaylandError> for DispatchError {
376    fn from(source: WaylandError) -> Self {
377        DispatchError::Backend(source)
378    }
379}
380
381/// A weak handle to a Wayland object
382///
383/// This handle does not keep the underlying user data alive, and can be converted back to a full proxy
384/// using [`Weak::upgrade()`].
385#[derive(Debug, Clone)]
386pub struct Weak<I> {
387    backend: WeakBackend,
388    id: ObjectId,
389    _iface: std::marker::PhantomData<I>,
390}
391
392impl<I: Proxy> Weak<I> {
393    /// Try to upgrade with weak handle back into a full proxy.
394    ///
395    /// This will fail if either:
396    /// - the object represented by this handle has already been destroyed at the protocol level
397    /// - the Wayland connection has already been closed
398    pub fn upgrade(&self) -> Result<I, InvalidId> {
399        let backend = self.backend.upgrade().ok_or(InvalidId)?;
400        // Check if the object has been destroyed
401        backend.info(&self.id)?;
402        let conn = Connection::from_backend(backend);
403        I::from_id(&conn, self.id.clone())
404    }
405
406    /// The underlying [`ObjectId`]
407    pub fn id(&self) -> &ObjectId {
408        &self.id
409    }
410}
411
412impl<I> PartialEq for Weak<I> {
413    fn eq(&self, other: &Self) -> bool {
414        self.id == other.id
415    }
416}
417
418impl<I> Eq for Weak<I> {}
419
420impl<I> Hash for Weak<I> {
421    fn hash<H: Hasher>(&self, state: &mut H) {
422        self.id.hash(state);
423    }
424}
425
426impl<I: Proxy> PartialEq<I> for Weak<I> {
427    fn eq(&self, other: &I) -> bool {
428        self.id == *other.id()
429    }
430}