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