Documentation 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-client provides safe, idiomatic Rust bindings for the Wayland client protocol. The library is structured around four core concepts: the Connection that owns the socket to the compositor, EventQueue instances that buffer and dispatch incoming events, proxy types that represent individual Wayland objects, and the Dispatch trait that routes events to your application logic. This guide walks through each of those pieces and ends with a complete, runnable example.
Prerequisites
You need a Linux machine (or any system running a Wayland compositor) and a recent Rust toolchain. The minimum supported Rust version forwayland-client 0.31 is 1.86.
Add the dependency
systemlibwayland-client.so. Required for FFI interop with other C libraries (e.g. raw-window-handle).dlopenlibwayland-client.so at runtime instead of linking at compile time. Your binary starts successfully even when no Wayland library is installed—useful for shipping cross-platform binaries that gracefully fall back when running under X11 or Windows. Must be combined with system to take effect.If neither
system nor dlopen is specified, wayland-client uses its own pure-Rust Wayland backend. That backend is fully functional but cannot share a connection with C code.Connection::connect_to_env() reads the standard Wayland environment variables (WAYLAND_SOCKET, WAYLAND_DISPLAY, XDG_RUNTIME_DIR) and opens the socket:An
EventQueue buffers events read from the socket and dispatches them to your state. Every Wayland object you create must be assigned to a queue via a QueueHandle obtained from that queue:The type parameter
AppData is your application state—the struct that will receive all dispatched events through Dispatch implementations.WlDisplay is the root Wayland object. From it you request a WlRegistry, which the server uses to advertise all available globals:The second argument to
get_registry is the user data associated with this particular registry object. Here () suffices because we have no per-object state to track.For every Wayland object your application processes, you must implement
Dispatch<ObjectType, AppState> for your user-data type. The event() method receives &self (the user data), &mut State (your application state), the proxy, the event, and handles for further object creation:use wayland_client::{protocol::wl_registry, Connection, Dispatch, QueueHandle};
struct AppData;
// Dispatch<WlRegistry, AppData> is implemented for `()` — the user-data type
// attached to the registry object. `AppData` is the application state.
impl Dispatch<wl_registry::WlRegistry, AppData> for () {
fn event(
&self,
_state: &mut AppData,
_proxy: &wl_registry::WlRegistry,
event: wl_registry::Event,
_conn: &Connection,
_qhandle: &QueueHandle<AppData>,
) {
if let wl_registry::Event::Global { name, interface, version } = event {
println!("[{name}] {interface} (v{version})");
}
}
}
Dispatch<I, State> is implemented on the user-data type (here ()), not on State. The first type parameter is the proxy type (WlRegistry); the second is your application state type (AppData). You can have multiple Dispatch implementations for the same proxy type as long as the user-data types differ.EventQueue::roundtrip() flushes all pending outgoing messages to the server, then blocks until the server has processed them all and sent back a wl_display.done callback. During this time every wl_registry.global event is buffered and then dispatched to your Dispatch implementation:Complete example
The following is thelist_globals example taken directly from the repository. It demonstrates all six steps above in under 80 lines, including the comments that explain each decision:
Next steps
Connection
Deep-dive into
Connection: alternate constructors, FFI interop, and error handling.Event Queues
Learn synchronous roundtrips, blocking dispatch, and multi-queue patterns.
Globals
Use
GlobalList and registry_queue_init to discover and bind compositor capabilities.Dispatch
Master
Dispatch trait implementations for every object type your client uses.