From 08ee1d052fa531bca8d1823bbf3537f9076133f3 Mon Sep 17 00:00:00 2001 From: Supreeeme Date: Thu, 4 Apr 2024 15:56:49 -0400 Subject: [PATCH] wayland-client: add example for bypassing Dispatch Also mention ObjectData in the docs for bypassing Dispatch. --- .../examples/list_globals_no_dispatch.rs | 59 +++++++++++++++++++ wayland-client/src/lib.rs | 3 +- 2 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 wayland-client/examples/list_globals_no_dispatch.rs diff --git a/wayland-client/examples/list_globals_no_dispatch.rs b/wayland-client/examples/list_globals_no_dispatch.rs new file mode 100644 index 00000000000..f5471c4538f --- /dev/null +++ b/wayland-client/examples/list_globals_no_dispatch.rs @@ -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); + +// 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, + _: &Backend, + msg: backend::protocol::Message, + ) -> Option> { + // 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(); +} diff --git a/wayland-client/src/lib.rs b/wayland-client/src/lib.rs index 5027e535373..fdbbb006e86 100644 --- a/wayland-client/src/lib.rs +++ b/wayland-client/src/lib.rs @@ -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 +//! assign such callbacks to objects. //! //! ### Interaction with FFI //!