EveryDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/smithay/wayland-rs/llms.txt
Use this file to discover all available pages before exploring further.
wayland-server compositor revolves around two closely related types: Display<D> and DisplayHandle. Display<D> owns the Wayland protocol backend and must be driven from your event loop — it is the type you call dispatch_clients() and flush_clients() on. DisplayHandle is a clonable, type-erased handle derived from the display that you pass to functions needing to interact with the protocol (creating globals, sending events, looking up clients). Because DisplayHandle erases the state type D, it can be stored in data structures and passed across code boundaries without carrying the full generic parameter.
Creating a Display
Display::new() is the only constructor. It can fail only when both the system and dlopen Cargo features of wayland-server are enabled (which activate the server_system and dlopen features of wayland-backend respectively) and the libwayland-server.so library cannot be found at runtime.
D must be 'static. Borrow checker rules mean that during dispatch_clients() the display holds an exclusive borrow on D, so the state struct itself does not need to implement any special traits beyond being 'static.
Obtaining a DisplayHandle
Display::handle() returns a DisplayHandle. The handle clones cheaply and does not keep the Display alive.
Dispatching client requests
Display::dispatch_clients() reads all pending data from every connected client socket and calls the appropriate Dispatch implementations on your state. Call it whenever the display’s file descriptor becomes readable.
io::Error. Messages that do not map to a valid request cause the offending client to be killed with a protocol error — they do not bubble up as Rust errors here.
Flushing outgoing events
Sending an event withresource.send_event() places data into an internal per-client output buffer. Call flush_clients() to drain those buffers into the corresponding Unix sockets.
Integrating into an event loop
The canonical integration pattern is to:For calloop users, the
calloop-wayland-source crate (a separate crate, not part of wayland-server) provides a purpose-built calloop event source that handles both dispatch and flush automatically. The manual Generic approach below also works when you prefer not to add the extra dependency.- Poll the display file descriptor for readability.
- Poll the
ListeningSocketfile descriptor for new connections. - Dispatch and flush inside the readable branch.
Display implements AsFd, so it works directly with epoll, kqueue, or any Rust event-loop crate that accepts AsFd.
- Manual poll loop
- With calloop
Getting the poll file descriptor
If you need the raw file descriptor to pass toepoll_ctl or similar:
DisplayHandle operations
DisplayHandle is the primary API surface for compositor logic that runs outside of Display. All methods are available through display.handle() or any clone of it.
Creating globals
GlobalDispatch story.
Disabling and removing globals
Looking up clients
Sending events and posting errors
Optional features
Accessing the backend
For FFI interop (e.g. passing*mut wl_display to Mesa), access the backend through Display::backend():
Summary
| Method | Where | Purpose |
|---|---|---|
Display::new() | Display<D> | Create the compositor display |
Display::handle() | Display<D> | Obtain a DisplayHandle |
Display::dispatch_clients(&mut D) | Display<D> | Process all incoming requests |
Display::flush_clients() | Display<D> | Write events to sockets |
Display::backend() | Display<D> | Access the raw backend for FFI |
DisplayHandle::create_global() | DisplayHandle | Advertise a new global |
DisplayHandle::disable_global() | DisplayHandle | Soft-remove a global |
DisplayHandle::remove_global() | DisplayHandle | Hard-remove a global |
DisplayHandle::get_client() | DisplayHandle | Look up a client by object ID |
DisplayHandle::send_event() | DisplayHandle | Send a protocol event (low-level) |
DisplayHandle::post_error() | DisplayHandle | Post a fatal protocol error |