diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 38d2103ee..77328a6ba 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ jobs: strategy: fail-fast: false matrix: - rust: ['1.71.0', 'stable', 'beta'] + rust: ['1.71.1', 'stable', 'beta'] runs-on: ubuntu-latest steps: diff --git a/CHANGELOG.md b/CHANGELOG.md index a53fa647e..9568ba8ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Change Log +## Unreleased + +#### Breaking Changes +- `*DataExt` traits removed; now `*Data` types wrap custom data + * Any calls to `Proxy::data` will need to be updated for new type +- All `delegate_*!` macros except `delegate_registry!` replaced with single + `delegate_dispatch2!` in preparation for future wayland-rs release. + ## 0.20.0 - 2025-07-29 #### Breaking Changes diff --git a/examples/data_device.rs b/examples/data_device.rs index 154f636b9..c229c8a1e 100644 --- a/examples/data_device.rs +++ b/examples/data_device.rs @@ -11,16 +11,14 @@ use smithay_client_toolkit::reexports::calloop::{ }; use smithay_client_toolkit::reexports::calloop_wayland_source::WaylandSource; use smithay_client_toolkit::{ - compositor::{CompositorHandler, CompositorState}, + compositor::{CompositorHandler, CompositorState, FrameCallbackData}, data_device_manager::{ data_device::{DataDevice, DataDeviceHandler}, data_offer::{DataOfferHandler, DragOffer, SelectionOffer}, data_source::{CopyPasteSource, DataSourceHandler, DragSource}, DataDeviceManagerState, WritePipe, }, - delegate_compositor, delegate_data_device, delegate_keyboard, delegate_output, - delegate_pointer, delegate_primary_selection, delegate_registry, delegate_seat, delegate_shm, - delegate_xdg_shell, delegate_xdg_window, + delegate_registry, output::{OutputHandler, OutputState}, primary_selection::{ device::{PrimarySelectionDevice, PrimarySelectionDeviceHandler}, @@ -614,7 +612,7 @@ impl DataDeviceWindow { self.window.wl_surface().damage_buffer(0, 0, self.width as i32, self.height as i32); // Request our next frame - self.window.wl_surface().frame(qh, self.window.wl_surface().clone()); + self.window.wl_surface().frame(qh, FrameCallbackData(self.window.wl_surface().clone())); // Attach and commit to present. buffer.attach_to(self.window.wl_surface()).expect("buffer attach"); @@ -1081,21 +1079,6 @@ struct SeatObject { primary_device: Option, } -delegate_compositor!(DataDeviceWindow); -delegate_output!(DataDeviceWindow); -delegate_shm!(DataDeviceWindow); - -delegate_seat!(DataDeviceWindow); -delegate_keyboard!(DataDeviceWindow); -delegate_pointer!(DataDeviceWindow); - -delegate_xdg_shell!(DataDeviceWindow); -delegate_xdg_window!(DataDeviceWindow); - -delegate_data_device!(DataDeviceWindow); - -delegate_primary_selection!(DataDeviceWindow); - delegate_registry!(DataDeviceWindow); const SUPPORTED_MIME_TYPES: &[&str; 6] = &[ @@ -1115,3 +1098,5 @@ fn pick_mime(mime_types: &[String]) -> Option { None } + +smithay_client_toolkit::delegate_dispatch2!(DataDeviceWindow); diff --git a/examples/dmabuf_formats.rs b/examples/dmabuf_formats.rs index 18b505bcb..8f9193cda 100644 --- a/examples/dmabuf_formats.rs +++ b/examples/dmabuf_formats.rs @@ -127,5 +127,5 @@ fn print_format(format: &DmabufFormat) { println!(", Modifier: {:?}", DrmModifier::from(format.modifier)); } -smithay_client_toolkit::delegate_dmabuf!(AppData); smithay_client_toolkit::delegate_registry!(AppData); +smithay_client_toolkit::delegate_dispatch2!(AppData); diff --git a/examples/foreign-toplevel-monitor.rs b/examples/foreign-toplevel-monitor.rs index 5e634d679..7ff4d747d 100644 --- a/examples/foreign-toplevel-monitor.rs +++ b/examples/foreign-toplevel-monitor.rs @@ -1,7 +1,7 @@ use std::error::Error; use smithay_client_toolkit::{ - delegate_foreign_toplevel_list, delegate_registry, + delegate_registry, foreign_toplevel_list::{ForeignToplevelList, ForeignToplevelListHandler}, registry::{ProvidesRegistryState, RegistryState}, registry_handlers, @@ -77,5 +77,5 @@ impl ForeignToplevelListHandler for State { } } -delegate_foreign_toplevel_list!(State); delegate_registry!(State); +smithay_client_toolkit::delegate_dispatch2!(State); diff --git a/examples/generic_list_seats.rs b/examples/generic_list_seats.rs index 0aad545d9..8b1263ed5 100644 --- a/examples/generic_list_seats.rs +++ b/examples/generic_list_seats.rs @@ -1,5 +1,5 @@ use smithay_client_toolkit::{ - delegate_registry, delegate_seat, + delegate_registry, registry::{ProvidesRegistryState, RegistryState}, registry_handlers, seat::{Capability, SeatHandler, SeatState}, @@ -81,8 +81,6 @@ impl SeatHandler for ListSeats { } } -delegate_seat!(@ ListSeats); - delegate_registry!(@ ListSeats); impl ProvidesRegistryState for ListSeats { @@ -92,3 +90,5 @@ impl ProvidesRegistryState for ListSeats { registry_handlers!(SeatState); } + +smithay_client_toolkit::delegate_dispatch2!(@ ListSeats); diff --git a/examples/generic_simple_window.rs b/examples/generic_simple_window.rs index d06a1d674..eda4bc565 100644 --- a/examples/generic_simple_window.rs +++ b/examples/generic_simple_window.rs @@ -1,9 +1,8 @@ use std::convert::TryInto; use smithay_client_toolkit::{ - compositor::{CompositorHandler, CompositorState}, - delegate_compositor, delegate_keyboard, delegate_output, delegate_pointer, delegate_registry, - delegate_seat, delegate_shm, delegate_xdg_shell, delegate_xdg_window, + compositor::{CompositorHandler, CompositorState, FrameCallbackData}, + delegate_registry, output::{OutputHandler, OutputState}, registry::{ProvidesRegistryState, RegistryState}, registry_handlers, @@ -468,7 +467,7 @@ impl SimpleWindow { self.window.wl_surface().damage_buffer(0, 0, self.width as i32, self.height as i32); // Request our next frame - self.window.wl_surface().frame(qh, self.window.wl_surface().clone()); + self.window.wl_surface().frame(qh, FrameCallbackData(self.window.wl_surface().clone())); // Attach and commit to present. buffer.attach_to(self.window.wl_surface()).expect("buffer attach"); @@ -476,17 +475,6 @@ impl SimpleWindow { } } -delegate_compositor!(@ SimpleWindow); -delegate_output!(@ SimpleWindow); -delegate_shm!(@ SimpleWindow); - -delegate_seat!(@ SimpleWindow); -delegate_keyboard!(@ SimpleWindow); -delegate_pointer!(@ SimpleWindow); - -delegate_xdg_shell!(@ SimpleWindow); -delegate_xdg_window!(@ SimpleWindow); - delegate_registry!(@ SimpleWindow); impl ProvidesRegistryState for SimpleWindow { @@ -495,3 +483,5 @@ impl ProvidesRegistryState for SimpleWindow { } registry_handlers![OutputState, SeatState,]; } + +smithay_client_toolkit::delegate_dispatch2!(@ SimpleWindow); diff --git a/examples/image_viewer.rs b/examples/image_viewer.rs index 1057ecfaa..1488e4542 100644 --- a/examples/image_viewer.rs +++ b/examples/image_viewer.rs @@ -1,9 +1,8 @@ use std::env; use smithay_client_toolkit::{ - compositor::{CompositorHandler, CompositorState}, - delegate_compositor, delegate_output, delegate_registry, delegate_shm, delegate_xdg_shell, - delegate_xdg_window, + compositor::{CompositorHandler, CompositorState, FrameCallbackData}, + delegate_registry, output::{OutputHandler, OutputState}, registry::{ProvidesRegistryState, RegistryState}, registry_handlers, @@ -309,7 +308,7 @@ impl State { viewer.damaged = false; // Request our next frame - window.wl_surface().frame(qh, window.wl_surface().clone()); + window.wl_surface().frame(qh, FrameCallbackData(window.wl_surface().clone())); // Attach and commit to present. buffer.attach_to(window.wl_surface()).expect("buffer attach"); @@ -318,13 +317,6 @@ impl State { } } -delegate_compositor!(State); -delegate_output!(State); -delegate_shm!(State); - -delegate_xdg_shell!(State); -delegate_xdg_window!(State); - delegate_registry!(State); impl ProvidesRegistryState for State { @@ -334,3 +326,5 @@ impl ProvidesRegistryState for State { registry_handlers!(OutputState); } + +smithay_client_toolkit::delegate_dispatch2!(State); diff --git a/examples/image_viewporter.rs b/examples/image_viewporter.rs index c9f380b79..6610a37b0 100644 --- a/examples/image_viewporter.rs +++ b/examples/image_viewporter.rs @@ -2,8 +2,7 @@ use std::{env, path::Path}; use smithay_client_toolkit::{ compositor::{CompositorHandler, CompositorState}, - delegate_compositor, delegate_output, delegate_registry, delegate_shm, delegate_simple, - delegate_xdg_shell, delegate_xdg_window, + delegate_registry, output::{OutputHandler, OutputState}, registry::{ProvidesRegistryState, RegistryState, SimpleGlobal}, registry_handlers, @@ -318,14 +317,7 @@ impl State { } } -delegate_compositor!(State); -delegate_output!(State); -delegate_shm!(State); - -delegate_xdg_shell!(State); -delegate_xdg_window!(State); - -delegate_simple!(State, WpViewporter, 1); +wayland_client::delegate_noop!(State: WpViewporter); delegate_registry!(State); @@ -361,3 +353,5 @@ impl Drop for ImageViewer { self.viewport.destroy() } } + +smithay_client_toolkit::delegate_dispatch2!(State); diff --git a/examples/list_outputs.rs b/examples/list_outputs.rs index a2e23298b..7cc509de6 100644 --- a/examples/list_outputs.rs +++ b/examples/list_outputs.rs @@ -3,7 +3,7 @@ use std::error::Error; use smithay_client_toolkit::{ - delegate_output, delegate_registry, + delegate_registry, output::{OutputHandler, OutputInfo, OutputState}, registry::{ProvidesRegistryState, RegistryState}, registry_handlers, @@ -103,10 +103,6 @@ impl OutputHandler for ListOutputs { } } -// Now we need to say we are delegating the responsibility of output related events for our application data -// type to the requisite delegate. -delegate_output!(ListOutputs); - // In order for our delegate to know of the existence of globals, we need to implement registry // handling for the program. This trait will forward events to the RegistryHandler trait // implementations. @@ -125,7 +121,7 @@ impl ProvidesRegistryState for ListOutputs { registry_handlers! { // Here we specify that OutputState needs to receive events regarding the creation and destruction of // globals. - OutputState, + OutputState } } @@ -157,3 +153,5 @@ fn print_output(info: &OutputInfo) { println!("\t\t{mode}"); } } + +smithay_client_toolkit::delegate_dispatch2!(ListOutputs); diff --git a/examples/list_seats.rs b/examples/list_seats.rs index 49c1631a0..b3f42c318 100644 --- a/examples/list_seats.rs +++ b/examples/list_seats.rs @@ -1,5 +1,5 @@ use smithay_client_toolkit::{ - delegate_registry, delegate_seat, + delegate_registry, registry::{ProvidesRegistryState, RegistryState}, registry_handlers, seat::{Capability, SeatHandler, SeatState}, @@ -69,8 +69,6 @@ impl SeatHandler for ListSeats { } } -delegate_seat!(ListSeats); - delegate_registry!(ListSeats); impl ProvidesRegistryState for ListSeats { @@ -80,3 +78,5 @@ impl ProvidesRegistryState for ListSeats { registry_handlers!(SeatState); } + +smithay_client_toolkit::delegate_dispatch2!(ListSeats); diff --git a/examples/list_shm_formats.rs b/examples/list_shm_formats.rs index 1e9af1eec..7c2961986 100644 --- a/examples/list_shm_formats.rs +++ b/examples/list_shm_formats.rs @@ -1,8 +1,5 @@ /// Example app showing how to use delegate types from Smithay's client toolkit and initializing state. -use smithay_client_toolkit::{ - delegate_shm, - shm::{Shm, ShmHandler}, -}; +use smithay_client_toolkit::shm::{Shm, ShmHandler}; use wayland_client::{ globals::{registry_queue_init, GlobalListContents}, protocol::wl_registry, @@ -45,9 +42,6 @@ impl ShmHandler for ListShmFormats { } } -// Delegate handling of the wl_shm protocol to our state object. -delegate_shm!(ListShmFormats); - impl Dispatch for ListShmFormats { fn event( _state: &mut Self, @@ -60,3 +54,5 @@ impl Dispatch for ListShmFormats { // We don't need any other globals. } } + +smithay_client_toolkit::delegate_dispatch2!(ListShmFormats); diff --git a/examples/relative_pointer.rs b/examples/relative_pointer.rs index 667d9edc8..693ab69be 100644 --- a/examples/relative_pointer.rs +++ b/examples/relative_pointer.rs @@ -1,10 +1,8 @@ //! An example demonstrating relative pointer and (if supported) pointer constraints use smithay_client_toolkit::{ - compositor::{CompositorHandler, CompositorState}, - delegate_compositor, delegate_output, delegate_pointer, delegate_pointer_constraints, - delegate_registry, delegate_relative_pointer, delegate_seat, delegate_shm, delegate_xdg_shell, - delegate_xdg_window, + compositor::{CompositorHandler, CompositorState, FrameCallbackData}, + delegate_registry, globals::ProvidesBoundGlobal, output::{OutputHandler, OutputState}, registry::{ProvidesRegistryState, RegistryState}, @@ -444,7 +442,7 @@ impl SimpleWindow { window.wl_surface().damage_buffer(0, 0, self.width as i32, self.height as i32); // Request our next frame - window.wl_surface().frame(qh, window.wl_surface().clone()); + window.wl_surface().frame(qh, FrameCallbackData(window.wl_surface().clone())); // Attach and commit to present. buffer.attach_to(window.wl_surface()).expect("buffer attach"); @@ -546,18 +544,6 @@ impl SimpleWindow { } } -delegate_compositor!(SimpleWindow); -delegate_output!(SimpleWindow); -delegate_shm!(SimpleWindow); - -delegate_seat!(SimpleWindow); -delegate_pointer!(SimpleWindow); -delegate_pointer_constraints!(SimpleWindow); -delegate_relative_pointer!(SimpleWindow); - -delegate_xdg_shell!(SimpleWindow); -delegate_xdg_window!(SimpleWindow); - delegate_registry!(SimpleWindow); impl ProvidesRegistryState for SimpleWindow { @@ -578,3 +564,5 @@ impl Dispatch for SimpleWindow { ) { } } + +smithay_client_toolkit::delegate_dispatch2!(SimpleWindow); diff --git a/examples/session_lock.rs b/examples/session_lock.rs index 03f8d1be6..077063754 100644 --- a/examples/session_lock.rs +++ b/examples/session_lock.rs @@ -249,9 +249,6 @@ impl ShmHandler for AppData { } } -smithay_client_toolkit::delegate_compositor!(AppData); -smithay_client_toolkit::delegate_output!(AppData); -smithay_client_toolkit::delegate_session_lock!(AppData); -smithay_client_toolkit::delegate_shm!(AppData); smithay_client_toolkit::delegate_registry!(AppData); wayland_client::delegate_noop!(AppData: ignore wl_buffer::WlBuffer); +smithay_client_toolkit::delegate_dispatch2!(AppData); diff --git a/examples/simple_layer.rs b/examples/simple_layer.rs index 8b5e6d228..671dbfcb5 100644 --- a/examples/simple_layer.rs +++ b/examples/simple_layer.rs @@ -3,9 +3,8 @@ use std::{convert::TryInto, num::NonZeroU32}; use smithay_client_toolkit::{ - compositor::{CompositorHandler, CompositorState}, - delegate_compositor, delegate_keyboard, delegate_layer, delegate_output, delegate_pointer, - delegate_registry, delegate_seat, delegate_shm, + compositor::{CompositorHandler, CompositorState, FrameCallbackData}, + delegate_registry, output::{OutputHandler, OutputState}, registry::{ProvidesRegistryState, RegistryState}, registry_handlers, @@ -437,7 +436,7 @@ impl SimpleLayer { self.layer.wl_surface().damage_buffer(0, 0, width as i32, height as i32); // Request our next frame - self.layer.wl_surface().frame(qh, self.layer.wl_surface().clone()); + self.layer.wl_surface().frame(qh, FrameCallbackData(self.layer.wl_surface().clone())); // Attach and commit to present. buffer.attach_to(self.layer.wl_surface()).expect("buffer attach"); @@ -449,16 +448,6 @@ impl SimpleLayer { } } -delegate_compositor!(SimpleLayer); -delegate_output!(SimpleLayer); -delegate_shm!(SimpleLayer); - -delegate_seat!(SimpleLayer); -delegate_keyboard!(SimpleLayer); -delegate_pointer!(SimpleLayer); - -delegate_layer!(SimpleLayer); - delegate_registry!(SimpleLayer); impl ProvidesRegistryState for SimpleLayer { @@ -467,3 +456,5 @@ impl ProvidesRegistryState for SimpleLayer { } registry_handlers![OutputState, SeatState]; } + +smithay_client_toolkit::delegate_dispatch2!(SimpleLayer); diff --git a/examples/simple_window.rs b/examples/simple_window.rs index 97aaba556..8069530e2 100644 --- a/examples/simple_window.rs +++ b/examples/simple_window.rs @@ -5,9 +5,8 @@ use smithay_client_toolkit::reexports::calloop::{EventLoop, LoopHandle}; use smithay_client_toolkit::reexports::calloop_wayland_source::WaylandSource; use smithay_client_toolkit::{ activation::{ActivationHandler, ActivationState}, - compositor::{CompositorHandler, CompositorState}, - delegate_activation, delegate_compositor, delegate_keyboard, delegate_output, delegate_pointer, - delegate_registry, delegate_seat, delegate_shm, delegate_xdg_shell, delegate_xdg_window, + compositor::{CompositorHandler, CompositorState, FrameCallbackData}, + delegate_registry, output::{OutputHandler, OutputState}, registry::{ProvidesRegistryState, RegistryState}, registry_handlers, @@ -85,6 +84,7 @@ fn main() { seat_and_serial: None, surface: Some(window.wl_surface().clone()), app_id: Some(String::from("io.github.smithay.client-toolkit.SimpleWindow")), + udata: (), }, ) } @@ -258,9 +258,9 @@ impl WindowHandler for SimpleWindow { } impl ActivationHandler for SimpleWindow { - type RequestData = RequestData; + type RequestUdata = (); - fn new_token(&mut self, token: String, _data: &Self::RequestData) { + fn new_token(&mut self, token: String, _data: &RequestData<()>) { self.xdg_activation .as_ref() .unwrap() @@ -508,7 +508,7 @@ impl SimpleWindow { self.window.wl_surface().damage_buffer(0, 0, self.width as i32, self.height as i32); // Request our next frame - self.window.wl_surface().frame(qh, self.window.wl_surface().clone()); + self.window.wl_surface().frame(qh, FrameCallbackData(self.window.wl_surface().clone())); // Attach and commit to present. buffer.attach_to(self.window.wl_surface()).expect("buffer attach"); @@ -516,18 +516,6 @@ impl SimpleWindow { } } -delegate_compositor!(SimpleWindow); -delegate_output!(SimpleWindow); -delegate_shm!(SimpleWindow); - -delegate_seat!(SimpleWindow); -delegate_keyboard!(SimpleWindow); -delegate_pointer!(SimpleWindow); - -delegate_xdg_shell!(SimpleWindow); -delegate_xdg_window!(SimpleWindow); -delegate_activation!(SimpleWindow); - delegate_registry!(SimpleWindow); impl ProvidesRegistryState for SimpleWindow { @@ -536,3 +524,5 @@ impl ProvidesRegistryState for SimpleWindow { } registry_handlers![OutputState, SeatState,]; } + +smithay_client_toolkit::delegate_dispatch2!(SimpleWindow); diff --git a/examples/themed_window.rs b/examples/themed_window.rs index 10d6fd405..dd762fbf8 100644 --- a/examples/themed_window.rs +++ b/examples/themed_window.rs @@ -12,9 +12,8 @@ use smithay_client_toolkit::reexports::csd_frame::{ }; use smithay_client_toolkit::reexports::protocols::xdg::shell::client::xdg_toplevel::ResizeEdge as XdgResizeEdge; use smithay_client_toolkit::{ - compositor::{CompositorHandler, CompositorState}, - delegate_compositor, delegate_keyboard, delegate_output, delegate_pointer, delegate_registry, - delegate_seat, delegate_shm, delegate_subcompositor, delegate_xdg_shell, delegate_xdg_window, + compositor::{CompositorHandler, CompositorState, FrameCallbackData}, + delegate_registry, output::{OutputHandler, OutputState}, registry::{ProvidesRegistryState, RegistryState}, registry_handlers, @@ -387,7 +386,7 @@ impl SeatHandler for SimpleWindow { let surface = self.compositor_state.create_surface(qh); let themed_pointer = self .seat_state - .get_pointer_with_theme( + .get_pointer_with_theme::<_, ()>( qh, &seat, self.shm_state.wl_shm(), @@ -563,7 +562,7 @@ impl PointerHandler for SimpleWindow { impl SimpleWindow { fn frame_action(&mut self, pointer: &wl_pointer::WlPointer, serial: u32, action: FrameAction) { - let pointer_data = pointer.data::().unwrap(); + let pointer_data = pointer.data::>().unwrap(); let seat = pointer_data.seat(); match action { FrameAction::Close => self.exit = true, @@ -665,7 +664,7 @@ impl SimpleWindow { self.window.wl_surface().damage_buffer(0, 0, width as i32, height as i32); // Request our next frame - self.window.wl_surface().frame(qh, self.window.wl_surface().clone()); + self.window.wl_surface().frame(qh, FrameCallbackData(self.window.wl_surface().clone())); // Attach and commit to present. buffer.attach_to(self.window.wl_surface()).expect("buffer attach"); @@ -673,18 +672,6 @@ impl SimpleWindow { } } -delegate_compositor!(SimpleWindow); -delegate_subcompositor!(SimpleWindow); -delegate_output!(SimpleWindow); -delegate_shm!(SimpleWindow); - -delegate_seat!(SimpleWindow); -delegate_keyboard!(SimpleWindow); -delegate_pointer!(SimpleWindow); - -delegate_xdg_shell!(SimpleWindow); -delegate_xdg_window!(SimpleWindow); - delegate_registry!(SimpleWindow); impl ProvidesRegistryState for SimpleWindow { @@ -693,3 +680,5 @@ impl ProvidesRegistryState for SimpleWindow { } registry_handlers![OutputState, SeatState,]; } + +smithay_client_toolkit::delegate_dispatch2!(SimpleWindow); diff --git a/examples/wgpu.rs b/examples/wgpu.rs index a583f6c64..1ed24853a 100644 --- a/examples/wgpu.rs +++ b/examples/wgpu.rs @@ -3,8 +3,7 @@ use raw_window_handle::{ }; use smithay_client_toolkit::{ compositor::{CompositorHandler, CompositorState}, - delegate_compositor, delegate_output, delegate_registry, delegate_seat, delegate_xdg_shell, - delegate_xdg_window, + delegate_registry, output::{OutputHandler, OutputState}, registry::{ProvidesRegistryState, RegistryState}, registry_handlers, @@ -300,14 +299,6 @@ impl SeatHandler for Wgpu { fn remove_seat(&mut self, _: &Connection, _: &QueueHandle, _: wl_seat::WlSeat) {} } -delegate_compositor!(Wgpu); -delegate_output!(Wgpu); - -delegate_seat!(Wgpu); - -delegate_xdg_shell!(Wgpu); -delegate_xdg_window!(Wgpu); - delegate_registry!(Wgpu); impl ProvidesRegistryState for Wgpu { @@ -316,3 +307,5 @@ impl ProvidesRegistryState for Wgpu { } registry_handlers![OutputState]; } + +smithay_client_toolkit::delegate_dispatch2!(Wgpu); diff --git a/src/activation.rs b/src/activation.rs index 69914f031..c0e37e114 100644 --- a/src/activation.rs +++ b/src/activation.rs @@ -6,6 +6,7 @@ use wayland_client::{ use wayland_protocols::xdg::activation::v1::client::{xdg_activation_token_v1, xdg_activation_v1}; use crate::{ + dispatch2::Dispatch2, error::GlobalError, globals::{GlobalData, ProvidesBoundGlobal}, }; @@ -15,7 +16,7 @@ use crate::{ /// Use a custom type implementing [`RequestDataExt`] to store more data with a token request /// e.g. to identify which request produced which token. #[derive(Debug, Clone)] -pub struct RequestData { +pub struct RequestData { /// App_id of the application requesting the token, if applicable pub app_id: Option, /// Seat and serial of the window requesting the token, if applicable. @@ -28,44 +29,17 @@ pub struct RequestData { /// *Warning*: Many compositors will issue invalid tokens for requests from /// unfocused surfaces. There is no way to detect this from the client-side. pub surface: Option, -} - -/// Data attached to a token request -pub trait RequestDataExt: Send + Sync { - /// App_id of the application requesting the token, if applicable - fn app_id(&self) -> Option<&str>; - /// Seat and serial of the window requesting the token, if applicable. - /// - /// *Warning*: Many compositors will issue invalid tokens for requests without - /// recent serials. There is no way to detect this from the client-side. - fn seat_and_serial(&self) -> Option<(&wl_seat::WlSeat, u32)>; - /// Surface of the window requesting the token, if applicable. - /// - /// *Warning*: Many compositors will issue invalid tokens for requests from - /// unfocused surfaces. There is no way to detect this from the client-side. - fn surface(&self) -> Option<&wl_surface::WlSurface>; -} -impl RequestDataExt for RequestData { - fn app_id(&self) -> Option<&str> { - self.app_id.as_deref() - } - - fn seat_and_serial(&self) -> Option<(&wl_seat::WlSeat, u32)> { - self.seat_and_serial.as_ref().map(|(seat, serial)| (seat, *serial)) - } - - fn surface(&self) -> Option<&wl_surface::WlSurface> { - self.surface.as_ref() - } + pub udata: U, } /// Handler for xdg-activation pub trait ActivationHandler: Sized { /// Data type used for requesting activation tokens - type RequestData: RequestDataExt; + // TODO: Default to `()` if default associated types are ever supported + type RequestUdata; /// A token was issued for a previous request with `data`. - fn new_token(&mut self, token: String, data: &Self::RequestData); + fn new_token(&mut self, token: String, data: &RequestData); } /// State for xdg-activation @@ -96,48 +70,36 @@ impl ActivationState { /// /// To attach custom data to the request implement [`RequestDataExt`] on a custom type /// and use [`Self::request_token_with_data`] instead. - pub fn request_token(&self, qh: &QueueHandle, request_data: RequestData) - where - D: ActivationHandler, - D: Dispatch + 'static, - { - Self::request_token_with_data::(self, qh, request_data) - } - - /// Request a token for surface activation with user data. - /// - /// To use this method you need to provide [`delegate_activation`][crate::delegate_activation] with your custom type. - /// E.g. `delegate_activation!(SimpleWindow, MyRequestData);` - pub fn request_token_with_data(&self, qh: &QueueHandle, request_data: R) + pub fn request_token(&self, qh: &QueueHandle, request_data: RequestData) where - D: ActivationHandler, - D: Dispatch + 'static, - R: RequestDataExt + 'static, + D: ActivationHandler, + D: Dispatch> + 'static, + U: Send + Sync + 'static, { let token = self.xdg_activation.get_activation_token(qh, request_data); - let data = token.data::().unwrap(); - if let Some(app_id) = data.app_id() { + let data = token.data::>().unwrap(); + if let Some(app_id) = &data.app_id { token.set_app_id(String::from(app_id)); } - if let Some((seat, serial)) = data.seat_and_serial() { - token.set_serial(serial, seat); + if let Some((seat, serial)) = &data.seat_and_serial { + token.set_serial(*serial, seat); } - if let Some(surface) = data.surface() { + if let Some(surface) = &data.surface { token.set_surface(surface); } token.commit(); } } -impl Dispatch for ActivationState +impl Dispatch2 for GlobalData where - D: Dispatch + ActivationHandler, + D: ActivationHandler, { fn event( + &self, _: &mut D, _: &xdg_activation_v1::XdgActivationV1, _: ::Event, - _: &GlobalData, _: &wayland_client::Connection, _: &QueueHandle, ) { @@ -151,50 +113,20 @@ impl ProvidesBoundGlobal for ActivationSt } } -impl Dispatch for ActivationState +impl Dispatch2 for RequestData where - D: Dispatch - + ActivationHandler, - R: RequestDataExt, + D: ActivationHandler, { fn event( + &self, state: &mut D, _proxy: &xdg_activation_token_v1::XdgActivationTokenV1, event: ::Event, - data: &R, _conn: &wayland_client::Connection, _qhandle: &QueueHandle, ) { if let xdg_activation_token_v1::Event::Done { token } = event { - state.new_token(token, data); + state.new_token(token, self); } } } - -#[macro_export] -macro_rules! delegate_activation { - ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => { - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: - [ - $crate::reexports::protocols::xdg::activation::v1::client::xdg_activation_v1::XdgActivationV1: $crate::globals::GlobalData - ] => $crate::activation::ActivationState - ); - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: - [ - $crate::reexports::protocols::xdg::activation::v1::client::xdg_activation_token_v1::XdgActivationTokenV1: $crate::activation::RequestData - ] => $crate::activation::ActivationState - ); - }; - ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty, $data: ty) => { - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: - [ - $crate::reexports::protocols::xdg::activation::v1::client::xdg_activation_v1::XdgActivationV1: $crate::globals::GlobalData - ] => $crate::activation::ActivationState - ); - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: - [ - $crate::reexports::protocols::xdg::activation::v1::client::xdg_activation_token_v1::XdgActivationTokenV1: $data - ] => $crate::activation::ActivationState - ); - }; -} diff --git a/src/background_effect.rs b/src/background_effect.rs index 764cb3b0b..8f06bb8ad 100644 --- a/src/background_effect.rs +++ b/src/background_effect.rs @@ -5,7 +5,7 @@ use wayland_protocols::ext::background_effect::v1::client::{ ext_background_effect_manager_v1, ext_background_effect_surface_v1, }; -use crate::{error::GlobalError, globals::GlobalData, registry::GlobalProxy}; +use crate::{dispatch2::Dispatch2, error::GlobalError, globals::GlobalData, registry::GlobalProxy}; #[derive(Debug)] pub struct BackgroundEffectState { @@ -62,17 +62,15 @@ pub trait BackgroundEffectHandler { fn update_capabilities(&mut self); } -impl Dispatch - for BackgroundEffectState +impl Dispatch2 for GlobalData where - D: Dispatch - + BackgroundEffectHandler, + D: BackgroundEffectHandler, { fn event( + &self, data: &mut D, _manager: &ext_background_effect_manager_v1::ExtBackgroundEffectManagerV1, event: ext_background_effect_manager_v1::Event, - _: &GlobalData, _conn: &Connection, _qh: &QueueHandle, ) { @@ -92,31 +90,17 @@ where } } -impl Dispatch - for BackgroundEffectState -where - D: Dispatch, +impl Dispatch2 + for GlobalData { fn event( + &self, _data: &mut D, _surface: &ext_background_effect_surface_v1::ExtBackgroundEffectSurfaceV1, _event: ext_background_effect_surface_v1::Event, - _: &GlobalData, _conn: &Connection, _qh: &QueueHandle, ) { unreachable!() } } - -#[macro_export] -macro_rules! delegate_background_effect { - ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => { - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ - $crate::reexports::protocols::ext::background_effect::v1::client::ext_background_effect_manager_v1::ExtBackgroundEffectManagerV1: $crate::globals::GlobalData - ] => $crate::background_effect::BackgroundEffectState); - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ - $crate::reexports::protocols::ext::background_effect::v1::client::ext_background_effect_surface_v1::ExtBackgroundEffectSurfaceV1: $crate::globals::GlobalData - ] => $crate::background_effect::BackgroundEffectState); - }; -} diff --git a/src/compositor.rs b/src/compositor.rs index ba0f4ad34..016db0f89 100644 --- a/src/compositor.rs +++ b/src/compositor.rs @@ -16,6 +16,7 @@ use wayland_client::{ }; use crate::{ + dispatch2::Dispatch2, error::GlobalError, globals::{GlobalData, ProvidesBoundGlobal}, output::{OutputData, OutputHandler, OutputState, ScaleWatcherHandle}, @@ -77,16 +78,6 @@ pub trait CompositorHandler: Sized { ); } -pub trait SurfaceDataExt: Send + Sync { - fn surface_data(&self) -> &SurfaceData; -} - -impl SurfaceDataExt for SurfaceData { - fn surface_data(&self) -> &SurfaceData { - self - } -} - #[derive(Clone, Debug)] pub struct CompositorState { wl_compositor: wl_compositor::WlCompositor, @@ -116,27 +107,30 @@ impl CompositorState { pub fn create_surface(&self, qh: &QueueHandle) -> wl_surface::WlSurface where - D: Dispatch + 'static, + D: Dispatch> + 'static, { - self.create_surface_with_data(qh, Default::default()) + self.create_surface_with_data(qh, None, 1, ()) } pub fn create_surface_with_data( &self, qh: &QueueHandle, + parent_surface: Option, + scale_factor: i32, data: U, ) -> wl_surface::WlSurface where - D: Dispatch + 'static, - U: SurfaceDataExt + 'static, + D: Dispatch> + 'static, + U: Send + Sync + 'static, { + let data = SurfaceData::new(parent_surface, scale_factor, data); self.wl_compositor.create_surface(qh, data) } } /// Data associated with a [`WlSurface`]. #[derive(Debug)] -pub struct SurfaceData { +pub struct SurfaceData { /// The scale factor of the output with the highest scale factor. pub(crate) scale_factor: AtomicI32, @@ -147,18 +141,29 @@ pub struct SurfaceData { /// The inner mutable storage. inner: Mutex, + + udata: U, } -impl SurfaceData { +impl SurfaceData { /// Create a new surface that initially reports the given scale factor and parent. - pub fn new(parent_surface: Option, scale_factor: i32) -> Self { + pub fn new(parent_surface: Option, scale_factor: i32, udata: U) -> Self { Self { scale_factor: AtomicI32::new(scale_factor), parent_surface, inner: Default::default(), + udata, } } + pub fn data(&self) -> &U { + &self.udata + } + + pub fn data_mut(&mut self) -> &mut U { + &mut self.udata + } + /// The scale factor of the output with the highest scale factor. pub fn scale_factor(&self) -> i32 { self.scale_factor.load(Ordering::Relaxed) @@ -183,11 +188,13 @@ impl SurfaceData { } } +/* XXX impl Default for SurfaceData { fn default() -> Self { Self::new(None, 1) } } +*/ #[derive(Debug)] struct SurfaceDataInner { @@ -222,9 +229,9 @@ impl Surface { qh: &QueueHandle, ) -> Result where - D: Dispatch + 'static, + D: Dispatch> + 'static, { - Self::with_data(compositor, qh, Default::default()) + Self::with_data(compositor, qh, None, 1, ()) } pub fn with_data( @@ -233,12 +240,15 @@ impl Surface { { CompositorState::API_VERSION_MAX }, >, qh: &QueueHandle, + parent_surface: Option, + scale_factor: i32, data: U, ) -> Result where - D: Dispatch + 'static, + D: Dispatch> + 'static, U: Send + Sync + 'static, { + let data = SurfaceData::new(parent_surface, scale_factor, data); Ok(Surface(compositor.bound_global()?.create_surface(qh, data))) } @@ -259,57 +269,20 @@ impl Drop for Surface { } } -#[macro_export] -macro_rules! delegate_compositor { - ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => { - $crate::delegate_compositor!(@{ $(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty }; surface: []); - $crate::delegate_compositor!(@{ $(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty }; surface-only: $crate::compositor::SurfaceData); - }; - ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty, surface: [$($surface: ty),*$(,)?]) => { - $crate::delegate_compositor!(@{ $(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty }; surface: [ $($surface),* ]); - }; - (@{$($ty:tt)*}; surface: []) => { - $crate::reexports::client::delegate_dispatch!($($ty)*: - [ - $crate::reexports::client::protocol::wl_compositor::WlCompositor: $crate::globals::GlobalData - ] => $crate::compositor::CompositorState - ); - $crate::reexports::client::delegate_dispatch!($($ty)*: - [ - $crate::reexports::client::protocol::wl_callback::WlCallback: $crate::reexports::client::protocol::wl_surface::WlSurface - ] => $crate::compositor::CompositorState - ); - }; - (@{$($ty:tt)*}; surface-only: $surface:ty) => { - $crate::reexports::client::delegate_dispatch!($($ty)*: - [ - $crate::reexports::client::protocol::wl_surface::WlSurface: $surface - ] => $crate::compositor::CompositorState - ); - }; - (@$ty:tt; surface: [ $($surface:ty),+ ]) => { - $crate::delegate_compositor!(@$ty; surface: []); - $( - $crate::delegate_compositor!(@$ty; surface-only: $surface); - )* - }; -} - -impl Dispatch for CompositorState +impl Dispatch2 for SurfaceData where - D: Dispatch + CompositorHandler + OutputHandler + 'static, - U: SurfaceDataExt + 'static, + D: CompositorHandler + OutputHandler + 'static, + U: Send + Sync + 'static, { fn event( + &self, state: &mut D, surface: &wl_surface::WlSurface, event: wl_surface::Event, - data: &U, conn: &Connection, qh: &QueueHandle, ) { - let data = data.surface_data(); - let mut inner = data.inner.lock().unwrap(); + let mut inner = self.inner.lock().unwrap(); let mut enter_or_leave_output: Option<(wl_output::WlOutput, bool)> = None; @@ -323,9 +296,9 @@ where enter_or_leave_output.replace((output, false)); } wl_surface::Event::PreferredBufferScale { factor } => { - let current_scale = data.scale_factor.load(Ordering::Relaxed); + let current_scale = self.scale_factor.load(Ordering::Relaxed); drop(inner); - data.scale_factor.store(factor, Ordering::Relaxed); + self.scale_factor.store(factor, Ordering::Relaxed); if current_scale != factor { state.scale_factor_changed(conn, qh, surface, factor); } @@ -365,8 +338,7 @@ where OutputState::add_scale_watcher(state, move |state, conn, qh, _| { let id = id.clone(); if let Ok(surface) = wl_surface::WlSurface::from_id(conn, id) { - if let Some(data) = surface.data::() { - let data = data.surface_data(); + if let Some(data) = surface.data::>() { let inner = data.inner.lock().unwrap(); dispatch_surface_state_updates(state, conn, qh, &surface, data, inner); } @@ -374,7 +346,7 @@ where }) }); - dispatch_surface_state_updates(state, conn, qh, surface, data, inner); + dispatch_surface_state_updates(state, conn, qh, surface, self, inner); match enter_or_leave_output { Some((output, true)) => state.surface_enter(conn, qh, surface, &output), @@ -389,11 +361,10 @@ fn dispatch_surface_state_updates( conn: &Connection, qh: &QueueHandle, surface: &WlSurface, - data: &SurfaceData, + data: &SurfaceData, mut inner: MutexGuard, ) where - D: Dispatch + CompositorHandler + OutputHandler + 'static, - U: SurfaceDataExt + 'static, + D: CompositorHandler + OutputHandler + 'static, { let current_scale = data.scale_factor.load(Ordering::Relaxed); let (factor, transform) = match inner @@ -481,15 +452,15 @@ impl wayland_client::backend::ObjectData for RegionData { fn destroyed(&self, _: wayland_client::backend::ObjectId) {} } -impl Dispatch for CompositorState +impl Dispatch2 for GlobalData where - D: Dispatch + CompositorHandler, + D: CompositorHandler, { fn event( + &self, _: &mut D, _: &wl_compositor::WlCompositor, _: wl_compositor::Event, - _: &GlobalData, _: &Connection, _: &QueueHandle, ) { @@ -505,21 +476,24 @@ impl ProvidesBoundGlobal Dispatch for CompositorState +#[derive(Debug)] +pub struct FrameCallbackData(pub wl_surface::WlSurface); + +impl Dispatch2 for FrameCallbackData where - D: Dispatch + CompositorHandler, + D: CompositorHandler, { fn event( + &self, state: &mut D, _: &wl_callback::WlCallback, event: wl_callback::Event, - surface: &wl_surface::WlSurface, conn: &Connection, qh: &QueueHandle, ) { match event { wl_callback::Event::Done { callback_data } => { - state.frame(conn, qh, surface, callback_data); + state.frame(conn, qh, &self.0, callback_data); } _ => unreachable!(), diff --git a/src/data_device_manager/data_device.rs b/src/data_device_manager/data_device.rs index 087e457f4..82aef3c7b 100644 --- a/src/data_device_manager/data_device.rs +++ b/src/data_device_manager/data_device.rs @@ -7,6 +7,7 @@ use wayland_client::protocol::wl_surface::WlSurface; use crate::{ data_device_manager::data_offer::DataDeviceOffer, + dispatch2::Dispatch2, reexports::client::{ event_created_child, protocol::{ @@ -18,10 +19,7 @@ use crate::{ }, }; -use super::{ - data_offer::{DataOfferData, DataOfferHandler, DragOffer, SelectionOffer}, - DataDeviceManagerState, -}; +use super::data_offer::{DataOfferData, DataOfferHandler, DragOffer, SelectionOffer}; /// Handler trait for DataDevice events. /// @@ -105,10 +103,9 @@ impl Drop for DataDevice { } } -impl Dispatch for DataDeviceManagerState +impl Dispatch2 for DataDeviceData where - D: Dispatch - + Dispatch + D: Dispatch + DataDeviceHandler + DataOfferHandler + 'static, @@ -118,15 +115,15 @@ where ]); fn event( + &self, state: &mut D, data_device: &wl_data_device::WlDataDevice, event: wl_data_device::Event, - data: &DataDeviceData, conn: &Connection, qh: &QueueHandle, ) { use wayland_client::protocol::wl_data_device::Event; - let mut inner = data.inner.lock().unwrap(); + let mut inner = self.inner.lock().unwrap(); match event { Event::DataOffer { id } => { diff --git a/src/data_device_manager/data_offer.rs b/src/data_device_manager/data_offer.rs index 3614a790e..ad69c9257 100644 --- a/src/data_device_manager/data_offer.rs +++ b/src/data_device_manager/data_offer.rs @@ -6,16 +6,17 @@ use std::{ use log::warn; +use crate::dispatch2::Dispatch2; use crate::reexports::client::{ protocol::{ wl_data_device_manager::DndAction, wl_data_offer::{self, WlDataOffer}, wl_surface::WlSurface, }, - Connection, Dispatch, Proxy, QueueHandle, + Connection, Proxy, QueueHandle, }; -use super::{DataDeviceManagerState, ReadPipe}; +use super::ReadPipe; /// Handler trait for DataOffer events. /// @@ -359,27 +360,27 @@ impl Default for DataDeviceOffer { } } -impl Dispatch for DataDeviceManagerState +impl Dispatch2 for DataOfferData where - D: Dispatch + DataOfferHandler, + D: DataOfferHandler, { fn event( + &self, state: &mut D, _offer: &wl_data_offer::WlDataOffer, event: ::Event, - data: &DataOfferData, conn: &wayland_client::Connection, qh: &wayland_client::QueueHandle, ) { match event { wl_data_offer::Event::Offer { mime_type } => { - data.push_mime_type(mime_type); + self.push_mime_type(mime_type); } wl_data_offer::Event::SourceActions { source_actions } => { match source_actions { wayland_client::WEnum::Value(a) => { - data.set_source_action(a); - match &mut data.inner.lock().unwrap().offer { + self.set_source_action(a); + match &mut self.inner.lock().unwrap().offer { DataDeviceOffer::Drag(o) => { state.source_actions(conn, qh, o, a); } @@ -393,8 +394,8 @@ where wl_data_offer::Event::Action { dnd_action } => { match dnd_action { wayland_client::WEnum::Value(a) => { - data.set_selected_action(a); - match &mut data.inner.lock().unwrap().offer { + self.set_selected_action(a); + match &mut self.inner.lock().unwrap().offer { DataDeviceOffer::Drag(o) => { state.selected_action(conn, qh, o, a); } diff --git a/src/data_device_manager/data_source.rs b/src/data_device_manager/data_source.rs index aa523549b..01d6660c8 100644 --- a/src/data_device_manager/data_source.rs +++ b/src/data_device_manager/data_source.rs @@ -1,24 +1,31 @@ +use crate::dispatch2::Dispatch2; use crate::reexports::client::{ protocol::{ wl_data_device_manager::DndAction, wl_data_source::{self, WlDataSource}, wl_surface::WlSurface, }, - Connection, Dispatch, Proxy, QueueHandle, WEnum, + Connection, Proxy, QueueHandle, WEnum, }; -use super::{data_device::DataDevice, DataDeviceManagerState, WritePipe}; +use super::{data_device::DataDevice, WritePipe}; #[derive(Debug, Default)] -pub struct DataSourceData {} - -pub trait DataSourceDataExt: Send + Sync { - fn data_source_data(&self) -> &DataSourceData; +pub struct DataSourceData { + udata: U, } -impl DataSourceDataExt for DataSourceData { - fn data_source_data(&self) -> &DataSourceData { - self +impl DataSourceData { + pub fn new(udata: U) -> Self { + Self { udata } + } + + pub fn data(&self) -> &U { + &self.udata + } + + pub fn data_mut(&mut self) -> &mut U { + &mut self.udata } } @@ -68,16 +75,15 @@ pub trait DataSourceHandler: Sized { ); } -impl Dispatch for DataDeviceManagerState +impl Dispatch2 for DataSourceData where - D: Dispatch + DataSourceHandler, - U: DataSourceDataExt, + D: DataSourceHandler, { fn event( + &self, state: &mut D, source: &wl_data_source::WlDataSource, event: ::Event, - _data: &U, conn: &wayland_client::Connection, qh: &wayland_client::QueueHandle, ) { diff --git a/src/data_device_manager/mod.rs b/src/data_device_manager/mod.rs index a61693ae4..63697cc3c 100644 --- a/src/data_device_manager/mod.rs +++ b/src/data_device_manager/mod.rs @@ -1,3 +1,4 @@ +use crate::dispatch2::Dispatch2; use crate::error::GlobalError; use crate::globals::{GlobalData, ProvidesBoundGlobal}; use crate::reexports::client::{ @@ -48,7 +49,7 @@ impl DataDeviceManagerState { mime_types: impl IntoIterator, ) -> CopyPasteSource where - D: Dispatch + 'static, + D: Dispatch> + 'static, { CopyPasteSource { inner: self.create_data_source(qh, mime_types, None) } } @@ -61,7 +62,7 @@ impl DataDeviceManagerState { dnd_actions: DndAction, ) -> DragSource where - D: Dispatch + 'static, + D: Dispatch> + 'static, { DragSource { inner: self.create_data_source(qh, mime_types, Some(dnd_actions)) } } @@ -74,7 +75,7 @@ impl DataDeviceManagerState { dnd_actions: Option, ) -> WlDataSource where - D: Dispatch + 'static, + D: Dispatch> + 'static, { let source = self.manager.create_data_source(qh, Default::default()); @@ -107,43 +108,15 @@ impl ProvidesBoundGlobal for DataDeviceManagerState { } } -impl Dispatch - for DataDeviceManagerState -where - D: Dispatch, -{ +impl Dispatch2 for GlobalData { fn event( + &self, _state: &mut D, _proxy: &wl_data_device_manager::WlDataDeviceManager, _event: ::Event, - _data: &GlobalData, _conn: &Connection, _qhandle: &QueueHandle, ) { unreachable!("wl_data_device_manager has no events") } } - -#[macro_export] -macro_rules! delegate_data_device { - ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => { - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: - [ - $crate::reexports::client::protocol::wl_data_device_manager::WlDataDeviceManager: $crate::globals::GlobalData - ] => $crate::data_device_manager::DataDeviceManagerState); - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: - [ - $crate::reexports::client::protocol::wl_data_offer::WlDataOffer: $crate::data_device_manager::data_offer::DataOfferData - ] => $crate::data_device_manager::DataDeviceManagerState); - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: - [ - $crate::reexports::client::protocol::wl_data_source::WlDataSource: $crate::data_device_manager::data_source::DataSourceData - ] => $crate::data_device_manager::DataDeviceManagerState - ); - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: - [ - $crate::reexports::client::protocol::wl_data_device::WlDataDevice: $crate::data_device_manager::data_device::DataDeviceData - ] => $crate::data_device_manager::DataDeviceManagerState - ); - }; -} diff --git a/src/dispatch2.rs b/src/dispatch2.rs new file mode 100644 index 000000000..a2082b3fe --- /dev/null +++ b/src/dispatch2.rs @@ -0,0 +1,47 @@ +use std::sync::Arc; +use wayland_client::backend::ObjectData; +use wayland_client::{Connection, Proxy, QueueHandle}; + +pub trait Dispatch2 { + fn event( + &self, + _: &mut State, + _: &I, + _: ::Event, + _: &Connection, + _: &QueueHandle, + ); + + fn event_created_child(opcode: u16, _qh: &QueueHandle) -> Arc { + panic!( + "Missing event_created_child specialization for event opcode {} of {}", + opcode, + I::interface().name + ); + } +} + +#[macro_export] +macro_rules! delegate_dispatch2 { + ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => { + impl<$( $( $lt $( : $clt $(+ $dlt )* )? ),+, )? I, UserData> $crate::reexports::client::Dispatch for $ty + where + I: $crate::reexports::client::Proxy, + UserData: $crate::dispatch2::Dispatch2 { + fn event( + state: &mut $ty, + proxy: &I, + event: ::Event, + data: &UserData, + conn: &$crate::reexports::client::Connection, + qh: &$crate::reexports::client::QueueHandle<$ty>, + ) { + data.event(state, proxy, event, conn, qh); + } + + fn event_created_child(opcode: u16, qh: &$crate::reexports::client::QueueHandle<$ty>) -> ::std::sync::Arc { + UserData::event_created_child(opcode, qh) + } + } + }; +} diff --git a/src/dmabuf.rs b/src/dmabuf.rs index 6661e8a4a..54b4ba30e 100644 --- a/src/dmabuf.rs +++ b/src/dmabuf.rs @@ -1,4 +1,4 @@ -use crate::{error::GlobalError, globals::GlobalData, registry::GlobalProxy}; +use crate::{dispatch2::Dispatch2, error::GlobalError, globals::GlobalData, registry::GlobalProxy}; use memmap2::{Mmap, MmapOptions}; use std::{fmt, mem, os::unix::io::BorrowedFd, slice, sync::Mutex}; use wayland_client::{ @@ -275,15 +275,15 @@ impl DmabufParams { } } -impl Dispatch for DmabufState +impl Dispatch2 for GlobalData where - D: Dispatch + DmabufHandler, + D: DmabufHandler, { fn event( + &self, state: &mut D, proxy: &zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1, event: zwp_linux_dmabuf_v1::Event, - _: &GlobalData, _: &Connection, _: &QueueHandle, ) { @@ -307,23 +307,21 @@ where } } -impl Dispatch - for DmabufState +impl Dispatch2 for DmabufFeedbackData where - D: Dispatch - + DmabufHandler, + D: DmabufHandler, { fn event( + &self, state: &mut D, proxy: &zwp_linux_dmabuf_feedback_v1::ZwpLinuxDmabufFeedbackV1, event: zwp_linux_dmabuf_feedback_v1::Event, - data: &DmabufFeedbackData, conn: &Connection, qh: &QueueHandle, ) { match event { zwp_linux_dmabuf_feedback_v1::Event::Done => { - let feedback = mem::take(&mut *data.pending.lock().unwrap()); + let feedback = mem::take(&mut *self.pending.lock().unwrap()); state.dmabuf_feedback(conn, qh, proxy, feedback); } zwp_linux_dmabuf_feedback_v1::Event::FormatTable { fd, size } => { @@ -335,46 +333,43 @@ where let entry_size = mem::size_of::(); assert!((size % entry_size) == 0); let len = size / entry_size; - data.pending.lock().unwrap().format_table = Some((mmap, len)); + self.pending.lock().unwrap().format_table = Some((mmap, len)); } zwp_linux_dmabuf_feedback_v1::Event::MainDevice { device } => { let device = dev_t::from_ne_bytes(device.try_into().unwrap()); - data.pending.lock().unwrap().main_device = device; + self.pending.lock().unwrap().main_device = device; } zwp_linux_dmabuf_feedback_v1::Event::TrancheDone => { - let tranche = mem::take(&mut *data.pending_tranche.lock().unwrap()); - data.pending.lock().unwrap().tranches.push(tranche); + let tranche = mem::take(&mut *self.pending_tranche.lock().unwrap()); + self.pending.lock().unwrap().tranches.push(tranche); } zwp_linux_dmabuf_feedback_v1::Event::TrancheTargetDevice { device } => { let device = dev_t::from_ne_bytes(device.try_into().unwrap()); - data.pending_tranche.lock().unwrap().device = device; + self.pending_tranche.lock().unwrap().device = device; } zwp_linux_dmabuf_feedback_v1::Event::TrancheFormats { indices } => { assert!((indices.len() % 2) == 0); let indices = indices.chunks(2).map(|i| u16::from_ne_bytes([i[0], i[1]])).collect::>(); - data.pending_tranche.lock().unwrap().formats = indices; + self.pending_tranche.lock().unwrap().formats = indices; } zwp_linux_dmabuf_feedback_v1::Event::TrancheFlags { flags } => { - data.pending_tranche.lock().unwrap().flags = flags; + self.pending_tranche.lock().unwrap().flags = flags; } _ => unreachable!(), } } } -impl Dispatch for DmabufState +impl Dispatch2 for GlobalData where - D: Dispatch - + Dispatch - + DmabufHandler - + 'static, + D: Dispatch + DmabufHandler + 'static, { fn event( + &self, state: &mut D, proxy: &zwp_linux_buffer_params_v1::ZwpLinuxBufferParamsV1, event: zwp_linux_buffer_params_v1::Event, - _: &GlobalData, conn: &Connection, qh: &QueueHandle, ) { @@ -394,15 +389,15 @@ where ]); } -impl Dispatch for DmabufState +impl Dispatch2 for DmaBufferData where - D: Dispatch + DmabufHandler, + D: DmabufHandler, { fn event( + &self, state: &mut D, proxy: &wl_buffer::WlBuffer, event: wl_buffer::Event, - _: &DmaBufferData, conn: &Connection, qh: &QueueHandle, ) { @@ -412,29 +407,3 @@ where } } } - -#[macro_export] -macro_rules! delegate_dmabuf { - ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => { - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: - [ - $crate::reexports::protocols::wp::linux_dmabuf::zv1::client::zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1: $crate::globals::GlobalData - ] => $crate::dmabuf::DmabufState - ); - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: - [ - $crate::reexports::protocols::wp::linux_dmabuf::zv1::client::zwp_linux_buffer_params_v1::ZwpLinuxBufferParamsV1: $crate::globals::GlobalData - ] => $crate::dmabuf::DmabufState - ); - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: - [ - $crate::reexports::protocols::wp::linux_dmabuf::zv1::client::zwp_linux_dmabuf_feedback_v1::ZwpLinuxDmabufFeedbackV1: $crate::dmabuf::DmabufFeedbackData - ] => $crate::dmabuf::DmabufState - ); - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: - [ - $crate::reexports::client::protocol::wl_buffer::WlBuffer: $crate::dmabuf::DmaBufferData - ] => $crate::dmabuf::DmabufState - ); - }; -} diff --git a/src/foreign_toplevel_list.rs b/src/foreign_toplevel_list.rs index 5670af4e7..e94ade8bc 100644 --- a/src/foreign_toplevel_list.rs +++ b/src/foreign_toplevel_list.rs @@ -1,4 +1,4 @@ -use crate::{globals::GlobalData, registry::GlobalProxy}; +use crate::{dispatch2::Dispatch2, globals::GlobalData, registry::GlobalProxy}; use std::sync::{Arc, Mutex}; use wayland_client::{globals::GlobalList, Connection, Dispatch, Proxy, QueueHandle}; use wayland_protocols::ext::foreign_toplevel_list::v1::client::{ @@ -96,19 +96,17 @@ pub trait ForeignToplevelListHandler: Sized { fn finished(&mut self, _conn: &Connection, _qh: &QueueHandle) {} } -impl Dispatch - for ForeignToplevelList +impl Dispatch2 for GlobalData where - D: Dispatch - + Dispatch + D: Dispatch + ForeignToplevelListHandler + 'static, { fn event( + &self, state: &mut D, proxy: &ext_foreign_toplevel_list_v1::ExtForeignToplevelListV1, event: ext_foreign_toplevel_list_v1::Event, - _: &GlobalData, conn: &Connection, qh: &QueueHandle, ) { @@ -127,17 +125,16 @@ where ]); } -impl Dispatch - for ForeignToplevelList +impl Dispatch2 + for ForeignToplevelData where - D: Dispatch - + ForeignToplevelListHandler, + D: ForeignToplevelListHandler, { fn event( + &self, state: &mut D, handle: &ext_foreign_toplevel_handle_v1::ExtForeignToplevelHandleV1, event: ext_foreign_toplevel_handle_v1::Event, - data: &ForeignToplevelData, conn: &Connection, qh: &QueueHandle, ) { @@ -151,7 +148,7 @@ where handle.destroy(); } ext_foreign_toplevel_handle_v1::Event::Done => { - let mut inner = data.0.lock().unwrap(); + let mut inner = self.0.lock().unwrap(); let just_created = inner.current_info.is_none(); inner.current_info = Some(inner.pending_info.clone()); drop(inner); @@ -163,31 +160,15 @@ where } } ext_foreign_toplevel_handle_v1::Event::Title { title } => { - data.0.lock().unwrap().pending_info.title = title; + self.0.lock().unwrap().pending_info.title = title; } ext_foreign_toplevel_handle_v1::Event::AppId { app_id } => { - data.0.lock().unwrap().pending_info.app_id = app_id; + self.0.lock().unwrap().pending_info.app_id = app_id; } ext_foreign_toplevel_handle_v1::Event::Identifier { identifier } => { - data.0.lock().unwrap().pending_info.identifier = identifier; + self.0.lock().unwrap().pending_info.identifier = identifier; } _ => unreachable!(), } } } - -#[macro_export] -macro_rules! delegate_foreign_toplevel_list { - ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => { - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: - [ - $crate::reexports::protocols::ext::foreign_toplevel_list::v1::client::ext_foreign_toplevel_list_v1::ExtForeignToplevelListV1: $crate::globals::GlobalData - ] => $crate::foreign_toplevel_list::ForeignToplevelList - ); - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: - [ - $crate::reexports::protocols::ext::foreign_toplevel_list::v1::client::ext_foreign_toplevel_handle_v1::ExtForeignToplevelHandleV1: $crate::foreign_toplevel_list::ForeignToplevelData - ] => $crate::foreign_toplevel_list::ForeignToplevelList - ); - }; -} diff --git a/src/lib.rs b/src/lib.rs index a0d0f10a2..71bfdbd1f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,6 +26,7 @@ pub mod activation; pub mod background_effect; pub mod compositor; pub mod data_device_manager; +pub mod dispatch2; pub mod dmabuf; pub mod error; pub mod foreign_toplevel_list; diff --git a/src/output.rs b/src/output.rs index c2dc47446..90d32e827 100644 --- a/src/output.rs +++ b/src/output.rs @@ -16,6 +16,7 @@ use wayland_protocols::xdg::xdg_output::zv1::client::{ }; use crate::{ + dispatch2::Dispatch2, globals::GlobalData, registry::{GlobalProxy, ProvidesRegistryState, RegistryHandler}, }; @@ -68,7 +69,7 @@ type ScaleWatcherFn = /// use smithay_client_toolkit::output::{OutputHandler,OutputState}; /// use smithay_client_toolkit::registry::{ProvidesRegistryState,RegistryHandler}; /// # use smithay_client_toolkit::registry::RegistryState; -/// use smithay_client_toolkit::{registry_handlers,delegate_output, delegate_registry}; +/// use smithay_client_toolkit::{registry_handlers, delegate_registry}; /// use wayland_client::{Connection,QueueHandle,protocol::wl_output}; /// /// struct ExampleState { @@ -96,7 +97,7 @@ type ScaleWatcherFn = /// /// // Delegating to the registry is required to use `OutputState`. /// delegate_registry!(ExampleState); -/// delegate_output!(ExampleState); +/// smithay_client_toolkit::delegate_dispatch2!(ExampleState); /// /// impl ProvidesRegistryState for ExampleState { /// # fn registry(&mut self) -> &mut RegistryState { @@ -391,30 +392,15 @@ pub struct OutputInfo { pub description: Option, } -#[macro_export] -macro_rules! delegate_output { - ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => { - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ - $crate::reexports::client::protocol::wl_output::WlOutput: $crate::output::OutputData - ] => $crate::output::OutputState); - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ - $crate::reexports::protocols::xdg::xdg_output::zv1::client::zxdg_output_manager_v1::ZxdgOutputManagerV1: $crate::globals::GlobalData - ] => $crate::output::OutputState); - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ - $crate::reexports::protocols::xdg::xdg_output::zv1::client::zxdg_output_v1::ZxdgOutputV1: $crate::output::OutputData - ] => $crate::output::OutputState); - }; -} - -impl Dispatch for OutputState +impl Dispatch2 for OutputData where - D: Dispatch + OutputHandler + 'static, + D: OutputHandler + 'static, { fn event( + &self, state: &mut D, output: &wl_output::WlOutput, event: wl_output::Event, - data: &OutputData, conn: &Connection, qh: &QueueHandle, ) { @@ -519,7 +505,7 @@ where inner.pending_wl = false; // Set the user data, see if we need to run scale callbacks - let run_callbacks = data.set(info); + let run_callbacks = self.set(info); // Don't call `new_output` until we have xdg output info if !inner.pending_xdg { @@ -545,15 +531,15 @@ where } } -impl Dispatch for OutputState +impl Dispatch2 for GlobalData where - D: Dispatch + OutputHandler, + D: OutputHandler, { fn event( + &self, _: &mut D, _: &zxdg_output_manager_v1::ZxdgOutputManagerV1, _: zxdg_output_manager_v1::Event, - _: &GlobalData, _: &Connection, _: &QueueHandle, ) { @@ -561,15 +547,15 @@ where } } -impl Dispatch for OutputState +impl Dispatch2 for OutputData where - D: Dispatch + OutputHandler, + D: OutputHandler, { fn event( + &self, state: &mut D, output: &zxdg_output_v1::ZxdgOutputV1, event: zxdg_output_v1::Event, - data: &OutputData, conn: &Connection, qh: &QueueHandle, ) { @@ -631,7 +617,7 @@ where inner.pending_xdg = false; // Set the user data - data.set(info); + self.set(info); let pending_wl = inner.pending_wl; let just_created = inner.just_created; diff --git a/src/presentation_time.rs b/src/presentation_time.rs index 27654de84..2c14c44ae 100644 --- a/src/presentation_time.rs +++ b/src/presentation_time.rs @@ -6,7 +6,7 @@ use wayland_client::{ }; use wayland_protocols::wp::presentation_time::client::{wp_presentation, wp_presentation_feedback}; -use crate::{error::GlobalError, globals::GlobalData, registry::GlobalProxy}; +use crate::{dispatch2::Dispatch2, error::GlobalError, globals::GlobalData, registry::GlobalProxy}; #[derive(Debug)] pub struct PresentTime { @@ -84,15 +84,15 @@ pub struct PresentationTimeData { sync_outputs: Mutex>, } -impl Dispatch for PresentationTimeState +impl Dispatch2 for GlobalData where - D: Dispatch + PresentationTimeHandler, + D: PresentationTimeHandler, { fn event( + &self, data: &mut D, _presentation: &wp_presentation::WpPresentation, event: wp_presentation::Event, - _: &GlobalData, _conn: &Connection, _qh: &QueueHandle, ) { @@ -105,23 +105,21 @@ where } } -impl Dispatch - for PresentationTimeState +impl Dispatch2 for PresentationTimeData where - D: Dispatch - + PresentationTimeHandler, + D: PresentationTimeHandler, { fn event( + &self, data: &mut D, feedback: &wp_presentation_feedback::WpPresentationFeedback, event: wp_presentation_feedback::Event, - udata: &PresentationTimeData, conn: &Connection, qh: &QueueHandle, ) { match event { wp_presentation_feedback::Event::SyncOutput { output } => { - udata.sync_outputs.lock().unwrap().push(output); + self.sync_outputs.lock().unwrap().push(output); } wp_presentation_feedback::Event::Presented { tv_sec_hi, @@ -132,7 +130,7 @@ where seq_lo, flags, } => { - let sync_outputs = mem::take(&mut *udata.sync_outputs.lock().unwrap()); + let sync_outputs = mem::take(&mut *self.sync_outputs.lock().unwrap()); let clk_id = data.presentation_time_state().clk_id.unwrap(); // XXX unwrap let time = PresentTime { clk_id, @@ -144,7 +142,7 @@ where conn, qh, feedback, - &udata.wl_surface, + &self.wl_surface, sync_outputs, time, refresh, @@ -153,21 +151,9 @@ where ); } wp_presentation_feedback::Event::Discarded => { - data.discarded(conn, qh, feedback, &udata.wl_surface) + data.discarded(conn, qh, feedback, &self.wl_surface) } _ => {} } } } - -#[macro_export] -macro_rules! delegate_presentation_time { - ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => { - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ - $crate::reexports::protocols::wp::presentation_time::client::wp_presentation::WpPresentation: $crate::globals::GlobalData - ] => $crate::presentation_time::PresentationTimeState); - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ - $crate::reexports::protocols::wp::presentation_time::client::wp_presentation_feedback::WpPresentationFeedback: $crate::presentation_time::PresentationTimeData - ] => $crate::presentation_time::PresentationTimeState); - }; -} diff --git a/src/primary_selection/device.rs b/src/primary_selection/device.rs index 7b2e5cd12..1389c9c71 100644 --- a/src/primary_selection/device.rs +++ b/src/primary_selection/device.rs @@ -8,10 +8,9 @@ use crate::reexports::protocols::wp::primary_selection::zv1::client::{ zwp_primary_selection_offer_v1::ZwpPrimarySelectionOfferV1, }; -use super::{ - offer::{PrimarySelectionOffer, PrimarySelectionOfferData}, - PrimarySelectionManagerState, -}; +use crate::dispatch2::Dispatch2; + +use super::offer::{PrimarySelectionOffer, PrimarySelectionOfferData}; pub trait PrimarySelectionDeviceHandler: Sized { /// The new selection is received. @@ -54,11 +53,9 @@ impl Drop for PrimarySelectionDevice { } } -impl Dispatch - for PrimarySelectionManagerState +impl Dispatch2 for PrimarySelectionDeviceData where - State: Dispatch - + Dispatch + State: Dispatch + PrimarySelectionDeviceHandler + 'static, { @@ -67,15 +64,15 @@ where ]); fn event( + &self, state: &mut State, proxy: &ZwpPrimarySelectionDeviceV1, event: ::Event, - data: &PrimarySelectionDeviceData, conn: &Connection, qhandle: &QueueHandle, ) { use wayland_protocols::wp::primary_selection::zv1::client::zwp_primary_selection_device_v1::Event; - let mut data = data.inner.lock().unwrap(); + let mut data = self.inner.lock().unwrap(); match event { Event::DataOffer { offer } => { // Try to resist faulty compositors. diff --git a/src/primary_selection/mod.rs b/src/primary_selection/mod.rs index aafe15086..a46a8fdb1 100644 --- a/src/primary_selection/mod.rs +++ b/src/primary_selection/mod.rs @@ -1,3 +1,4 @@ +use crate::dispatch2::Dispatch2; use crate::globals::GlobalData; use crate::reexports::client::{ globals::{BindError, GlobalList}, @@ -81,40 +82,15 @@ impl Drop for PrimarySelectionManagerState { } } -impl Dispatch for PrimarySelectionManagerState -where - D: Dispatch, -{ +impl Dispatch2 for GlobalData { fn event( + &self, _: &mut D, _: &ZwpPrimarySelectionDeviceManagerV1, _: ::Event, - _: &GlobalData, _: &wayland_client::Connection, _: &QueueHandle, ) { unreachable!("zwp_primary_selection_device_manager_v1 has no events") } } - -#[macro_export] -macro_rules! delegate_primary_selection { - ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => { - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: - [ - $crate::reexports::protocols::wp::primary_selection::zv1::client::zwp_primary_selection_device_manager_v1::ZwpPrimarySelectionDeviceManagerV1: $crate::globals::GlobalData - ] => $crate::primary_selection::PrimarySelectionManagerState); - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: - [ - $crate::reexports::protocols::wp::primary_selection::zv1::client::zwp_primary_selection_device_v1::ZwpPrimarySelectionDeviceV1: $crate::primary_selection::device::PrimarySelectionDeviceData - ] => $crate::primary_selection::PrimarySelectionManagerState); - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: - [ - $crate::reexports::protocols::wp::primary_selection::zv1::client::zwp_primary_selection_offer_v1::ZwpPrimarySelectionOfferV1: $crate::primary_selection::offer::PrimarySelectionOfferData - ] => $crate::primary_selection::PrimarySelectionManagerState); - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: - [ - $crate::reexports::protocols::wp::primary_selection::zv1::client::zwp_primary_selection_source_v1::ZwpPrimarySelectionSourceV1: $crate::globals::GlobalData - ] => $crate::primary_selection::PrimarySelectionManagerState); - }; -} diff --git a/src/primary_selection/offer.rs b/src/primary_selection/offer.rs index 546dfd453..129687e93 100644 --- a/src/primary_selection/offer.rs +++ b/src/primary_selection/offer.rs @@ -3,12 +3,11 @@ use std::{ sync::Mutex, }; -use crate::reexports::client::{Connection, Dispatch, QueueHandle, Proxy}; +use crate::reexports::client::{Connection, QueueHandle, Proxy}; use crate::reexports::protocols::wp::primary_selection::zv1::client::zwp_primary_selection_offer_v1::ZwpPrimarySelectionOfferV1; use crate::data_device_manager::ReadPipe; - -use super::PrimarySelectionManagerState; +use crate::dispatch2::Dispatch2; /// Wrapper around the [`ZwpPrimarySelectionOfferV1`]. #[derive(Debug, Clone, PartialEq, Eq)] @@ -54,23 +53,19 @@ impl PrimarySelectionOffer { } } -impl Dispatch - for PrimarySelectionManagerState -where - State: Dispatch, -{ +impl Dispatch2 for PrimarySelectionOfferData { fn event( + &self, _: &mut State, _: &ZwpPrimarySelectionOfferV1, event: ::Event, - data: &PrimarySelectionOfferData, _: &Connection, _: &QueueHandle, ) { use wayland_protocols::wp::primary_selection::zv1::client::zwp_primary_selection_offer_v1::Event; match event { Event::Offer { mime_type } => { - data.mimes.lock().unwrap().push(mime_type); + self.mimes.lock().unwrap().push(mime_type); } _ => unreachable!(), } diff --git a/src/primary_selection/selection.rs b/src/primary_selection/selection.rs index 348fadaa7..cad79b4c1 100644 --- a/src/primary_selection/selection.rs +++ b/src/primary_selection/selection.rs @@ -1,8 +1,9 @@ -use crate::reexports::client::{Connection, Dispatch, QueueHandle}; +use crate::dispatch2::Dispatch2; +use crate::reexports::client::{Connection, QueueHandle}; use crate::reexports::protocols::wp::primary_selection::zv1::client::zwp_primary_selection_source_v1::ZwpPrimarySelectionSourceV1; use crate::{data_device_manager::WritePipe, globals::GlobalData}; -use super::{device::PrimarySelectionDevice, PrimarySelectionManagerState}; +use super::device::PrimarySelectionDevice; /// Handler trait for `PrimarySelectionSource` events. /// @@ -57,16 +58,15 @@ impl Drop for PrimarySelectionSource { } } -impl Dispatch - for PrimarySelectionManagerState +impl Dispatch2 for GlobalData where - State: Dispatch + PrimarySelectionSourceHandler, + State: PrimarySelectionSourceHandler, { fn event( + &self, state: &mut State, proxy: &ZwpPrimarySelectionSourceV1, event: ::Event, - _: &GlobalData, conn: &wayland_client::Connection, qhandle: &QueueHandle, ) { diff --git a/src/registry.rs b/src/registry.rs index 4b6d63258..e41335282 100644 --- a/src/registry.rs +++ b/src/registry.rs @@ -278,7 +278,7 @@ impl RegistryState { /// /// ``` /// use smithay_client_toolkit::{ -/// delegate_registry, delegate_shm, registry_handlers, +/// delegate_registry, registry_handlers, /// shm::{ShmHandler, Shm}, /// }; /// @@ -286,14 +286,13 @@ impl RegistryState { /// shm_state: Shm, /// } /// -/// // Here is the implementation of wl_shm to compile: -/// delegate_shm!(ExampleApp); -/// /// impl ShmHandler for ExampleApp { /// fn shm_state(&mut self) -> &mut Shm { /// &mut self.shm_state /// } /// } +/// +/// smithay_client_toolkit::delegate_dispatch2!(ExampleApp); /// ``` #[macro_export] macro_rules! delegate_registry { @@ -419,16 +418,6 @@ impl ProvidesBoundGlobal Dispatch for SimpleGlobal -where - D: Dispatch, - I: Proxy, -{ - fn event(_: &mut D, _: &I, _: ::Event, _: &(), _: &Connection, _: &QueueHandle) { - unreachable!("SimpleGlobal is not suitable for {} which has events", I::interface().name); - } -} - /// Binds all globals with a given interface. pub(crate) fn bind_all( registry: &wl_registry::WlRegistry, @@ -507,15 +496,6 @@ where Err(BindError::NotPresent) } -#[macro_export] -macro_rules! delegate_simple { - ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty:ty, $iface:ty, $max:expr) => { - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ $iface: () ] - => $crate::registry::SimpleGlobal<$iface, $max> - ); - }; -} - /// A helper macro for implementing [`ProvidesRegistryState`]. /// /// See [`delegate_registry`][crate::delegate_registry] for an example. diff --git a/src/seat/input_method.rs b/src/seat/input_method.rs index 6ab3b18e4..bff553b32 100644 --- a/src/seat/input_method.rs +++ b/src/seat/input_method.rs @@ -26,6 +26,8 @@ use wayland_protocols_misc::zwp_input_method_v2::client::{ zwp_input_method_v2, }; +use crate::dispatch2::Dispatch2; + #[derive(Debug)] pub struct InputMethodManager { manager: ZwpInputMethodManagerV2, @@ -45,29 +47,40 @@ impl InputMethodManager { /// seat. pub fn get_input_method(&self, qh: &QueueHandle, seat: &WlSeat) -> InputMethod where - State: Dispatch + 'static, + State: Dispatch, State> + 'static, + { + self.get_input_method_with_data(qh, seat, ()) + } + + pub fn get_input_method_with_data( + &self, + qh: &QueueHandle, + seat: &WlSeat, + udata: U, + ) -> InputMethod + where + State: Dispatch, State> + 'static, + U: Send + Sync + 'static, { InputMethod { input_method: self.manager.get_input_method( seat, qh, - InputMethodData::new(seat.clone()), + InputMethodData::new(seat.clone(), udata), ), } } } -impl Dispatch - for InputMethodManager +impl Dispatch2 for GlobalData where - D: Dispatch - + InputMethodHandler, + D: InputMethodHandler, { fn event( + &self, _data: &mut D, _manager: &zwp_input_method_manager_v2::ZwpInputMethodManagerV2, _event: zwp_input_method_manager_v2::Event, - _: &GlobalData, _conn: &Connection, _qh: &QueueHandle, ) { @@ -109,23 +122,23 @@ impl InputMethod { self.input_method.delete_surrounding_text(before_length, after_length) } - pub fn commit(&self) { - let data = self.input_method.data::().unwrap(); + pub fn commit(&self) { + let data = self.input_method.data::>().unwrap(); let inner = data.inner.lock().unwrap(); self.input_method.commit(inner.serial.0) } } #[derive(Debug)] -pub struct InputMethodData { +pub struct InputMethodData { seat: WlSeat, - inner: Mutex, + udata: U, } -impl InputMethodData { +impl InputMethodData { /// Create the new input method data associated with the given seat. - pub fn new(seat: WlSeat) -> Self { + pub fn new(seat: WlSeat, udata: U) -> Self { Self { seat, inner: Mutex::new(InputMethodDataInner { @@ -133,9 +146,18 @@ impl InputMethodData { current_state: Default::default(), serial: Wrapping(0), }), + udata, } } + pub fn data(&self) -> &U { + &self.udata + } + + pub fn data_mut(&mut self) -> &mut U { + &mut self.udata + } + /// Get the associated seat from the data. pub fn seat(&self) -> &WlSeat { &self.seat @@ -240,28 +262,6 @@ impl Active { } } -#[macro_export] -macro_rules! delegate_input_method { - ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => { - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ - $crate::reexports::protocols_misc::zwp_input_method_v2::client::zwp_input_method_manager_v2::ZwpInputMethodManagerV2: $crate::globals::GlobalData - ] => $crate::seat::input_method::InputMethodManager); - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ - $crate::reexports::protocols_misc::zwp_input_method_v2::client::zwp_input_method_v2::ZwpInputMethodV2: $crate::seat::input_method::InputMethodData - ] => $crate::seat::input_method::InputMethod); - }; -} - -pub trait InputMethodDataExt: Send + Sync { - fn input_method_data(&self) -> &InputMethodData; -} - -impl InputMethodDataExt for InputMethodData { - fn input_method_data(&self) -> &InputMethodData { - self - } -} - pub trait InputMethodHandler: Sized { fn handle_done( &self, @@ -278,21 +278,20 @@ pub trait InputMethodHandler: Sized { ); } -impl Dispatch for InputMethod +impl Dispatch2 for InputMethodData where - D: Dispatch + InputMethodHandler, - U: InputMethodDataExt, + D: InputMethodHandler, { fn event( + &self, data: &mut D, input_method: &ZwpInputMethodV2, event: zwp_input_method_v2::Event, - udata: &U, conn: &Connection, qh: &QueueHandle, ) { let mut imdata: std::sync::MutexGuard<'_, InputMethodDataInner> = - udata.input_method_data().inner.lock().unwrap(); + self.inner.lock().unwrap(); use zwp_input_method_v2::Event; @@ -392,7 +391,7 @@ mod test { } } - delegate_input_method!(Handler); + crate::delegate_dispatch2!(Handler); fn assert_is_manager_delegate() where @@ -402,7 +401,7 @@ mod test { fn assert_is_delegate() where - T: wayland_client::Dispatch, + T: wayland_client::Dispatch>, { } diff --git a/src/seat/input_method_v3.rs b/src/seat/input_method_v3.rs index 4ab61537c..cf74a430a 100644 --- a/src/seat/input_method_v3.rs +++ b/src/seat/input_method_v3.rs @@ -30,6 +30,8 @@ use wayland_client::{Connection, Dispatch, Proxy, QueueHandle}; use crate::reexports::protocols_experimental::input_method::v1::client as protocol; +use crate::dispatch2::Dispatch2; + pub use protocol::xx_input_method_v1::XxInputMethodV1; pub use protocol::xx_input_popup_positioner_v1::XxInputPopupPositionerV1; pub use protocol::xx_input_popup_surface_v2::XxInputPopupSurfaceV2; @@ -74,13 +76,26 @@ impl InputMethodManager { /// seat. pub fn get_input_method(&self, qh: &QueueHandle, seat: &WlSeat) -> InputMethod where - State: Dispatch + 'static, + State: Dispatch, State> + 'static, + { + self.get_input_method_with_data(qh, seat, ()) + } + + pub fn get_input_method_with_data( + &self, + qh: &QueueHandle, + seat: &WlSeat, + udata: U, + ) -> InputMethod + where + State: Dispatch, State> + 'static, + U: Send + Sync + 'static, { InputMethod { input_method: self.manager.get_input_method( seat, qh, - InputMethodData::new(seat.clone()), + InputMethodData::new(seat.clone(), udata), ), } } @@ -93,17 +108,15 @@ impl InputMethodManager { } } -impl Dispatch - for InputMethodManager +impl Dispatch2 for GlobalData where - D: Dispatch - + InputMethodHandler, + D: InputMethodHandler, { fn event( + &self, _data: &mut D, _manager: &xx_input_method_manager_v2::XxInputMethodManagerV2, _event: xx_input_method_manager_v2::Event, - _: &GlobalData, _conn: &Connection, _qh: &QueueHandle, ) { @@ -132,15 +145,15 @@ impl Drop for PopupPositioner { } } -impl Dispatch for PopupPositioner +impl Dispatch2 for PositionerData where - D: Dispatch + InputMethodHandler, + D: InputMethodHandler, { fn event( + &self, _data: &mut D, _manager: &XxInputPopupPositionerV1, _event: xx_input_popup_positioner_v1::Event, - _: &PositionerData, _conn: &Connection, _qh: &QueueHandle, ) { @@ -226,13 +239,16 @@ impl InputMethod { self.input_method.move_cursor(cursor, anchor) } - pub fn commit(&self) { - let data = self.input_method.data::().unwrap(); + pub fn commit(&self) + where + U: Send + Sync + 'static, + { + let data = self.input_method.data::>().unwrap(); let inner = &data.inner.lock().unwrap(); self.input_method.commit(inner.serial.0) } - pub fn get_input_popup_surface( + pub fn get_input_popup_surface( &self, qh: &QueueHandle, surface: impl Into, @@ -240,8 +256,9 @@ impl InputMethod { ) -> Popup where D: Dispatch + 'static, + U: Send + Sync + 'static, { - let data = self.input_method.data::().unwrap(); + let data = self.input_method.data::>().unwrap(); let surface = surface.into(); Popup { input_method: self.input_method.clone(), @@ -257,15 +274,15 @@ impl InputMethod { } #[derive(Debug)] -pub struct InputMethodData { +pub struct InputMethodData { seat: WlSeat, - inner: Arc>, + udata: U, } -impl InputMethodData { +impl InputMethodData { /// Create the new touch data associated with the given seat. - pub fn new(seat: WlSeat) -> Self { + pub fn new(seat: WlSeat, udata: U) -> Self { Self { seat, inner: Arc::new(Mutex::new(InputMethodDataInner { @@ -273,9 +290,18 @@ impl InputMethodData { current_state: Default::default(), serial: Wrapping(0), })), + udata, } } + pub fn data(&self) -> &U { + &self.udata + } + + pub fn data_mut(&mut self) -> &mut U { + &mut self.udata + } + /// Get the associated seat from the data. pub fn seat(&self) -> &WlSeat { &self.seat @@ -480,19 +506,19 @@ impl Popup { } } -impl Dispatch for Popup +impl Dispatch2 for PopupData where - D: Dispatch + InputMethodHandler, + D: InputMethodHandler, { fn event( + &self, _data: &mut D, popup: &XxInputPopupSurfaceV2, event: xx_input_popup_surface_v2::Event, - udata: &PopupData, _conn: &Connection, _qh: &QueueHandle, ) { - let inner: MutexGuard<'_, PopupDataInner> = udata.inner.lock().unwrap(); + let inner: MutexGuard<'_, PopupDataInner> = self.inner.lock().unwrap(); if let Some(im) = inner.im.upgrade() { let mut im = im.lock().unwrap(); @@ -588,34 +614,6 @@ impl PopupDataInner { } } -#[macro_export] -macro_rules! delegate_input_method_v3 { - ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => { - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ - $crate::reexports::protocols_experimental::input_method::v1::client::xx_input_method_manager_v2::XxInputMethodManagerV2: $crate::globals::GlobalData - ] => $crate::seat::input_method_v3::InputMethodManager); - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ - $crate::reexports::protocols_experimental::input_method::v1::client::xx_input_method_v1::XxInputMethodV1: $crate::seat::input_method_v3::InputMethodData - ] => $crate::seat::input_method_v3::InputMethod); - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ - $crate::reexports::protocols_experimental::input_method::v1::client::xx_input_popup_surface_v2::XxInputPopupSurfaceV2: $crate::seat::input_method_v3::PopupData - ] => $crate::seat::input_method_v3::Popup); - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ - $crate::reexports::protocols_experimental::input_method::v1::client::xx_input_popup_positioner_v1::XxInputPopupPositionerV1: $crate::seat::input_method_v3::PositionerData - ] => $crate::seat::input_method_v3::PopupPositioner); - }; -} - -pub trait InputMethodDataExt: Send + Sync { - fn input_method_data(&self) -> &InputMethodData; -} - -impl InputMethodDataExt for InputMethodData { - fn input_method_data(&self) -> &InputMethodData { - self - } -} - pub trait InputMethodHandler: Sized { fn handle_done( &mut self, @@ -633,21 +631,19 @@ pub trait InputMethodHandler: Sized { fn handle_unavailable(&mut self, qh: &QueueHandle, input_method: &XxInputMethodV1); } -impl Dispatch for InputMethod +impl Dispatch2 for InputMethodData where - D: Dispatch + InputMethodHandler, - U: InputMethodDataExt, + D: InputMethodHandler, { fn event( + &self, data: &mut D, input_method: &XxInputMethodV1, event: xx_input_method_v1::Event, - udata: &U, _conn: &Connection, qh: &QueueHandle, ) { - let mut imdata: MutexGuard<'_, InputMethodDataInner> = - udata.input_method_data().inner.lock().unwrap(); + let mut imdata: MutexGuard<'_, InputMethodDataInner> = self.inner.lock().unwrap(); use xx_input_method_v1::Event; @@ -778,7 +774,7 @@ mod test { } } - delegate_input_method_v3!(Handler); + crate::delegate_dispatch2!(Handler); fn assert_is_manager_delegate() where @@ -791,7 +787,10 @@ mod test { fn assert_is_delegate() where - T: wayland_client::Dispatch, + T: wayland_client::Dispatch< + protocol::xx_input_method_v1::XxInputMethodV1, + InputMethodData<()>, + >, { } diff --git a/src/seat/keyboard/mod.rs b/src/seat/keyboard/mod.rs index 2c6384ace..666f155c6 100644 --- a/src/seat/keyboard/mod.rs +++ b/src/seat/keyboard/mod.rs @@ -26,6 +26,8 @@ use xkbcommon::xkb; #[cfg(feature = "calloop")] use repeat::{RepeatData, RepeatedKey}; +use crate::dispatch2::Dispatch2; + use super::{Capability, SeatError, SeatHandler, SeatState}; #[cfg(feature = "calloop")] @@ -58,24 +60,31 @@ impl SeatState { /// ## Errors /// /// This will return [`SeatError::UnsupportedCapability`] if the seat does not support a keyboard. - pub fn get_keyboard( + pub fn get_keyboard( &mut self, qh: &QueueHandle, seat: &wl_seat::WlSeat, rmlvo: Option, ) -> Result where - D: Dispatch> + D: Dispatch> + SeatHandler + KeyboardHandler + 'static, { let udata = match rmlvo { - Some(rmlvo) => KeyboardData::from_rmlvo(seat.clone(), rmlvo)?, - None => KeyboardData::new(seat.clone()), + Some(rmlvo) => KeyboardData::from_rmlvo(seat.clone(), rmlvo, ())?, + None => KeyboardData::new(seat.clone(), ()), }; - self.get_keyboard_with_data(qh, seat, udata) + let inner = + self.seats.iter().find(|inner| &inner.seat == seat).ok_or(SeatError::DeadObject)?; + + if !inner.data.has_keyboard.load(Ordering::SeqCst) { + return Err(SeatError::UnsupportedCapability(Capability::Keyboard).into()); + } + + Ok(seat.get_keyboard(qh, udata)) } /// Creates a keyboard from a seat. @@ -95,8 +104,11 @@ impl SeatState { udata: U, ) -> Result where - D: Dispatch + SeatHandler + KeyboardHandler + 'static, - U: KeyboardDataExt + 'static, + D: Dispatch> + + SeatHandler + + KeyboardHandler + + 'static, + U: Send + Sync + 'static, { let inner = self.seats.iter().find(|inner| &inner.seat == seat).ok_or(SeatError::DeadObject)?; @@ -105,6 +117,8 @@ impl SeatState { return Err(SeatError::UnsupportedCapability(Capability::Keyboard).into()); } + let udata = KeyboardData::new(seat.clone(), udata); + Ok(seat.get_keyboard(qh, udata)) } } @@ -338,7 +352,7 @@ pub struct RMLVO { pub options: Option, } -pub struct KeyboardData { +pub struct KeyboardData { seat: wl_seat::WlSeat, first_event: AtomicBool, xkb_context: Mutex, @@ -347,46 +361,27 @@ pub struct KeyboardData { xkb_state: Mutex>, xkb_compose: Mutex>, #[cfg(feature = "calloop")] - repeat_data: Arc>>>, + repeat_data: Arc>>>, focus: Mutex>, - _phantom_data: PhantomData, + _phantom_data: PhantomData, + udata: U, } -impl Debug for KeyboardData { +impl Debug for KeyboardData { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("KeyboardData").finish_non_exhaustive() } } -#[macro_export] -macro_rules! delegate_keyboard { - ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => { - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: - [ - $crate::reexports::client::protocol::wl_keyboard::WlKeyboard: $crate::seat::keyboard::KeyboardData<$ty> - ] => $crate::seat::SeatState - ); - }; - ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty, keyboard: [$($udata:ty),* $(,)?]) => { - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: - [ - $( - $crate::reexports::client::protocol::wl_keyboard::WlKeyboard: $udata, - )* - ] => $crate::seat::SeatState - ); - }; -} - // SAFETY: The state does not share state with any other rust types. -unsafe impl Send for KeyboardData {} +unsafe impl Send for KeyboardData {} // SAFETY: The state is guarded by a mutex since libxkbcommon has no internal synchronization. -unsafe impl Sync for KeyboardData {} +unsafe impl Sync for KeyboardData {} -impl KeyboardData { - pub fn new(seat: wl_seat::WlSeat) -> Self { +impl KeyboardData { + pub fn new(seat: wl_seat::WlSeat, udata: U) -> Self { let xkb_context = xkb::Context::new(xkb::CONTEXT_NO_FLAGS); - let udata = KeyboardData { + let keyboard_data = KeyboardData { seat, first_event: AtomicBool::new(false), xkb_context: Mutex::new(xkb_context), @@ -397,18 +392,31 @@ impl KeyboardData { repeat_data: Arc::new(Mutex::new(None)), focus: Mutex::new(None), _phantom_data: PhantomData, + udata, }; - udata.init_compose(); + keyboard_data.init_compose(); - udata + keyboard_data + } + + pub fn data(&mut self) -> &U { + &self.udata + } + + pub fn data_mut(&mut self) -> &U { + &self.udata } pub fn seat(&self) -> &wl_seat::WlSeat { &self.seat } - pub fn from_rmlvo(seat: wl_seat::WlSeat, rmlvo: RMLVO) -> Result { + pub fn from_rmlvo( + seat: wl_seat::WlSeat, + rmlvo: RMLVO, + udata: U, + ) -> Result { let xkb_context = xkb::Context::new(xkb::CONTEXT_NO_FLAGS); let keymap = xkb::Keymap::new_from_names( &xkb_context, @@ -426,7 +434,7 @@ impl KeyboardData { let xkb_state = Some(xkb::State::new(&keymap.unwrap())); - let udata = KeyboardData { + let keyboard_data = KeyboardData { seat, first_event: AtomicBool::new(false), xkb_context: Mutex::new(xkb_context), @@ -437,11 +445,12 @@ impl KeyboardData { repeat_data: Arc::new(Mutex::new(None)), focus: Mutex::new(None), _phantom_data: PhantomData, + udata, }; - udata.init_compose(); + keyboard_data.init_compose(); - Ok(udata) + Ok(keyboard_data) } fn init_compose(&self) { @@ -484,44 +493,23 @@ impl KeyboardData { } } -pub trait KeyboardDataExt: Send + Sync { - type State: 'static; - fn keyboard_data(&self) -> &KeyboardData; - fn keyboard_data_mut(&mut self) -> &mut KeyboardData; -} - -impl KeyboardDataExt for KeyboardData { - /// The type of the user defined state - type State = T; - fn keyboard_data(&self) -> &KeyboardData { - self - } - - fn keyboard_data_mut(&mut self) -> &mut KeyboardData { - self - } -} - -impl Dispatch for SeatState +impl Dispatch2 for KeyboardData where - D: Dispatch + KeyboardHandler, - U: KeyboardDataExt, + D: KeyboardHandler + 'static, { fn event( + &self, data: &mut D, keyboard: &wl_keyboard::WlKeyboard, event: wl_keyboard::Event, - udata: &U, conn: &Connection, qh: &QueueHandle, ) { - let udata = udata.keyboard_data(); - // The compositor has no way to tell clients if the seat is not version 4 or above. // In this case, send a synthetic repeat info event using the default repeat values used by the X // server. - if keyboard.version() < 4 && udata.first_event.load(Ordering::SeqCst) { - udata.first_event.store(true, Ordering::SeqCst); + if keyboard.version() < 4 && self.first_event.load(Ordering::SeqCst) { + self.first_event.store(true, Ordering::SeqCst); data.update_repeat_info( conn, @@ -540,12 +528,12 @@ where } wl_keyboard::KeymapFormat::XkbV1 => { - if udata.user_specified_rmlvo { + if self.user_specified_rmlvo { // state is locked, ignore keymap updates return; } - let context = udata.xkb_context.lock().unwrap(); + let context = self.xkb_context.lock().unwrap(); // 0.5.0-beta.0 does not mark this function as unsafe but upstream rightly makes // this function unsafe. @@ -568,7 +556,7 @@ where Ok(Some(keymap)) => { let state = xkb::State::new(&keymap); { - let mut state_guard = udata.xkb_state.lock().unwrap(); + let mut state_guard = self.xkb_state.lock().unwrap(); *state_guard = Some(state); } data.update_keymap(conn, qh, keyboard, Keymap(&keymap)); @@ -594,7 +582,7 @@ where } wl_keyboard::Event::Enter { serial, surface, keys } => { - let state_guard = udata.xkb_state.lock().unwrap(); + let state_guard = self.xkb_state.lock().unwrap(); if let Some(guard) = state_guard.as_ref() { // Keysyms are encoded as an array of u32 @@ -626,7 +614,7 @@ where ); } - *udata.focus.lock().unwrap() = Some(surface); + *self.focus.lock().unwrap() = Some(surface); } wl_keyboard::Event::Leave { serial, surface } => { @@ -634,19 +622,19 @@ where // sent before entering a new surface. #[cfg(feature = "calloop")] { - if let Some(repeat_data) = udata.repeat_data.lock().unwrap().as_mut() { + if let Some(repeat_data) = self.repeat_data.lock().unwrap().as_mut() { repeat_data.current_repeat.take(); } } data.leave(conn, qh, keyboard, &surface, serial); - *udata.focus.lock().unwrap() = None; + *self.focus.lock().unwrap() = None; } wl_keyboard::Event::Key { serial, time, key, state } => match state { WEnum::Value(state) => { - let state_guard = udata.xkb_state.lock().unwrap(); + let state_guard = self.xkb_state.lock().unwrap(); if let Some(guard) = state_guard.as_ref() { // We must add 8 to the keycode for any functions we pass the raw keycode into per @@ -654,7 +642,7 @@ where let keycode = KeyCode::new(key + 8); let keysym = guard.key_get_one_sym(keycode); let utf8 = if state == wl_keyboard::KeyState::Pressed { - let mut compose = udata.xkb_compose.lock().unwrap(); + let mut compose = self.xkb_compose.lock().unwrap(); match compose.as_mut() { Some(compose) => match compose.feed(keysym) { @@ -683,7 +671,7 @@ where #[cfg(feature = "calloop")] { if let Some(repeat_data) = - udata.repeat_data.lock().unwrap().as_mut() + self.repeat_data.lock().unwrap().as_mut() { if Some(event.raw_code) == repeat_data @@ -707,10 +695,10 @@ where #[cfg(feature = "calloop")] { if let Some(repeat_data) = - udata.repeat_data.lock().unwrap().as_mut() + self.repeat_data.lock().unwrap().as_mut() { let loop_handle = &mut repeat_data.loop_handle; - let state_guard = udata.xkb_state.lock().unwrap(); + let state_guard = self.xkb_state.lock().unwrap(); let key_repeats = state_guard .as_ref() .map(|guard| { @@ -725,17 +713,22 @@ where loop_handle.remove(token); } - let surface = - match udata.focus.lock().unwrap().as_ref().cloned() - { - Some(surface) => surface, - - None => { - log::warn!( - "wl_keyboard::key with no focused surface"); - return; - } - }; + let surface = match self + .focus + .lock() + .unwrap() + .as_ref() + .cloned() + { + Some(surface) => surface, + + None => { + log::warn!( + "wl_keyboard::key with no focused surface" + ); + return; + } + }; // Update the current repeat key. repeat_data.current_repeat.replace(RepeatedKey { @@ -754,7 +747,7 @@ where let timer = Timer::from_duration( Duration::from_millis(delay as u64), ); - let repeat_data2 = udata.repeat_data.clone(); + let repeat_data2 = self.repeat_data.clone(); // Start the timer. let kbd = keyboard.clone(); @@ -813,7 +806,7 @@ where mods_locked, group, } => { - let mut guard = udata.xkb_state.lock().unwrap(); + let mut guard = self.xkb_state.lock().unwrap(); let state = match guard.as_mut() { Some(state) => state, @@ -825,11 +818,11 @@ where // Update the currently repeating key if any. #[cfg(feature = "calloop")] - if let Some(repeat_data) = udata.repeat_data.lock().unwrap().as_mut() { + if let Some(repeat_data) = self.repeat_data.lock().unwrap().as_mut() { if let Some(mut event) = repeat_data.current_repeat.take() { // Apply new modifiers to get new utf8. event.key.utf8 = { - let mut compose = udata.xkb_compose.lock().unwrap(); + let mut compose = self.xkb_compose.lock().unwrap(); match compose.as_mut() { Some(compose) => match compose.feed(event.key.keysym) { @@ -866,7 +859,7 @@ where }; // Always issue the modifiers update for the user. - let modifiers = udata.update_modifiers(); + let modifiers = self.update_modifiers(); data.update_modifiers(conn, qh, keyboard, serial, modifiers, raw_modifiers, group); } @@ -882,7 +875,7 @@ where #[cfg(feature = "calloop")] { - if let Some(repeat_data) = udata.repeat_data.lock().unwrap().as_mut() { + if let Some(repeat_data) = self.repeat_data.lock().unwrap().as_mut() { repeat_data.repeat_info = info; } } diff --git a/src/seat/keyboard/repeat.rs b/src/seat/keyboard/repeat.rs index 0a549c9ce..3160315f2 100644 --- a/src/seat/keyboard/repeat.rs +++ b/src/seat/keyboard/repeat.rs @@ -10,8 +10,8 @@ use wayland_client::{ }; use super::{ - Capability, KeyEvent, KeyboardData, KeyboardDataExt, KeyboardError, KeyboardHandler, - RepeatInfo, SeatError, RMLVO, + Capability, KeyEvent, KeyboardData, KeyboardError, KeyboardHandler, RepeatInfo, SeatError, + RMLVO, }; use crate::seat::SeatState; @@ -55,24 +55,39 @@ impl SeatState { /// This will return [`SeatError::UnsupportedCapability`] if the seat does not support a keyboard. /// /// [`EventSource`]: calloop::EventSource - pub fn get_keyboard_with_repeat( + pub fn get_keyboard_with_repeat( &mut self, qh: &QueueHandle, seat: &wl_seat::WlSeat, rmlvo: Option, - loop_handle: LoopHandle<'static, T>, - callback: RepeatCallback, + loop_handle: LoopHandle<'static, D>, + callback: RepeatCallback, ) -> Result where - D: Dispatch> + KeyboardHandler + 'static, - T: 'static, + D: Dispatch> + KeyboardHandler + 'static, { let udata = match rmlvo { - Some(rmlvo) => KeyboardData::from_rmlvo(seat.clone(), rmlvo)?, - None => KeyboardData::new(seat.clone()), + Some(rmlvo) => KeyboardData::from_rmlvo(seat.clone(), rmlvo, ())?, + None => KeyboardData::new(seat.clone(), ()), }; - self.get_keyboard_with_repeat_with_data(qh, seat, udata, loop_handle, callback) + let inner = + self.seats.iter().find(|inner| &inner.seat == seat).ok_or(SeatError::DeadObject)?; + + if !inner.data.has_keyboard.load(Ordering::SeqCst) { + return Err(SeatError::UnsupportedCapability(Capability::Keyboard).into()); + } + + udata.repeat_data.lock().unwrap().replace(RepeatData { + current_repeat: None, + repeat_info: RepeatInfo::Disable, + loop_handle: loop_handle.clone(), + callback, + repeat_token: None, + }); + udata.init_compose(); + + Ok(seat.get_keyboard(qh, udata)) } /// Creates a keyboard from a seat. @@ -93,13 +108,13 @@ impl SeatState { &mut self, qh: &QueueHandle, seat: &wl_seat::WlSeat, - mut udata: U, - loop_handle: LoopHandle<'static, ::State>, - callback: RepeatCallback<::State>, + udata: U, + loop_handle: LoopHandle<'static, D>, + callback: RepeatCallback, ) -> Result where - D: Dispatch + KeyboardHandler + 'static, - U: KeyboardDataExt + 'static, + D: Dispatch> + KeyboardHandler + 'static, + U: Send + Sync + 'static, { let inner = self.seats.iter().find(|inner| &inner.seat == seat).ok_or(SeatError::DeadObject)?; @@ -108,15 +123,16 @@ impl SeatState { return Err(SeatError::UnsupportedCapability(Capability::Keyboard).into()); } - let kbd_data = udata.keyboard_data_mut(); - kbd_data.repeat_data.lock().unwrap().replace(RepeatData { + let udata = KeyboardData::new(seat.clone(), udata); + + udata.repeat_data.lock().unwrap().replace(RepeatData { current_repeat: None, repeat_info: RepeatInfo::Disable, loop_handle: loop_handle.clone(), callback, repeat_token: None, }); - kbd_data.init_compose(); + udata.init_compose(); Ok(seat.get_keyboard(qh, udata)) } diff --git a/src/seat/keyboard_filter.rs b/src/seat/keyboard_filter.rs index 69cfd2490..b460b5abf 100644 --- a/src/seat/keyboard_filter.rs +++ b/src/seat/keyboard_filter.rs @@ -11,6 +11,7 @@ use wayland_protocols_experimental::keyboard_filter::v3::client::{ self as protocol, xx_keyboard_filter_manager_v1, xx_keyboard_filter_v1, }; +use crate::dispatch2::Dispatch2; use crate::globals::GlobalData; #[derive(Debug)] @@ -42,21 +43,24 @@ impl KeyboardFilterManager { surface: &WlSurface, ) -> KeyboardFilter where - D: Dispatch + 'static, + D: Dispatch + 'static, { - KeyboardFilter(self.manager.bind_to_input_method(keyboard, input_method, surface, qh, ())) + KeyboardFilter(self.manager.bind_to_input_method( + keyboard, + input_method, + surface, + qh, + GlobalData, + )) } } -impl Dispatch for KeyboardFilterManager -where - D: Dispatch, -{ +impl Dispatch2 for GlobalData { fn event( + &self, _data: &mut D, _manager: &XxKeyboardFilterManagerV1, _event: xx_keyboard_filter_manager_v1::Event, - _: &GlobalData, _conn: &Connection, _qh: &QueueHandle, ) { @@ -82,15 +86,12 @@ impl KeyboardFilter { #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct KeyboardVersion(pub u32); -impl Dispatch for KeyboardFilter -where - D: Dispatch, -{ +impl Dispatch2 for GlobalData { fn event( + &self, _data: &mut D, _keyboard: &XxKeyboardFilterV1, _event: xx_keyboard_filter_v1::Event, - _: &(), _conn: &Connection, _qh: &QueueHandle, ) { @@ -98,25 +99,13 @@ where } } -#[macro_export] -macro_rules! delegate_keyboard_filter_v1 { - ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => { - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ - $crate::reexports::protocols_experimental::keyboard_filter::v3::client::xx_keyboard_filter_manager_v1::XxKeyboardFilterManagerV1: $crate::globals::GlobalData - ] => $crate::seat::keyboard_filter::KeyboardFilterManager); - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ - $crate::reexports::protocols_experimental::keyboard_filter::v3::client::xx_keyboard_filter_v1::XxKeyboardFilterV1: () - ] => $crate::seat::keyboard_filter::KeyboardFilter); - }; -} - #[cfg(test)] mod test { use super::*; struct Handler {} - delegate_keyboard_filter_v1!(Handler); + crate::delegate_dispatch2!(Handler); fn assert_is_manager_delegate() where @@ -129,7 +118,10 @@ mod test { fn assert_is_delegate() where - T: wayland_client::Dispatch, + T: wayland_client::Dispatch< + protocol::xx_keyboard_filter_v1::XxKeyboardFilterV1, + crate::globals::GlobalData, + >, { } diff --git a/src/seat/mod.rs b/src/seat/mod.rs index 82764025c..97aac1667 100644 --- a/src/seat/mod.rs +++ b/src/seat/mod.rs @@ -15,7 +15,8 @@ use crate::reexports::client::{ use crate::reexports::protocols::wp::cursor_shape::v1::client::wp_cursor_shape_device_v1::WpCursorShapeDeviceV1; use crate::reexports::protocols::wp::cursor_shape::v1::client::wp_cursor_shape_manager_v1::WpCursorShapeManagerV1; use crate::{ - compositor::SurfaceDataExt, + compositor::SurfaceData, + dispatch2::Dispatch2, globals::GlobalData, registry::{ProvidesRegistryState, RegistryHandler}, }; @@ -31,8 +32,8 @@ pub mod relative_pointer; pub mod touch; use pointer::cursor_shape::CursorShapeManager; -use pointer::{PointerData, PointerDataExt, PointerHandler, ThemeSpec, ThemedPointer, Themes}; -use touch::{TouchData, TouchDataExt, TouchHandler}; +use pointer::{PointerData, PointerHandler, ThemeSpec, ThemedPointer, Themes}; +use touch::{TouchData, TouchHandler}; #[non_exhaustive] #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -152,9 +153,9 @@ impl SeatState { seat: &wl_seat::WlSeat, ) -> Result where - D: Dispatch + PointerHandler + 'static, + D: Dispatch> + PointerHandler + 'static, { - self.get_pointer_with_data(qh, seat, PointerData::new(seat.clone())) + self.get_pointer_with_data(qh, seat, ()) } /// Creates a pointer from a seat with the provided theme. @@ -171,24 +172,16 @@ impl SeatState { shm: &wl_shm::WlShm, surface: wl_surface::WlSurface, theme: ThemeSpec, - ) -> Result, SeatError> + ) -> Result, SeatError> where - D: Dispatch - + Dispatch + D: Dispatch> + + Dispatch> + Dispatch + Dispatch + PointerHandler + 'static, - S: SurfaceDataExt + 'static, { - self.get_pointer_with_theme_and_data( - qh, - seat, - shm, - surface, - theme, - PointerData::new(seat.clone()), - ) + self.get_pointer_with_theme_and_data(qh, seat, shm, surface, theme, ()) } /// Creates a pointer from a seat. @@ -203,8 +196,8 @@ impl SeatState { pointer_data: U, ) -> Result where - D: Dispatch + PointerHandler + 'static, - U: PointerDataExt + 'static, + D: Dispatch> + PointerHandler + 'static, + U: Send + Sync + 'static, { let inner = self.seats.iter().find(|inner| &inner.seat == seat).ok_or(SeatError::DeadObject)?; @@ -213,6 +206,7 @@ impl SeatState { return Err(SeatError::UnsupportedCapability(Capability::Pointer)); } + let pointer_data = PointerData::new(seat.clone(), pointer_data); Ok(seat.get_pointer(qh, pointer_data)) } @@ -221,7 +215,7 @@ impl SeatState { /// ## Errors /// /// This will return [`SeatError::UnsupportedCapability`] if the seat does not support a pointer. - pub fn get_pointer_with_theme_and_data( + pub fn get_pointer_with_theme_and_data( &mut self, qh: &QueueHandle, seat: &wl_seat::WlSeat, @@ -231,14 +225,12 @@ impl SeatState { pointer_data: U, ) -> Result, SeatError> where - D: Dispatch - + Dispatch + D: Dispatch> + Dispatch + Dispatch + PointerHandler + 'static, - S: SurfaceDataExt + 'static, - U: PointerDataExt + 'static, + U: Send + Sync + 'static, { let inner = self.seats.iter().find(|inner| &inner.seat == seat).ok_or(SeatError::DeadObject)?; @@ -247,6 +239,7 @@ impl SeatState { return Err(SeatError::UnsupportedCapability(Capability::Pointer)); } + let pointer_data = PointerData::new(seat.clone(), pointer_data); let wl_ptr = seat.get_pointer(qh, pointer_data); if let CursorShapeManagerState::Pending { registry, global } = @@ -295,9 +288,9 @@ impl SeatState { seat: &wl_seat::WlSeat, ) -> Result where - D: Dispatch + TouchHandler + 'static, + D: Dispatch> + TouchHandler + 'static, { - self.get_touch_with_data(qh, seat, TouchData::new(seat.clone())) + self.get_touch_with_data(qh, seat, ()) } /// Creates a touch handle from a seat. @@ -312,8 +305,8 @@ impl SeatState { udata: U, ) -> Result where - D: Dispatch + TouchHandler + 'static, - U: TouchDataExt + 'static, + D: Dispatch> + TouchHandler + 'static, + U: Send + Sync + 'static, { let inner = self.seats.iter().find(|inner| &inner.seat == seat).ok_or(SeatError::DeadObject)?; @@ -322,7 +315,8 @@ impl SeatState { return Err(SeatError::UnsupportedCapability(Capability::Touch)); } - Ok(seat.get_touch(qh, udata)) + let data = TouchData::new(seat.clone(), udata); + Ok(seat.get_touch(qh, data)) } } @@ -425,32 +419,21 @@ pub struct SeatData { id: u32, } -#[macro_export] -macro_rules! delegate_seat { - ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => { - $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: - [ - $crate::reexports::client::protocol::wl_seat::WlSeat: $crate::seat::SeatData - ] => $crate::seat::SeatState - ); - }; -} - #[derive(Debug)] struct SeatInner { seat: wl_seat::WlSeat, data: SeatData, } -impl Dispatch for SeatState +impl Dispatch2 for SeatData where - D: Dispatch + SeatHandler, + D: SeatHandler, { fn event( + &self, state: &mut D, seat: &wl_seat::WlSeat, event: wl_seat::Event, - data: &SeatData, conn: &Connection, qh: &QueueHandle, ) { @@ -459,15 +442,15 @@ where let capabilities = wl_seat::Capability::from_bits_truncate(capabilities.into()); let keyboard = capabilities.contains(wl_seat::Capability::Keyboard); - let has_keyboard = data.has_keyboard.load(Ordering::SeqCst); + let has_keyboard = self.has_keyboard.load(Ordering::SeqCst); let pointer = capabilities.contains(wl_seat::Capability::Pointer); - let has_pointer = data.has_pointer.load(Ordering::SeqCst); + let has_pointer = self.has_pointer.load(Ordering::SeqCst); let touch = capabilities.contains(wl_seat::Capability::Touch); - let has_touch = data.has_touch.load(Ordering::SeqCst); + let has_touch = self.has_touch.load(Ordering::SeqCst); // Update capabilities as necessary if keyboard != has_keyboard { - data.has_keyboard.store(keyboard, Ordering::SeqCst); + self.has_keyboard.store(keyboard, Ordering::SeqCst); match keyboard { true => state.new_capability(conn, qh, seat.clone(), Capability::Keyboard), @@ -478,7 +461,7 @@ where } if pointer != has_pointer { - data.has_pointer.store(pointer, Ordering::SeqCst); + self.has_pointer.store(pointer, Ordering::SeqCst); match pointer { true => state.new_capability(conn, qh, seat.clone(), Capability::Pointer), @@ -489,7 +472,7 @@ where } if touch != has_touch { - data.has_touch.store(touch, Ordering::SeqCst); + self.has_touch.store(touch, Ordering::SeqCst); match touch { true => state.new_capability(conn, qh, seat.clone(), Capability::Touch), @@ -499,7 +482,7 @@ where } wl_seat::Event::Name { name } => { - *data.name.lock().unwrap() = Some(name); + *self.name.lock().unwrap() = Some(name); } _ => unreachable!(), diff --git a/src/seat/pointer/cursor_shape.rs b/src/seat/pointer/cursor_shape.rs index 1d1821012..f4be25808 100644 --- a/src/seat/pointer/cursor_shape.rs +++ b/src/seat/pointer/cursor_shape.rs @@ -1,5 +1,6 @@ use cursor_icon::CursorIcon; +use crate::dispatch2::Dispatch2; use crate::globals::GlobalData; use crate::reexports::client::globals::{BindError, GlobalList}; use crate::reexports::client::protocol::wl_pointer::WlPointer; @@ -45,15 +46,12 @@ impl CursorShapeManager { } } -impl Dispatch for CursorShapeManager -where - State: Dispatch, -{ +impl Dispatch2 for GlobalData { fn event( + &self, _: &mut State, _: &WpCursorShapeManagerV1, _: ::Event, - _: &GlobalData, _: &Connection, _: &QueueHandle, ) { @@ -61,15 +59,12 @@ where } } -impl Dispatch for CursorShapeManager -where - State: Dispatch, -{ +impl Dispatch2 for GlobalData { fn event( + &self, _: &mut State, _: &WpCursorShapeDeviceV1, _: ::Event, - _: &GlobalData, _: &Connection, _: &QueueHandle, ) { diff --git a/src/seat/pointer/mod.rs b/src/seat/pointer/mod.rs index 137ec0acc..e4c455f95 100644 --- a/src/seat/pointer/mod.rs +++ b/src/seat/pointer/mod.rs @@ -12,17 +12,12 @@ use wayland_client::{ wl_shm::WlShm, wl_surface::WlSurface, }, - Connection, Dispatch, Proxy, QueueHandle, WEnum, + Connection, Proxy, QueueHandle, WEnum, }; use wayland_cursor::{Cursor, CursorTheme}; use wayland_protocols::wp::cursor_shape::v1::client::wp_cursor_shape_device_v1::WpCursorShapeDeviceV1; -use crate::{ - compositor::{SurfaceData, SurfaceDataExt}, - error::GlobalError, -}; - -use super::SeatState; +use crate::{compositor::SurfaceData, dispatch2::Dispatch2, error::GlobalError}; #[doc(inline)] pub use cursor_icon::{CursorIcon, ParseError as CursorIconParseError}; @@ -158,14 +153,23 @@ pub trait PointerHandler: Sized { } #[derive(Debug)] -pub struct PointerData { +pub struct PointerData { seat: WlSeat, pub(crate) inner: Mutex, + udata: U, } -impl PointerData { - pub fn new(seat: WlSeat) -> Self { - Self { seat, inner: Default::default() } +impl PointerData { + pub fn new(seat: WlSeat, udata: U) -> Self { + Self { seat, inner: Default::default(), udata } + } + + pub fn data(&self) -> &U { + &self.udata + } + + pub fn data_mut(&mut self) -> &mut U { + &mut self.udata } /// The seat associated with this pointer. @@ -185,50 +189,6 @@ impl PointerData { } } -pub trait PointerDataExt: Send + Sync { - fn pointer_data(&self) -> &PointerData; -} - -impl PointerDataExt for PointerData { - fn pointer_data(&self) -> &PointerData { - self - } -} - -#[macro_export] -macro_rules! delegate_pointer { - ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => { - $crate::delegate_pointer!(@{ $(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty }; pointer: []); - $crate::delegate_pointer!(@{ $(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty }; pointer-only: $crate::seat::pointer::PointerData); - }; - ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty, pointer: [$($pointer_data:ty),* $(,)?]) => { - $crate::delegate_pointer!(@{ $(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty }; pointer: [ $($pointer_data),* ]); - }; - (@{$($ty:tt)*}; pointer: []) => { - $crate::reexports::client::delegate_dispatch!($($ty)*: - [ - $crate::reexports::protocols::wp::cursor_shape::v1::client::wp_cursor_shape_manager_v1::WpCursorShapeManagerV1: $crate::globals::GlobalData - ] => $crate::seat::pointer::cursor_shape::CursorShapeManager - ); - $crate::reexports::client::delegate_dispatch!($($ty)*: - [ - $crate::reexports::protocols::wp::cursor_shape::v1::client::wp_cursor_shape_device_v1::WpCursorShapeDeviceV1: $crate::globals::GlobalData - ] => $crate::seat::pointer::cursor_shape::CursorShapeManager - ); - }; - (@{$($ty:tt)*}; pointer-only: $pointer_data:ty) => { - $crate::reexports::client::delegate_dispatch!($($ty)*: - [ - $crate::reexports::client::protocol::wl_pointer::WlPointer: $pointer_data - ] => $crate::seat::SeatState - ); - }; - (@$ty:tt; pointer: [$($pointer:ty),*]) => { - $crate::delegate_pointer!(@$ty; pointer: []); - $( $crate::delegate_pointer!(@$ty; pointer-only: $pointer); )* - } -} - #[derive(Debug, Default)] pub(crate) struct PointerDataInner { /// Surface the pointer most recently entered @@ -246,21 +206,20 @@ pub(crate) struct PointerDataInner { pub(crate) latest_btn: Option, } -impl Dispatch for SeatState +impl Dispatch2 for PointerData where - D: Dispatch + PointerHandler, - U: PointerDataExt, + D: PointerHandler, + U: Send + Sync + 'static, { fn event( + &self, data: &mut D, pointer: &WlPointer, event: wl_pointer::Event, - udata: &U, conn: &Connection, qh: &QueueHandle, ) { - let udata = udata.pointer_data(); - let mut guard = udata.inner.lock().unwrap(); + let mut guard = self.inner.lock().unwrap(); let mut leave_surface = None; let kind = match event { wl_pointer::Event::Enter { surface, surface_x, surface_y, serial } => { @@ -501,7 +460,7 @@ where /// Pointer themeing #[derive(Debug)] -pub struct ThemedPointer { +pub struct ThemedPointer { pub(super) themes: Arc>, /// The underlying wl_pointer. pub(super) pointer: WlPointer, @@ -513,19 +472,17 @@ pub struct ThemedPointer { pub(super) _surface_data: std::marker::PhantomData, } -impl ThemedPointer { +impl ThemedPointer { /// Set the cursor to the given [`CursorIcon`]. /// /// The cursor icon should be reloaded on every [`PointerEventKind::Enter`] event. pub fn set_cursor(&self, conn: &Connection, icon: CursorIcon) -> Result<(), PointerThemeError> { - let serial = match self - .pointer - .data::() - .and_then(|data| data.pointer_data().latest_enter_serial()) - { - Some(serial) => serial, - None => return Err(PointerThemeError::MissingEnterSerial), - }; + let serial = + match self.pointer.data::>().and_then(|data| data.latest_enter_serial()) + { + Some(serial) => serial, + None => return Err(PointerThemeError::MissingEnterSerial), + }; if let Some(shape_device) = self.shape_device.as_ref() { shape_device.set_shape(serial, cursor_icon_to_shape(icon, shape_device.version())); @@ -545,7 +502,7 @@ impl ThemedPointer Result<(), PointerThemeError> { let mut themes = self.themes.lock().unwrap(); - let scale = self.surface.data::().unwrap().surface_data().scale_factor(); + let scale = self.surface.data::>().unwrap().scale_factor(); for cursor_icon_name in iter::once(&icon.name()).chain(icon.alt_names().iter()) { if let Some(cursor) = themes .get_cursor(conn, cursor_icon_name, scale as u32, &self.shm) @@ -587,8 +544,8 @@ impl ThemedPointer