pub trait Dispatch<I: Resource, UserData, State = Self>: Sized {
// Required method
fn request(
state: &mut State,
client: &Client,
resource: &I,
request: I::Request,
data: &UserData,
dhandle: &DisplayHandle,
data_init: &mut DataInit<'_, State>,
);
// Provided method
fn destroyed(
_state: &mut State,
_client: ClientId,
_resource: &I,
_data: &UserData,
) { ... }
}
Expand description
A trait which provides an implementation for handling a client’s requests from a resource with some type of associated user data.
§General usage
You need to implement this trait on your State
for every type of Wayland object that will be processed
by the Display
working with your State
.
You can have different implementations of the trait for the same interface but different UserData
type,
this way the events for a given object will be processed by the adequate implementation depending on
which UserData
was assigned to it at creation.
The way this trait works is that the Dispatch::request()
method will be invoked by the
Display
for every request received by an object. Your implementation can then match
on the associated Resource::Request
enum and do any processing needed with that event.
If the request being processed created a new object, you’ll receive it as a New<I>
. When that is the
case, you must initialize it using the DataInit
argument. **Failing to do so will cause a panic.
§Modularity
To provide generic handlers for downstream usage, it is possible to make an implementation of the trait
that is generic over the last type argument, as illustrated below. Users will then be able to
automatically delegate their implementation to yours using the delegate_dispatch!()
macro.
As a result, when your implementation is instanciated, the last type parameter State
will be the state
struct of the app using your generic implementation. You can put additional trait constraints on it to
specify an interface between your module and downstream code, as illustrated in this example:
use wayland_server::{protocol::wl_output, Dispatch};
/// The type we want to delegate to
struct DelegateToMe;
/// The user data relevant for your implementation.
/// When providing delegate implementation, it is recommended to use your own type here, even if it is
/// just a unit struct: using () would cause a risk of clashing with an other such implementation.
struct MyUserData;
// Now a generic implementation of Dispatch, we are generic over the last type argument instead of using
// the default State=Self.
impl<State> Dispatch<wl_output::WlOutput, MyUserData, State> for DelegateToMe
where
// State is the type which has delegated to this type, so it needs to have an impl of Dispatch itself
State: Dispatch<wl_output::WlOutput, MyUserData>,
// If your delegate type has some internal state, it'll need to access it, and you can
// require it by adding custom trait bounds.
// In this example, we just require an AsMut implementation
State: AsMut<DelegateToMe>,
{
fn request(
state: &mut State,
_client: &wayland_server::Client,
_resource: &wl_output::WlOutput,
_request: wl_output::Request,
_udata: &MyUserData,
_dhandle: &wayland_server::DisplayHandle,
_data_init: &mut wayland_server::DataInit<'_, State>,
) {
// Here the delegate may handle incoming requests as it pleases.
// For example, it retrives its state and does some processing with it
let me: &mut DelegateToMe = state.as_mut();
// do something with `me` ...
}
}
Note: Due to limitations in Rust’s trait resolution algorithm, a type providing a generic
implementation of Dispatch
cannot be used directly as the dispatching state, as rustc
currently fails to understand that it also provides Dispatch<I, U, Self>
(assuming all other
trait bounds are respected as well).
Required Methods§
Sourcefn request(
state: &mut State,
client: &Client,
resource: &I,
request: I::Request,
data: &UserData,
dhandle: &DisplayHandle,
data_init: &mut DataInit<'_, State>,
)
fn request( state: &mut State, client: &Client, resource: &I, request: I::Request, data: &UserData, dhandle: &DisplayHandle, data_init: &mut DataInit<'_, State>, )
Called when a request from a client is processed.
The implementation of this function will vary depending on what protocol is being implemented. Typically the server may respond to clients by sending events to the resource, or some other resource stored in the user data.
Provided Methods§
Sourcefn destroyed(
_state: &mut State,
_client: ClientId,
_resource: &I,
_data: &UserData,
)
fn destroyed( _state: &mut State, _client: ClientId, _resource: &I, _data: &UserData, )
Called when the object this user data is associated with has been destroyed.
Note this type only provides an immutable reference to the user data, you will need to use interior mutability to change it.
Typically a Mutex
would be used to have interior mutability.
You are given the ObjectId
and ClientId
associated with the destroyed object for cleanup
convenience.
By default this method does nothing.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.