Skip to content

Commit

Permalink
wayland-client: add example for bypassing Dispatch
Browse files Browse the repository at this point in the history
Also mention ObjectData in the docs for bypassing Dispatch.
  • Loading branch information
Supreeeme committed Apr 4, 2024
1 parent 738cef0 commit 08ee1d0
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 1 deletion.
59 changes: 59 additions & 0 deletions wayland-client/examples/list_globals_no_dispatch.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
use std::os::fd::OwnedFd;
use std::sync::Arc;
use wayland_client::{
backend::{self, Backend},
protocol::{wl_display, wl_registry},
Connection, Proxy,
};

// This struct represents the data associated with our registry.
struct RegistryData(Arc<Connection>);

// Instead of implementing Dispatch on some global state, we will implement
// ObjectData for our registry. This is required to receive events
// (specifically, the wl_registry.global events) after our wl_registry.get_registry request.
impl backend::ObjectData for RegistryData {
fn event(
self: Arc<Self>,
_: &Backend,
msg: backend::protocol::Message<backend::ObjectId, OwnedFd>,
) -> Option<Arc<dyn backend::ObjectData>> {
// Here, we parse the wire message into an event using Proxy::parse_event.
let (_registry, event) = wl_registry::WlRegistry::parse_event(&self.0, msg).unwrap();

// Similar to the dispatch example, we only care about the global event and
// will print out the received globals.
if let wl_registry::Event::Global { name, interface, version } = event {
println!("[{}] {} (v{})", name, interface, version);
}
None
}

// This method is called whenever the object is destroyed. In the case of our registry,
// however, there is no way to destroy it, so we will mark it as unreachable.
fn destroyed(&self, _: wayland_backend::client::ObjectId) {
unreachable!();
}
}

fn main() {
// Create our connection like the Dispatch example, except we store it in an Arc
// to share with our registry object data.
let conn = Arc::new(Connection::connect_to_env().unwrap());
let display = conn.display();

let registry_data = Arc::new(RegistryData(conn.clone()));

// Send the `wl_display.get_registry` request, which returns a `wl_registry` to us.
// Since this request creates a new object, we will use the `Proxy::send_constructor` method
// to send it. If it didn't, we would use `Proxy::send_request`.
let _registry: wl_registry::WlRegistry = display
.send_constructor(wl_display::Request::GetRegistry {}, registry_data.clone())
.unwrap();

println!("Advertised globals:");

// Invoke our roundtrip to receive the events. This essentially is the same as the
// `EventQueue::roundtrip` method, except it does not have a state to dispatch methods on.
conn.roundtrip().unwrap();
}
3 changes: 2 additions & 1 deletion wayland-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@
//! APIs from `wayland-backend`, allowing you to register callbacks for those objects that will be invoked
//! whenever they receive an event and *any* event queue from the program is being dispatched. Those
//! callbacks are more constrained: they don't get a `&mut State` reference, and must be threadsafe. See
//! [`Proxy::send_constructor`] for details about how to assign such callbacks to objects.
//! [`Proxy::send_constructor`] and [`ObjectData`](crate::backend::ObjectData) for details about how to

Check warning on line 143 in wayland-client/src/lib.rs

View workflow job for this annotation

GitHub Actions / Documentation on Github Pages

redundant explicit link target
//! assign such callbacks to objects.
//!
//! ### Interaction with FFI
//!
Expand Down

0 comments on commit 08ee1d0

Please sign in to comment.