From cb3ceb6e8ca4a05676f8582f66104d3dca6e6fb1 Mon Sep 17 00:00:00 2001 From: PolyMeilex Date: Sun, 11 Feb 2024 19:51:02 +0100 Subject: [PATCH 1/6] Server side delegate --- wayland-scanner/src/server_gen.rs | 7 +- .../tests/scanner_assets/test-server-code.rs | 60 ++++- wayland-server/examples/delegated.rs | 114 +++++++++ wayland-server/src/client.rs | 34 ++- wayland-server/src/dispatch.rs | 242 +++++++++++++----- wayland-server/src/display.rs | 30 ++- wayland-server/src/global.rs | 20 +- wayland-server/src/lib.rs | 19 +- 8 files changed, 439 insertions(+), 87 deletions(-) create mode 100644 wayland-server/examples/delegated.rs diff --git a/wayland-scanner/src/server_gen.rs b/wayland-scanner/src/server_gen.rs index af13af35e52..99a991b0f6a 100644 --- a/wayland-scanner/src/server_gen.rs +++ b/wayland-scanner/src/server_gen.rs @@ -65,7 +65,7 @@ fn generate_objects_for(interface: &Interface) -> TokenStream { smallvec, ObjectData, ObjectId, InvalidId, WeakHandle, protocol::{WEnum, Argument, Message, Interface, same_interface} }, - Resource, Dispatch, DisplayHandle, DispatchError, ResourceData, New, Weak, + Resource, Dispatch, DisplayHandle, DispatchError, ResourceData, DelegatedResourceData, New, Weak, }; #enums @@ -136,6 +136,11 @@ fn generate_objects_for(interface: &Interface) -> TokenStream { self.data.as_ref().and_then(|arc| (&**arc).downcast_ref::>()).map(|data| &data.udata) } + #[inline] + fn delegated_data(&self) -> Option<&U> { + self.data.as_ref().and_then(|arc| (&**arc).downcast_ref::>()).map(|data| &data.udata) + } + #[inline] fn object_data(&self) -> Option<&Arc> { self.data.as_ref() diff --git a/wayland-scanner/tests/scanner_assets/test-server-code.rs b/wayland-scanner/tests/scanner_assets/test-server-code.rs index 495fe6d5eaa..618f7feb081 100644 --- a/wayland-scanner/tests/scanner_assets/test-server-code.rs +++ b/wayland-scanner/tests/scanner_assets/test-server-code.rs @@ -5,10 +5,11 @@ pub mod wl_callback { protocol::{same_interface, Argument, Interface, Message, WEnum}, smallvec, InvalidId, ObjectData, ObjectId, WeakHandle, }, - Dispatch, DispatchError, DisplayHandle, New, Resource, ResourceData, Weak, + DelegatedResourceData, Dispatch, DispatchError, DisplayHandle, New, Resource, ResourceData, + Weak, }; - use std::sync::Arc; use std::os::unix::io::OwnedFd; + use std::sync::Arc; #[doc = r" The minimal object version supporting this event"] pub const EVT_DONE_SINCE: u32 = 1u32; #[doc = r" The wire opcode for this event"] @@ -101,6 +102,13 @@ pub mod wl_callback { .map(|data| &data.udata) } #[inline] + fn delegated_data(&self) -> Option<&U> { + self.data + .as_ref() + .and_then(|arc| (&**arc).downcast_ref::>()) + .map(|data| &data.udata) + } + #[inline] fn object_data(&self) -> Option<&Arc> { self.data.as_ref() } @@ -173,10 +181,11 @@ pub mod test_global { protocol::{same_interface, Argument, Interface, Message, WEnum}, smallvec, InvalidId, ObjectData, ObjectId, WeakHandle, }, - Dispatch, DispatchError, DisplayHandle, New, Resource, ResourceData, Weak, + DelegatedResourceData, Dispatch, DispatchError, DisplayHandle, New, Resource, ResourceData, + Weak, }; - use std::sync::Arc; use std::os::unix::io::OwnedFd; + use std::sync::Arc; #[doc = r" The minimal object version supporting this request"] pub const REQ_MANY_ARGS_SINCE: u32 = 1u32; #[doc = r" The wire opcode for this request"] @@ -367,6 +376,13 @@ pub mod test_global { .map(|data| &data.udata) } #[inline] + fn delegated_data(&self) -> Option<&U> { + self.data + .as_ref() + .and_then(|arc| (&**arc).downcast_ref::>()) + .map(|data| &data.udata) + } + #[inline] fn object_data(&self) -> Option<&Arc> { self.data.as_ref() } @@ -782,10 +798,11 @@ pub mod secondary { protocol::{same_interface, Argument, Interface, Message, WEnum}, smallvec, InvalidId, ObjectData, ObjectId, WeakHandle, }, - Dispatch, DispatchError, DisplayHandle, New, Resource, ResourceData, Weak, + DelegatedResourceData, Dispatch, DispatchError, DisplayHandle, New, Resource, ResourceData, + Weak, }; - use std::sync::Arc; use std::os::unix::io::OwnedFd; + use std::sync::Arc; #[doc = r" The minimal object version supporting this request"] pub const REQ_DESTROY_SINCE: u32 = 2u32; #[doc = r" The wire opcode for this request"] @@ -877,6 +894,13 @@ pub mod secondary { .map(|data| &data.udata) } #[inline] + fn delegated_data(&self) -> Option<&U> { + self.data + .as_ref() + .and_then(|arc| (&**arc).downcast_ref::>()) + .map(|data| &data.udata) + } + #[inline] fn object_data(&self) -> Option<&Arc> { self.data.as_ref() } @@ -945,10 +969,11 @@ pub mod tertiary { protocol::{same_interface, Argument, Interface, Message, WEnum}, smallvec, InvalidId, ObjectData, ObjectId, WeakHandle, }, - Dispatch, DispatchError, DisplayHandle, New, Resource, ResourceData, Weak, + DelegatedResourceData, Dispatch, DispatchError, DisplayHandle, New, Resource, ResourceData, + Weak, }; - use std::sync::Arc; use std::os::unix::io::OwnedFd; + use std::sync::Arc; #[doc = r" The minimal object version supporting this request"] pub const REQ_DESTROY_SINCE: u32 = 3u32; #[doc = r" The wire opcode for this request"] @@ -1040,6 +1065,13 @@ pub mod tertiary { .map(|data| &data.udata) } #[inline] + fn delegated_data(&self) -> Option<&U> { + self.data + .as_ref() + .and_then(|arc| (&**arc).downcast_ref::>()) + .map(|data| &data.udata) + } + #[inline] fn object_data(&self) -> Option<&Arc> { self.data.as_ref() } @@ -1108,10 +1140,11 @@ pub mod quad { protocol::{same_interface, Argument, Interface, Message, WEnum}, smallvec, InvalidId, ObjectData, ObjectId, WeakHandle, }, - Dispatch, DispatchError, DisplayHandle, New, Resource, ResourceData, Weak, + DelegatedResourceData, Dispatch, DispatchError, DisplayHandle, New, Resource, ResourceData, + Weak, }; - use std::sync::Arc; use std::os::unix::io::OwnedFd; + use std::sync::Arc; #[doc = r" The minimal object version supporting this request"] pub const REQ_DESTROY_SINCE: u32 = 3u32; #[doc = r" The wire opcode for this request"] @@ -1203,6 +1236,13 @@ pub mod quad { .map(|data| &data.udata) } #[inline] + fn delegated_data(&self) -> Option<&U> { + self.data + .as_ref() + .and_then(|arc| (&**arc).downcast_ref::>()) + .map(|data| &data.udata) + } + #[inline] fn object_data(&self) -> Option<&Arc> { self.data.as_ref() } diff --git a/wayland-server/examples/delegated.rs b/wayland-server/examples/delegated.rs new file mode 100644 index 00000000000..07281a60124 --- /dev/null +++ b/wayland-server/examples/delegated.rs @@ -0,0 +1,114 @@ +#![allow(clippy::single_match)] + +use delegated::{OutputHandler, OutputManagerState}; +use wayland_server::Display; + +/// A demonstration of how delegateing can make implementing protocols an implementation detail +/// +/// Users of this module only need to implement `OutputHandler` trait on their state, +/// Implementations of `GlobalDispatch` and `Dispatch` can remain an internal detail of the module. +/// +/// In a way you can pretend that everything inside of this submodule is a library / different crate +mod delegated { + use wayland_server::{ + backend::GlobalId, + protocol::wl_output::{self, WlOutput}, + Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, + }; + + pub trait OutputHandler { + fn state(&mut self) -> &mut OutputManagerState; + fn some_callback_one_might_need(&mut self); + } + + pub struct OutputManagerState { + global_id: GlobalId, + } + + impl OutputManagerState { + /// Create a [`WlOutput`] global, and handle it's requests internally + /// It can use [`OutputHandler`] trait to callback to your `D` state. + pub fn create_delegated_global(dh: &DisplayHandle) -> Self + where + D: OutputHandler + 'static, + { + // Let's create a global that dispatches it's bind requests to our + // `OutputManagerState::bind` rather than to `D`, + // that way it can remain an implementation detail + let global_id = dh.create_delegated_global::(4, ()); + Self { global_id } + } + + /// Let's expose global id to the user, so they can remove the global when needed + pub fn global_id(&self) -> GlobalId { + self.global_id.clone() + } + } + + impl GlobalDispatch for OutputManagerState { + /// Called whenever a global created via `create_delegated_global<_, WlOutput, _, OutputManagerState>` + /// gets binded by a client + fn bind( + state: &mut D, + _handle: &DisplayHandle, + _client: &Client, + resource: New, + _global_data: &(), + data_init: &mut DataInit<'_, D>, + ) { + // Let's init the object as delegated as well, that way it will dispatch it's requests to our `OutputManagerState::request` + // rather than to `D` + let _output = data_init.init_delegated::<_, _, Self>(resource, ()); + + // Wa can easily callback the `D` from here if needed, eg. + let _some_state_one_might_need = state.state(); + state.some_callback_one_might_need(); + } + } + + impl Dispatch for OutputManagerState { + /// Called whenever an object created via `init_delegated` + /// receives a client request + fn request( + state: &mut D, + _client: &Client, + _resource: &WlOutput, + request: wl_output::Request, + _data: &(), + _dhandle: &DisplayHandle, + _data_init: &mut DataInit<'_, D>, + ) { + match request { + wl_output::Request::Release => { + // Wa can easily callback the `D` from here if needed, eg. + state.some_callback_one_might_need(); + } + _ => {} + } + } + } +} + +struct App { + output_state: OutputManagerState, +} + +impl OutputHandler for App { + fn state(&mut self) -> &mut OutputManagerState { + &mut self.output_state + } + + fn some_callback_one_might_need(&mut self) {} +} + +fn main() { + let display = Display::::new().unwrap(); + + // Let's ask `OutputManagerState` to implement `WlOutput` for us, only calling us back whenever + // necessary via `OutputHandler` trait + let output_state = OutputManagerState::create_delegated_global::(&display.handle()); + + let app = App { output_state }; + + display.handle().remove_global::(app.output_state.global_id()); +} diff --git a/wayland-server/src/client.rs b/wayland-server/src/client.rs index b7ce805e6ed..f74262e9808 100644 --- a/wayland-server/src/client.rs +++ b/wayland-server/src/client.rs @@ -5,7 +5,10 @@ use wayland_backend::{ server::{ClientData, ClientId, DisconnectReason, InvalidId, ObjectData}, }; -use crate::{dispatch::ResourceData, Dispatch, DisplayHandle, Resource}; +use crate::{ + dispatch::{DelegatedResourceData, ResourceData}, + Dispatch, DisplayHandle, Resource, +}; /// A struct representing a Wayland client connected to your compositor. #[derive(Clone, Debug)] @@ -70,6 +73,35 @@ impl Client { I::from_id(handle, id) } + /// Create a new Wayland object in the protocol state of this client + /// + /// The newly created resource should be immediately sent to the client through an associated event with + /// a `new_id` argument. Not doing so risks corrupting the protocol state and causing protocol errors at + /// a later time. + /// + /// This is a delegating variant of [`Self::create_resource`], which means that all requests + /// related to this object will be dispatched via [`Dispatch`] to `DelegateTo` generic type, + /// rather than `D`. + pub fn create_delegated_resource< + I: Resource + 'static, + U: Send + Sync + 'static, + D: 'static, + DelegateTo: Dispatch + 'static, + >( + &self, + handle: &DisplayHandle, + version: u32, + user_data: U, + ) -> Result { + let id = handle.handle.create_object::( + self.id.clone(), + I::interface(), + version, + Arc::new(DelegatedResourceData::::new(user_data)) as Arc<_>, + )?; + I::from_id(handle, id) + } + /// Create a new Wayland object in the protocol state of this client, from an [`ObjectData`] /// /// This is a lower-level method than [`create_resource()`][Self::create_resource()], in case you need to diff --git a/wayland-server/src/dispatch.rs b/wayland-server/src/dispatch.rs index ea99edc6750..aca9777ec5c 100644 --- a/wayland-server/src/dispatch.rs +++ b/wayland-server/src/dispatch.rs @@ -31,11 +31,10 @@ use crate::{Client, DisplayHandle, Resource}; /// /// 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. +/// automatically delegate their implementation to yours using the [`DataInit::init_delegated()`] or +/// [`Client::create_delegated_resource()`]. /// -/// [`delegate_dispatch!()`]: crate::delegate_dispatch!() -/// -/// As a result, when your implementation is instanciated, the last type parameter `State` will be the state +/// As a result, when your implementation is instantiated, 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: /// @@ -56,8 +55,6 @@ use crate::{Client, DisplayHandle, Resource}; /// // the default State=Self. /// impl Dispatch 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, /// // 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 @@ -168,11 +165,24 @@ impl<'a, D> DataInit<'a, D> { where D: Dispatch + 'static, { - let arc = Arc::new(ResourceData::::new(data)); - *self.store = Some(arc.clone() as Arc<_>); - let mut obj = resource.id; - obj.__set_object_data(arc); - obj + self.custom_init(resource, Arc::new(ResourceData::::new(data))) + } + + /// Initialize an object by assigning it its user-data + /// + /// This is a delegating variant of [`Self::init`], which means that all requests + /// related to this object will be dispatched via [`Dispatch`] to `DelegateTo` generic type, + /// rather than `D`. + pub fn init_delegated( + &mut self, + resource: New, + data: U, + ) -> I + where + D: 'static, + DelegateTo: Dispatch + 'static, + { + self.custom_init(resource, Arc::new(DelegatedResourceData::::new(data))) } /// Set a custom [`ObjectData`] for this object @@ -229,52 +239,76 @@ impl + 'stati client_id: wayland_backend::server::ClientId, msg: wayland_backend::protocol::Message, ) -> Option>> { - let dhandle = DisplayHandle::from(handle.clone()); - let client = match Client::from_id(&dhandle, client_id) { - Ok(v) => v, - Err(_) => { - crate::log_error!("Receiving a request from a dead client ?!"); - return None; - } - }; - - let (sender_id, opcode) = (msg.sender_id.protocol_id(), msg.opcode); - - let (resource, request) = match I::parse_request(&dhandle, msg) { - Ok(v) => v, - Err(e) => { - crate::log_warn!("Dispatching error encountered: {:?}, killing client.", e); - handle.kill_client( - client.id(), - DisconnectReason::ProtocolError(ProtocolError { - code: 1, - object_id: 0, - object_interface: "wl_display".into(), - message: format!( - "Malformed request received for id {} and opcode {}.", - sender_id, opcode - ), - }), - ); - return None; - } - }; - let udata = resource.data::().expect("Wrong user_data value for object"); - - let mut new_data = None; + on_request::(handle, data, client_id, msg, |resource| { + resource.data().expect("Wrong user_data value for object") + }) + } - >::request( + fn destroyed( + self: Arc, + handle: &wayland_backend::server::Handle, + data: &mut D, + client_id: ClientId, + object_id: ObjectId, + ) { + on_destroyed::( + self.clone(), + &self.udata, + handle, data, - &client, - &resource, - request, - udata, - &dhandle, - // The error is None since the creating object posts an error. - &mut DataInit { store: &mut new_data, error: &mut None }, - ); - - new_data + client_id, + object_id, + ) + } +} + +/// The [`ObjectData`] implementation that is internally used by this crate +/// +/// This is a delegating variant of [`ResourceData`], +/// In contrast to [`ResourceData`] you have to specify `DelegatedTo` generic type that this object +/// is delegated to. +/// +/// Object being delegated to `DelegatedTo` means that that type is handling it's requests via +/// [`Dispatch`] +#[derive(Debug)] +pub struct DelegatedResourceData { + /// The user-data associated with this object + pub udata: U, + marker: std::marker::PhantomData<(I, DelegatedTo)>, +} + +impl DelegatedResourceData { + pub(crate) fn new(udata: U) -> Self + where + D: 'static, + I: Resource + 'static, + M: Dispatch + 'static, + U: Send + Sync + 'static, + { + DelegatedResourceData { udata, marker: std::marker::PhantomData::<(I, M)> } + } +} + +unsafe impl Send for DelegatedResourceData {} +unsafe impl Sync for DelegatedResourceData {} + +impl ObjectData for DelegatedResourceData +where + I: Resource + 'static, + U: Send + Sync + 'static, + D: 'static, + DelegatedTo: Dispatch + 'static, +{ + fn request( + self: Arc, + handle: &wayland_backend::server::Handle, + data: &mut D, + client_id: wayland_backend::server::ClientId, + msg: wayland_backend::protocol::Message, + ) -> Option>> { + on_request::(handle, data, client_id, msg, |resource| { + resource.delegated_data::().expect("Wrong user_data value for object") + }) } fn destroyed( @@ -284,15 +318,99 @@ impl + 'stati client_id: ClientId, object_id: ObjectId, ) { - let dhandle = DisplayHandle::from(handle.clone()); - let mut resource = I::from_id(&dhandle, object_id).unwrap(); + on_destroyed::( + self.clone(), + &self.udata, + handle, + data, + client_id, + object_id, + ) + } +} - // Proxy::from_id will return an inert protocol object wrapper inside of ObjectData::destroyed, - // therefore manually initialize the data associated with protocol object wrapper. - resource.__set_object_data(self.clone()); +pub(crate) fn on_request( + handle: &wayland_backend::server::Handle, + data: &mut D, + client_id: wayland_backend::server::ClientId, + msg: wayland_backend::protocol::Message, + get_data: impl FnOnce(&I) -> &U, +) -> Option>> +where + I: Resource, + U: Send + Sync + 'static, + D: 'static, + DelegatedTo: Dispatch, +{ + let dhandle = DisplayHandle::from(handle.clone()); + let client = match Client::from_id(&dhandle, client_id) { + Ok(v) => v, + Err(_) => { + crate::log_error!("Receiving a request from a dead client ?!"); + return None; + } + }; - >::destroyed(data, client_id, &resource, &self.udata) - } + let (sender_id, opcode) = (msg.sender_id.protocol_id(), msg.opcode); + + let (resource, request) = match I::parse_request(&dhandle, msg) { + Ok(v) => v, + Err(e) => { + crate::log_warn!("Dispatching error encountered: {:?}, killing client.", e); + handle.kill_client( + client.id(), + DisconnectReason::ProtocolError(ProtocolError { + code: 1, + object_id: 0, + object_interface: "wl_display".into(), + message: format!( + "Malformed request received for id {} and opcode {}.", + sender_id, opcode + ), + }), + ); + return None; + } + }; + let udata = get_data(&resource); + + let mut new_data = None; + + >::request( + data, + &client, + &resource, + request, + udata, + &dhandle, + // The error is None since the creating object posts an error. + &mut DataInit { store: &mut new_data, error: &mut None }, + ); + + new_data +} + +pub(crate) fn on_destroyed( + this: Arc, + udata: &U, + handle: &wayland_backend::server::Handle, + data: &mut D, + client_id: ClientId, + object_id: ObjectId, +) where + I: Resource, + U: Send + Sync + 'static, + DATA: Send + Sync + 'static, + DelegatedTo: Dispatch, +{ + let dhandle = DisplayHandle::from(handle.clone()); + let mut resource = I::from_id(&dhandle, object_id).unwrap(); + + // Proxy::from_id will return an inert protocol object wrapper inside of ObjectData::destroyed, + // therefore manually initialize the data associated with protocol object wrapper. + resource.__set_object_data(this); + + >::destroyed(data, client_id, &resource, udata) } /// A helper macro which delegates a set of [`Dispatch`] implementations for a resource to some other type which diff --git a/wayland-server/src/display.rs b/wayland-server/src/display.rs index 324f08ff5f8..b18326301df 100644 --- a/wayland-server/src/display.rs +++ b/wayland-server/src/display.rs @@ -134,7 +134,35 @@ impl DisplayHandle { self.handle.create_global::( I::interface(), version, - Arc::new(GlobalData { data, _types: std::marker::PhantomData }), + Arc::new(GlobalData { data, _types: std::marker::PhantomData::<(_, _, State)> }), + ) + } + + /// Create a new protocol global + /// + /// Delegating variant of [`Self::create_global`] + /// + /// This global will be advertized to clients through the `wl_registry` according to the rules + /// defined by [`GlobalDispatch`] implemented on `DelegateTo` type for the given interface. Whenever a client + /// binds this global, the associated [`GlobalDispatch::bind()`] method will be invoked on `DelegateTo` type. + pub fn create_delegated_global( + &self, + version: u32, + data: U, + ) -> GlobalId + where + State: 'static, + I: Resource + 'static, + U: Send + Sync + 'static, + DelegateTo: GlobalDispatch + 'static, + { + self.handle.create_global::( + I::interface(), + version, + Arc::new(GlobalData { + data, + _types: std::marker::PhantomData::<(I, State, DelegateTo)>, + }), ) } diff --git a/wayland-server/src/global.rs b/wayland-server/src/global.rs index 16f520daa51..0e52152195b 100644 --- a/wayland-server/src/global.rs +++ b/wayland-server/src/global.rs @@ -7,20 +7,24 @@ use wayland_backend::server::{ use crate::{Client, DataInit, DisplayHandle, New, Resource}; -pub(crate) struct GlobalData { +pub(crate) struct GlobalData { pub(crate) data: U, - pub(crate) _types: std::marker::PhantomData<(I, D)>, + pub(crate) _types: std::marker::PhantomData<(I, D, DelegatedTo)>, } -unsafe impl Send for GlobalData {} -unsafe impl Sync for GlobalData {} +unsafe impl Send for GlobalData {} +unsafe impl Sync for GlobalData {} -impl + 'static> - GlobalHandler for GlobalData +impl GlobalHandler for GlobalData +where + I: Resource + 'static, + U: Send + Sync + 'static, + D: 'static, + DelegatedTo: GlobalDispatch + 'static, { fn can_view(&self, id: ClientId, data: &Arc, _: GlobalId) -> bool { let client = Client { id, data: data.clone() }; - >::can_view(client, &self.data) + >::can_view(client, &self.data) } fn bind( @@ -39,7 +43,7 @@ impl + let mut new_data = None; let mut protocol_error = None; - >::bind( + >::bind( data, &handle, &client, diff --git a/wayland-server/src/lib.rs b/wayland-server/src/lib.rs index 17545cbccdd..71c7a6901a5 100644 --- a/wayland-server/src/lib.rs +++ b/wayland-server/src/lib.rs @@ -24,10 +24,12 @@ //! `Dispatch` for every Wayland object `O` it needs to process events for. //! //! However, implementing all those traits on your own is a lot of (often uninteresting) work. To make this -//! easier a composition mechanism is provided using the [`delegate_dispatch!()`] macro. This way, another +//! easier a composition mechanism is provided using [`DisplayHandle::create_delegated_global()`]. This way, another //! library (such as Smithay) can provide generic [`Dispatch`] implementations that you can reuse on your -//! own app by delegating those objects to that provided implementation. See the documentation of those -//! traits and macro for details. +//! own app by delegating those objects to that provided implementation. See the documentation of +//! that method for details. +//! There is also [delegated.rs](https://github.com/Smithay/wayland-rs/blob/master/wayland-server/examples/delegated.rs) example +//! which demonstrates how delegating works. //! //! ## Globals //! @@ -92,7 +94,7 @@ mod global; mod socket; pub use client::Client; -pub use dispatch::{DataInit, Dispatch, New, ResourceData}; +pub use dispatch::{DataInit, DelegatedResourceData, Dispatch, New, ResourceData}; pub use display::{Display, DisplayHandle}; pub use global::GlobalDispatch; pub use socket::{BindError, ListeningSocket}; @@ -172,6 +174,15 @@ pub trait Resource: Clone + std::fmt::Debug + Sized { /// Access the user-data associated with this object fn data(&self) -> Option<&U>; + /// Access the user-data associated with this object + /// + /// This is a delegating variant of [`Resource::data`], + /// Used to acces user data assosiated with objects that are delegated to `DelegatedTo` generic type. + /// + /// Object being delegated to `DelegatedTo` means that that type is handling it's requests via + /// [`Dispatch`] + fn delegated_data(&self) -> Option<&U>; + /// Access the raw data associated with this object. /// /// It is given to you as a `dyn Any`, and you are responsible for downcasting it. From 67e040853d471fc961c3ed91a0193b0175b0a9b9 Mon Sep 17 00:00:00 2001 From: PolyMeilex Date: Fri, 16 Feb 2024 20:38:03 +0100 Subject: [PATCH 2/6] Client side delegate --- wayland-client/examples/delegated.rs | 122 ++++++++++++++++++ wayland-client/src/event_queue.rs | 66 +++++++--- wayland-client/src/globals.rs | 59 ++++++++- wayland-client/src/lib.rs | 10 +- wayland-scanner/src/client_gen.rs | 4 +- .../tests/scanner_assets/test-client-code.rs | 12 +- wayland-tests/tests/client_bad_requests.rs | 2 +- 7 files changed, 236 insertions(+), 39 deletions(-) create mode 100644 wayland-client/examples/delegated.rs diff --git a/wayland-client/examples/delegated.rs b/wayland-client/examples/delegated.rs new file mode 100644 index 00000000000..ebcac9b7bd5 --- /dev/null +++ b/wayland-client/examples/delegated.rs @@ -0,0 +1,122 @@ +#![allow(clippy::single_match)] + +use wayland_client::{ + protocol::{ + wl_compositor::{self, WlCompositor}, + wl_display::{self, WlDisplay}, + wl_registry::{self, WlRegistry}, + }, + Connection, Dispatch, Proxy, QueueHandle, +}; + +/// A demonstration of how delegateing can make implementing protocols an implementation detail +/// +/// Users of this module only need to implement `RegistryHandler` trait on their state, +/// Implementation of `Dispatch` can remain an internal detail of the module. +/// +/// In a way you can pretend that everything inside of this submodule is a library / different crate +mod delegated { + use super::*; + + pub trait RegistryHandler: 'static { + fn state(&mut self) -> &mut Registry; + fn new_global(&mut self, name: u32, interface: &str, version: u32); + } + + pub struct Registry { + wl_registry: WlRegistry, + } + + impl Registry { + /// Create a [`WlRegistry`] object, and handle it's events internally + /// It can use [`RegistryHandler`] trait to callback to your `D` state. + pub fn new(qh: &QueueHandle, display: &WlDisplay) -> Self { + // Let's construct a `WlRegistry` object that dispatches it's events to our + // `Registry::event` rather than to `D`, + // that way it can remain an implementation detail + let data = qh.make_data::(()); + let wl_registry = + display.send_constructor(wl_display::Request::GetRegistry {}, data).unwrap(); + + Self { wl_registry } + } + + pub fn wl_registry(&self) -> WlRegistry { + self.wl_registry.clone() + } + } + + impl Dispatch for Registry { + /// Called whenever an object created via `make_data` + /// receives a server event + fn event( + state: &mut D, + _: &wl_registry::WlRegistry, + event: wl_registry::Event, + _: &(), + _: &Connection, + _: &QueueHandle, + ) { + let _state = state.state(); + + if let wl_registry::Event::Global { name, interface, version } = event { + // Let's callback the user of this abstraction, informing them about new global + state.new_global(name, &interface, version); + } + } + } +} + +struct AppData { + registry: delegated::Registry, + qh: QueueHandle, +} + +impl delegated::RegistryHandler for AppData { + fn state(&mut self) -> &mut delegated::Registry { + &mut self.registry + } + + // Even tho we did not implement WlRegistry, `delegated::Registry` implemented it for us, + // and will call this method whenever new globals appear + fn new_global(&mut self, name: u32, interface: &str, version: u32) { + println!("[{}] {} (v{})", name, interface, version); + + match interface { + "wl_compositor" => { + self.registry.wl_registry().bind(name, version, &self.qh, ()); + } + _ => {} + } + } +} + +impl Dispatch for AppData { + fn event( + _state: &mut Self, + _proxy: &WlCompositor, + _event: wl_compositor::Event, + _data: &(), + _conn: &Connection, + _qhandle: &QueueHandle, + ) { + } +} + +fn main() { + let conn = Connection::connect_to_env().unwrap(); + + let display = conn.display(); + + let mut event_queue = conn.new_event_queue::(); + let qh = event_queue.handle(); + + // Let's ask `delegated::Registry` to implement `WlRegistry` for us, only calling us back whenever + // necessary via `RegistryHandler` trait + let registry = delegated::Registry::new(&qh, &display); + + let mut app = AppData { registry, qh: qh.clone() }; + + println!("Advertized globals:"); + event_queue.roundtrip(&mut app).unwrap(); +} diff --git a/wayland-client/src/event_queue.rs b/wayland-client/src/event_queue.rs index ba46db8e195..1cafd357e5a 100644 --- a/wayland-client/src/event_queue.rs +++ b/wayland-client/src/event_queue.rs @@ -39,9 +39,9 @@ use crate::{conn::SyncData, Connection, DispatchError, Proxy}; /// /// 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. +/// automatically delegate their implementation to yours using the `DelegateTo` generic in [`QueueHandle::make_data()`]. /// -/// [`delegate_dispatch!()`]: crate::delegate_dispatch!() +/// See `wayland-client` `delegated.rs` example for more info. /// /// As a result, when your implementation is instantiated, 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 @@ -63,8 +63,6 @@ use crate::{conn::SyncData, Connection, DispatchError, Proxy}; /// // the default State=Self. /// impl Dispatch 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, /// // 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 @@ -96,7 +94,6 @@ pub trait Dispatch where Self: Sized, I: Proxy, - State: Dispatch, { /// Called when an event from the server is processed /// @@ -176,7 +173,7 @@ macro_rules! event_created_child { match opcode { $( $opcode => { - qhandle.make_data::<$child_iface, _>({$child_udata}) + qhandle.make_data::<$child_iface, _, $selftype>({$child_udata}) }, )* _ => { @@ -328,16 +325,17 @@ pub(crate) struct EventQueueInner { } impl EventQueueInner { - pub(crate) fn enqueue_event( + pub(crate) fn enqueue_event( &mut self, msg: Message, odata: Arc, ) where - State: Dispatch + 'static, + State: 'static, + DispatchTo: Dispatch + 'static, U: Send + Sync + 'static, I: Proxy + 'static, { - let func = queue_callback::; + let func = queue_callback::; self.queue.push_back(QueueEvent(func, msg, odata)); if self.freeze_count == 0 { if let Some(waker) = self.waker.take() { @@ -608,14 +606,35 @@ impl QueueHandle { /// This creates an implementation of [`ObjectData`] fitting for direct use with `wayland-backend` APIs /// that forwards all events to the event queue associated with this token, integrating the object into /// the [`Dispatch`]-based logic of `wayland-client`. - pub fn make_data( + /// + /// Events will be dispatched via [`Dispatch`] to a `DelegateTo` generic type. + /// Eg. + /// ```ignore + /// struct OutputDispatcher; + /// + /// impl Dispatch for OutputDispatcher { + /// // if `DelegateTo` of an object is set to `OutputDispatcher` events will be dispatched + /// // to this impl + /// } + /// + /// struct SeatDispatcher; + /// + /// impl Dispatch for SeatDispatcher { + /// // if `DelegateTo` of an object is set to `SeatDispatcher` events will be dispatched here + /// // to this impl + /// } + /// + /// let obj1 = qh.make_data::(()); + /// let obj2 = qh.make_data::(()); + /// ``` + pub fn make_data( &self, user_data: U, ) -> Arc where - State: Dispatch, + DelegateTo: Dispatch + 'static, { - Arc::new(QueueProxyData:: { + Arc::new(QueueProxyData:: { handle: self.clone(), udata: user_data, _phantom: PhantomData, @@ -647,7 +666,8 @@ impl<'a, State> Drop for QueueFreezeGuard<'a, State> { fn queue_callback< I: Proxy + 'static, U: Send + Sync + 'static, - State: Dispatch + 'static, + State, + DelegateTo: Dispatch + 'static, >( handle: &Connection, msg: Message, @@ -657,21 +677,23 @@ fn queue_callback< ) -> Result<(), DispatchError> { let (proxy, event) = I::parse_event(handle, msg)?; let udata = odata.data_as_any().downcast_ref().expect("Wrong user_data value for object"); - >::event(data, &proxy, event, udata, handle, qhandle); + >::event(data, &proxy, event, udata, handle, qhandle); Ok(()) } /// The [`ObjectData`] implementation used by Wayland proxies, integrating with [`Dispatch`] -pub struct QueueProxyData { +pub struct QueueProxyData { handle: QueueHandle, /// The user data associated with this object pub udata: U, - _phantom: PhantomData, + _phantom: PhantomData, } -impl ObjectData for QueueProxyData +impl ObjectData + for QueueProxyData where - State: Dispatch + 'static, + State: 'static, + DispatchTo: Dispatch + 'static, { fn event( self: Arc, @@ -682,9 +704,9 @@ where .args .iter() .any(|arg| matches!(arg, Argument::NewId(id) if !id.is_null())) - .then(|| State::event_created_child(msg.opcode, &self.handle)); + .then(|| DispatchTo::event_created_child(msg.opcode, &self.handle)); - self.handle.inner.lock().unwrap().enqueue_event::(msg, self.clone()); + self.handle.inner.lock().unwrap().enqueue_event::(msg, self.clone()); new_data } @@ -696,7 +718,9 @@ where } } -impl std::fmt::Debug for QueueProxyData { +impl std::fmt::Debug + for QueueProxyData +{ #[cfg_attr(coverage, coverage(off))] fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("QueueProxyData").field("udata", &self.udata).finish() diff --git a/wayland-client/src/globals.rs b/wayland-client/src/globals.rs index d422b6962b6..308d07942d2 100644 --- a/wayland-client/src/globals.rs +++ b/wayland-client/src/globals.rs @@ -54,6 +54,7 @@ use std::{ fmt, + marker::PhantomData, ops::RangeInclusive, os::unix::io::OwnedFd, sync::{ @@ -80,13 +81,30 @@ pub fn registry_queue_init( ) -> Result<(GlobalList, EventQueue), GlobalError> where State: Dispatch + 'static, +{ + registry_queue_init_delegated::(conn) +} + +/// Initialize a new event queue with its associated registry and retrieve the initial list of globals +/// +/// This is a delegating variant of [`registry_queue_init`], it dispatches events to `DelegateTo` +/// generic rather than to `State`. +/// +/// See [the module level documentation][self] for more. +pub fn registry_queue_init_delegated( + conn: &Connection, +) -> Result<(GlobalList, EventQueue), GlobalError> +where + State: 'static, + DelegateTo: Dispatch + 'static, { let event_queue = conn.new_event_queue(); let display = conn.display(); - let data = Arc::new(RegistryState { + let data = Arc::new(RegistryState:: { globals: GlobalListContents { contents: Default::default() }, handle: event_queue.handle(), initial_roundtrip_done: AtomicBool::new(false), + _ph: PhantomData, }); let registry = display.send_constructor(wl_display::Request::GetRegistry {}, data.clone())?; // We don't need to dispatch the event queue as for now nothing will be sent to it @@ -139,6 +157,25 @@ impl GlobalList { I: Proxy + 'static, State: Dispatch + 'static, U: Send + Sync + 'static, + { + self.bind_delegated::(qh, version, udata) + } + + /// Binds a global, returning a new protocol object associated with the global. + /// + /// This is a delegating variant of [`Self::bind`], it dispatches events to `DelegateTo` + /// generic rather than to `State`. Read full docs at [`Self::bind`]. + pub fn bind_delegated( + &self, + qh: &QueueHandle, + version: RangeInclusive, + udata: U, + ) -> Result + where + I: Proxy + 'static, + State: 'static, + U: Send + Sync + 'static, + DelegateTo: Dispatch + 'static, { let version_start = *version.start(); let version_end = *version.end(); @@ -175,7 +212,13 @@ impl GlobalList { // requested version. let version = version.min(version_end); - Ok(self.registry.bind(name, version, qh, udata)) + Ok(self + .registry + .send_constructor( + wl_registry::Request::Bind { name, id: (I::interface(), version) }, + qh.make_data::(udata), + ) + .unwrap()) } /// Returns the [`WlRegistry`][wl_registry] protocol object. @@ -293,15 +336,16 @@ impl GlobalListContents { } } -struct RegistryState { +struct RegistryState { globals: GlobalListContents, handle: QueueHandle, initial_roundtrip_done: AtomicBool, + _ph: PhantomData DelegateTo>, } -impl ObjectData for RegistryState +impl ObjectData for RegistryState where - State: Dispatch, + DelegateTo: Dispatch, { fn event( self: Arc, @@ -344,7 +388,10 @@ where .inner .lock() .unwrap() - .enqueue_event::(msg, self.clone()) + .enqueue_event::( + msg, + self.clone(), + ) } // We do not create any objects in this event handler. diff --git a/wayland-client/src/lib.rs b/wayland-client/src/lib.rs index 9500c953ff6..3b9f79c1fb8 100644 --- a/wayland-client/src/lib.rs +++ b/wayland-client/src/lib.rs @@ -41,10 +41,14 @@ //! managing the newly created object. //! //! However, implementing all those traits on your own is a lot of (often uninteresting) work. To make this -//! easier a composition mechanism is provided using the [`delegate_dispatch!`] macro. This way, another -//! library (such as Smithay's Client Toolkit) can provide generic [`Dispatch`] implementations that you +//! easier a composition mechanism is provided. Using the [`QueueHandle::make_data()`] method +//! one is able to create object handlers manually, making it possible to specify `DispatchTo` type different +//! from your `State`. +//! Libraries (such as Smithay's Client Toolkit) can use that mechanism to provide generic [`Dispatch`] implementations that you //! can reuse in your own app by delegating those objects to that provided implementation. See the -//! documentation of those traits and macro for details. +//! documentation of [`QueueHandle::make_data()`] for details. +//! There is also [delegated.rs](https://github.com/Smithay/wayland-rs/blob/master/wayland-client/examples/delegated.rs) example +//! which demonstrates how delegating works. //! //! ## Getting started example //! diff --git a/wayland-scanner/src/client_gen.rs b/wayland-scanner/src/client_gen.rs index b116f55879b..5bc9ce23590 100644 --- a/wayland-scanner/src/client_gen.rs +++ b/wayland-scanner/src/client_gen.rs @@ -269,7 +269,7 @@ fn gen_methods(interface: &Interface) -> TokenStream { Request::#enum_variant { #(#enum_args),* }, - qh.make_data::(udata), + qh.make_data::(udata), ).unwrap_or_else(|_| Proxy::inert(self.backend.clone())) } } @@ -284,7 +284,7 @@ fn gen_methods(interface: &Interface) -> TokenStream { Request::#enum_variant { #(#enum_args),* }, - qh.make_data::(udata), + qh.make_data::(udata), ).unwrap_or_else(|_| Proxy::inert(self.backend.clone())) } } diff --git a/wayland-scanner/tests/scanner_assets/test-client-code.rs b/wayland-scanner/tests/scanner_assets/test-client-code.rs index 6028b8baffd..1f6bd5245a2 100644 --- a/wayland-scanner/tests/scanner_assets/test-client-code.rs +++ b/wayland-scanner/tests/scanner_assets/test-client-code.rs @@ -290,7 +290,7 @@ pub mod wl_display { ) -> super::wl_callback::WlCallback { self.send_constructor( Request::Sync {}, - qh.make_data::(udata), + qh.make_data::(udata), ) .unwrap_or_else(|_| Proxy::inert(self.backend.clone())) } @@ -306,7 +306,7 @@ pub mod wl_display { ) -> super::wl_registry::WlRegistry { self.send_constructor( Request::GetRegistry {}, - qh.make_data::(udata), + qh.make_data::(udata), ) .unwrap_or_else(|_| Proxy::inert(self.backend.clone())) } @@ -560,7 +560,7 @@ pub mod wl_registry { ) -> I { self.send_constructor( Request::Bind { name, id: (I::interface(), version) }, - qh.make_data::(udata), + qh.make_data::(udata), ) .unwrap_or_else(|_| Proxy::inert(self.backend.clone())) } @@ -1236,7 +1236,7 @@ pub mod test_global { ) -> super::secondary::Secondary { self.send_constructor( Request::GetSecondary {}, - qh.make_data::(udata), + qh.make_data::(udata), ) .unwrap_or_else(|_| Proxy::inert(self.backend.clone())) } @@ -1251,7 +1251,7 @@ pub mod test_global { ) -> super::tertiary::Tertiary { self.send_constructor( Request::GetTertiary {}, - qh.make_data::(udata), + qh.make_data::(udata), ) .unwrap_or_else(|_| Proxy::inert(self.backend.clone())) } @@ -1315,7 +1315,7 @@ pub mod test_global { ) -> super::quad::Quad { self.send_constructor( Request::NewidAndAllowNull { sec: sec.cloned(), ter: ter.clone() }, - qh.make_data::(udata), + qh.make_data::(udata), ) .unwrap_or_else(|_| Proxy::inert(self.backend.clone())) } diff --git a/wayland-tests/tests/client_bad_requests.rs b/wayland-tests/tests/client_bad_requests.rs index 8b054525b2b..e16f4bbb77b 100644 --- a/wayland-tests/tests/client_bad_requests.rs +++ b/wayland-tests/tests/client_bad_requests.rs @@ -68,7 +68,7 @@ fn send_constructor_wrong_type() { client .event_queue .handle() - .make_data::(()), + .make_data::(()), ), ) .unwrap(); From 79e68dad840f428108a8aea9ef85ab8266650d48 Mon Sep 17 00:00:00 2001 From: PolyMeilex Date: Sun, 3 Mar 2024 02:32:19 +0100 Subject: [PATCH 3/6] Update CHANGELOG --- wayland-client/CHANGELOG.md | 9 +++++++++ wayland-scanner/CHANGELOG.md | 6 ++++++ wayland-server/CHANGELOG.md | 9 +++++++++ 3 files changed, 24 insertions(+) diff --git a/wayland-client/CHANGELOG.md b/wayland-client/CHANGELOG.md index 5e2e399b3b4..2e0fd346fa7 100644 --- a/wayland-client/CHANGELOG.md +++ b/wayland-client/CHANGELOG.md @@ -2,6 +2,15 @@ ## Unreleased +#### Breaking changes + +- `QueueHandle::make_data` now accepts additional `DelegateTo` generic, + therefore allowing users to dispatch events to types different than main `State` + +#### Additions + +- `globals::registry_queue_init_delegated` and `GlobalList::bind_delegated` + ## 0.31.7 -- 2024-10-23 - Updated Wayland core protocol to 1.23 diff --git a/wayland-scanner/CHANGELOG.md b/wayland-scanner/CHANGELOG.md index fb1950ea3b4..77153b20bd8 100644 --- a/wayland-scanner/CHANGELOG.md +++ b/wayland-scanner/CHANGELOG.md @@ -4,6 +4,12 @@ - Update `quick-xml` to 0.37 +#### Breaking changes + +- Aligned with braking changes in wayland-client and wayland-server + - Generate `Resource::delegated_data()` + - Generate additional generic for `QueueHandle::make_data()` + ## 0.31.5 -- 2024-09-04 - Update `quick-xml` to 0.36 diff --git a/wayland-server/CHANGELOG.md b/wayland-server/CHANGELOG.md index 32870e5e676..13fe4ccfef9 100644 --- a/wayland-server/CHANGELOG.md +++ b/wayland-server/CHANGELOG.md @@ -2,6 +2,15 @@ ## Unreleased +#### Breaking changes +- Added `Resource::delegated_data<_, DelegatedTo>` for accessing user data of delegated objects + +#### Additions +- Added a way to create delegated objects, globals and resources (a way to dispatch events to types different than the main `State`) + - `Client::create_delegated_resource<_, _, _, DelegateTo>()` + - `DataInit::init_delegated<_, _, DelegateTo>()` + - `DisplayHandle::create_delegated_global<_, _, _, DelegateTo>()` + ## 0.31.6 -- 2024-10-23 - Updated Wayland core protocol to 1.23 From 6473d063a23d650d74c83dfee94eac60b99d2afd Mon Sep 17 00:00:00 2001 From: PolyMeilex Date: Thu, 7 Mar 2024 22:04:45 +0100 Subject: [PATCH 4/6] Remove delegate macros --- wayland-client/CHANGELOG.md | 1 + wayland-client/src/event_queue.rs | 95 ----------- wayland-server/CHANGELOG.md | 1 + wayland-server/src/dispatch.rs | 77 --------- wayland-server/src/global.rs | 147 ------------------ wayland-tests/tests/attach_to_surface.rs | 30 ++-- wayland-tests/tests/client_bad_requests.rs | 33 ++-- wayland-tests/tests/client_connect_to_env.rs | 12 +- .../tests/client_connect_to_socket.rs | 16 +- wayland-tests/tests/client_proxies.rs | 46 ++---- wayland-tests/tests/destructors.rs | 44 ++---- wayland-tests/tests/globals.rs | 75 +++++---- wayland-tests/tests/helpers/globals.rs | 36 +++-- wayland-tests/tests/protocol_errors.rs | 16 +- wayland-tests/tests/server_clients.rs | 23 +-- wayland-tests/tests/server_created_object.rs | 57 +++---- wayland-tests/tests/server_global_filter.rs | 29 ++-- .../tests/server_global_post_error.rs | 22 +-- wayland-tests/tests/server_resources.rs | 78 ++-------- wayland-tests/tests/xdg_shell_ping.rs | 22 +-- 20 files changed, 183 insertions(+), 677 deletions(-) diff --git a/wayland-client/CHANGELOG.md b/wayland-client/CHANGELOG.md index 2e0fd346fa7..0a1fcaafdef 100644 --- a/wayland-client/CHANGELOG.md +++ b/wayland-client/CHANGELOG.md @@ -6,6 +6,7 @@ - `QueueHandle::make_data` now accepts additional `DelegateTo` generic, therefore allowing users to dispatch events to types different than main `State` +- `delegate_dispatch` Removed in favour of `DelegateTo` generic on `QueueHandle::make_data` #### Additions diff --git a/wayland-client/src/event_queue.rs b/wayland-client/src/event_queue.rs index 1cafd357e5a..ec398118d1e 100644 --- a/wayland-client/src/event_queue.rs +++ b/wayland-client/src/event_queue.rs @@ -727,101 +727,6 @@ impl std::fmt::Debug } } -/* - * Dispatch delegation helpers - */ - -/// A helper macro which delegates a set of [`Dispatch`] implementations for proxies to some other type which -/// provides a generic [`Dispatch`] implementation. -/// -/// This macro allows more easily delegating smaller parts of the protocol an application may wish to handle -/// in a modular fashion. -/// -/// # Usage -/// -/// For example, say you want to delegate events for [`WlRegistry`][crate::protocol::wl_registry::WlRegistry] -/// to the struct `DelegateToMe` for the [`Dispatch`] documentatione example. -/// -/// ``` -/// use wayland_client::{delegate_dispatch, protocol::wl_registry}; -/// # -/// # use wayland_client::Dispatch; -/// # -/// # struct DelegateToMe; -/// # struct MyUserData; -/// # -/// # impl Dispatch for DelegateToMe -/// # where -/// # State: Dispatch + AsMut, -/// # { -/// # fn event( -/// # _state: &mut State, -/// # _proxy: &wl_registry::WlRegistry, -/// # _event: wl_registry::Event, -/// # _udata: &MyUserData, -/// # _conn: &wayland_client::Connection, -/// # _qhandle: &wayland_client::QueueHandle, -/// # ) { -/// # } -/// # } -/// -/// // ExampleApp is the type events will be dispatched to. -/// -/// /// The application state -/// struct ExampleApp { -/// /// The delegate for handling wl_registry events. -/// delegate: DelegateToMe, -/// } -/// -/// // Use delegate_dispatch to implement Dispatch for ExampleApp -/// delegate_dispatch!(ExampleApp: [wl_registry::WlRegistry: MyUserData] => DelegateToMe); -/// -/// // DelegateToMe requires that ExampleApp implements AsMut, so we provide the -/// // trait implementation. -/// impl AsMut for ExampleApp { -/// fn as_mut(&mut self) -> &mut DelegateToMe { -/// &mut self.delegate -/// } -/// } -/// -/// // To explain the macro above, you may read it as the following: -/// // -/// // For ExampleApp, delegate WlRegistry to DelegateToMe. -/// -/// // Assert ExampleApp can Dispatch events for wl_registry -/// fn assert_is_registry_delegate() -/// where -/// T: Dispatch, -/// { -/// } -/// -/// assert_is_registry_delegate::(); -/// ``` -#[macro_export] -macro_rules! delegate_dispatch { - ($(@< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? $dispatch_from:ty : [$interface: ty: $udata: ty] => $dispatch_to: ty) => { - impl$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $crate::Dispatch<$interface, $udata> for $dispatch_from { - fn event( - state: &mut Self, - proxy: &$interface, - event: <$interface as $crate::Proxy>::Event, - data: &$udata, - conn: &$crate::Connection, - qhandle: &$crate::QueueHandle, - ) { - <$dispatch_to as $crate::Dispatch<$interface, $udata, Self>>::event(state, proxy, event, data, conn, qhandle) - } - - fn event_created_child( - opcode: u16, - qhandle: &$crate::QueueHandle - ) -> ::std::sync::Arc { - <$dispatch_to as $crate::Dispatch<$interface, $udata, Self>>::event_created_child(opcode, qhandle) - } - } - }; -} - /// A helper macro which delegates a set of [`Dispatch`] implementations for proxies to a static handler. /// /// # Usage diff --git a/wayland-server/CHANGELOG.md b/wayland-server/CHANGELOG.md index 13fe4ccfef9..6687158ac03 100644 --- a/wayland-server/CHANGELOG.md +++ b/wayland-server/CHANGELOG.md @@ -4,6 +4,7 @@ #### Breaking changes - Added `Resource::delegated_data<_, DelegatedTo>` for accessing user data of delegated objects +- `delegate_dispatch` and `delegate_global_dispatch` Removed in favour of `DataInit::init_delegated` and `DisplayHandle::create_delegated_global` #### Additions - Added a way to create delegated objects, globals and resources (a way to dispatch events to types different than the main `State`) diff --git a/wayland-server/src/dispatch.rs b/wayland-server/src/dispatch.rs index aca9777ec5c..fb0fc517c90 100644 --- a/wayland-server/src/dispatch.rs +++ b/wayland-server/src/dispatch.rs @@ -412,80 +412,3 @@ pub(crate) fn on_destroyed( >::destroyed(data, client_id, &resource, udata) } - -/// A helper macro which delegates a set of [`Dispatch`] implementations for a resource to some other type which -/// provides a generic [`Dispatch`] implementation. -/// -/// This macro allows more easily delegating smaller parts of the protocol a compositor may wish to handle -/// in a modular fashion. -/// -/// # Usage -/// -/// For example, say you want to delegate events for [`WlOutput`][crate::protocol::wl_output::WlOutput] -/// to the `DelegateToMe` type from the [`Dispatch`] documentation. -/// -/// ``` -/// use wayland_server::{delegate_dispatch, protocol::wl_output}; -/// # -/// # use wayland_server::Dispatch; -/// # -/// # struct DelegateToMe; -/// # -/// # impl Dispatch for DelegateToMe -/// # where -/// # D: Dispatch + AsMut, -/// # { -/// # fn request( -/// # _state: &mut D, -/// # _client: &wayland_server::Client, -/// # _resource: &wl_output::WlOutput, -/// # _request: wl_output::Request, -/// # _data: &(), -/// # _dhandle: &wayland_server::DisplayHandle, -/// # _data_init: &mut wayland_server::DataInit<'_, D>, -/// # ) { -/// # } -/// # } -/// # -/// # type MyUserData = (); -/// -/// // ExampleApp is the type events will be dispatched to. -/// -/// /// The application state -/// struct ExampleApp { -/// /// The delegate for handling wl_registry events. -/// delegate: DelegateToMe, -/// } -/// -/// // Use delegate_dispatch to implement Dispatch for ExampleApp. -/// delegate_dispatch!(ExampleApp: [wl_output::WlOutput: MyUserData] => DelegateToMe); -/// -/// // DelegateToMe requires that ExampleApp implements AsMut, so we provide the trait implementation. -/// impl AsMut for ExampleApp { -/// fn as_mut(&mut self) -> &mut DelegateToMe { -/// &mut self.delegate -/// } -/// } -/// ``` -#[macro_export] -macro_rules! delegate_dispatch { - ($(@< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? $dispatch_from:ty : [$interface: ty: $udata: ty] => $dispatch_to: ty) => { - impl$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $crate::Dispatch<$interface, $udata> for $dispatch_from { - fn request( - state: &mut Self, - client: &$crate::Client, - resource: &$interface, - request: <$interface as $crate::Resource>::Request, - data: &$udata, - dhandle: &$crate::DisplayHandle, - data_init: &mut $crate::DataInit<'_, Self>, - ) { - <$dispatch_to as $crate::Dispatch<$interface, $udata, Self>>::request(state, client, resource, request, data, dhandle, data_init) - } - - fn destroyed(state: &mut Self, client: $crate::backend::ClientId, resource: &$interface, data: &$udata) { - <$dispatch_to as $crate::Dispatch<$interface, $udata, Self>>::destroyed(state, client, resource, data) - } - } - }; -} diff --git a/wayland-server/src/global.rs b/wayland-server/src/global.rs index 0e52152195b..2f9d3670590 100644 --- a/wayland-server/src/global.rs +++ b/wayland-server/src/global.rs @@ -124,150 +124,3 @@ pub trait GlobalDispatch: Sized { true } } - -/* - * Dispatch delegation helpers - */ - -/// A helper macro which delegates a set of [`GlobalDispatch`] implementations for a resource to some other type which -/// provdes a generic [`GlobalDispatch`] implementation. -/// -/// Its usage is similar to the [`delegate_dispatch!()`] macro. -/// -/// [`delegate_dispatch!()`]: crate::delegate_dispatch!() -#[macro_export] -macro_rules! delegate_global_dispatch { - ($(@< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? $dispatch_from:ty : [$interface: ty: $udata: ty] => $dispatch_to: ty) => { - impl$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $crate::GlobalDispatch<$interface, $udata> for $dispatch_from { - fn bind( - state: &mut Self, - dhandle: &$crate::DisplayHandle, - client: &$crate::Client, - resource: $crate::New<$interface>, - global_data: &$udata, - data_init: &mut $crate::DataInit<'_, Self>, - ) { - <$dispatch_to as $crate::GlobalDispatch<$interface, $udata, Self>>::bind(state, dhandle, client, resource, global_data, data_init) - } - - fn can_view(client: $crate::Client, global_data: &$udata) -> bool { - <$dispatch_to as $crate::GlobalDispatch<$interface, $udata, Self>>::can_view(client, global_data) - } - } - }; -} - -#[cfg(test)] -mod tests { - #[test] - fn smoke_test_dispatch_global_dispatch() { - use crate::{ - delegate_dispatch, protocol::wl_output, Client, DataInit, Dispatch, DisplayHandle, - GlobalDispatch, New, - }; - - struct DelegateToMe; - - impl Dispatch for DelegateToMe - where - D: Dispatch + AsMut, - { - fn request( - _state: &mut D, - _client: &Client, - _resource: &wl_output::WlOutput, - _request: wl_output::Request, - _data: &(), - _dhandle: &DisplayHandle, - _data_init: &mut DataInit<'_, D>, - ) { - } - } - impl GlobalDispatch for DelegateToMe - where - D: GlobalDispatch, - D: Dispatch, - D: AsMut, - { - fn bind( - _state: &mut D, - _handle: &DisplayHandle, - _client: &Client, - _resource: New, - _global_data: &(), - _data_init: &mut DataInit<'_, D>, - ) { - } - } - - struct ExampleApp { - delegate: DelegateToMe, - } - - delegate_dispatch!(ExampleApp: [wl_output::WlOutput: ()] => DelegateToMe); - delegate_global_dispatch!(ExampleApp: [wl_output::WlOutput: ()] => DelegateToMe); - - impl AsMut for ExampleApp { - fn as_mut(&mut self) -> &mut DelegateToMe { - &mut self.delegate - } - } - } - - #[test] - fn smoke_test_dispatch_global_dispatch_generics() { - use crate::{ - delegate_dispatch, protocol::wl_output, Client, DataInit, Dispatch, DisplayHandle, - GlobalDispatch, New, - }; - - struct DelegateToMe(A); - - impl Dispatch for DelegateToMe - where - A: 'static, - D: Dispatch + AsMut>, - { - fn request( - _state: &mut D, - _client: &Client, - _resource: &wl_output::WlOutput, - _request: wl_output::Request, - _data: &(), - _dhandle: &DisplayHandle, - _data_init: &mut DataInit<'_, D>, - ) { - } - } - impl GlobalDispatch for DelegateToMe - where - A: 'static, - D: GlobalDispatch, - D: Dispatch, - D: AsMut>, - { - fn bind( - _state: &mut D, - _handle: &DisplayHandle, - _client: &Client, - _resource: New, - _global_data: &(), - _data_init: &mut DataInit<'_, D>, - ) { - } - } - - struct ExampleApp { - delegate: DelegateToMe, - } - - delegate_dispatch!(@ ExampleApp: [wl_output::WlOutput: ()] => DelegateToMe); - delegate_global_dispatch!(@ ExampleApp: [wl_output::WlOutput: ()] => DelegateToMe); - - impl AsMut> for ExampleApp { - fn as_mut(&mut self) -> &mut DelegateToMe { - &mut self.delegate - } - } - } -} diff --git a/wayland-tests/tests/attach_to_surface.rs b/wayland-tests/tests/attach_to_surface.rs index 664f5c52c5c..5ab9e2deaf3 100644 --- a/wayland-tests/tests/attach_to_surface.rs +++ b/wayland-tests/tests/attach_to_surface.rs @@ -7,7 +7,7 @@ use std::os::unix::io::{AsFd, OwnedFd}; #[macro_use] mod helpers; -use helpers::{globals, roundtrip, wayc, ways, TestServer}; +use helpers::{globals, roundtrip, wayc, ways, TestClient, TestServer}; use wayc::protocol::wl_shm::Format; @@ -27,9 +27,7 @@ fn attach_null() { // Client setup // let (_, mut client) = server.add_client(); - let mut client_ddata = ClientHandler { globals: globals::GlobalList::new() }; - - let registry = client.display.get_registry(&client.event_queue.handle(), ()); + let mut client_ddata = ClientHandler::new(&client); // Initial sync roundtrip(&mut client, &mut server, &mut client_ddata, &mut server_ddata).unwrap(); @@ -38,7 +36,6 @@ fn attach_null() { .globals .bind::( &client.event_queue.handle(), - ®istry, 1..2, (), ) @@ -66,21 +63,14 @@ fn attach_buffer() { // Client setup // let (_, mut client) = server.add_client(); - let mut client_ddata = ClientHandler { globals: globals::GlobalList::new() }; - - let registry = client.display.get_registry(&client.event_queue.handle(), ()); + let mut client_ddata = ClientHandler::new(&client); // Initial sync roundtrip(&mut client, &mut server, &mut client_ddata, &mut server_ddata).unwrap(); let shm = client_ddata .globals - .bind::( - &client.event_queue.handle(), - ®istry, - 1..2, - (), - ) + .bind::(&client.event_queue.handle(), 1..2, ()) .unwrap(); let mut file = tempfile::tempfile().unwrap(); @@ -93,7 +83,6 @@ fn attach_buffer() { .globals .bind::( &client.event_queue.handle(), - ®istry, 1..2, (), ) @@ -218,16 +207,19 @@ struct ClientHandler { globals: globals::GlobalList, } +impl ClientHandler { + fn new(client: &TestClient) -> ClientHandler { + let globals = globals::GlobalList::new(&client.display, &client.event_queue.handle()); + ClientHandler { globals } + } +} + impl AsMut for ClientHandler { fn as_mut(&mut self) -> &mut globals::GlobalList { &mut self.globals } } -wayc::delegate_dispatch!(ClientHandler: - [wayc::protocol::wl_registry::WlRegistry: ()] => globals::GlobalList -); - client_ignore_impl!(ClientHandler => [ wayc::protocol::wl_compositor::WlCompositor, wayc::protocol::wl_surface::WlSurface, diff --git a/wayland-tests/tests/client_bad_requests.rs b/wayland-tests/tests/client_bad_requests.rs index e16f4bbb77b..ec94b0f4980 100644 --- a/wayland-tests/tests/client_bad_requests.rs +++ b/wayland-tests/tests/client_bad_requests.rs @@ -13,20 +13,13 @@ fn constructor_dead() { .create_global::(1, ()); let (_, mut client) = server.add_client(); - let mut client_ddata = ClientHandler { globals: globals::GlobalList::new() }; - - let registry = client.display.get_registry(&client.event_queue.handle(), ()); + let mut client_ddata = ClientHandler::new(&client); roundtrip(&mut client, &mut server, &mut client_ddata, &mut ServerHandler).unwrap(); let seat = client_ddata .globals - .bind::( - &client.event_queue.handle(), - ®istry, - 1..2, - (), - ) + .bind::(&client.event_queue.handle(), 1..2, ()) .unwrap(); seat.release(); @@ -43,20 +36,13 @@ fn send_constructor_wrong_type() { .create_global::(1, ()); let (_, mut client) = server.add_client(); - let mut client_ddata = ClientHandler { globals: globals::GlobalList::new() }; - - let registry = client.display.get_registry(&client.event_queue.handle(), ()); + let mut client_ddata = ClientHandler::new(&client); roundtrip(&mut client, &mut server, &mut client_ddata, &mut ServerHandler).unwrap(); let seat = client_ddata .globals - .bind::( - &client.event_queue.handle(), - ®istry, - 1..2, - (), - ) + .bind::(&client.event_queue.handle(), 1..2, ()) .unwrap(); let id = client @@ -85,16 +71,19 @@ struct ClientHandler { globals: globals::GlobalList, } +impl ClientHandler { + fn new(client: &TestClient) -> ClientHandler { + let globals = globals::GlobalList::new(&client.display, &client.event_queue.handle()); + ClientHandler { globals } + } +} + impl AsMut for ClientHandler { fn as_mut(&mut self) -> &mut globals::GlobalList { &mut self.globals } } -wayc::delegate_dispatch!(ClientHandler: - [wayc::protocol::wl_registry::WlRegistry: ()] => globals::GlobalList -); - client_ignore_impl!(ClientHandler => [ wayc::protocol::wl_seat::WlSeat, wayc::protocol::wl_pointer::WlPointer, diff --git a/wayland-tests/tests/client_connect_to_env.rs b/wayland-tests/tests/client_connect_to_env.rs index c2c8dff4fc3..55f3c01495a 100644 --- a/wayland-tests/tests/client_connect_to_env.rs +++ b/wayland-tests/tests/client_connect_to_env.rs @@ -22,8 +22,7 @@ fn main() { // connect the client let mut client = TestClient::new_from_env(); - let mut client_data = ClientHandler::new(); - client.display.get_registry(&client.event_queue.handle(), ()); + let mut client_data = ClientHandler::new(&client); // setup server-side let client_stream = listening.accept().unwrap().unwrap(); @@ -52,8 +51,9 @@ struct ClientHandler { } impl ClientHandler { - fn new() -> ClientHandler { - ClientHandler { globals: Default::default() } + fn new(client: &TestClient) -> ClientHandler { + let globals = globals::GlobalList::new(&client.display, &client.event_queue.handle()); + ClientHandler { globals } } } @@ -62,7 +62,3 @@ impl AsMut for ClientHandler { &mut self.globals } } - -wayc::delegate_dispatch!(ClientHandler: - [wayc::protocol::wl_registry::WlRegistry: ()] => globals::GlobalList -); diff --git a/wayland-tests/tests/client_connect_to_socket.rs b/wayland-tests/tests/client_connect_to_socket.rs index 6b298b664cd..caf4a142aeb 100644 --- a/wayland-tests/tests/client_connect_to_socket.rs +++ b/wayland-tests/tests/client_connect_to_socket.rs @@ -1,7 +1,7 @@ #[macro_use] mod helpers; -use helpers::{globals, roundtrip, wayc, ways, DumbClientData, TestClient, TestServer}; +use helpers::{globals, roundtrip, ways, DumbClientData, TestClient, TestServer}; use ways::protocol::wl_output::WlOutput as ServerOutput; @@ -20,10 +20,7 @@ fn main() { ::std::env::set_var("WAYLAND_SOCKET", format!("{}", fd2)); let mut client = TestClient::new_from_env(); - - let mut client_data = ClientHandler::new(); - - client.display.get_registry(&client.event_queue.handle(), ()); + let mut client_data = ClientHandler::new(&client); roundtrip(&mut client, &mut server, &mut client_data, &mut ServerData).unwrap(); // check that we connected to the right compositor @@ -56,8 +53,9 @@ struct ClientHandler { } impl ClientHandler { - fn new() -> ClientHandler { - ClientHandler { globals: Default::default() } + fn new(client: &TestClient) -> ClientHandler { + let globals = globals::GlobalList::new(&client.display, &client.event_queue.handle()); + ClientHandler { globals } } } @@ -66,7 +64,3 @@ impl AsMut for ClientHandler { &mut self.globals } } - -wayc::delegate_dispatch!(ClientHandler: - [wayc::protocol::wl_registry::WlRegistry: ()] => globals::GlobalList -); diff --git a/wayland-tests/tests/client_proxies.rs b/wayland-tests/tests/client_proxies.rs index 24ad421aa07..34bee64fda1 100644 --- a/wayland-tests/tests/client_proxies.rs +++ b/wayland-tests/tests/client_proxies.rs @@ -1,7 +1,7 @@ #[macro_use] mod helpers; -use helpers::{globals, roundtrip, wayc, ways, TestServer}; +use helpers::{globals, roundtrip, wayc, ways, TestClient, TestServer}; use ways::Resource; @@ -17,9 +17,7 @@ fn proxy_equals() { let mut server_ddata = ServerHandler { output: None }; let (_, mut client) = server.add_client(); - let mut client_ddata = ClientHandler::new(); - - let registry = client.display.get_registry(&client.event_queue.handle(), ()); + let mut client_ddata = ClientHandler::new(&client); roundtrip(&mut client, &mut server, &mut client_ddata, &mut server_ddata).unwrap(); @@ -27,7 +25,6 @@ fn proxy_equals() { .globals .bind::( &client.event_queue.handle(), - ®istry, 1..2, 0, ) @@ -37,7 +34,6 @@ fn proxy_equals() { .globals .bind::( &client.event_queue.handle(), - ®istry, 1..2, 0, ) @@ -61,9 +57,7 @@ fn proxy_user_data() { let mut server_ddata = ServerHandler { output: None }; let (_, mut client) = server.add_client(); - let mut client_ddata = ClientHandler::new(); - - let registry = client.display.get_registry(&client.event_queue.handle(), ()); + let mut client_ddata = ClientHandler::new(&client); roundtrip(&mut client, &mut server, &mut client_ddata, &mut server_ddata).unwrap(); @@ -71,7 +65,6 @@ fn proxy_user_data() { .globals .bind::( &client.event_queue.handle(), - ®istry, 1..2, 0xDEADBEEFusize, ) @@ -81,7 +74,6 @@ fn proxy_user_data() { .globals .bind::( &client.event_queue.handle(), - ®istry, 1..2, 0xBADC0FFEusize, ) @@ -106,20 +98,13 @@ fn dead_proxies() { let mut server_ddata = ServerHandler { output: None }; let (_, mut client) = server.add_client(); - let mut client_ddata = ClientHandler::new(); - - let registry = client.display.get_registry(&client.event_queue.handle(), ()); + let mut client_ddata = ClientHandler::new(&client); roundtrip(&mut client, &mut server, &mut client_ddata, &mut server_ddata).unwrap(); let output = client_ddata .globals - .bind::( - &client.event_queue.handle(), - ®istry, - 3..4, - (), - ) + .bind::(&client.event_queue.handle(), 3..4, ()) .unwrap(); roundtrip(&mut client, &mut server, &mut client_ddata, &mut server_ddata).unwrap(); @@ -154,26 +139,18 @@ fn dead_object_argument() { let mut server_ddata = ServerHandler { output: None }; let (_, mut client) = server.add_client(); - let mut client_ddata = ClientHandler::new(); - - let registry = client.display.get_registry(&client.event_queue.handle(), ()); + let mut client_ddata = ClientHandler::new(&client); roundtrip(&mut client, &mut server, &mut client_ddata, &mut server_ddata).unwrap(); let output = client_ddata .globals - .bind::( - &client.event_queue.handle(), - ®istry, - 3..4, - (), - ) + .bind::(&client.event_queue.handle(), 3..4, ()) .unwrap(); let compositor = client_ddata .globals .bind::( &client.event_queue.handle(), - ®istry, 1..2, 0, ) @@ -239,8 +216,9 @@ struct ClientHandler { } impl ClientHandler { - fn new() -> ClientHandler { - ClientHandler { globals: Default::default(), entered: false } + fn new(client: &TestClient) -> ClientHandler { + let globals = globals::GlobalList::new(&client.display, &client.event_queue.handle()); + ClientHandler { globals, entered: false } } } @@ -250,10 +228,6 @@ impl AsMut for ClientHandler { } } -wayc::delegate_dispatch!(ClientHandler: - [wayc::protocol::wl_registry::WlRegistry: ()] => globals::GlobalList -); - impl wayc::Dispatch for ClientHandler { fn event( _: &mut Self, diff --git a/wayland-tests/tests/destructors.rs b/wayland-tests/tests/destructors.rs index ecac0f4142f..78a4f256e2e 100644 --- a/wayland-tests/tests/destructors.rs +++ b/wayland-tests/tests/destructors.rs @@ -1,7 +1,7 @@ #[macro_use] mod helpers; -use helpers::{globals, roundtrip, wayc, ways, TestServer}; +use helpers::{globals, roundtrip, wayc, ways, TestClient, TestServer}; use std::sync::{ atomic::{AtomicBool, Ordering}, @@ -18,20 +18,13 @@ fn resource_destructor_request() { let mut server_ddata = ServerHandler { destructor_called: Arc::new(AtomicBool::new(false)) }; let (_, mut client) = server.add_client(); - let mut client_ddata = ClientHandler::new(); - - let registry = client.display.get_registry(&client.event_queue.handle(), ()); + let mut client_ddata = ClientHandler::new(&client); roundtrip(&mut client, &mut server, &mut client_ddata, &mut server_ddata).unwrap(); let output = client_ddata .globals - .bind::( - &client.event_queue.handle(), - ®istry, - 3..4, - (), - ) + .bind::(&client.event_queue.handle(), 3..4, ()) .unwrap(); roundtrip(&mut client, &mut server, &mut client_ddata, &mut server_ddata).unwrap(); @@ -53,20 +46,13 @@ fn resource_destructor_cleanup() { let mut server_ddata = ServerHandler { destructor_called: Arc::new(AtomicBool::new(false)) }; let (_, mut client) = server.add_client(); - let mut client_ddata = ClientHandler::new(); - - let registry = client.display.get_registry(&client.event_queue.handle(), ()); + let mut client_ddata = ClientHandler::new(&client); roundtrip(&mut client, &mut server, &mut client_ddata, &mut server_ddata).unwrap(); client_ddata .globals - .bind::( - &client.event_queue.handle(), - ®istry, - 3..4, - (), - ) + .bind::(&client.event_queue.handle(), 3..4, ()) .unwrap(); roundtrip(&mut client, &mut server, &mut client_ddata, &mut server_ddata).unwrap(); @@ -91,20 +77,13 @@ fn client_destructor_cleanup() { let (_, mut client) = server.add_client_with_data(Arc::new(DestructorClientData(destructor_called.clone()))); - let mut client_ddata = ClientHandler::new(); - - let registry = client.display.get_registry(&client.event_queue.handle(), ()); + let mut client_ddata = ClientHandler::new(&client); roundtrip(&mut client, &mut server, &mut client_ddata, &mut server_ddata).unwrap(); client_ddata .globals - .bind::( - &client.event_queue.handle(), - ®istry, - 3..4, - (), - ) + .bind::(&client.event_queue.handle(), 3..4, ()) .unwrap(); roundtrip(&mut client, &mut server, &mut client_ddata, &mut server_ddata).unwrap(); @@ -176,8 +155,9 @@ struct ClientHandler { } impl ClientHandler { - fn new() -> ClientHandler { - ClientHandler { globals: Default::default() } + fn new(client: &TestClient) -> ClientHandler { + let globals = globals::GlobalList::new(&client.display, &client.event_queue.handle()); + ClientHandler { globals } } } @@ -187,10 +167,6 @@ impl AsMut for ClientHandler { } } -wayc::delegate_dispatch!(ClientHandler: - [wayc::protocol::wl_registry::WlRegistry: ()] => globals::GlobalList -); - client_ignore_impl!(ClientHandler => [ wayc::protocol::wl_output::WlOutput ]); diff --git a/wayland-tests/tests/globals.rs b/wayland-tests/tests/globals.rs index 176dc24cd95..bd6a340050c 100644 --- a/wayland-tests/tests/globals.rs +++ b/wayland-tests/tests/globals.rs @@ -1,7 +1,7 @@ #[macro_use] mod helpers; -use helpers::{globals, roundtrip, wayc, ways, TestServer}; +use helpers::{globals, roundtrip, wayc, ways, TestClient, TestServer}; use ways::protocol::wl_compositor::WlCompositor as ServerCompositor; use ways::protocol::wl_output::WlOutput as ServerOutput; @@ -13,9 +13,7 @@ fn simple_global() { server.display.handle().create_global::(1, ()); let (_, mut client) = server.add_client(); - let mut client_ddata = ClientHandler { globals: globals::GlobalList::new() }; - - client.display.get_registry(&client.event_queue.handle(), ()); + let mut client_ddata = ClientHandler::new(&client); roundtrip(&mut client, &mut server, &mut client_ddata, &mut ServerHandler).unwrap(); @@ -35,9 +33,7 @@ fn multi_versions() { server.display.handle().create_global::(1, ()); let (_, mut client) = server.add_client(); - let mut client_ddata = ClientHandler { globals: globals::GlobalList::new() }; - - client.display.get_registry(&client.event_queue.handle(), ()); + let mut client_ddata = ClientHandler::new(&client); roundtrip(&mut client, &mut server, &mut client_ddata, &mut ServerHandler).unwrap(); @@ -57,9 +53,7 @@ fn dynamic_global() { server.display.handle().create_global::(1, ()); let (_, mut client) = server.add_client(); - let mut client_ddata = ClientHandler { globals: globals::GlobalList::new() }; - - client.display.get_registry(&client.event_queue.handle(), ()); + let mut client_ddata = ClientHandler::new(&client); roundtrip(&mut client, &mut server, &mut client_ddata, &mut ServerHandler).unwrap(); assert!(client_ddata.globals.list().len() == 1); @@ -95,14 +89,12 @@ fn wrong_global() { server.display.handle().create_global::(4, ()); let (_, mut client) = server.add_client(); - let mut client_ddata = ClientHandler { globals: globals::GlobalList::new() }; - - let registry = client.display.get_registry(&client.event_queue.handle(), ()); + let mut client_ddata = ClientHandler::new(&client); // instantiate a wrong global, this should kill the client // but currently does not fail on native_lib - registry.bind::(1, 1, &client.event_queue.handle(), ()); + client_ddata.globals.registry().bind::(1, 1, &client.event_queue.handle(), ()); assert!(roundtrip(&mut client, &mut server, &mut client_ddata, &mut ServerHandler).is_err()); } @@ -115,13 +107,16 @@ fn wrong_global_version() { server.display.handle().create_global::(1, ()); let (_, mut client) = server.add_client(); - let mut client_ddata = ClientHandler { globals: globals::GlobalList::new() }; - - let registry = client.display.get_registry(&client.event_queue.handle(), ()); + let mut client_ddata = ClientHandler::new(&client); // instantiate a global with wrong version, this should kill the client - registry.bind::(1, 2, &client.event_queue.handle(), ()); + client_ddata.globals.registry().bind::( + 1, + 2, + &client.event_queue.handle(), + (), + ); assert!(roundtrip(&mut client, &mut server, &mut client_ddata, &mut ServerHandler).is_err()); } @@ -134,13 +129,16 @@ fn invalid_global_version() { server.display.handle().create_global::(1, ()); let (_, mut client) = server.add_client(); - let mut client_ddata = ClientHandler { globals: globals::GlobalList::new() }; - - let registry = client.display.get_registry(&client.event_queue.handle(), ()); + let mut client_ddata = ClientHandler::new(&client); // instantiate a global with version 0, which is invalid this should kill the client - registry.bind::(1, 0, &client.event_queue.handle(), ()); + client_ddata.globals.registry().bind::( + 1, + 0, + &client.event_queue.handle(), + (), + ); assert!(roundtrip(&mut client, &mut server, &mut client_ddata, &mut ServerHandler).is_err()); } @@ -153,13 +151,16 @@ fn wrong_global_id() { server.display.handle().create_global::(1, ()); let (_, mut client) = server.add_client(); - let mut client_ddata = ClientHandler { globals: globals::GlobalList::new() }; - - let registry = client.display.get_registry(&client.event_queue.handle(), ()); + let mut client_ddata = ClientHandler::new(&client); // instantiate a global with version 0, which is invalid this should kill the client - registry.bind::(3, 1, &client.event_queue.handle(), ()); + client_ddata.globals.registry().bind::( + 3, + 1, + &client.event_queue.handle(), + (), + ); assert!(roundtrip(&mut client, &mut server, &mut client_ddata, &mut ServerHandler).is_err()); } @@ -172,9 +173,7 @@ fn two_step_binding() { server.display.handle().create_global::(1, ()); let (_, mut client) = server.add_client(); - let mut client_ddata = ClientHandler { globals: globals::GlobalList::new() }; - - let registry = client.display.get_registry(&client.event_queue.handle(), ()); + let mut client_ddata = ClientHandler::new(&client); roundtrip(&mut client, &mut server, &mut client_ddata, &mut ServerHandler).unwrap(); @@ -185,13 +184,10 @@ fn two_step_binding() { client_ddata .globals - .bind::(&client.event_queue.handle(), ®istry, 1..2, ()) + .bind::(&client.event_queue.handle(), 1..2, ()) .unwrap(); - client_ddata - .globals - .bind::(&client.event_queue.handle(), ®istry, 1..2, ()) - .unwrap(); + client_ddata.globals.bind::(&client.event_queue.handle(), 1..2, ()).unwrap(); roundtrip(&mut client, &mut server, &mut client_ddata, &mut ServerHandler).unwrap(); } @@ -205,16 +201,19 @@ struct ClientHandler { globals: globals::GlobalList, } +impl ClientHandler { + fn new(client: &TestClient) -> ClientHandler { + let globals = globals::GlobalList::new(&client.display, &client.event_queue.handle()); + ClientHandler { globals } + } +} + impl AsMut for ClientHandler { fn as_mut(&mut self) -> &mut globals::GlobalList { &mut self.globals } } -wayc::delegate_dispatch!(ClientHandler: - [wayc::protocol::wl_registry::WlRegistry: ()] => globals::GlobalList -); - client_ignore_impl!(ClientHandler => [ wayc::protocol::wl_compositor::WlCompositor, wayc::protocol::wl_shell::WlShell, diff --git a/wayland-tests/tests/helpers/globals.rs b/wayland-tests/tests/helpers/globals.rs index 4caec8b3451..c98f4f007dc 100644 --- a/wayland-tests/tests/helpers/globals.rs +++ b/wayland-tests/tests/helpers/globals.rs @@ -2,7 +2,13 @@ use std::ops::Range; -use wayland_client::{protocol::wl_registry, Connection, Dispatch, Proxy, QueueHandle}; +use wayland_client::{ + protocol::{ + wl_display::{self, WlDisplay}, + wl_registry::{self, WlRegistry}, + }, + Connection, Dispatch, Proxy, QueueHandle, +}; /// Description of an advertized global #[derive(Debug)] @@ -24,11 +30,12 @@ pub struct GlobalDescription { #[derive(Debug)] pub struct GlobalList { globals: Vec, + registry: WlRegistry, } impl Dispatch for GlobalList where - D: Dispatch + AsMut, + D: AsMut, { fn event( handle: &mut D, @@ -59,16 +66,22 @@ impl AsMut for GlobalList { } } -impl Default for GlobalList { - fn default() -> Self { - Self::new() - } -} - impl GlobalList { /// Create a new `GlobalList` - pub fn new() -> Self { - Self { globals: Vec::new() } + pub fn new(display: &WlDisplay, qh: &QueueHandle) -> Self + where + D: AsMut + 'static, + { + let data = qh.make_data::(()); + let registry = display + .send_constructor::(wl_display::Request::GetRegistry {}, data) + .unwrap(); + + Self { globals: Vec::new(), registry } + } + + pub fn registry(&self) -> WlRegistry { + self.registry.clone() } /// Access the list of currently advertized globals @@ -83,7 +96,6 @@ impl GlobalList { pub fn bind + 'static>( &self, qh: &QueueHandle, - registry: &wl_registry::WlRegistry, version: Range, user_data: U, ) -> Result { @@ -93,7 +105,7 @@ impl GlobalList { } if version.contains(&desc.version) { - return Ok(registry.bind::(desc.name, desc.version, qh, user_data)); + return Ok(self.registry.bind::(desc.name, desc.version, qh, user_data)); } else { return Err(BindError::WrongVersion { interface: I::interface().name, diff --git a/wayland-tests/tests/protocol_errors.rs b/wayland-tests/tests/protocol_errors.rs index c95fd06c840..e8a8fdc4414 100644 --- a/wayland-tests/tests/protocol_errors.rs +++ b/wayland-tests/tests/protocol_errors.rs @@ -1,7 +1,7 @@ #[macro_use] mod helpers; -use helpers::{globals, roundtrip, wayc, ways, TestServer}; +use helpers::{globals, roundtrip, wayc, ways, TestClient, TestServer}; use ways::Resource; #[test] @@ -14,9 +14,7 @@ fn client_receive_generic_error() { let (s_client, mut client) = server.add_client(); - let mut client_ddata = ClientHandler::new(); - - let registry = client.display.get_registry(&client.event_queue.handle(), ()); + let mut client_ddata = ClientHandler::new(&client); roundtrip(&mut client, &mut server, &mut client_ddata, &mut ServerHandler).unwrap(); @@ -25,7 +23,6 @@ fn client_receive_generic_error() { .globals .bind::( &client.event_queue.handle(), - ®istry, 1..2, (), ) @@ -62,8 +59,9 @@ struct ClientHandler { } impl ClientHandler { - fn new() -> ClientHandler { - ClientHandler { globals: Default::default() } + fn new(client: &TestClient) -> ClientHandler { + let globals = globals::GlobalList::new(&client.display, &client.event_queue.handle()); + ClientHandler { globals } } } @@ -73,10 +71,6 @@ impl AsMut for ClientHandler { } } -wayc::delegate_dispatch!(ClientHandler: - [wayc::protocol::wl_registry::WlRegistry: ()] => globals::GlobalList -); - client_ignore_impl!(ClientHandler => [ wayc::protocol::wl_compositor::WlCompositor ]); diff --git a/wayland-tests/tests/server_clients.rs b/wayland-tests/tests/server_clients.rs index 6811cb9849f..11e80f4da5c 100644 --- a/wayland-tests/tests/server_clients.rs +++ b/wayland-tests/tests/server_clients.rs @@ -1,7 +1,7 @@ #[macro_use] mod helpers; -use helpers::{globals, roundtrip, wayc, ways, TestServer}; +use helpers::{globals, roundtrip, wayc, ways, TestClient, TestServer}; use std::sync::{ atomic::{AtomicBool, Ordering}, @@ -25,21 +25,14 @@ fn client_user_data() { has_compositor: AtomicBool::new(false), has_output: AtomicBool::new(false), })); - let mut client_ddata = ClientHandler::new(); - - let registry = client.display.get_registry(&client.event_queue.handle(), ()); + let mut client_ddata = ClientHandler::new(&client); roundtrip(&mut client, &mut server, &mut client_ddata, &mut server_ddata).unwrap(); // Instantiate the globals client_ddata .globals - .bind::( - &client.event_queue.handle(), - ®istry, - 1..2, - (), - ) + .bind::(&client.event_queue.handle(), 1..2, ()) .unwrap(); roundtrip(&mut client, &mut server, &mut client_ddata, &mut server_ddata).unwrap(); @@ -54,7 +47,6 @@ fn client_user_data() { .globals .bind::( &client.event_queue.handle(), - ®istry, 1..2, (), ) @@ -103,8 +95,9 @@ struct ClientHandler { } impl ClientHandler { - fn new() -> ClientHandler { - ClientHandler { globals: Default::default() } + fn new(client: &TestClient) -> ClientHandler { + let globals = globals::GlobalList::new(&client.display, &client.event_queue.handle()); + ClientHandler { globals } } } @@ -114,10 +107,6 @@ impl AsMut for ClientHandler { } } -wayc::delegate_dispatch!(ClientHandler: - [wayc::protocol::wl_registry::WlRegistry: ()] => globals::GlobalList -); - client_ignore_impl!(ClientHandler => [ wayc::protocol::wl_output::WlOutput, wayc::protocol::wl_compositor::WlCompositor diff --git a/wayland-tests/tests/server_created_object.rs b/wayland-tests/tests/server_created_object.rs index d04a3702ff8..b56fec0f7da 100644 --- a/wayland-tests/tests/server_created_object.rs +++ b/wayland-tests/tests/server_created_object.rs @@ -1,7 +1,7 @@ #[macro_use] mod helpers; -use helpers::{globals, roundtrip, wayc, ways, TestServer}; +use helpers::{globals, roundtrip, wayc, ways, TestClient, TestServer}; use ways::protocol::wl_data_device::WlDataDevice as ServerDD; use ways::protocol::wl_data_device_manager::{ @@ -25,19 +25,17 @@ fn data_offer() { let mut server_ddata = ServerHandler { data_device: None }; let (_, mut client) = server.add_client(); - let mut client_ddata = ClientHandler::new(); - - let registry = client.display.get_registry(&client.event_queue.handle(), ()); + let mut client_ddata = ClientHandler::new(&client); roundtrip(&mut client, &mut server, &mut client_ddata, &mut server_ddata).unwrap(); let seat = client_ddata .globals - .bind::(&client.event_queue.handle(), ®istry, 1..2, ()) + .bind::(&client.event_queue.handle(), 1..2, ()) .unwrap(); let ddmgr = client_ddata .globals - .bind::(&client.event_queue.handle(), ®istry, 3..4, ()) + .bind::(&client.event_queue.handle(), 3..4, ()) .unwrap(); ddmgr.get_data_device(&seat, &client.event_queue.handle(), ()); @@ -71,19 +69,17 @@ fn server_id_reuse() { let mut server_ddata = ServerHandler { data_device: None }; let (_, mut client) = server.add_client(); - let mut client_ddata = ClientHandler::new(); - - let registry = client.display.get_registry(&client.event_queue.handle(), ()); + let mut client_ddata = ClientHandler::new(&client); roundtrip(&mut client, &mut server, &mut client_ddata, &mut server_ddata).unwrap(); let seat = client_ddata .globals - .bind::(&client.event_queue.handle(), ®istry, 1..2, ()) + .bind::(&client.event_queue.handle(), 1..2, ()) .unwrap(); let ddmgr = client_ddata .globals - .bind::(&client.event_queue.handle(), ®istry, 3..4, ()) + .bind::(&client.event_queue.handle(), 3..4, ()) .unwrap(); ddmgr.get_data_device(&seat, &client.event_queue.handle(), ()); @@ -126,7 +122,7 @@ fn server_id_reuse() { roundtrip(&mut client, &mut server, &mut client_ddata, &mut server_ddata).unwrap(); - // Send a third data offer, server shoudl reuse id 0xFF000000 + // Send a third data offer, server should reuse id 0xFF000000 let offer = s_client .create_resource::( &server.display.handle(), @@ -152,19 +148,17 @@ fn server_created_race() { let mut server_ddata = ServerHandler { data_device: None }; let (_, mut client) = server.add_client(); - let mut client_ddata = ClientHandler::new(); - - let registry = client.display.get_registry(&client.event_queue.handle(), ()); + let mut client_ddata = ClientHandler::new(&client); roundtrip(&mut client, &mut server, &mut client_ddata, &mut server_ddata).unwrap(); let seat = client_ddata .globals - .bind::(&client.event_queue.handle(), ®istry, 1..2, ()) + .bind::(&client.event_queue.handle(), 1..2, ()) .unwrap(); let ddmgr = client_ddata .globals - .bind::(&client.event_queue.handle(), ®istry, 3..4, ()) + .bind::(&client.event_queue.handle(), 3..4, ()) .unwrap(); ddmgr.get_data_device(&seat, &client.event_queue.handle(), ()); @@ -215,19 +209,17 @@ fn creation_destruction_race() { let mut server_ddata = ServerHandler { data_device: None }; let (_, mut client) = server.add_client(); - let mut client_ddata = ClientHandler::new(); - - let registry = client.display.get_registry(&client.event_queue.handle(), ()); + let mut client_ddata = ClientHandler::new(&client); roundtrip(&mut client, &mut server, &mut client_ddata, &mut server_ddata).unwrap(); let seat = client_ddata .globals - .bind::(&client.event_queue.handle(), ®istry, 1..2, ()) + .bind::(&client.event_queue.handle(), 1..2, ()) .unwrap(); let ddmgr = client_ddata .globals - .bind::(&client.event_queue.handle(), ®istry, 3..4, ()) + .bind::(&client.event_queue.handle(), 3..4, ()) .unwrap(); // client creates two data devices @@ -286,19 +278,17 @@ fn creation_destruction_queue_dispatch_race() { let mut server_ddata = ServerHandler { data_device: None }; let (_, mut client) = server.add_client(); - let mut client_ddata = ClientHandler::new(); - - let registry = client.display.get_registry(&client.event_queue.handle(), ()); + let mut client_ddata = ClientHandler::new(&client); roundtrip(&mut client, &mut server, &mut client_ddata, &mut server_ddata).unwrap(); let seat = client_ddata .globals - .bind::(&client.event_queue.handle(), ®istry, 1..2, ()) + .bind::(&client.event_queue.handle(), 1..2, ()) .unwrap(); let ddmgr = client_ddata .globals - .bind::(&client.event_queue.handle(), ®istry, 3..4, ()) + .bind::(&client.event_queue.handle(), 3..4, ()) .unwrap(); let client_dd = ddmgr.get_data_device(&seat, &client.event_queue.handle(), ()); @@ -344,13 +334,9 @@ struct ClientHandler { } impl ClientHandler { - fn new() -> ClientHandler { - ClientHandler { - globals: Default::default(), - data_offer: None, - received: None, - received_dead: false, - } + fn new(client: &TestClient) -> ClientHandler { + let globals = globals::GlobalList::new(&client.display, &client.event_queue.handle()); + ClientHandler { globals, data_offer: None, received: None, received_dead: false } } } @@ -360,9 +346,6 @@ impl AsMut for ClientHandler { } } -wayc::delegate_dispatch!(ClientHandler: - [wayc::protocol::wl_registry::WlRegistry: ()] => globals::GlobalList -); client_ignore_impl!(ClientHandler => [ ClientSeat, ClientDDMgr diff --git a/wayland-tests/tests/server_global_filter.rs b/wayland-tests/tests/server_global_filter.rs index 7c62c3e6601..ecd4b444c47 100644 --- a/wayland-tests/tests/server_global_filter.rs +++ b/wayland-tests/tests/server_global_filter.rs @@ -1,7 +1,7 @@ #[macro_use] mod helpers; -use helpers::{globals, roundtrip, wayc, ways, TestServer}; +use helpers::{globals, roundtrip, wayc, ways, TestClient, TestServer}; use ways::protocol::{wl_compositor, wl_output, wl_shm}; @@ -24,9 +24,7 @@ fn global_filter() { let mut server_ddata = ServerHandler; let (_, mut client) = server.add_client_with_data(Arc::new(MyClientData { privileged: false })); - let mut client_ddata = ClientHandler::new(); - - client.display.get_registry(&client.event_queue.handle(), ()); + let mut client_ddata = ClientHandler::new(&client); roundtrip(&mut client, &mut server, &mut client_ddata, &mut server_ddata).unwrap(); @@ -34,9 +32,7 @@ fn global_filter() { let (_, mut priv_client) = server.add_client_with_data(Arc::new(MyClientData { privileged: true })); - let mut priv_client_ddata = ClientHandler::new(); - - priv_client.display.get_registry(&priv_client.event_queue.handle(), ()); + let mut priv_client_ddata = ClientHandler::new(&priv_client); roundtrip(&mut priv_client, &mut server, &mut priv_client_ddata, &mut server_ddata).unwrap(); @@ -68,17 +64,16 @@ fn global_filter_try_force() { // normal client that cannot bind the privileged global let (_, mut client) = server.add_client_with_data(Arc::new(MyClientData { privileged: false })); - let mut client_ddata = ClientHandler::new(); + let mut client_ddata = ClientHandler::new(&client); // privileged client that can let (_, mut priv_client) = server.add_client_with_data(Arc::new(MyClientData { privileged: true })); - let mut priv_client_ddata = ClientHandler::new(); + let mut priv_client_ddata = ClientHandler::new(&priv_client); // privileged client can bind it - let priv_registry = priv_client.display.get_registry(&priv_client.event_queue.handle(), ()); - priv_registry.bind::( + priv_client_ddata.globals.registry().bind::( 1, 1, &priv_client.event_queue.handle(), @@ -87,8 +82,7 @@ fn global_filter_try_force() { roundtrip(&mut priv_client, &mut server, &mut priv_client_ddata, &mut server_ddata).unwrap(); // unprivileged client cannot - let registry = client.display.get_registry(&client.event_queue.handle(), ()); - registry.bind::( + client_ddata.globals.registry().bind::( 1, 1, &client.event_queue.handle(), @@ -103,8 +97,9 @@ struct ClientHandler { } impl ClientHandler { - fn new() -> ClientHandler { - ClientHandler { globals: Default::default() } + fn new(client: &TestClient) -> ClientHandler { + let globals = globals::GlobalList::new(&client.display, &client.event_queue.handle()); + ClientHandler { globals } } } @@ -114,10 +109,6 @@ impl AsMut for ClientHandler { } } -wayc::delegate_dispatch!(ClientHandler: - [wayc::protocol::wl_registry::WlRegistry: ()] => globals::GlobalList -); - client_ignore_impl!(ClientHandler => [ wayc::protocol::wl_compositor::WlCompositor, wayc::protocol::wl_shm::WlShm, diff --git a/wayland-tests/tests/server_global_post_error.rs b/wayland-tests/tests/server_global_post_error.rs index 45995214266..fa86a4084ca 100644 --- a/wayland-tests/tests/server_global_post_error.rs +++ b/wayland-tests/tests/server_global_post_error.rs @@ -1,7 +1,7 @@ #[macro_use] mod helpers; -use helpers::{globals, roundtrip, wayc, ways, TestServer}; +use helpers::{globals, roundtrip, wayc, ways, TestClient, TestServer}; use wayc::{protocol::wl_output::WlOutput as ClientOutput, Proxy}; @@ -15,21 +15,14 @@ fn global_init_post_error() { let mut server_ddata = ServerHandler; let (_, mut client) = server.add_client(); - let mut client_ddata = ClientHandler::new(); - - let registry = client.display.get_registry(&client.event_queue.handle(), ()); + let mut client_ddata = ClientHandler::new(&client); roundtrip(&mut client, &mut server, &mut client_ddata, &mut server_ddata).unwrap(); // create an outputs let client_output = client_ddata .globals - .bind::( - &client.event_queue.handle(), - ®istry, - 3..4, - (), - ) + .bind::(&client.event_queue.handle(), 3..4, ()) .unwrap(); let _ = roundtrip(&mut client, &mut server, &mut client_ddata, &mut server_ddata); @@ -49,8 +42,9 @@ struct ClientHandler { } impl ClientHandler { - fn new() -> ClientHandler { - ClientHandler { globals: Default::default() } + fn new(client: &TestClient) -> ClientHandler { + let globals = globals::GlobalList::new(&client.display, &client.event_queue.handle()); + ClientHandler { globals } } } @@ -60,10 +54,6 @@ impl AsMut for ClientHandler { } } -wayc::delegate_dispatch!(ClientHandler: - [wayc::protocol::wl_registry::WlRegistry: ()] => globals::GlobalList -); - client_ignore_impl!(ClientHandler => [ClientOutput]); struct ServerHandler; diff --git a/wayland-tests/tests/server_resources.rs b/wayland-tests/tests/server_resources.rs index 047cb72b542..4cce5be80cd 100644 --- a/wayland-tests/tests/server_resources.rs +++ b/wayland-tests/tests/server_resources.rs @@ -1,7 +1,7 @@ #[macro_use] mod helpers; -use helpers::{globals, roundtrip, wayc, ways, TestServer}; +use helpers::{globals, roundtrip, wayc, ways, TestClient, TestServer}; use ways::{ protocol::{wl_compositor, wl_output}, @@ -20,30 +20,18 @@ fn resource_equals() { let mut server_ddata = ServerHandler { outputs: Vec::new() }; let (_, mut client) = server.add_client(); - let mut client_ddata = ClientHandler::new(); - - let registry = client.display.get_registry(&client.event_queue.handle(), ()); + let mut client_ddata = ClientHandler::new(&client); roundtrip(&mut client, &mut server, &mut client_ddata, &mut server_ddata).unwrap(); // create two outputs client_ddata .globals - .bind::( - &client.event_queue.handle(), - ®istry, - 3..4, - (), - ) + .bind::(&client.event_queue.handle(), 3..4, ()) .unwrap(); client_ddata .globals - .bind::( - &client.event_queue.handle(), - ®istry, - 3..4, - (), - ) + .bind::(&client.event_queue.handle(), 3..4, ()) .unwrap(); roundtrip(&mut client, &mut server, &mut client_ddata, &mut server_ddata).unwrap(); @@ -67,30 +55,18 @@ fn resource_user_data() { let mut server_ddata = ServerHandler { outputs: Vec::new() }; let (_, mut client) = server.add_client(); - let mut client_ddata = ClientHandler::new(); - - let registry = client.display.get_registry(&client.event_queue.handle(), ()); + let mut client_ddata = ClientHandler::new(&client); roundtrip(&mut client, &mut server, &mut client_ddata, &mut server_ddata).unwrap(); // create two outputs client_ddata .globals - .bind::( - &client.event_queue.handle(), - ®istry, - 3..4, - (), - ) + .bind::(&client.event_queue.handle(), 3..4, ()) .unwrap(); client_ddata .globals - .bind::( - &client.event_queue.handle(), - ®istry, - 3..4, - (), - ) + .bind::(&client.event_queue.handle(), 3..4, ()) .unwrap(); roundtrip(&mut client, &mut server, &mut client_ddata, &mut server_ddata).unwrap(); @@ -111,30 +87,18 @@ fn dead_resources() { let mut server_ddata = ServerHandler { outputs: Vec::new() }; let (_, mut client) = server.add_client(); - let mut client_ddata = ClientHandler::new(); - - let registry = client.display.get_registry(&client.event_queue.handle(), ()); + let mut client_ddata = ClientHandler::new(&client); roundtrip(&mut client, &mut server, &mut client_ddata, &mut server_ddata).unwrap(); // create two outputs let client_output_1 = client_ddata .globals - .bind::( - &client.event_queue.handle(), - ®istry, - 3..4, - (), - ) + .bind::(&client.event_queue.handle(), 3..4, ()) .unwrap(); client_ddata .globals - .bind::( - &client.event_queue.handle(), - ®istry, - 3..4, - (), - ) + .bind::(&client.event_queue.handle(), 3..4, ()) .unwrap(); roundtrip(&mut client, &mut server, &mut client_ddata, &mut server_ddata).unwrap(); @@ -163,21 +127,14 @@ fn get_resource() { let mut server_ddata = ServerHandler { outputs: Vec::new() }; let (_, mut client) = server.add_client(); - let mut client_ddata = ClientHandler::new(); - - let registry = client.display.get_registry(&client.event_queue.handle(), ()); + let mut client_ddata = ClientHandler::new(&client); roundtrip(&mut client, &mut server, &mut client_ddata, &mut server_ddata).unwrap(); // create an outputs client_ddata .globals - .bind::( - &client.event_queue.handle(), - ®istry, - 3..4, - (), - ) + .bind::(&client.event_queue.handle(), 3..4, ()) .unwrap(); roundtrip(&mut client, &mut server, &mut client_ddata, &mut server_ddata).unwrap(); @@ -193,7 +150,7 @@ fn get_resource() { assert!(client .object_from_protocol_id::(&server.display.handle(), 4) .is_err()); - // but this suceeds + // but this succeeds assert!(client .object_from_protocol_id::(&server.display.handle(), 3) .is_ok()); @@ -204,8 +161,9 @@ struct ClientHandler { } impl ClientHandler { - fn new() -> ClientHandler { - ClientHandler { globals: Default::default() } + fn new(client: &TestClient) -> ClientHandler { + let globals = globals::GlobalList::new(&client.display, &client.event_queue.handle()); + ClientHandler { globals } } } @@ -215,10 +173,6 @@ impl AsMut for ClientHandler { } } -wayc::delegate_dispatch!(ClientHandler: - [wayc::protocol::wl_registry::WlRegistry: ()] => globals::GlobalList -); - client_ignore_impl!(ClientHandler => [ClientOutput]); struct ServerHandler { diff --git a/wayland-tests/tests/xdg_shell_ping.rs b/wayland-tests/tests/xdg_shell_ping.rs index 7960a6a4b9e..3fd2f6f64ed 100644 --- a/wayland-tests/tests/xdg_shell_ping.rs +++ b/wayland-tests/tests/xdg_shell_ping.rs @@ -1,7 +1,7 @@ #[macro_use] mod helpers; -use helpers::{globals, roundtrip, wayc, ways, TestServer}; +use helpers::{globals, roundtrip, wayc, ways, TestClient, TestServer}; use wayland_protocols::xdg::shell::{client as xs_client, server as xs_server}; @@ -15,20 +15,13 @@ fn xdg_ping() { let mut server_ddata = ServerHandler { received_pong: false }; let (_, mut client) = server.add_client(); - let mut client_ddata = ClientHandler::new(); - - let registry = client.display.get_registry(&client.event_queue.handle(), ()); + let mut client_ddata = ClientHandler::new(&client); roundtrip(&mut client, &mut server, &mut client_ddata, &mut server_ddata).unwrap(); client_ddata .globals - .bind::( - &client.event_queue.handle(), - ®istry, - 1..2, - (), - ) + .bind::(&client.event_queue.handle(), 1..2, ()) .unwrap(); roundtrip(&mut client, &mut server, &mut client_ddata, &mut server_ddata).unwrap(); @@ -80,8 +73,9 @@ struct ClientHandler { } impl ClientHandler { - fn new() -> ClientHandler { - ClientHandler { globals: Default::default() } + fn new(client: &TestClient) -> ClientHandler { + let globals = globals::GlobalList::new(&client.display, &client.event_queue.handle()); + ClientHandler { globals } } } @@ -91,10 +85,6 @@ impl AsMut for ClientHandler { } } -wayc::delegate_dispatch!(ClientHandler: - [wayc::protocol::wl_registry::WlRegistry: ()] => globals::GlobalList -); - impl wayc::Dispatch for ClientHandler { fn event( _: &mut Self, From 64760aa5ee579ab24c36ddda31826b358aa84667 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Mary=C5=84czak?= Date: Sat, 14 Dec 2024 22:41:46 +0100 Subject: [PATCH 5/6] Clippy fixes --- wayland-backend/src/debug.rs | 2 +- wayland-client/src/event_queue.rs | 2 +- wayland-server/src/dispatch.rs | 2 +- wayland-sys/src/server.rs | 1 + 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/wayland-backend/src/debug.rs b/wayland-backend/src/debug.rs index 322961c2b50..24c2fc3f4c3 100644 --- a/wayland-backend/src/debug.rs +++ b/wayland-backend/src/debug.rs @@ -58,7 +58,7 @@ pub fn print_send_message( pub(crate) struct DisplaySlice<'a, D>(pub &'a [D]); -impl<'a, D: Display> Display for DisplaySlice<'a, D> { +impl Display for DisplaySlice<'_, D> { #[cfg_attr(coverage, coverage(off))] fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let mut it = self.0.iter(); diff --git a/wayland-client/src/event_queue.rs b/wayland-client/src/event_queue.rs index ec398118d1e..3d1b36f44c6 100644 --- a/wayland-client/src/event_queue.rs +++ b/wayland-client/src/event_queue.rs @@ -651,7 +651,7 @@ impl QueueHandle { } } -impl<'a, State> Drop for QueueFreezeGuard<'a, State> { +impl Drop for QueueFreezeGuard<'_, State> { fn drop(&mut self) { let mut lock = self.qh.inner.lock().unwrap(); lock.freeze_count -= 1; diff --git a/wayland-server/src/dispatch.rs b/wayland-server/src/dispatch.rs index fb0fc517c90..2fb1cdaf4b5 100644 --- a/wayland-server/src/dispatch.rs +++ b/wayland-server/src/dispatch.rs @@ -155,7 +155,7 @@ pub struct DataInit<'a, D: 'static> { pub(crate) error: &'a mut Option<(u32, String)>, } -impl<'a, D> DataInit<'a, D> { +impl DataInit<'_, D> { /// Initialize an object by assigning it its user-data pub fn init( &mut self, diff --git a/wayland-sys/src/server.rs b/wayland-sys/src/server.rs index b11e8ed7060..b941d629319 100644 --- a/wayland-sys/src/server.rs +++ b/wayland-sys/src/server.rs @@ -251,6 +251,7 @@ pub mod signal { // Safety: the signal pointer is valid unsafe { list_for_each!(l, &mut (*signal).listener_list as *mut wl_list, wl_listener, link, { + #[allow(unknown_lints, unpredictable_function_pointer_comparisons)] if (*l).notify == notify { return l; } From 508cf999f2eecfc6abaad5c0836c0c9178bac0bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Mary=C5=84czak?= Date: Sat, 14 Dec 2024 22:44:32 +0100 Subject: [PATCH 6/6] Allow new unicode license --- deny.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deny.toml b/deny.toml index 8d235dbd6e9..b385ec10350 100644 --- a/deny.toml +++ b/deny.toml @@ -32,5 +32,5 @@ allow = [ # Fedora believes it is a free license: https://fedoraproject.org/wiki/Licensing/Unicode # Google categorizes the license under "notice" which means it can be used (with some exceptions like # notices or advertising clauses): https://opensource.google/documentation/reference/thirdparty/licenses#notice - "Unicode-DFS-2016", + "Unicode-3.0", ]