From fb576037b53b680630794acc6b226a8aa4fc0223 Mon Sep 17 00:00:00 2001 From: PolyMeilex Date: Sun, 11 Feb 2024 19:51:02 +0100 Subject: [PATCH 1/8] Server side delegate --- wayland-backend/tests/rs_sys_impls.rs | 2 + wayland-scanner/src/server_gen.rs | 7 +- .../tests/scanner_assets/test-server-code.rs | 60 ++++- wayland-server/examples/delegated.rs | 84 +++++++ wayland-server/src/client.rs | 34 ++- wayland-server/src/dispatch.rs | 233 +++++++++++++----- wayland-server/src/display.rs | 29 ++- wayland-server/src/global.rs | 20 +- wayland-server/src/lib.rs | 18 +- 9 files changed, 406 insertions(+), 81 deletions(-) create mode 100644 wayland-server/examples/delegated.rs diff --git a/wayland-backend/tests/rs_sys_impls.rs b/wayland-backend/tests/rs_sys_impls.rs index 45d384cbb5d..234c2c01ef6 100644 --- a/wayland-backend/tests/rs_sys_impls.rs +++ b/wayland-backend/tests/rs_sys_impls.rs @@ -1,3 +1,5 @@ +#![allow(clippy::test_attr_in_doctest)] + //! Tests to ensure the rust and sys types implement the same traits. /// A macro used to assert a type defined in both the rust and sys implementations of wayland-backend diff --git a/wayland-scanner/src/server_gen.rs b/wayland-scanner/src/server_gen.rs index 8f4a27f4d12..36a8d0368b0 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 @@ -132,6 +132,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 e6773cbc24a..9ed7b7bf330 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"] @@ -97,6 +98,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() } @@ -169,10 +177,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"] @@ -359,6 +368,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() } @@ -774,10 +790,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"] @@ -865,6 +882,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() } @@ -933,10 +957,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"] @@ -1024,6 +1049,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() } @@ -1092,10 +1124,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"] @@ -1183,6 +1216,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..f298c1e08ac --- /dev/null +++ b/wayland-server/examples/delegated.rs @@ -0,0 +1,84 @@ +use delegated::{OutputHandler, OutputManagerState}; +use wayland_server::Display; + +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(&mut self); + } + + pub struct OutputManagerState { + global_id: GlobalId, + } + + impl OutputManagerState { + pub fn create_delegated_global(dh: &DisplayHandle) -> Self + where + D: OutputHandler + 'static, + { + let global_id = dh.create_delegated_global::(4, ()); + Self { global_id } + } + + pub fn gloabl_id(&self) -> GlobalId { + self.global_id.clone() + } + } + + impl GlobalDispatch for OutputManagerState { + fn bind( + state: &mut D, + _handle: &DisplayHandle, + _client: &Client, + resource: New, + _global_data: &(), + data_init: &mut DataInit<'_, D>, + ) { + let _output = data_init.init_delegated::<_, _, Self>(resource, ()); + + state.state(); + state.some_callback(); + } + } + + impl Dispatch for OutputManagerState { + fn request( + _state: &mut D, + _client: &Client, + _resource: &WlOutput, + _request: wl_output::Request, + _data: &(), + _dhandle: &DisplayHandle, + _data_init: &mut DataInit<'_, D>, + ) { + } + } +} + +struct App { + output_state: OutputManagerState, +} + +impl OutputHandler for App { + fn state(&mut self) -> &mut OutputManagerState { + &mut self.output_state + } + + fn some_callback(&mut self) {} +} + +fn main() { + let display = Display::::new().unwrap(); + + let output_state = OutputManagerState::create_delegated_global::(&display.handle()); + + let app = App { output_state }; + + display.handle().remove_global::(app.output_state.gloabl_id()); +} diff --git a/wayland-server/src/client.rs b/wayland-server/src/client.rs index e98d67f52a8..bcbdc6c30b4 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`](Client::create_resource), in case you need to diff --git a/wayland-server/src/dispatch.rs b/wayland-server/src/dispatch.rs index f68fc5b84dd..5c30d6c7393 100644 --- a/wayland-server/src/dispatch.rs +++ b/wayland-server/src/dispatch.rs @@ -166,11 +166,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, + M: Dispatch + 'static, + { + self.custom_init(resource, Arc::new(DelegatedResourceData::::new(data))) } /// Set a custom [`ObjectData`] for this object @@ -227,52 +240,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( @@ -282,15 +319,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 fb1fcaa2329..f65c24f5ddc 100644 --- a/wayland-server/src/display.rs +++ b/wayland-server/src/display.rs @@ -134,7 +134,34 @@ 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 + /// + /// This global will be advertized to clients through the `wl_registry` according to the rules + /// defined by your [`GlobalDispatch`] implementation for the given interface. Whenever a client + /// binds this global, the associated [`GlobalDispatch::bind()`] method will be invoked on your + /// `State`. + 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 42835c0b4b7..107bf4c8782 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 7526f430a46..5afc38c0911 100644 --- a/wayland-server/src/lib.rs +++ b/wayland-server/src/lib.rs @@ -24,10 +24,11 @@ //! `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` example in `wayland-rs/wayland-server`. //! //! ## Globals //! @@ -92,7 +93,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}; @@ -171,6 +172,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 38c1c2b6594a21d671aba978aa63166a81035283 Mon Sep 17 00:00:00 2001 From: PolyMeilex Date: Fri, 16 Feb 2024 20:38:03 +0100 Subject: [PATCH 2/8] Client side delegate --- wayland-client/examples/delegated.rs | 103 ++++++++++++++++++ wayland-client/src/event_queue.rs | 41 ++++--- wayland-client/src/globals.rs | 5 +- wayland-client/src/lib.rs | 9 +- 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, 146 insertions(+), 30 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..ce8aa6d1e1b --- /dev/null +++ b/wayland-client/examples/delegated.rs @@ -0,0 +1,103 @@ +#![allow(clippy::single_match)] + +use wayland_client::{ + protocol::{ + wl_compositor::{self, WlCompositor}, + wl_display::{self, WlDisplay}, + wl_registry::{self, WlRegistry}, + }, + Connection, Dispatch, Proxy, QueueHandle, +}; + +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 { + pub fn new(qh: &QueueHandle, display: &WlDisplay) -> Self { + 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 { + fn event( + state: &mut D, + _: &wl_registry::WlRegistry, + event: wl_registry::Event, + _: &(), + _: &Connection, + _: &QueueHandle, + ) { + if let wl_registry::Event::Global { name, interface, version } = event { + 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 + } + + 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 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 f3878cf89c7..0ee24d7bd11 100644 --- a/wayland-client/src/event_queue.rs +++ b/wayland-client/src/event_queue.rs @@ -94,7 +94,6 @@ pub trait Dispatch where Self: Sized, I: Proxy, - State: Dispatch, { /// Called when an event from the server is processed /// @@ -172,7 +171,7 @@ macro_rules! event_created_child { match opcode { $( $opcode => { - qhandle.make_data::<$child_iface, _>({$child_udata}) + qhandle.make_data::<$child_iface, _, $selftype>({$child_udata}) }, )* _ => { @@ -324,16 +323,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() { @@ -604,14 +604,16 @@ 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. + 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, @@ -643,7 +645,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, @@ -653,21 +656,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, @@ -678,9 +683,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 } @@ -692,7 +697,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 dc897a3edfc..2e6946cfac2 100644 --- a/wayland-client/src/globals.rs +++ b/wayland-client/src/globals.rs @@ -344,7 +344,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 5027e535373..637cbac857b 100644 --- a/wayland-client/src/lib.rs +++ b/wayland-client/src/lib.rs @@ -42,10 +42,13 @@ //! 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 diferent +//! then your `State`. +//! Library (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` example in `wayland-rs/wayland-client`. //! //! ## 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 ee9140d38bbf6922653196a3fbe1200b175808cc Mon Sep 17 00:00:00 2001 From: PolyMeilex Date: Sun, 3 Mar 2024 02:14:38 +0100 Subject: [PATCH 3/8] Address review comments --- wayland-client/src/event_queue.rs | 19 +++++++++++++++++++ wayland-client/src/lib.rs | 9 +++++---- wayland-server/src/display.rs | 7 ++++--- wayland-server/src/lib.rs | 3 ++- 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/wayland-client/src/event_queue.rs b/wayland-client/src/event_queue.rs index 0ee24d7bd11..3e6b4d3deef 100644 --- a/wayland-client/src/event_queue.rs +++ b/wayland-client/src/event_queue.rs @@ -606,6 +606,25 @@ impl QueueHandle { /// the [`Dispatch`]-based logic of `wayland-client`. /// /// 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, diff --git a/wayland-client/src/lib.rs b/wayland-client/src/lib.rs index 637cbac857b..68c108cf80d 100644 --- a/wayland-client/src/lib.rs +++ b/wayland-client/src/lib.rs @@ -43,12 +43,13 @@ //! //! 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 [`QueueHandle::make_data()`] method -//! one is able to create object handlers manually, making it possible to specify `DispatchTo` type diferent -//! then your `State`. -//! Library (such as Smithay's Client Toolkit) can use that mechanism to provide generic [`Dispatch`] implementations that you +//! 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 [`QueueHandle::make_data()`] for details. -//! There is also `delegated.rs` example in `wayland-rs/wayland-client`. +//! 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-server/src/display.rs b/wayland-server/src/display.rs index f65c24f5ddc..9bad3b3487d 100644 --- a/wayland-server/src/display.rs +++ b/wayland-server/src/display.rs @@ -140,10 +140,11 @@ impl DisplayHandle { /// 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 your [`GlobalDispatch`] implementation for the given interface. Whenever a client - /// binds this global, the associated [`GlobalDispatch::bind()`] method will be invoked on your - /// `State`. + /// 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, diff --git a/wayland-server/src/lib.rs b/wayland-server/src/lib.rs index 5afc38c0911..0ae06f2a8bf 100644 --- a/wayland-server/src/lib.rs +++ b/wayland-server/src/lib.rs @@ -28,7 +28,8 @@ //! 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 //! that method for details. -//! There is also `delegated.rs` example in `wayland-rs/wayland-server`. +//! 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 //! From 3de74a3743d0b28a11b29d90824f1889895f2bc1 Mon Sep 17 00:00:00 2001 From: PolyMeilex Date: Sun, 3 Mar 2024 02:33:29 +0100 Subject: [PATCH 4/8] Rename `M` generic to `DelegateTo` in `init_delegated` --- wayland-server/src/dispatch.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wayland-server/src/dispatch.rs b/wayland-server/src/dispatch.rs index 5c30d6c7393..b364d8fd4ef 100644 --- a/wayland-server/src/dispatch.rs +++ b/wayland-server/src/dispatch.rs @@ -174,16 +174,16 @@ impl<'a, D> DataInit<'a, D> { /// 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( + pub fn init_delegated( &mut self, resource: New, data: U, ) -> I where D: 'static, - M: Dispatch + 'static, + DelegateTo: Dispatch + 'static, { - self.custom_init(resource, Arc::new(DelegatedResourceData::::new(data))) + self.custom_init(resource, Arc::new(DelegatedResourceData::::new(data))) } /// Set a custom [`ObjectData`] for this object From 3a7f4c5453ab94e200692bc302e66699760b8015 Mon Sep 17 00:00:00 2001 From: PolyMeilex Date: Sun, 3 Mar 2024 03:37:47 +0100 Subject: [PATCH 5/8] Improve delegate example --- wayland-client/examples/delegated.rs | 19 ++++++++++- wayland-server/examples/delegated.rs | 48 ++++++++++++++++++++++------ 2 files changed, 57 insertions(+), 10 deletions(-) diff --git a/wayland-client/examples/delegated.rs b/wayland-client/examples/delegated.rs index ce8aa6d1e1b..4979955bcf6 100644 --- a/wayland-client/examples/delegated.rs +++ b/wayland-client/examples/delegated.rs @@ -9,6 +9,12 @@ use wayland_client::{ 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::*; @@ -22,9 +28,13 @@ mod delegated { } 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(); @@ -37,6 +47,8 @@ mod delegated { } impl Dispatch for Registry { + /// Called whenever an object created via `make_data` + /// receives a server event fn event( state: &mut D, _: &wl_registry::WlRegistry, @@ -46,6 +58,7 @@ mod delegated { _: &QueueHandle, ) { 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); } } @@ -62,6 +75,8 @@ impl delegated::RegistryHandler for AppData { &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); @@ -94,6 +109,8 @@ fn main() { 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() }; diff --git a/wayland-server/examples/delegated.rs b/wayland-server/examples/delegated.rs index f298c1e08ac..07281a60124 100644 --- a/wayland-server/examples/delegated.rs +++ b/wayland-server/examples/delegated.rs @@ -1,6 +1,14 @@ +#![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, @@ -10,7 +18,7 @@ mod delegated { pub trait OutputHandler { fn state(&mut self) -> &mut OutputManagerState; - fn some_callback(&mut self); + fn some_callback_one_might_need(&mut self); } pub struct OutputManagerState { @@ -18,20 +26,28 @@ mod delegated { } 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 } } - pub fn gloabl_id(&self) -> GlobalId { + /// 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, @@ -40,23 +56,35 @@ mod delegated { _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, ()); - state.state(); - state.some_callback(); + // 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 { + impl Dispatch for OutputManagerState { + /// Called whenever an object created via `init_delegated` + /// receives a client request fn request( - _state: &mut D, + state: &mut D, _client: &Client, _resource: &WlOutput, - _request: wl_output::Request, + 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(); + } + _ => {} + } } } } @@ -70,15 +98,17 @@ impl OutputHandler for App { &mut self.output_state } - fn some_callback(&mut self) {} + 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.gloabl_id()); + display.handle().remove_global::(app.output_state.global_id()); } From 4027d57492faca32c5ec250d94a8757255d6ea18 Mon Sep 17 00:00:00 2001 From: PolyMeilex Date: Sun, 3 Mar 2024 02:32:19 +0100 Subject: [PATCH 6/8] Update CHANGELOG --- wayland-client/CHANGELOG.md | 4 ++++ wayland-scanner/CHANGELOG.md | 5 +++++ wayland-server/CHANGELOG.md | 9 +++++++++ 3 files changed, 18 insertions(+) diff --git a/wayland-client/CHANGELOG.md b/wayland-client/CHANGELOG.md index b07612a9773..1c954f05884 100644 --- a/wayland-client/CHANGELOG.md +++ b/wayland-client/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +#### Breaking changes +- `QueueHandle::make_data` now accepts additional `DelegateTo` generic, + therefore allowing users to dispatch events to types different than main `State` + ## 0.31.2 -- 2024-01-29 #### Additions diff --git a/wayland-scanner/CHANGELOG.md b/wayland-scanner/CHANGELOG.md index 46f7610014f..83d546ac999 100644 --- a/wayland-scanner/CHANGELOG.md +++ b/wayland-scanner/CHANGELOG.md @@ -2,6 +2,11 @@ ## Unreleased +#### 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.1 -- 2024-01-29 - Include an `std::convert::Infallible` in hidden `__phantom_lifetime` enum variants, diff --git a/wayland-server/CHANGELOG.md b/wayland-server/CHANGELOG.md index c0c420ea1d4..fbc44b733b1 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.1 -- 2024-01-29 - Dropped `nix` dependency in favor of `rustix` From bd0372597e2ba7d475108e0b140ba3924875cad1 Mon Sep 17 00:00:00 2001 From: PolyMeilex Date: Thu, 7 Mar 2024 21:49:09 +0100 Subject: [PATCH 7/8] Fix make_data doc comment --- wayland-client/src/event_queue.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wayland-client/src/event_queue.rs b/wayland-client/src/event_queue.rs index 3e6b4d3deef..f0001fce469 100644 --- a/wayland-client/src/event_queue.rs +++ b/wayland-client/src/event_queue.rs @@ -622,8 +622,8 @@ impl QueueHandle { /// // to this impl /// } /// - /// let obj1 = qh.make_data; - /// let obj2 = qh.make_data; + /// let obj1 = qh.make_data::(()); + /// let obj2 = qh.make_data::(()); /// ``` pub fn make_data( &self, From 9c1e3698017267c6f88666883b9ae8c41e747fc8 Mon Sep 17 00:00:00 2001 From: PolyMeilex Date: Thu, 7 Mar 2024 22:04:45 +0100 Subject: [PATCH 8/8] Remove delegate macros --- wayland-client/CHANGELOG.md | 1 + wayland-client/src/event_queue.rs | 91 ----------- wayland-server/CHANGELOG.md | 1 + wayland-server/src/dispatch.rs | 77 ---------- wayland-server/src/global.rs | 145 ------------------ 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(+), 671 deletions(-) diff --git a/wayland-client/CHANGELOG.md b/wayland-client/CHANGELOG.md index 1c954f05884..06242393e4d 100644 --- a/wayland-client/CHANGELOG.md +++ b/wayland-client/CHANGELOG.md @@ -5,6 +5,7 @@ #### Breaking changes - `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` ## 0.31.2 -- 2024-01-29 diff --git a/wayland-client/src/event_queue.rs b/wayland-client/src/event_queue.rs index f0001fce469..75bb9802d08 100644 --- a/wayland-client/src/event_queue.rs +++ b/wayland-client/src/event_queue.rs @@ -743,97 +743,6 @@ impl ObjectData for TemporaryData { * 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 fbc44b733b1..f438d9e8ea4 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 b364d8fd4ef..24b9e41c4f0 100644 --- a/wayland-server/src/dispatch.rs +++ b/wayland-server/src/dispatch.rs @@ -413,80 +413,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 107bf4c8782..73d8623b4c9 100644 --- a/wayland-server/src/global.rs +++ b/wayland-server/src/global.rs @@ -124,148 +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!`](crate::delegate_dispatch) macro. -#[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 7c40864047a..5d0cc8da1a6 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 a1a614bde7a..dad145c32a1 100644 --- a/wayland-tests/tests/server_global_filter.rs +++ b/wayland-tests/tests/server_global_filter.rs @@ -5,7 +5,7 @@ extern crate wayland_sys; #[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}; @@ -28,9 +28,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(); @@ -38,9 +36,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(); @@ -72,17 +68,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(), @@ -91,8 +86,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(), @@ -107,8 +101,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 } } } @@ -118,10 +113,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,