diff --git a/src/acceptor.rs b/src/acceptor.rs index e3bbafcf..bae366ce 100644 --- a/src/acceptor.rs +++ b/src/acceptor.rs @@ -104,10 +104,7 @@ impl Acceptor { } impl EventLoopDispatcher for Acceptor { - fn dispatch( - self: Rc, - events: i32, - ) -> Result<(), Box> { + fn dispatch(self: Rc, events: i32) -> Result<(), Box> { if events & (c::EPOLLERR | c::EPOLLHUP) != 0 { return Err(Box::new(AcceptorError::ErrorEvent)); } diff --git a/src/async_engine.rs b/src/async_engine.rs index d3c01fc2..e1576ca8 100644 --- a/src/async_engine.rs +++ b/src/async_engine.rs @@ -134,7 +134,7 @@ mod timeout { } impl WheelDispatcher for TimeoutData { - fn dispatch(self: Rc) -> Result<(), Box> { + fn dispatch(self: Rc) -> Result<(), Box> { self.expired.set(true); if let Some(w) = self.waker.borrow_mut().take() { w.wake(); @@ -438,7 +438,7 @@ mod queue { } impl EventLoopDispatcher for Dispatcher { - fn dispatch(self: Rc, _events: i32) -> Result<(), Box> { + fn dispatch(self: Rc, _events: i32) -> Result<(), Box> { loop { self.queue.iteration.fetch_add(1); let mut stash = self.stash.borrow_mut(); @@ -552,7 +552,7 @@ mod fd { } impl EventLoopDispatcher for AsyncFdData { - fn dispatch(self: Rc, events: i32) -> Result<(), Box> { + fn dispatch(self: Rc, events: i32) -> Result<(), Box> { if events & (c::EPOLLERR | c::EPOLLHUP) != 0 { self.erroneous.set(true); if let Err(e) = self.el.remove(self.id) { diff --git a/src/backends/xorg/mod.rs b/src/backends/xorg/mod.rs index 2bd9094a..bae99ad4 100644 --- a/src/backends/xorg/mod.rs +++ b/src/backends/xorg/mod.rs @@ -902,7 +902,7 @@ impl XorgBackend { } impl EventLoopDispatcher for XorgBackend { - fn dispatch(self: Rc, events: i32) -> Result<(), Box> { + fn dispatch(self: Rc, events: i32) -> Result<(), Box> { if events & (c::EPOLLERR | c::EPOLLHUP) != 0 { return Err(Box::new(XorgBackendError::ErrorEvent)); } @@ -912,7 +912,7 @@ impl EventLoopDispatcher for XorgBackend { } impl WheelDispatcher for XorgBackend { - fn dispatch(self: Rc) -> Result<(), Box> { + fn dispatch(self: Rc) -> Result<(), Box> { Ok(()) } } diff --git a/src/client/error.rs b/src/client/error.rs index 295e4292..2cd92508 100644 --- a/src/client/error.rs +++ b/src/client/error.rs @@ -1,38 +1,8 @@ use crate::client::ClientId; -use crate::ifs::org_kde_kwin_server_decoration::OrgKdeKwinServerDecorationError; -use crate::ifs::org_kde_kwin_server_decoration_manager::OrgKdeKwinServerDecorationManagerError; -use crate::ifs::wl_buffer::{WlBufferError, WlBufferId}; -use crate::ifs::wl_compositor::WlCompositorError; -use crate::ifs::wl_data_device::WlDataDeviceError; -use crate::ifs::wl_data_device_manager::WlDataDeviceManagerError; -use crate::ifs::wl_data_offer::WlDataOfferError; -use crate::ifs::wl_data_source::{WlDataSourceError, WlDataSourceId}; -use crate::ifs::wl_display::WlDisplayError; -use crate::ifs::wl_drm::WlDrmError; -use crate::ifs::wl_output::WlOutputError; -use crate::ifs::wl_region::{WlRegionError, WlRegionId}; -use crate::ifs::wl_registry::WlRegistryError; -use crate::ifs::wl_seat::wl_keyboard::WlKeyboardError; -use crate::ifs::wl_seat::wl_pointer::WlPointerError; -use crate::ifs::wl_seat::wl_touch::WlTouchError; -use crate::ifs::wl_seat::{WlSeatError, WlSeatId}; -use crate::ifs::wl_shm::WlShmError; -use crate::ifs::wl_shm_pool::WlShmPoolError; -use crate::ifs::wl_subcompositor::WlSubcompositorError; -use crate::ifs::wl_surface::wl_subsurface::WlSubsurfaceError; -use crate::ifs::wl_surface::xdg_surface::xdg_popup::XdgPopupError; -use crate::ifs::wl_surface::xdg_surface::xdg_toplevel::{XdgToplevelError, XdgToplevelId}; -use crate::ifs::wl_surface::xdg_surface::{XdgSurfaceError, XdgSurfaceId}; -use crate::ifs::wl_surface::{WlSurfaceError, WlSurfaceId}; -use crate::ifs::xdg_positioner::{XdgPositionerError, XdgPositionerId}; -use crate::ifs::xdg_wm_base::XdgWmBaseError; -use crate::ifs::zwp_linux_buffer_params_v1::ZwpLinuxBufferParamsV1Error; -use crate::ifs::zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1Error; -use crate::ifs::zxdg_decoration_manager_v1::ZxdgDecorationManagerV1Error; -use crate::ifs::zxdg_toplevel_decoration_v1::ZxdgToplevelDecorationV1Error; -use crate::object::ObjectId; +use crate::object::{Interface, ObjectId}; use crate::utils::buffd::{BufFdError, MsgParserError}; use crate::AsyncError; +use std::error::Error; use thiserror::Error; #[derive(Debug, Error)] @@ -53,22 +23,6 @@ pub enum ClientError { UnalignedMessage, #[error("The requested client {0} does not exist")] ClientDoesNotExist(ClientId), - #[error("There is no wl_region with id {0}")] - RegionDoesNotExist(WlRegionId), - #[error("There is no wl_buffer with id {0}")] - BufferDoesNotExist(WlBufferId), - #[error("There is no wl_surface with id {0}")] - SurfaceDoesNotExist(WlSurfaceId), - #[error("There is no xdg_surface with id {0}")] - XdgSurfaceDoesNotExist(XdgSurfaceId), - #[error("There is no wl_data_source with id {0}")] - WlDataSourceDoesNotExist(WlDataSourceId), - #[error("There is no xdg_toplevel with id {0}")] - XdgToplevelDoesNotExist(XdgToplevelId), - #[error("There is no xdg_positioner with id {0}")] - XdgPositionerDoesNotExist(XdgPositionerId), - #[error("There is no wl_seat with id {0}")] - WlSeatDoesNotExist(WlSeatId), #[error("Cannot parse the message")] ParserError(#[source] Box), #[error("Server tried to allocate more than 0x1_00_00_00 ids")] @@ -81,109 +35,34 @@ pub enum ClientError { IdAlreadyInUse, #[error("The client object id is out of bounds")] ClientIdOutOfBounds, - #[error("An error occurred in a `wl_display`")] - WlDisplayError(#[source] Box), - #[error("An error occurred in a `wl_registry`")] - WlRegistryError(#[source] Box), - #[error("Could not add object {0} to the client")] - AddObjectError(ObjectId, #[source] Box), - #[error("An error occurred in a `wl_surface`")] - WlSurfaceError(#[source] Box), - #[error("An error occurred in a `wl_compositor`")] - WlCompositorError(#[source] Box), - #[error("An error occurred in a `wl_shm`")] - WlShmError(#[source] Box), - #[error("An error occurred in a `wl_shm_pool`")] - WlShmPoolError(#[source] Box), - #[error("An error occurred in a `wl_region`")] - WlRegionError(#[source] Box), - #[error("An error occurred in a `wl_subsurface`")] - WlSubsurfaceError(#[source] Box), - #[error("An error occurred in a `wl_subcompositor`")] - WlSubcompositorError(#[source] Box), - #[error("An error occurred in a `xdg_surface`")] - XdgSurfaceError(#[source] Box), - #[error("An error occurred in a `xdg_positioner`")] - XdgPositionerError(#[source] Box), - #[error("An error occurred in a `xdg_popup`")] - XdgPopupError(#[source] Box), - #[error("An error occurred in a `xdg_toplevel`")] - XdgToplevelError(#[source] Box), - #[error("An error occurred in a `xdg_wm_base`")] - XdgWmBaseError(#[source] Box), - #[error("An error occurred in a `wl_buffer`")] - WlBufferError(#[source] Box), - #[error("An error occurred in a `wl_output`")] - WlOutputError(#[source] Box), - #[error("An error occurred in a `wl_seat`")] - WlSeatError(#[source] Box), - #[error("An error occurred in a `wl_pointer`")] - WlPointerError(#[source] Box), - #[error("An error occurred in a `wl_keyboard`")] - WlKeyboardError(#[source] Box), - #[error("An error occurred in a `wl_touch`")] - WlTouchError(#[source] Box), #[error("Object {0} is not a display")] NotADisplay(ObjectId), - #[error("An error occurred in a `wl_data_device`")] - WlDataDeviceError(#[source] Box), - #[error("An error occurred in a `wl_data_device_manager`")] - WlDataDeviceManagerError(#[source] Box), - #[error("An error occurred in a `wl_data_offer`")] - WlDataOfferError(#[source] Box), - #[error("An error occurred in a `wl_data_source`")] - WlDataSourceError(#[source] Box), - #[error("An error occurred in a `zwp_linx_dmabuf_v1`")] - ZwpLinuxDmabufV1Error(#[source] Box), - #[error("An error occurred in a `zwp_linx_buffer_params_v1`")] - ZwpLinuxBufferParamsV1Error(#[source] Box), - #[error("An error occurred in a `wl_drm`")] - WlDrmError(#[source] Box), - #[error("An error occurred in a `zxdg_decoration_manager_v1`")] - ZxdgDecorationManagerV1Error(#[source] Box), - #[error("An error occurred in a `zxdg_toplevel_decoration_v1`")] - ZxdgToplevelDecorationV1Error(#[source] Box), - #[error("An error occurred in a `org_kde_kwin_server_decoration_manager`")] - OrgKdeKwinServerDecorationManagerError(#[source] Box), - #[error("An error occurred in a `org_kde_kwin_server_decoration`")] - OrgKdeKwinServerDecorationError(#[source] Box), + #[error(transparent)] + ObjectError(ObjectError), + #[error(transparent)] + LookupError(LookupError), + #[error("Could not add object {0} to the client")] + AddObjectError(ObjectId, #[source] Box), } - efrom!(ClientError, ParserError, MsgParserError); -efrom!(ClientError, WlDisplayError); -efrom!(ClientError, WlRegistryError); -efrom!(ClientError, WlSurfaceError); -efrom!(ClientError, WlCompositorError); -efrom!(ClientError, WlShmError); -efrom!(ClientError, WlShmPoolError); -efrom!(ClientError, WlRegionError); -efrom!(ClientError, WlSubsurfaceError); -efrom!(ClientError, WlSubcompositorError); -efrom!(ClientError, XdgSurfaceError); -efrom!(ClientError, XdgPositionerError); -efrom!(ClientError, XdgWmBaseError); -efrom!(ClientError, XdgToplevelError); -efrom!(ClientError, XdgPopupError); -efrom!(ClientError, WlBufferError); -efrom!(ClientError, WlOutputError); -efrom!(ClientError, WlSeatError); -efrom!(ClientError, WlTouchError); -efrom!(ClientError, WlPointerError); -efrom!(ClientError, WlKeyboardError); -efrom!(ClientError, WlDataDeviceManagerError); -efrom!(ClientError, WlDataDeviceError); -efrom!(ClientError, WlDataSourceError); -efrom!(ClientError, WlDataOfferError); -efrom!(ClientError, ZwpLinuxDmabufV1Error); -efrom!(ClientError, ZwpLinuxBufferParamsV1Error); -efrom!(ClientError, WlDrmError); -efrom!(ClientError, ZxdgDecorationManagerV1Error); -efrom!(ClientError, ZxdgToplevelDecorationV1Error); -efrom!(ClientError, OrgKdeKwinServerDecorationManagerError); -efrom!(ClientError, OrgKdeKwinServerDecorationError); impl ClientError { pub fn peer_closed(&self) -> bool { matches!(self, ClientError::Io(BufFdError::Closed)) } } + +#[derive(Debug, Error)] +#[error("An error occurred in a `{}`", .interface.name())] +pub struct ObjectError { + pub interface: Interface, + #[source] + pub error: Box, +} + +#[derive(Debug, Error)] +#[error("There is no `{}` with id {}", .interface.name(), .id)] +pub struct LookupError { + pub interface: Interface, + pub id: ObjectId, +} diff --git a/src/client/mod.rs b/src/client/mod.rs index 2a75752a..a4c132c9 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -1,38 +1,10 @@ use crate::async_engine::{AsyncFd, SpawnedFuture}; +use crate::client::error::LookupError; use crate::client::objects::Objects; -use crate::ifs::org_kde_kwin_server_decoration::OrgKdeKwinServerDecoration; -use crate::ifs::org_kde_kwin_server_decoration_manager::OrgKdeKwinServerDecorationManagerObj; -use crate::ifs::wl_buffer::{WlBuffer, WlBufferId}; use crate::ifs::wl_callback::WlCallback; -use crate::ifs::wl_compositor::WlCompositorObj; -use crate::ifs::wl_data_device::WlDataDevice; -use crate::ifs::wl_data_device_manager::WlDataDeviceManagerObj; -use crate::ifs::wl_data_offer::WlDataOffer; -use crate::ifs::wl_data_source::{WlDataSource, WlDataSourceId}; use crate::ifs::wl_display::WlDisplay; -use crate::ifs::wl_drm::WlDrmObj; -use crate::ifs::wl_output::WlOutputObj; -use crate::ifs::wl_region::{WlRegion, WlRegionId}; use crate::ifs::wl_registry::{WlRegistry, WlRegistryId}; -use crate::ifs::wl_seat::wl_keyboard::WlKeyboard; -use crate::ifs::wl_seat::wl_pointer::WlPointer; -use crate::ifs::wl_seat::wl_touch::WlTouch; -use crate::ifs::wl_seat::{WlSeatId, WlSeatObj}; -use crate::ifs::wl_shm::WlShmObj; -use crate::ifs::wl_shm_pool::WlShmPool; -use crate::ifs::wl_subcompositor::WlSubcompositorObj; -use crate::ifs::wl_surface::wl_subsurface::WlSubsurface; -use crate::ifs::wl_surface::xdg_surface::xdg_popup::XdgPopup; -use crate::ifs::wl_surface::xdg_surface::xdg_toplevel::{XdgToplevel, XdgToplevelId}; -use crate::ifs::wl_surface::xdg_surface::{XdgSurface, XdgSurfaceId}; -use crate::ifs::wl_surface::{WlSurface, WlSurfaceId}; -use crate::ifs::xdg_positioner::{XdgPositioner, XdgPositionerId}; -use crate::ifs::xdg_wm_base::XdgWmBaseObj; -use crate::ifs::zwp_linux_buffer_params_v1::ZwpLinuxBufferParamsV1; -use crate::ifs::zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1Obj; -use crate::ifs::zxdg_decoration_manager_v1::ZxdgDecorationManagerV1Obj; -use crate::ifs::zxdg_toplevel_decoration_v1::ZxdgToplevelDecorationV1; -use crate::object::{Object, ObjectId, WL_DISPLAY_ID}; +use crate::object::{Interface, Object, ObjectId, WL_DISPLAY_ID}; use crate::state::State; use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError}; use crate::utils::numcell::NumCell; @@ -40,7 +12,7 @@ use crate::utils::oneshot::{oneshot, OneshotTx}; use crate::utils::queue::AsyncQueue; use crate::ErrorFmt; use ahash::AHashMap; -pub use error::ClientError; +pub use error::{ClientError, ObjectError}; use std::cell::{Cell, RefCell, RefMut}; use std::error::Error; use std::fmt::{Debug, Display, Formatter}; @@ -332,65 +304,6 @@ impl Client { self.checking_queue_size.set(false); } - pub fn get_buffer(&self, id: WlBufferId) -> Result, ClientError> { - match self.objects.buffers.get(&id) { - Some(r) => Ok(r), - _ => Err(ClientError::BufferDoesNotExist(id)), - } - } - - pub fn get_region(&self, id: WlRegionId) -> Result, ClientError> { - match self.objects.regions.get(&id) { - Some(r) => Ok(r), - _ => Err(ClientError::RegionDoesNotExist(id)), - } - } - - pub fn get_surface(&self, id: WlSurfaceId) -> Result, ClientError> { - match self.objects.surfaces.get(&id) { - Some(r) => Ok(r), - _ => Err(ClientError::SurfaceDoesNotExist(id)), - } - } - - pub fn get_xdg_surface(&self, id: XdgSurfaceId) -> Result, ClientError> { - match self.objects.xdg_surfaces.get(&id) { - Some(r) => Ok(r), - _ => Err(ClientError::XdgSurfaceDoesNotExist(id)), - } - } - - pub fn get_wl_data_source(&self, id: WlDataSourceId) -> Result, ClientError> { - match self.objects.wl_data_source.get(&id) { - Some(r) => Ok(r), - _ => Err(ClientError::WlDataSourceDoesNotExist(id)), - } - } - - pub fn get_xdg_toplevel(&self, id: XdgToplevelId) -> Result, ClientError> { - match self.objects.xdg_toplevel.get(&id) { - Some(r) => Ok(r), - _ => Err(ClientError::XdgToplevelDoesNotExist(id)), - } - } - - pub fn get_xdg_positioner( - &self, - id: XdgPositionerId, - ) -> Result, ClientError> { - match self.objects.xdg_positioners.get(&id) { - Some(r) => Ok(r), - _ => Err(ClientError::XdgPositionerDoesNotExist(id)), - } - } - - pub fn get_wl_seat(&self, id: WlSeatId) -> Result, ClientError> { - match self.objects.seats.get(&id) { - Some(r) => Ok(r), - _ => Err(ClientError::WlSeatDoesNotExist(id)), - } - } - pub fn lock_registries(&self) -> RefMut>> { self.objects.registries() } @@ -432,6 +345,18 @@ impl Client { obj.remove(self); self.objects.remove_obj(self, obj.id()) } + + pub fn lookup(&self, id: Id) -> Result, ClientError> { + match Id::lookup(self, id) { + Some(t) => Ok(t), + _ => { + return Err(ClientError::LookupError(LookupError { + interface: Id::INTERFACE, + id: id.into(), + })) + } + } + } } pub trait WaylandObject: Object { @@ -443,54 +368,9 @@ pub trait WaylandObject: Object { } } -macro_rules! simple_add_obj { - ($ty:ty) => { - impl WaylandObject for $ty {} - }; +pub trait WaylandObjectLookup: Copy + Into { + type Object; + const INTERFACE: Interface; + + fn lookup(client: &Client, id: Self) -> Option>; } - -simple_add_obj!(WlCompositorObj); -simple_add_obj!(WlCallback); -simple_add_obj!(WlRegistry); -simple_add_obj!(WlShmObj); -simple_add_obj!(WlShmPool); -simple_add_obj!(WlSubcompositorObj); -simple_add_obj!(WlSubsurface); -simple_add_obj!(XdgPopup); -simple_add_obj!(WlOutputObj); -simple_add_obj!(WlKeyboard); -simple_add_obj!(WlPointer); -simple_add_obj!(WlTouch); -simple_add_obj!(WlDataDeviceManagerObj); -simple_add_obj!(WlDataDevice); -simple_add_obj!(WlDataOffer); -simple_add_obj!(ZwpLinuxDmabufV1Obj); -simple_add_obj!(ZwpLinuxBufferParamsV1); -simple_add_obj!(WlDrmObj); -simple_add_obj!(ZxdgToplevelDecorationV1); -simple_add_obj!(ZxdgDecorationManagerV1Obj); -simple_add_obj!(OrgKdeKwinServerDecorationManagerObj); -simple_add_obj!(OrgKdeKwinServerDecoration); - -macro_rules! dedicated_add_obj { - ($ty:ty, $field:ident) => { - impl WaylandObject for $ty { - fn add(self: Rc, client: &Client) { - client.objects.$field.set(self.id().into(), self); - } - fn remove(&self, client: &Client) { - client.objects.$field.remove(&self.id().into()); - } - } - }; -} - -dedicated_add_obj!(WlRegion, regions); -dedicated_add_obj!(WlSurface, surfaces); -dedicated_add_obj!(XdgWmBaseObj, xdg_wm_bases); -dedicated_add_obj!(XdgSurface, xdg_surfaces); -dedicated_add_obj!(WlBuffer, buffers); -dedicated_add_obj!(WlSeatObj, seats); -dedicated_add_obj!(XdgPositioner, xdg_positioners); -dedicated_add_obj!(XdgToplevel, xdg_toplevel); -dedicated_add_obj!(WlDataSource, wl_data_source); diff --git a/src/client/objects.rs b/src/client/objects.rs index 3f5d71a7..ea9ebf53 100644 --- a/src/client/objects.rs +++ b/src/client/objects.rs @@ -4,12 +4,15 @@ use crate::ifs::wl_data_source::{WlDataSource, WlDataSourceId}; use crate::ifs::wl_display::WlDisplay; use crate::ifs::wl_region::{WlRegion, WlRegionId}; use crate::ifs::wl_registry::{WlRegistry, WlRegistryId}; -use crate::ifs::wl_seat::{WlSeatId, WlSeatObj}; +use crate::ifs::wl_seat::{WlSeat, WlSeatId}; use crate::ifs::wl_surface::xdg_surface::xdg_toplevel::{XdgToplevel, XdgToplevelId}; use crate::ifs::wl_surface::xdg_surface::{XdgSurface, XdgSurfaceId}; use crate::ifs::wl_surface::{WlSurface, WlSurfaceId}; use crate::ifs::xdg_positioner::{XdgPositioner, XdgPositionerId}; -use crate::ifs::xdg_wm_base::{XdgWmBaseId, XdgWmBaseObj}; +use crate::ifs::xdg_wm_base::{XdgWmBase, XdgWmBaseId}; +use crate::ifs::zwp_primary_selection_source_v1::{ + ZwpPrimarySelectionSourceV1, ZwpPrimarySelectionSourceV1Id, +}; use crate::object::{Object, ObjectId}; use crate::tree::Node; use crate::utils::clonecell::CloneCell; @@ -27,11 +30,13 @@ pub struct Objects { pub xdg_surfaces: CopyHashMap>, pub xdg_toplevel: CopyHashMap>, pub wl_data_source: CopyHashMap>, + pub zwp_primary_selection_source: + CopyHashMap>, pub xdg_positioners: CopyHashMap>, pub regions: CopyHashMap>, pub buffers: CopyHashMap>, - pub xdg_wm_bases: CopyHashMap>, - pub seats: CopyHashMap>, + pub xdg_wm_bases: CopyHashMap>, + pub seats: CopyHashMap>, ids: RefCell>, } @@ -48,6 +53,7 @@ impl Objects { xdg_surfaces: Default::default(), xdg_toplevel: Default::default(), wl_data_source: Default::default(), + zwp_primary_selection_source: Default::default(), xdg_positioners: Default::default(), regions: Default::default(), buffers: Default::default(), @@ -73,12 +79,16 @@ impl Objects { registry.clear(); } self.display.set(None); - self.regions.clear(); self.registries.clear(); self.surfaces.clear(); - self.xdg_wm_bases.clear(); self.xdg_surfaces.clear(); + self.wl_data_source.clear(); + self.zwp_primary_selection_source.clear(); + self.xdg_positioners.clear(); + self.regions.clear(); self.buffers.clear(); + self.xdg_wm_bases.clear(); + self.seats.clear(); } pub fn id(&self, client_data: &Client) -> Result diff --git a/src/event_loop.rs b/src/event_loop.rs index 102ba819..1914af94 100644 --- a/src/event_loop.rs +++ b/src/event_loop.rs @@ -13,7 +13,7 @@ pub enum EventLoopError { #[error("epoll_wait failed: {0}")] WaitFailed(std::io::Error), #[error("A dispatcher returned a fatal error: {0}")] - DispatcherError(Box), + DispatcherError(Box), #[error("Could not insert an fd to wait on: {0}")] InsertFailed(std::io::Error), #[error("Could not modify an fd to wait on: {0}")] @@ -30,10 +30,7 @@ pub enum EventLoopError { pub struct EventLoopId(u64); pub trait EventLoopDispatcher { - fn dispatch( - self: Rc, - events: i32, - ) -> Result<(), Box>; + fn dispatch(self: Rc, events: i32) -> Result<(), Box>; } #[derive(Clone)] diff --git a/src/globals.rs b/src/globals.rs index b39c6c9f..b17e7404 100644 --- a/src/globals.rs +++ b/src/globals.rs @@ -12,6 +12,9 @@ use crate::ifs::wl_shm::WlShmError; use crate::ifs::wl_subcompositor::WlSubcompositorError; use crate::ifs::xdg_wm_base::XdgWmBaseError; use crate::ifs::zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1Error; +use crate::ifs::zwp_primary_selection_device_manager_v1::{ + ZwpPrimarySelectionDeviceManagerV1Error, ZwpPrimarySelectionDeviceManagerV1Global, +}; use crate::ifs::zxdg_decoration_manager_v1::ZxdgDecorationManagerV1Error; use crate::object::{Interface, ObjectId}; use crate::utils::copyhashmap::CopyHashMap; @@ -26,7 +29,7 @@ use std::rc::Rc; use thiserror::Error; #[derive(Debug, Error)] -pub enum GlobalError { +pub enum GlobalsError { #[error("The requested global {0} does not exist")] GlobalDoesNotExist(GlobalName), #[error("An error occurred in a `wl_compositor` global")] @@ -53,19 +56,22 @@ pub enum GlobalError { ZxdgDecorationManagerV1Error(#[source] Box), #[error("An error occurred in a `org_kde_kwin_server_decoration_manager` global")] OrgKdeKwinServerDecorationManagerError(#[source] Box), + #[error("An error occurred in a `zwp_primary_selection_device_manager_v1` global")] + ZwpPrimarySelectionDeviceManagerV1Error(#[source] Box), } -efrom!(GlobalError, WlCompositorError); -efrom!(GlobalError, WlShmError); -efrom!(GlobalError, WlSubcompositorError); -efrom!(GlobalError, XdgWmBaseError); -efrom!(GlobalError, WlOutputError); -efrom!(GlobalError, WlSeatError); -efrom!(GlobalError, ZwpLinuxDmabufV1Error); -efrom!(GlobalError, WlDrmError); -efrom!(GlobalError, WlDataDeviceManagerError); -efrom!(GlobalError, ZxdgDecorationManagerV1Error); -efrom!(GlobalError, OrgKdeKwinServerDecorationManagerError); +efrom!(GlobalsError, WlCompositorError); +efrom!(GlobalsError, WlShmError); +efrom!(GlobalsError, WlSubcompositorError); +efrom!(GlobalsError, XdgWmBaseError); +efrom!(GlobalsError, WlOutputError); +efrom!(GlobalsError, WlSeatError); +efrom!(GlobalsError, ZwpLinuxDmabufV1Error); +efrom!(GlobalsError, WlDrmError); +efrom!(GlobalsError, WlDataDeviceManagerError); +efrom!(GlobalsError, ZxdgDecorationManagerV1Error); +efrom!(GlobalsError, OrgKdeKwinServerDecorationManagerError); +efrom!(GlobalsError, ZwpPrimarySelectionDeviceManagerV1Error); #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] pub struct GlobalName(u32); @@ -92,7 +98,7 @@ pub trait GlobalBind { client: &'a Rc, id: ObjectId, version: u32, - ) -> Result<(), GlobalError>; + ) -> Result<(), GlobalsError>; } pub trait Global: GlobalBind { @@ -106,8 +112,8 @@ pub trait Global: GlobalBind { pub struct Globals { next_name: NumCell, registry: CopyHashMap>, - outputs: CopyHashMap>, - seats: CopyHashMap>, + pub outputs: CopyHashMap>, + pub seats: CopyHashMap>, } impl Globals { @@ -132,6 +138,7 @@ impl Globals { add_singleton!(WlDrmGlobal); add_singleton!(ZxdgDecorationManagerV1Global); add_singleton!(OrgKdeKwinServerDecorationManagerGlobal); + add_singleton!(ZwpPrimarySelectionDeviceManagerV1Global); slf } @@ -156,13 +163,14 @@ impl Globals { self.broadcast(state, |r| r.global(&global)); } - pub fn get(&self, name: GlobalName) -> Result, GlobalError> { + pub fn get(&self, name: GlobalName) -> Result, GlobalsError> { self.take(name, false) } - pub fn remove(&self, state: &State, name: GlobalName) -> Result<(), GlobalError> { - let _global = self.take(name, true)?; - self.broadcast(state, |r| r.global_remove(name)); + pub fn remove(&self, state: &State, global: &T) -> Result<(), GlobalsError> { + let _global = self.take(global.name(), true)?; + global.remove(self); + self.broadcast(state, |r| r.global_remove(global.name())); Ok(()) } @@ -195,7 +203,7 @@ impl Globals { }); } - fn take(&self, name: GlobalName, remove: bool) -> Result, GlobalError> { + fn take(&self, name: GlobalName, remove: bool) -> Result, GlobalsError> { let res = if remove { self.registry.remove(&name) } else { @@ -203,75 +211,34 @@ impl Globals { }; match res { Some(g) => Ok(g), - None => Err(GlobalError::GlobalDoesNotExist(name)), + None => Err(GlobalsError::GlobalDoesNotExist(name)), } } #[allow(dead_code)] - pub fn get_output(&self, output: GlobalName) -> Result, GlobalError> { + pub fn get_output(&self, output: GlobalName) -> Result, GlobalsError> { match self.outputs.get(&output) { Some(o) => Ok(o), - _ => Err(GlobalError::OutputDoesNotExist(output)), + _ => Err(GlobalsError::OutputDoesNotExist(output)), } } + + pub fn add_global(&self, state: &State, global: &Rc) { + global.clone().add(self); + self.insert(state, global.clone()) + } + + pub fn add_global_no_broadcast(&self, global: &Rc) { + global.clone().add(self); + self.insert_no_broadcast(global.clone()); + } } -pub trait AddGlobal { - fn add_global(&self, state: &State, global: &Rc); - - fn add_global_no_broadcast(&self, global: &Rc); - - fn remove_global(&self, state: &State, global: &T) -> Result<(), GlobalError>; +pub trait WaylandGlobal: Global + 'static { + fn add(self: Rc, globals: &Globals) { + let _ = globals; + } + fn remove(&self, globals: &Globals) { + let _ = globals; + } } - -macro_rules! simple_add_global { - ($ty:ty) => { - impl AddGlobal<$ty> for Globals { - fn add_global(&self, state: &State, global: &Rc<$ty>) { - self.insert(state, global.clone()) - } - - fn add_global_no_broadcast(&self, global: &Rc<$ty>) { - self.insert_no_broadcast(global.clone()); - } - - fn remove_global(&self, state: &State, global: &$ty) -> Result<(), GlobalError> { - self.remove(state, global.name()) - } - } - }; -} - -simple_add_global!(WlCompositorGlobal); -simple_add_global!(WlShmGlobal); -simple_add_global!(WlSubcompositorGlobal); -simple_add_global!(XdgWmBaseGlobal); -simple_add_global!(WlDataDeviceManagerGlobal); -simple_add_global!(ZwpLinuxDmabufV1Global); -simple_add_global!(WlDrmGlobal); -simple_add_global!(ZxdgDecorationManagerV1Global); -simple_add_global!(OrgKdeKwinServerDecorationManagerGlobal); - -macro_rules! dedicated_add_global { - ($ty:ty, $field:ident) => { - impl AddGlobal<$ty> for Globals { - fn add_global(&self, state: &State, global: &Rc<$ty>) { - self.insert(state, global.clone()); - self.$field.set(global.name(), global.clone()); - } - - fn add_global_no_broadcast(&self, global: &Rc<$ty>) { - self.insert_no_broadcast(global.clone()); - self.$field.set(global.name(), global.clone()); - } - - fn remove_global(&self, state: &State, global: &$ty) -> Result<(), GlobalError> { - self.$field.remove(&global.name()); - self.remove(state, global.name()) - } - } - }; -} - -dedicated_add_global!(WlOutputGlobal, outputs); -dedicated_add_global!(WlSeatGlobal, seats); diff --git a/src/ifs/mod.rs b/src/ifs/mod.rs index 2e57170a..9ecdadc8 100644 --- a/src/ifs/mod.rs +++ b/src/ifs/mod.rs @@ -21,5 +21,9 @@ pub mod xdg_positioner; pub mod xdg_wm_base; pub mod zwp_linux_buffer_params_v1; pub mod zwp_linux_dmabuf_v1; +pub mod zwp_primary_selection_device_manager_v1; +pub mod zwp_primary_selection_device_v1; +pub mod zwp_primary_selection_offer_v1; +pub mod zwp_primary_selection_source_v1; pub mod zxdg_decoration_manager_v1; pub mod zxdg_toplevel_decoration_v1; diff --git a/src/ifs/org_kde_kwin_server_decoration/mod.rs b/src/ifs/org_kde_kwin_server_decoration/mod.rs index e488ac75..c5ce9665 100644 --- a/src/ifs/org_kde_kwin_server_decoration/mod.rs +++ b/src/ifs/org_kde_kwin_server_decoration/mod.rs @@ -1,5 +1,5 @@ use crate::client::{Client, DynEventFormatter}; -use crate::object::{Interface, Object, ObjectId}; +use crate::object::Object; use crate::utils::buffd::MsgParser; use std::cell::Cell; use std::rc::Rc; @@ -61,33 +61,19 @@ impl OrgKdeKwinServerDecoration { self.client.event(self.mode(mode)); Ok(()) } - - fn handle_request_( - self: &Rc, - request: u32, - parser: MsgParser<'_, '_>, - ) -> Result<(), OrgKdeKwinServerDecorationError> { - match request { - RELEASE => self.release(parser)?, - REQUEST_MODE => self.request_mode(parser)?, - _ => unreachable!(), - } - Ok(()) - } } -handle_request!(OrgKdeKwinServerDecoration); +object_base! { + OrgKdeKwinServerDecoration, OrgKdeKwinServerDecorationError; + + RELEASE => release, + REQUEST_MODE => request_mode, +} impl Object for OrgKdeKwinServerDecoration { - fn id(&self) -> ObjectId { - self.id.into() - } - - fn interface(&self) -> Interface { - Interface::OrgKdeKwinServerDecoration - } - fn num_requests(&self) -> u32 { REQUEST_MODE + 1 } } + +simple_add_obj!(OrgKdeKwinServerDecoration); diff --git a/src/ifs/org_kde_kwin_server_decoration_manager/mod.rs b/src/ifs/org_kde_kwin_server_decoration_manager/mod.rs index fc483f29..aa3329cf 100644 --- a/src/ifs/org_kde_kwin_server_decoration_manager/mod.rs +++ b/src/ifs/org_kde_kwin_server_decoration_manager/mod.rs @@ -1,7 +1,7 @@ use crate::client::{Client, DynEventFormatter}; use crate::globals::{Global, GlobalName}; use crate::ifs::org_kde_kwin_server_decoration::OrgKdeKwinServerDecoration; -use crate::object::{Interface, Object, ObjectId}; +use crate::object::{Interface, Object}; use crate::utils::buffd::MsgParser; use std::rc::Rc; pub use types::*; @@ -34,7 +34,7 @@ impl OrgKdeKwinServerDecorationManagerGlobal { client: &Rc, version: u32, ) -> Result<(), OrgKdeKwinServerDecorationManagerError> { - let obj = Rc::new(OrgKdeKwinServerDecorationManagerObj { + let obj = Rc::new(OrgKdeKwinServerDecorationManager { id, client: client.clone(), _version: version, @@ -65,13 +65,15 @@ impl Global for OrgKdeKwinServerDecorationManagerGlobal { } } -pub struct OrgKdeKwinServerDecorationManagerObj { +simple_add_global!(OrgKdeKwinServerDecorationManagerGlobal); + +pub struct OrgKdeKwinServerDecorationManager { id: OrgKdeKwinServerDecorationManagerGlobalId, client: Rc, _version: u32, } -impl OrgKdeKwinServerDecorationManagerObj { +impl OrgKdeKwinServerDecorationManager { fn default_mode(self: &Rc, mode: u32) -> DynEventFormatter { Box::new(DefaultMode { obj: self.clone(), @@ -81,39 +83,24 @@ impl OrgKdeKwinServerDecorationManagerObj { fn create(&self, parser: MsgParser<'_, '_>) -> Result<(), CreateError> { let req: Create = self.client.parse(self, parser)?; - let _ = self.client.get_surface(req.surface)?; + let _ = self.client.lookup(req.surface)?; let obj = Rc::new(OrgKdeKwinServerDecoration::new(req.id, &self.client)); self.client.add_client_obj(&obj)?; self.client.event(obj.mode(SERVER)); - log::info!("ayo"); - Ok(()) - } - - fn handle_request_( - self: &Rc, - request: u32, - parser: MsgParser<'_, '_>, - ) -> Result<(), OrgKdeKwinServerDecorationManagerError> { - match request { - CREATE => self.create(parser)?, - _ => unreachable!(), - } Ok(()) } } -handle_request!(OrgKdeKwinServerDecorationManagerObj); +object_base! { + OrgKdeKwinServerDecorationManager, OrgKdeKwinServerDecorationManagerError; -impl Object for OrgKdeKwinServerDecorationManagerObj { - fn id(&self) -> ObjectId { - self.id.into() - } - - fn interface(&self) -> Interface { - Interface::OrgKdeKwinServerDecorationManager - } + CREATE => create, +} +impl Object for OrgKdeKwinServerDecorationManager { fn num_requests(&self) -> u32 { CREATE + 1 } } + +simple_add_obj!(OrgKdeKwinServerDecorationManager); diff --git a/src/ifs/org_kde_kwin_server_decoration_manager/types.rs b/src/ifs/org_kde_kwin_server_decoration_manager/types.rs index d9b61139..0f888947 100644 --- a/src/ifs/org_kde_kwin_server_decoration_manager/types.rs +++ b/src/ifs/org_kde_kwin_server_decoration_manager/types.rs @@ -1,7 +1,7 @@ use crate::client::{ClientError, EventFormatter, RequestParser}; use crate::ifs::org_kde_kwin_server_decoration::OrgKdeKwinServerDecorationId; use crate::ifs::org_kde_kwin_server_decoration_manager::{ - OrgKdeKwinServerDecorationManagerObj, DEFAULT_MODE, + OrgKdeKwinServerDecorationManager, DEFAULT_MODE, }; use crate::ifs::wl_surface::WlSurfaceId; use crate::object::Object; @@ -52,7 +52,7 @@ impl Debug for Create { } pub(super) struct DefaultMode { - pub obj: Rc, + pub obj: Rc, pub mode: u32, } impl EventFormatter for DefaultMode { diff --git a/src/ifs/wl_buffer/mod.rs b/src/ifs/wl_buffer/mod.rs index 216a0bab..8f04e3b5 100644 --- a/src/ifs/wl_buffer/mod.rs +++ b/src/ifs/wl_buffer/mod.rs @@ -3,7 +3,7 @@ mod types; use crate::client::{Client, DynEventFormatter}; use crate::clientmem::{ClientMem, ClientMemOffset}; use crate::format::Format; -use crate::object::{Interface, Object, ObjectId}; +use crate::object::Object; use crate::rect::Rect; use crate::render::{Image, Texture}; use crate::utils::buffd::MsgParser; @@ -122,35 +122,21 @@ impl WlBuffer { Ok(()) } - fn handle_request_( - &self, - request: u32, - parser: MsgParser<'_, '_>, - ) -> Result<(), WlBufferError> { - match request { - DESTROY => self.destroy(parser)?, - _ => unreachable!(), - } - Ok(()) - } - pub fn release(self: &Rc) -> DynEventFormatter { Box::new(Release { obj: self.clone() }) } } -handle_request!(WlBuffer); +object_base! { + WlBuffer, WlBufferError; + + DESTROY => destroy, +} impl Object for WlBuffer { - fn id(&self) -> ObjectId { - self.id.into() - } - - fn interface(&self) -> Interface { - Interface::WlBuffer - } - fn num_requests(&self) -> u32 { DESTROY + 1 } } + +dedicated_add_obj!(WlBuffer, WlBufferId, buffers); diff --git a/src/ifs/wl_callback/mod.rs b/src/ifs/wl_callback/mod.rs index aa336641..622a667a 100644 --- a/src/ifs/wl_callback/mod.rs +++ b/src/ifs/wl_callback/mod.rs @@ -1,8 +1,7 @@ mod types; -use crate::client::{ClientError, DynEventFormatter}; -use crate::object::{Interface, Object, ObjectId}; -use crate::utils::buffd::MsgParser; +use crate::client::DynEventFormatter; +use crate::object::Object; use std::rc::Rc; use types::*; @@ -22,28 +21,16 @@ impl WlCallback { pub fn done(self: &Rc) -> DynEventFormatter { Box::new(Done { obj: self.clone() }) } - - fn handle_request_( - &self, - _request: u32, - _parser: MsgParser<'_, '_>, - ) -> Result<(), ClientError> { - unreachable!(); - } } -handle_request!(WlCallback); +object_base! { + WlCallback, WlCallbackError; +} impl Object for WlCallback { - fn id(&self) -> ObjectId { - self.id.into() - } - - fn interface(&self) -> Interface { - Interface::WlCallback - } - fn num_requests(&self) -> u32 { 0 } } + +simple_add_obj!(WlCallback); diff --git a/src/ifs/wl_callback/types.rs b/src/ifs/wl_callback/types.rs index 6e02ec63..d4001978 100644 --- a/src/ifs/wl_callback/types.rs +++ b/src/ifs/wl_callback/types.rs @@ -4,6 +4,10 @@ use crate::object::Object; use crate::utils::buffd::MsgFormatter; use std::fmt::{Debug, Formatter}; use std::rc::Rc; +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum WlCallbackError {} pub(super) struct Done { pub obj: Rc, diff --git a/src/ifs/wl_compositor/mod.rs b/src/ifs/wl_compositor/mod.rs index 78543af8..2f94b1ab 100644 --- a/src/ifs/wl_compositor/mod.rs +++ b/src/ifs/wl_compositor/mod.rs @@ -4,7 +4,7 @@ use crate::client::Client; use crate::globals::{Global, GlobalName}; use crate::ifs::wl_region::WlRegion; use crate::ifs::wl_surface::WlSurface; -use crate::object::{Interface, Object, ObjectId}; +use crate::object::{Interface, Object}; use crate::utils::buffd::MsgParser; use std::rc::Rc; pub use types::*; @@ -18,7 +18,7 @@ pub struct WlCompositorGlobal { name: GlobalName, } -pub struct WlCompositorObj { +pub struct WlCompositor { id: WlCompositorId, client: Rc, _version: u32, @@ -35,7 +35,7 @@ impl WlCompositorGlobal { client: &Rc, version: u32, ) -> Result<(), WlCompositorError> { - let obj = Rc::new(WlCompositorObj { + let obj = Rc::new(WlCompositor { id, client: client.clone(), _version: version, @@ -45,7 +45,7 @@ impl WlCompositorGlobal { } } -impl WlCompositorObj { +impl WlCompositor { fn create_surface(&self, parser: MsgParser<'_, '_>) -> Result<(), CreateSurfaceError> { let surface: CreateSurface = self.client.parse(self, parser)?; let surface = Rc::new(WlSurface::new(surface.id, &self.client)); @@ -59,19 +59,6 @@ impl WlCompositorObj { self.client.add_client_obj(®ion)?; Ok(()) } - - fn handle_request_( - &self, - request: u32, - parser: MsgParser<'_, '_>, - ) -> Result<(), WlCompositorError> { - match request { - CREATE_SURFACE => self.create_surface(parser)?, - CREATE_REGION => self.create_region(parser)?, - _ => unreachable!(), - } - Ok(()) - } } bind!(WlCompositorGlobal); @@ -94,18 +81,19 @@ impl Global for WlCompositorGlobal { } } -handle_request!(WlCompositorObj); +simple_add_global!(WlCompositorGlobal); -impl Object for WlCompositorObj { - fn id(&self) -> ObjectId { - self.id.into() - } +object_base! { + WlCompositor, WlCompositorError; - fn interface(&self) -> Interface { - Interface::WlCompositor - } + CREATE_SURFACE => create_surface, + CREATE_REGION => create_region, +} +impl Object for WlCompositor { fn num_requests(&self) -> u32 { CREATE_REGION + 1 } } + +simple_add_obj!(WlCompositor); diff --git a/src/ifs/wl_data_device/mod.rs b/src/ifs/wl_data_device/mod.rs index fc1dadbc..1f7a6359 100644 --- a/src/ifs/wl_data_device/mod.rs +++ b/src/ifs/wl_data_device/mod.rs @@ -1,10 +1,10 @@ mod types; -use crate::client::{DynEventFormatter}; -use crate::ifs::wl_data_device_manager::WlDataDeviceManagerObj; +use crate::client::DynEventFormatter; +use crate::ifs::wl_data_device_manager::WlDataDeviceManager; use crate::ifs::wl_data_offer::WlDataOfferId; -use crate::ifs::wl_seat::{WlSeatObj}; -use crate::object::{Interface, Object, ObjectId}; +use crate::ifs::wl_seat::WlSeat; +use crate::object::Object; use crate::utils::buffd::MsgParser; use std::rc::Rc; pub use types::*; @@ -27,16 +27,12 @@ id!(WlDataDeviceId); pub struct WlDataDevice { pub id: WlDataDeviceId, - pub manager: Rc, - seat: Rc, + pub manager: Rc, + seat: Rc, } impl WlDataDevice { - pub fn new( - id: WlDataDeviceId, - manager: &Rc, - seat: &Rc, - ) -> Self { + pub fn new(id: WlDataDeviceId, manager: &Rc, seat: &Rc) -> Self { Self { id, manager: manager.clone(), @@ -68,7 +64,7 @@ impl WlDataDevice { let src = if req.source.is_none() { None } else { - Some(self.manager.client.get_wl_data_source(req.source)?) + Some(self.manager.client.lookup(req.source)?) }; self.seat.global.set_selection(src)?; Ok(()) @@ -80,33 +76,17 @@ impl WlDataDevice { self.manager.client.remove_obj(self)?; Ok(()) } - - fn handle_request_( - self: &Rc, - request: u32, - parser: MsgParser<'_, '_>, - ) -> Result<(), WlDataDeviceError> { - match request { - START_DRAG => self.start_drag(parser)?, - SET_SELECTION => self.set_selection(parser)?, - RELEASE => self.release(parser)?, - _ => unreachable!(), - } - Ok(()) - } } -handle_request!(WlDataDevice); +object_base! { + WlDataDevice, WlDataDeviceError; + + START_DRAG => start_drag, + SET_SELECTION => set_selection, + RELEASE => release, +} impl Object for WlDataDevice { - fn id(&self) -> ObjectId { - self.id.into() - } - - fn interface(&self) -> Interface { - Interface::WlDataDevice - } - fn num_requests(&self) -> u32 { RELEASE + 1 } @@ -115,3 +95,5 @@ impl Object for WlDataDevice { self.seat.remove_data_device(self); } } + +simple_add_obj!(WlDataDevice); diff --git a/src/ifs/wl_data_device/types.rs b/src/ifs/wl_data_device/types.rs index b5c16145..aa68c5c5 100644 --- a/src/ifs/wl_data_device/types.rs +++ b/src/ifs/wl_data_device/types.rs @@ -243,3 +243,9 @@ impl Debug for Selection { write!(f, "selection(id: {})", self.id) } } +// +// msgs! { +// WlDataDevice::Selection = 5 { +// id: id(WlDataOffer), +// } +// } diff --git a/src/ifs/wl_data_device_manager/mod.rs b/src/ifs/wl_data_device_manager/mod.rs index 7ed1d9ff..fd914b27 100644 --- a/src/ifs/wl_data_device_manager/mod.rs +++ b/src/ifs/wl_data_device_manager/mod.rs @@ -4,7 +4,7 @@ use crate::client::Client; use crate::globals::{Global, GlobalName}; use crate::ifs::wl_data_device::WlDataDevice; use crate::ifs::wl_data_source::WlDataSource; -use crate::object::{Interface, Object, ObjectId}; +use crate::object::{Interface, Object}; use crate::utils::buffd::MsgParser; use std::rc::Rc; pub use types::*; @@ -27,7 +27,7 @@ pub struct WlDataDeviceManagerGlobal { name: GlobalName, } -pub struct WlDataDeviceManagerObj { +pub struct WlDataDeviceManager { pub id: WlDataDeviceManagerId, pub client: Rc, pub version: u32, @@ -44,7 +44,7 @@ impl WlDataDeviceManagerGlobal { client: &Rc, version: u32, ) -> Result<(), WlDataDeviceManagerError> { - let obj = Rc::new(WlDataDeviceManagerObj { + let obj = Rc::new(WlDataDeviceManager { id, client: client.clone(), version, @@ -54,7 +54,7 @@ impl WlDataDeviceManagerGlobal { } } -impl WlDataDeviceManagerObj { +impl WlDataDeviceManager { fn create_data_source(&self, parser: MsgParser<'_, '_>) -> Result<(), CreateDataSourceError> { let req: CreateDataSource = self.client.parse(self, parser)?; let res = Rc::new(WlDataSource::new(req.id, &self.client)); @@ -67,25 +67,12 @@ impl WlDataDeviceManagerObj { parser: MsgParser<'_, '_>, ) -> Result<(), GetDataDeviceError> { let req: GetDataDevice = self.client.parse(&**self, parser)?; - let seat = self.client.get_wl_seat(req.seat)?; + let seat = self.client.lookup(req.seat)?; let dev = Rc::new(WlDataDevice::new(req.id, self, &seat)); seat.add_data_device(&dev); self.client.add_client_obj(&dev)?; Ok(()) } - - fn handle_request_( - self: &Rc, - request: u32, - parser: MsgParser<'_, '_>, - ) -> Result<(), WlDataDeviceManagerError> { - match request { - CREATE_DATA_SOURCE => self.create_data_source(parser)?, - GET_DATA_DEVICE => self.get_data_device(parser)?, - _ => unreachable!(), - } - Ok(()) - } } bind!(WlDataDeviceManagerGlobal); @@ -108,18 +95,19 @@ impl Global for WlDataDeviceManagerGlobal { } } -handle_request!(WlDataDeviceManagerObj); +simple_add_global!(WlDataDeviceManagerGlobal); -impl Object for WlDataDeviceManagerObj { - fn id(&self) -> ObjectId { - self.id.into() - } +object_base! { + WlDataDeviceManager, WlDataDeviceManagerError; - fn interface(&self) -> Interface { - Interface::WlDataDeviceManager - } + CREATE_DATA_SOURCE => create_data_source, + GET_DATA_DEVICE => get_data_device, +} +impl Object for WlDataDeviceManager { fn num_requests(&self) -> u32 { GET_DATA_DEVICE + 1 } } + +simple_add_obj!(WlDataDeviceManager); diff --git a/src/ifs/wl_data_offer/mod.rs b/src/ifs/wl_data_offer/mod.rs index 990973b7..8d83746d 100644 --- a/src/ifs/wl_data_offer/mod.rs +++ b/src/ifs/wl_data_offer/mod.rs @@ -1,9 +1,9 @@ mod types; use crate::client::{Client, DynEventFormatter}; -use crate::ifs::wl_data_source::{WlDataSource}; +use crate::ifs::wl_data_source::WlDataSource; use crate::ifs::wl_seat::WlSeatGlobal; -use crate::object::{Interface, Object, ObjectId}; +use crate::object::Object; use crate::utils::buffd::MsgParser; use crate::utils::clonecell::CloneCell; use std::ops::Deref; @@ -121,35 +121,19 @@ impl WlDataOffer { let _req: SetActions = self.client.parse(self, parser)?; Ok(()) } - - fn handle_request_( - self: &Rc, - request: u32, - parser: MsgParser<'_, '_>, - ) -> Result<(), WlDataOfferError> { - match request { - ACCEPT => self.accept(parser)?, - RECEIVE => self.receive(parser)?, - DESTROY => self.destroy(parser)?, - FINISH => self.finish(parser)?, - SET_ACTIONS => self.set_actions(parser)?, - _ => unreachable!(), - } - Ok(()) - } } -handle_request!(WlDataOffer); +object_base! { + WlDataOffer, WlDataOfferError; + + ACCEPT => accept, + RECEIVE => receive, + DESTROY => destroy, + FINISH => finish, + SET_ACTIONS => set_actions, +} impl Object for WlDataOffer { - fn id(&self) -> ObjectId { - self.id.into() - } - - fn interface(&self) -> Interface { - Interface::WlDataOffer - } - fn num_requests(&self) -> u32 { SET_ACTIONS + 1 } @@ -158,3 +142,5 @@ impl Object for WlDataOffer { self.disconnect(); } } + +simple_add_obj!(WlDataOffer); diff --git a/src/ifs/wl_data_offer/types.rs b/src/ifs/wl_data_offer/types.rs index 0ff3277b..e2cbc817 100644 --- a/src/ifs/wl_data_offer/types.rs +++ b/src/ifs/wl_data_offer/types.rs @@ -2,7 +2,7 @@ use crate::client::{ClientError, EventFormatter, RequestParser}; use crate::ifs::wl_data_offer::{WlDataOffer, ACTION, OFFER, SOURCE_ACTIONS}; use crate::object::Object; use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError}; -use bstr::{BStr}; +use bstr::BStr; use std::fmt::{Debug, Formatter}; use std::rc::Rc; use thiserror::Error; @@ -180,7 +180,7 @@ impl EventFormatter for Offer { } impl Debug for Offer { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "target(mime_type: {:?})", self.mime_type) + write!(f, "offer(mime_type: {:?})", self.mime_type) } } diff --git a/src/ifs/wl_data_source/mod.rs b/src/ifs/wl_data_source/mod.rs index 1b53d01d..5c0a1e70 100644 --- a/src/ifs/wl_data_source/mod.rs +++ b/src/ifs/wl_data_source/mod.rs @@ -3,14 +3,14 @@ mod types; use crate::client::{Client, DynEventFormatter}; use crate::ifs::wl_data_offer::{DataOfferRole, WlDataOffer}; use crate::ifs::wl_seat::WlSeatGlobal; -use crate::object::{Interface, Object, ObjectId}; +use crate::object::Object; use crate::utils::buffd::MsgParser; use crate::utils::clonecell::{CloneCell, UnsafeCellCloneSafe}; use ahash::AHashSet; use std::cell::RefCell; use std::rc::Rc; -use uapi::OwnedFd; pub use types::*; +use uapi::OwnedFd; const OFFER: u32 = 0; const DESTROY: u32 = 1; @@ -62,15 +62,13 @@ impl WlDataSource { seat: &Rc, role: DataOfferRole, ) -> Result<(), WlDataSourceError> { - let old = self.attachment.set( - Some(Attachment { - seat: seat.clone(), - role, - }), - ); - if old.is_some() { + if self.attachment.get().is_some() { return Err(WlDataSourceError::AlreadyAttached); } + self.attachment.set(Some(Attachment { + seat: seat.clone(), + role, + })); Ok(()) } @@ -103,9 +101,7 @@ impl WlDataSource { } pub fn cancelled(self: &Rc) -> DynEventFormatter { - Box::new(Cancelled { - obj: self.clone(), - }) + Box::new(Cancelled { obj: self.clone() }) } pub fn send(self: &Rc, mime_type: &str, fd: OwnedFd) -> DynEventFormatter { @@ -138,7 +134,7 @@ impl WlDataSource { match attachment.role { DataOfferRole::Selection => { let _ = attachment.seat.set_selection(None); - }, + } } } } @@ -154,33 +150,17 @@ impl WlDataSource { let _req: SetActions = self.client.parse(self, parser)?; Ok(()) } - - fn handle_request_( - self: &Rc, - request: u32, - parser: MsgParser<'_, '_>, - ) -> Result<(), WlDataSourceError> { - match request { - OFFER => self.offer(parser)?, - DESTROY => self.destroy(parser)?, - SET_ACTIONS => self.set_actions(parser)?, - _ => unreachable!(), - } - Ok(()) - } } -handle_request!(WlDataSource); +object_base! { + WlDataSource, WlDataSourceError; + + OFFER => offer, + DESTROY => destroy, + SET_ACTIONS => set_actions, +} impl Object for WlDataSource { - fn id(&self) -> ObjectId { - self.id.into() - } - - fn interface(&self) -> Interface { - Interface::WlDataSource - } - fn num_requests(&self) -> u32 { SET_ACTIONS + 1 } @@ -189,3 +169,5 @@ impl Object for WlDataSource { self.disconnect(); } } + +dedicated_add_obj!(WlDataSource, WlDataSourceId, wl_data_source); diff --git a/src/ifs/wl_data_source/types.rs b/src/ifs/wl_data_source/types.rs index c6515993..4ed88fae 100644 --- a/src/ifs/wl_data_source/types.rs +++ b/src/ifs/wl_data_source/types.rs @@ -4,7 +4,7 @@ use crate::ifs::wl_data_source::{ }; use crate::object::Object; use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError}; -use bstr::{BString}; +use bstr::BString; use std::fmt::{Debug, Formatter}; use std::rc::Rc; use thiserror::Error; diff --git a/src/ifs/wl_display/mod.rs b/src/ifs/wl_display/mod.rs index bb0bb65b..d86f4304 100644 --- a/src/ifs/wl_display/mod.rs +++ b/src/ifs/wl_display/mod.rs @@ -3,7 +3,7 @@ mod types; use crate::client::{Client, DynEventFormatter}; use crate::ifs::wl_callback::WlCallback; use crate::ifs::wl_registry::WlRegistry; -use crate::object::{Interface, Object, ObjectId, WL_DISPLAY_ID}; +use crate::object::{Object, ObjectId, WL_DISPLAY_ID}; use crate::utils::buffd::MsgParser; use std::rc::Rc; pub use types::*; @@ -21,29 +21,18 @@ const NO_MEMORY: u32 = 2; const IMPLEMENTATION: u32 = 3; pub struct WlDisplay { + id: ObjectId, client: Rc, } impl WlDisplay { pub fn new(client: &Rc) -> Self { Self { + id: WL_DISPLAY_ID, client: client.clone(), } } - fn handle_request_( - &self, - request: u32, - parser: MsgParser<'_, '_>, - ) -> Result<(), WlDisplayError> { - match request { - SYNC => self.sync(parser)?, - GET_REGISTRY => self.get_registry(parser)?, - _ => unreachable!(), - } - Ok(()) - } - fn sync(&self, parser: MsgParser<'_, '_>) -> Result<(), SyncError> { let sync: Sync = self.client.parse(self, parser)?; let cb = Rc::new(WlCallback::new(sync.callback)); @@ -106,17 +95,14 @@ impl WlDisplay { } } -handle_request!(WlDisplay); +object_base! { + WlDisplay, WlDisplayError; + + SYNC => sync, + GET_REGISTRY => get_registry, +} impl Object for WlDisplay { - fn id(&self) -> ObjectId { - WL_DISPLAY_ID - } - - fn interface(&self) -> Interface { - Interface::WlDisplay - } - fn num_requests(&self) -> u32 { GET_REGISTRY + 1 } diff --git a/src/ifs/wl_display/types.rs b/src/ifs/wl_display/types.rs index d0f939d4..f1a2ed61 100644 --- a/src/ifs/wl_display/types.rs +++ b/src/ifs/wl_display/types.rs @@ -1,5 +1,5 @@ use crate::client::{ClientError, EventFormatter, RequestParser}; -use crate::globals::GlobalError; +use crate::globals::GlobalsError; use crate::ifs::wl_callback::WlCallbackId; use crate::ifs::wl_display::{WlDisplay, DELETE_ID, ERROR}; use crate::ifs::wl_registry::WlRegistryId; @@ -27,11 +27,11 @@ pub enum GetRegistryError { #[error(transparent)] ClientError(Box), #[error("An error occurred while processing globals")] - GlobalError(#[source] Box), + GlobalsError(#[source] Box), } efrom!(GetRegistryError, ParseFailed, MsgParserError); -efrom!(GetRegistryError, GlobalError); +efrom!(GetRegistryError, GlobalsError); efrom!(GetRegistryError, ClientError); #[derive(Debug, Error)] diff --git a/src/ifs/wl_drm/mod.rs b/src/ifs/wl_drm/mod.rs index df2ac774..54235ccd 100644 --- a/src/ifs/wl_drm/mod.rs +++ b/src/ifs/wl_drm/mod.rs @@ -1,6 +1,6 @@ use crate::client::{Client, DynEventFormatter}; use crate::globals::{Global, GlobalName}; -use crate::object::{Interface, Object, ObjectId}; +use crate::object::{Interface, Object}; use crate::utils::buffd::MsgParser; use std::ffi::CString; use std::rc::Rc; @@ -36,7 +36,7 @@ impl WlDrmGlobal { client: &Rc, version: u32, ) -> Result<(), WlDrmError> { - let obj = Rc::new(WlDrmObj { + let obj = Rc::new(WlDrm { id, client: client.clone(), _version: version, @@ -70,13 +70,15 @@ impl Global for WlDrmGlobal { } } -pub struct WlDrmObj { +simple_add_global!(WlDrmGlobal); + +pub struct WlDrm { id: WlDrmId, pub client: Rc, _version: u32, } -impl WlDrmObj { +impl WlDrm { fn device(self: &Rc, device: &Rc) -> DynEventFormatter { Box::new(Device { obj: self.clone(), @@ -113,34 +115,20 @@ impl WlDrmObj { let _req: CreatePlanarBuffer = self.client.parse(&**self, parser)?; Err(CreatePlanarBufferError::Unsupported) } - - fn handle_request_( - self: &Rc, - request: u32, - parser: MsgParser<'_, '_>, - ) -> Result<(), WlDrmError> { - match request { - AUTHENTICATE => self.authenticate(parser)?, - CREATE_BUFFER => self.create_buffer(parser)?, - CREATE_PLANAR_BUFFER => self.create_planar_buffer(parser)?, - _ => unreachable!(), - } - Ok(()) - } } -handle_request!(WlDrmObj); +object_base! { + WlDrm, WlDrmError; -impl Object for WlDrmObj { - fn id(&self) -> ObjectId { - self.id.into() - } - - fn interface(&self) -> Interface { - Interface::WlDrm - } + AUTHENTICATE => authenticate, + CREATE_BUFFER => create_buffer, + CREATE_PLANAR_BUFFER => create_planar_buffer, +} +impl Object for WlDrm { fn num_requests(&self) -> u32 { CREATE_PLANAR_BUFFER + 1 } } + +simple_add_obj!(WlDrm); diff --git a/src/ifs/wl_drm/types.rs b/src/ifs/wl_drm/types.rs index 1a0b4e0a..1e1b6a87 100644 --- a/src/ifs/wl_drm/types.rs +++ b/src/ifs/wl_drm/types.rs @@ -1,6 +1,6 @@ use crate::client::{ClientError, EventFormatter, RequestParser}; use crate::ifs::wl_buffer::WlBufferId; -use crate::ifs::wl_drm::{WlDrmObj, AUTHENTICATED, CAPABILITIES, DEVICE, FORMAT}; +use crate::ifs::wl_drm::{WlDrm, AUTHENTICATED, CAPABILITIES, DEVICE, FORMAT}; use crate::object::Object; use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError}; use std::ffi::CString; @@ -139,7 +139,7 @@ impl Debug for CreatePlanarBuffer { } pub(super) struct Device { - pub obj: Rc, + pub obj: Rc, pub name: Rc, } impl EventFormatter for Device { @@ -157,7 +157,7 @@ impl Debug for Device { } pub(super) struct Format { - pub obj: Rc, + pub obj: Rc, pub format: u32, } impl EventFormatter for Format { @@ -175,7 +175,7 @@ impl Debug for Format { } pub(super) struct Authenticated { - pub obj: Rc, + pub obj: Rc, } impl EventFormatter for Authenticated { fn format(self: Box, fmt: &mut MsgFormatter<'_>) { @@ -192,7 +192,7 @@ impl Debug for Authenticated { } pub(super) struct Capabilities { - pub obj: Rc, + pub obj: Rc, pub value: u32, } impl EventFormatter for Capabilities { diff --git a/src/ifs/wl_output/mod.rs b/src/ifs/wl_output/mod.rs index f4eac7b8..9d42854f 100644 --- a/src/ifs/wl_output/mod.rs +++ b/src/ifs/wl_output/mod.rs @@ -3,7 +3,7 @@ mod types; use crate::backend::Output; use crate::client::{Client, ClientId, DynEventFormatter, WlEvent}; use crate::globals::{Global, GlobalName}; -use crate::object::{Interface, Object, ObjectId}; +use crate::object::{Interface, Object}; use crate::utils::buffd::MsgParser; use ahash::AHashMap; use std::cell::{Cell, RefCell}; @@ -60,7 +60,7 @@ pub struct WlOutputGlobal { pub y: Cell, width: Cell, height: Cell, - pub bindings: RefCell>>>, + pub bindings: RefCell>>>, } impl WlOutputGlobal { @@ -112,7 +112,7 @@ impl WlOutputGlobal { client: &Rc, version: u32, ) -> Result<(), WlOutputError> { - let obj = Rc::new(WlOutputObj { + let obj = Rc::new(WlOutput { global: self.clone(), id, client: client.clone(), @@ -160,14 +160,16 @@ impl Global for WlOutputGlobal { } } -pub struct WlOutputObj { +dedicated_add_global!(WlOutputGlobal, outputs); + +pub struct WlOutput { global: Rc, pub id: WlOutputId, client: Rc, version: u32, } -impl WlOutputObj { +impl WlOutput { fn send_done(&self) -> bool { self.version >= 2 } @@ -226,31 +228,15 @@ impl WlOutputObj { self.client.remove_obj(self)?; Ok(()) } - - fn handle_request_( - &self, - request: u32, - parser: MsgParser<'_, '_>, - ) -> Result<(), WlOutputError> { - match request { - RELEASE => self.release(parser)?, - _ => unreachable!(), - } - Ok(()) - } } -handle_request!(WlOutputObj); +object_base! { + WlOutput, WlOutputError; -impl Object for WlOutputObj { - fn id(&self) -> ObjectId { - self.id.into() - } - - fn interface(&self) -> Interface { - Interface::WlOutput - } + RELEASE => release, +} +impl Object for WlOutput { fn num_requests(&self) -> u32 { if self.version < 3 { 0 @@ -263,3 +249,5 @@ impl Object for WlOutputObj { self.remove_binding(); } } + +simple_add_obj!(WlOutput); diff --git a/src/ifs/wl_output/types.rs b/src/ifs/wl_output/types.rs index 4b7cb051..eae81a3b 100644 --- a/src/ifs/wl_output/types.rs +++ b/src/ifs/wl_output/types.rs @@ -1,5 +1,5 @@ use crate::client::{ClientError, EventFormatter, RequestParser}; -use crate::ifs::wl_output::{WlOutputObj, DONE, GEOMETRY, MODE, SCALE}; +use crate::ifs::wl_output::{WlOutput, DONE, GEOMETRY, MODE, SCALE}; use crate::object::Object; use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError}; use std::fmt::{Debug, Formatter}; @@ -38,7 +38,7 @@ impl Debug for Release { } pub(super) struct Geometry { - pub obj: Rc, + pub obj: Rc, pub x: i32, pub y: i32, pub physical_width: i32, @@ -72,7 +72,7 @@ impl Debug for Geometry { } pub(super) struct Mode { - pub obj: Rc, + pub obj: Rc, pub flags: u32, pub width: i32, pub height: i32, @@ -101,7 +101,7 @@ impl Debug for Mode { } pub(super) struct Done { - pub obj: Rc, + pub obj: Rc, } impl EventFormatter for Done { fn format(self: Box, fmt: &mut MsgFormatter<'_>) { @@ -118,7 +118,7 @@ impl Debug for Done { } pub(super) struct Scale { - pub obj: Rc, + pub obj: Rc, pub factor: i32, } impl EventFormatter for Scale { diff --git a/src/ifs/wl_region/mod.rs b/src/ifs/wl_region/mod.rs index c382b5b6..e522ae5e 100644 --- a/src/ifs/wl_region/mod.rs +++ b/src/ifs/wl_region/mod.rs @@ -1,7 +1,7 @@ mod types; use crate::client::Client; -use crate::object::{Interface, Object, ObjectId}; +use crate::object::Object; use crate::pixman::Region; use crate::utils::buffd::MsgParser; use std::cell::RefCell; @@ -63,34 +63,20 @@ impl WlRegion { )); Ok(()) } - - fn handle_request_( - &self, - request: u32, - parser: MsgParser<'_, '_>, - ) -> Result<(), WlRegionError> { - match request { - DESTROY => self.destroy(parser)?, - ADD => self.add(parser)?, - SUBTRACT => self.subtract(parser)?, - _ => unreachable!(), - } - Ok(()) - } } -handle_request!(WlRegion); +object_base! { + WlRegion, WlRegionError; + + DESTROY => destroy, + ADD => add, + SUBTRACT => subtract, +} impl Object for WlRegion { - fn id(&self) -> ObjectId { - self.id.into() - } - - fn interface(&self) -> Interface { - Interface::WlRegion - } - fn num_requests(&self) -> u32 { SUBTRACT + 1 } } + +dedicated_add_obj!(WlRegion, WlRegionId, regions); diff --git a/src/ifs/wl_registry/mod.rs b/src/ifs/wl_registry/mod.rs index aee24a1d..4908be94 100644 --- a/src/ifs/wl_registry/mod.rs +++ b/src/ifs/wl_registry/mod.rs @@ -2,7 +2,7 @@ mod types; use crate::client::{Client, DynEventFormatter}; use crate::globals::{Global, GlobalName}; -use crate::object::{Interface, Object, ObjectId}; +use crate::object::Object; use crate::utils::buffd::MsgParser; use std::rc::Rc; pub use types::*; @@ -62,32 +62,18 @@ impl WlRegistry { global.bind(&self.client, bind.id, bind.version)?; Ok(()) } - - fn handle_request_( - &self, - request: u32, - parser: MsgParser<'_, '_>, - ) -> Result<(), WlRegistryError> { - match request { - BIND => self.bind(parser)?, - _ => unreachable!(), - } - Ok(()) - } } -handle_request!(WlRegistry); +object_base! { + WlRegistry, WlRegistryError; + + BIND => bind, +} impl Object for WlRegistry { - fn id(&self) -> ObjectId { - self.id.into() - } - - fn interface(&self) -> Interface { - Interface::WlRegistry - } - fn num_requests(&self) -> u32 { BIND + 1 } } + +simple_add_obj!(WlRegistry); diff --git a/src/ifs/wl_registry/types.rs b/src/ifs/wl_registry/types.rs index 26e29d0a..9ba0df61 100644 --- a/src/ifs/wl_registry/types.rs +++ b/src/ifs/wl_registry/types.rs @@ -1,5 +1,5 @@ use crate::client::{EventFormatter, RequestParser}; -use crate::globals::{Global, GlobalError, GlobalName}; +use crate::globals::{Global, GlobalsError, GlobalName}; use crate::ifs::wl_registry::{WlRegistry, GLOBAL, GLOBAL_REMOVE}; use crate::object::{Interface, Object, ObjectId}; use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError}; @@ -21,7 +21,7 @@ pub enum BindError { #[error("Parsing failed")] ParseError(#[source] Box), #[error(transparent)] - GlobalError(Box), + GlobalsError(Box), #[error("Tried to bind to global {} of type {} using interface {}", .0.name, .0.interface.name(), .0.actual)] InvalidInterface(InterfaceError), #[error("Tried to bind to global {} of type {} and version {} using version {}", .0.name, .0.interface.name(), .0.version, .0.actual)] @@ -44,7 +44,7 @@ pub struct VersionError { } efrom!(BindError, ParseError, MsgParserError); -efrom!(BindError, GlobalError); +efrom!(BindError, GlobalsError); pub(super) struct GlobalE { pub obj: Rc, diff --git a/src/ifs/wl_seat/handling.rs b/src/ifs/wl_seat/handling.rs index 9d89fe6f..88ae1252 100644 --- a/src/ifs/wl_seat/handling.rs +++ b/src/ifs/wl_seat/handling.rs @@ -2,16 +2,17 @@ use crate::backend::{KeyState, OutputId, ScrollAxis, SeatEvent, SeatId}; use crate::client::{ClientId, DynEventFormatter}; use crate::fixed::Fixed; use crate::ifs::wl_data_device::WlDataDevice; -use crate::ifs::wl_data_offer::{WlDataOfferId}; +use crate::ifs::wl_data_offer::WlDataOfferId; use crate::ifs::wl_seat::wl_keyboard::WlKeyboard; use crate::ifs::wl_seat::wl_pointer::{WlPointer, POINTER_FRAME_SINCE_VERSION}; use crate::ifs::wl_seat::{ - wl_keyboard, wl_pointer, PointerGrab, PointerGrabber, WlSeatGlobal, WlSeatObj, + wl_keyboard, wl_pointer, PointerGrab, PointerGrabber, WlSeat, WlSeatGlobal, }; use crate::ifs::wl_surface::xdg_surface::xdg_popup::XdgPopup; use crate::ifs::wl_surface::xdg_surface::xdg_toplevel::XdgToplevel; use crate::ifs::wl_surface::xdg_surface::XdgSurface; use crate::ifs::wl_surface::WlSurface; +use crate::ifs::zwp_primary_selection_device_v1::ZwpPrimarySelectionDeviceV1; use crate::tree::{FloatNode, FoundNode, Node}; use crate::utils::smallmap::SmallMap; use crate::xkbcommon::{ModifierState, XKB_KEY_DOWN, XKB_KEY_UP}; @@ -257,7 +258,7 @@ impl WlSeatGlobal { fn for_each_seat(&self, ver: u32, client: ClientId, mut f: C) where - C: FnMut(&Rc), + C: FnMut(&Rc), { let bindings = self.bindings.borrow(); if let Some(hm) = bindings.get(&client) { @@ -307,6 +308,20 @@ impl WlSeatGlobal { } } + pub fn for_each_primary_selection_device(&self, ver: u32, client: ClientId, mut f: C) + where + C: FnMut(&Rc), + { + let dd = self.primary_selection_devices.borrow_mut(); + if let Some(dd) = dd.get(&client) { + for dd in dd.values() { + if dd.manager.version >= ver { + f(dd); + } + } + } + } + fn surface_pointer_frame(&self, surface: &WlSurface) { self.surface_pointer_event(POINTER_FRAME_SINCE_VERSION, surface, |p| p.frame()); } diff --git a/src/ifs/wl_seat/mod.rs b/src/ifs/wl_seat/mod.rs index 122fdfa0..d01b31a4 100644 --- a/src/ifs/wl_seat/mod.rs +++ b/src/ifs/wl_seat/mod.rs @@ -16,7 +16,14 @@ use crate::ifs::wl_seat::wl_keyboard::{WlKeyboard, WlKeyboardId, REPEAT_INFO_SIN use crate::ifs::wl_seat::wl_pointer::{WlPointer, WlPointerId}; use crate::ifs::wl_seat::wl_touch::WlTouch; use crate::ifs::wl_surface::xdg_surface::xdg_toplevel::XdgToplevel; -use crate::object::{Interface, Object, ObjectId}; +use crate::ifs::zwp_primary_selection_device_v1::{ + ZwpPrimarySelectionDeviceV1, ZwpPrimarySelectionDeviceV1Id, +}; +use crate::ifs::zwp_primary_selection_offer_v1::ZwpPrimarySelectionOfferV1Id; +use crate::ifs::zwp_primary_selection_source_v1::{ + ZwpPrimarySelectionSourceV1, ZwpPrimarySelectionSourceV1Error, +}; +use crate::object::{Interface, Object}; use crate::tree::{FloatNode, FoundNode, Node}; use crate::utils::asyncevent::AsyncEvent; use crate::utils::buffd::MsgParser; @@ -88,8 +95,14 @@ pub struct WlSeatGlobal { toplevel_focus_history: LinkedList>, keyboard_node: CloneCell>, pressed_keys: RefCell>, - bindings: RefCell>>>, + bindings: RefCell>>>, data_devices: RefCell>>>, + primary_selection_devices: RefCell< + AHashMap< + ClientId, + AHashMap>, + >, + >, kb_state: RefCell, layout: Rc, layout_size: u32, @@ -98,6 +111,7 @@ pub struct WlSeatGlobal { grabber: RefCell>, tree_changed: Rc, selection: CloneCell>>, + primary_selection: CloneCell>>, } impl WlSeatGlobal { @@ -140,6 +154,7 @@ impl WlSeatGlobal { pressed_keys: RefCell::new(Default::default()), bindings: Default::default(), data_devices: RefCell::new(Default::default()), + primary_selection_devices: RefCell::new(Default::default()), kb_state: RefCell::new(kb_state), layout, layout_size, @@ -148,10 +163,14 @@ impl WlSeatGlobal { grabber: RefCell::new(None), tree_changed: tree_changed.clone(), selection: Default::default(), + primary_selection: Default::default(), } } - pub fn set_selection(self: &Rc, selection: Option>) -> Result<(), WlDataSourceError> { + pub fn set_selection( + self: &Rc, + selection: Option>, + ) -> Result<(), WlDataSourceError> { if let Some(new) = &selection { new.attach(self, DataOfferRole::Selection)?; } @@ -169,6 +188,33 @@ impl WlSeatGlobal { }); } } + client.flush(); + } + Ok(()) + } + + pub fn set_primary_selection( + self: &Rc, + selection: Option>, + ) -> Result<(), ZwpPrimarySelectionSourceV1Error> { + if let Some(new) = &selection { + new.attach(self)?; + } + if let Some(old) = self.primary_selection.set(selection.clone()) { + old.detach(); + } + if let Some(client) = self.keyboard_node.get().client() { + match selection { + Some(sel) => { + sel.create_offer(&client); + } + _ => { + self.for_each_primary_selection_device(0, client.id, |device| { + client.event(device.selection(ZwpPrimarySelectionOfferV1Id::NONE)); + }); + } + } + client.flush(); } Ok(()) } @@ -219,7 +265,7 @@ impl WlSeatGlobal { client: &Rc, version: u32, ) -> Result<(), WlSeatError> { - let obj = Rc::new(WlSeatObj { + let obj = Rc::new(WlSeat { global: self.clone(), id, client: client.clone(), @@ -265,7 +311,9 @@ impl Global for WlSeatGlobal { } } -pub struct WlSeatObj { +dedicated_add_global!(WlSeatGlobal, seats); + +pub struct WlSeat { pub global: Rc, id: WlSeatId, client: Rc, @@ -274,7 +322,7 @@ pub struct WlSeatObj { version: u32, } -impl WlSeatObj { +impl WlSeat { fn capabilities(self: &Rc) -> DynEventFormatter { Box::new(Capabilities { obj: self.clone(), @@ -306,6 +354,23 @@ impl WlSeatObj { } } + pub fn add_primary_selection_device(&self, device: &Rc) { + let mut dd = self.global.primary_selection_devices.borrow_mut(); + dd.entry(self.client.id) + .or_default() + .insert(device.id, device.clone()); + } + + pub fn remove_primary_selection_device(&self, device: &ZwpPrimarySelectionDeviceV1) { + let mut dd = self.global.primary_selection_devices.borrow_mut(); + if let Entry::Occupied(mut e) = dd.entry(self.client.id) { + e.get_mut().remove(&device.id); + if e.get().is_empty() { + e.remove(); + } + } + } + pub fn move_(&self, node: &Rc) { self.global.move_(node); } @@ -349,34 +414,18 @@ impl WlSeatObj { self.client.remove_obj(self)?; Ok(()) } - - fn handle_request_( - self: &Rc, - request: u32, - parser: MsgParser<'_, '_>, - ) -> Result<(), WlSeatError> { - match request { - GET_POINTER => self.get_pointer(parser)?, - GET_KEYBOARD => self.get_keyboard(parser)?, - GET_TOUCH => self.get_touch(parser)?, - RELEASE => self.release(parser)?, - _ => unreachable!(), - } - Ok(()) - } } -handle_request!(WlSeatObj); +object_base! { + WlSeat, WlSeatError; -impl Object for WlSeatObj { - fn id(&self) -> ObjectId { - self.id.into() - } - - fn interface(&self) -> Interface { - Interface::WlSeat - } + GET_POINTER => get_pointer, + GET_KEYBOARD => get_keyboard, + GET_TOUCH => get_touch, + RELEASE => release, +} +impl Object for WlSeat { fn num_requests(&self) -> u32 { if self.version < 5 { GET_TOUCH + 1 @@ -396,3 +445,5 @@ impl Object for WlSeatObj { self.keyboards.clear(); } } + +dedicated_add_obj!(WlSeat, WlSeatId, seats); diff --git a/src/ifs/wl_seat/types.rs b/src/ifs/wl_seat/types.rs index 5dd8ba57..f320c385 100644 --- a/src/ifs/wl_seat/types.rs +++ b/src/ifs/wl_seat/types.rs @@ -2,7 +2,7 @@ use crate::client::{ClientError, EventFormatter, RequestParser}; use crate::ifs::wl_seat::wl_keyboard::{WlKeyboardError, WlKeyboardId}; use crate::ifs::wl_seat::wl_pointer::WlPointerId; use crate::ifs::wl_seat::wl_touch::WlTouchId; -use crate::ifs::wl_seat::{WlSeatObj, CAPABILITIES, NAME}; +use crate::ifs::wl_seat::{WlSeat, CAPABILITIES, NAME}; use crate::object::Object; use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError}; use std::fmt::{Debug, Formatter}; @@ -128,7 +128,7 @@ impl Debug for Release { } pub(super) struct Capabilities { - pub obj: Rc, + pub obj: Rc, pub capabilities: u32, } impl EventFormatter for Capabilities { @@ -147,7 +147,7 @@ impl Debug for Capabilities { } pub(super) struct Name { - pub obj: Rc, + pub obj: Rc, pub name: Rc, } impl EventFormatter for Name { diff --git a/src/ifs/wl_seat/wl_keyboard/mod.rs b/src/ifs/wl_seat/wl_keyboard/mod.rs index c177ceea..d3214cf8 100644 --- a/src/ifs/wl_seat/wl_keyboard/mod.rs +++ b/src/ifs/wl_seat/wl_keyboard/mod.rs @@ -1,9 +1,9 @@ mod types; use crate::client::DynEventFormatter; -use crate::ifs::wl_seat::WlSeatObj; +use crate::ifs::wl_seat::WlSeat; use crate::ifs::wl_surface::WlSurfaceId; -use crate::object::{Interface, Object, ObjectId}; +use crate::object::Object; use crate::utils::buffd::MsgParser; use std::rc::Rc; pub use types::*; @@ -33,11 +33,11 @@ id!(WlKeyboardId); pub struct WlKeyboard { id: WlKeyboardId, - seat: Rc, + seat: Rc, } impl WlKeyboard { - pub fn new(id: WlKeyboardId, seat: &Rc) -> Self { + pub fn new(id: WlKeyboardId, seat: &Rc) -> Self { Self { id, seat: seat.clone(), @@ -152,32 +152,18 @@ impl WlKeyboard { self.seat.client.remove_obj(self)?; Ok(()) } - - fn handle_request_( - &self, - request: u32, - parser: MsgParser<'_, '_>, - ) -> Result<(), WlKeyboardError> { - match request { - RELEASE => self.release(parser)?, - _ => unreachable!(), - } - Ok(()) - } } -handle_request!(WlKeyboard); +object_base! { + WlKeyboard, WlKeyboardError; + + RELEASE => release, +} impl Object for WlKeyboard { - fn id(&self) -> ObjectId { - self.id.into() - } - - fn interface(&self) -> Interface { - Interface::WlKeyboard - } - fn num_requests(&self) -> u32 { RELEASE + 1 } } + +simple_add_obj!(WlKeyboard); diff --git a/src/ifs/wl_seat/wl_pointer/mod.rs b/src/ifs/wl_seat/wl_pointer/mod.rs index 3afb6dfd..995d82d3 100644 --- a/src/ifs/wl_seat/wl_pointer/mod.rs +++ b/src/ifs/wl_seat/wl_pointer/mod.rs @@ -3,9 +3,9 @@ mod types; use crate::client::DynEventFormatter; use crate::cursor::Cursor; use crate::fixed::Fixed; -use crate::ifs::wl_seat::WlSeatObj; +use crate::ifs::wl_seat::WlSeat; use crate::ifs::wl_surface::WlSurfaceId; -use crate::object::{Interface, Object, ObjectId}; +use crate::object::Object; use crate::utils::buffd::MsgParser; use std::rc::Rc; pub use types::*; @@ -47,11 +47,11 @@ id!(WlPointerId); pub struct WlPointer { id: WlPointerId, - seat: Rc, + seat: Rc, } impl WlPointer { - pub fn new(id: WlPointerId, seat: &Rc) -> Self { + pub fn new(id: WlPointerId, seat: &Rc) -> Self { Self { id, seat: seat.clone(), @@ -151,7 +151,7 @@ impl WlPointer { let req: SetCursor = self.seat.client.parse(self, parser)?; let mut cursor_opt = None; if req.surface.is_some() { - let surface = self.seat.client.get_surface(req.surface)?; + let surface = self.seat.client.lookup(req.surface)?; let cursor = surface.get_cursor(&self.seat.global)?; cursor.set_hotspot(req.hotspot_x, req.hotspot_y); cursor_opt = Some(cursor as Rc); @@ -176,33 +176,19 @@ impl WlPointer { self.seat.client.remove_obj(self)?; Ok(()) } - - fn handle_request_( - &self, - request: u32, - parser: MsgParser<'_, '_>, - ) -> Result<(), WlPointerError> { - match request { - SET_CURSOR => self.set_cursor(parser)?, - RELEASE => self.release(parser)?, - _ => unreachable!(), - } - Ok(()) - } } -handle_request!(WlPointer); +object_base! { + WlPointer, WlPointerError; + + SET_CURSOR => set_cursor, + RELEASE => release, +} impl Object for WlPointer { - fn id(&self) -> ObjectId { - self.id.into() - } - - fn interface(&self) -> Interface { - Interface::WlPointer - } - fn num_requests(&self) -> u32 { RELEASE + 1 } } + +simple_add_obj!(WlPointer); diff --git a/src/ifs/wl_seat/wl_touch/mod.rs b/src/ifs/wl_seat/wl_touch/mod.rs index 0673a9b3..fef5c00e 100644 --- a/src/ifs/wl_seat/wl_touch/mod.rs +++ b/src/ifs/wl_seat/wl_touch/mod.rs @@ -1,7 +1,7 @@ mod types; -use crate::ifs::wl_seat::WlSeatObj; -use crate::object::{Interface, Object, ObjectId}; +use crate::ifs::wl_seat::WlSeat; +use crate::object::Object; use crate::utils::buffd::MsgParser; use std::rc::Rc; pub use types::*; @@ -27,11 +27,11 @@ id!(WlTouchId); pub struct WlTouch { id: WlTouchId, - seat: Rc, + seat: Rc, } impl WlTouch { - pub fn new(id: WlTouchId, seat: &Rc) -> Self { + pub fn new(id: WlTouchId, seat: &Rc) -> Self { Self { id, seat: seat.clone(), @@ -43,28 +43,18 @@ impl WlTouch { self.seat.client.remove_obj(self)?; Ok(()) } - - fn handle_request_(&self, request: u32, parser: MsgParser<'_, '_>) -> Result<(), WlTouchError> { - match request { - RELEASE => self.release(parser)?, - _ => unreachable!(), - } - Ok(()) - } } -handle_request!(WlTouch); +object_base! { + WlTouch, WlTouchError; + + RELEASE => release, +} impl Object for WlTouch { - fn id(&self) -> ObjectId { - self.id.into() - } - - fn interface(&self) -> Interface { - Interface::WlTouch - } - fn num_requests(&self) -> u32 { RELEASE + 1 } } + +simple_add_obj!(WlTouch); diff --git a/src/ifs/wl_shm/mod.rs b/src/ifs/wl_shm/mod.rs index c8bcbd06..f04c4bbe 100644 --- a/src/ifs/wl_shm/mod.rs +++ b/src/ifs/wl_shm/mod.rs @@ -4,7 +4,7 @@ use crate::client::Client; use crate::format::FORMATS; use crate::globals::{Global, GlobalName}; use crate::ifs::wl_shm_pool::WlShmPool; -use crate::object::{Interface, Object, ObjectId}; +use crate::object::{Interface, Object}; use crate::utils::buffd::MsgParser; use std::rc::Rc; pub use types::*; @@ -19,7 +19,7 @@ pub struct WlShmGlobal { name: GlobalName, } -pub struct WlShmObj { +pub struct WlShm { _global: Rc, id: WlShmId, client: Rc, @@ -36,7 +36,7 @@ impl WlShmGlobal { client: &Rc, _version: u32, ) -> Result<(), WlShmError> { - let obj = Rc::new(WlShmObj { + let obj = Rc::new(WlShm { _global: self, id, client: client.clone(), @@ -52,7 +52,7 @@ impl WlShmGlobal { } } -impl WlShmObj { +impl WlShm { fn create_pool(&self, parser: MsgParser<'_, '_>) -> Result<(), CreatePoolError> { let create: CreatePool = self.client.parse(self, parser)?; if create.size < 0 { @@ -67,14 +67,6 @@ impl WlShmObj { self.client.add_client_obj(&pool)?; Ok(()) } - - fn handle_request_(&self, request: u32, parser: MsgParser<'_, '_>) -> Result<(), WlShmError> { - match request { - CREATE_POOL => self.create_pool(parser)?, - _ => unreachable!(), - } - Ok(()) - } } bind!(WlShmGlobal); @@ -97,18 +89,18 @@ impl Global for WlShmGlobal { } } -handle_request!(WlShmObj); +simple_add_global!(WlShmGlobal); -impl Object for WlShmObj { - fn id(&self) -> ObjectId { - self.id.into() - } +object_base! { + WlShm, WlShmError; - fn interface(&self) -> Interface { - Interface::WlShm - } + CREATE_POOL => create_pool, +} +impl Object for WlShm { fn num_requests(&self) -> u32 { CREATE_POOL + 1 } } + +simple_add_obj!(WlShm); diff --git a/src/ifs/wl_shm/types.rs b/src/ifs/wl_shm/types.rs index 32c2d3a4..98ea59b5 100644 --- a/src/ifs/wl_shm/types.rs +++ b/src/ifs/wl_shm/types.rs @@ -1,6 +1,6 @@ use crate::client::{ClientError, EventFormatter, RequestParser}; use crate::format::Format; -use crate::ifs::wl_shm::{WlShmObj, FORMAT}; +use crate::ifs::wl_shm::{WlShm, FORMAT}; use crate::ifs::wl_shm_pool::{WlShmPoolError, WlShmPoolId}; use crate::object::Object; use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError}; @@ -60,7 +60,7 @@ impl Debug for CreatePool { } pub(super) struct FormatE { - pub obj: Rc, + pub obj: Rc, pub format: &'static Format, } impl EventFormatter for FormatE { diff --git a/src/ifs/wl_shm_pool/mod.rs b/src/ifs/wl_shm_pool/mod.rs index f7e4a116..b5a37516 100644 --- a/src/ifs/wl_shm_pool/mod.rs +++ b/src/ifs/wl_shm_pool/mod.rs @@ -4,7 +4,7 @@ use crate::client::Client; use crate::clientmem::ClientMem; use crate::format::{formats, map_wayland_format_id}; use crate::ifs::wl_buffer::WlBuffer; -use crate::object::{Interface, Object, ObjectId}; +use crate::object::Object; use crate::utils::buffd::MsgParser; use crate::utils::clonecell::CloneCell; use std::rc::Rc; @@ -81,34 +81,20 @@ impl WlShmPool { .set(Rc::new(ClientMem::new(self.fd.raw(), req.size as usize)?)); Ok(()) } - - fn handle_request_( - &self, - request: u32, - parser: MsgParser<'_, '_>, - ) -> Result<(), WlShmPoolError> { - match request { - CREATE_BUFFER => self.create_buffer(parser)?, - DESTROY => self.destroy(parser)?, - RESIZE => self.resize(parser)?, - _ => unreachable!(), - } - Ok(()) - } } -handle_request!(WlShmPool); +object_base! { + WlShmPool, WlShmPoolError; + + CREATE_BUFFER => create_buffer, + DESTROY => destroy, + RESIZE => resize, +} impl Object for WlShmPool { - fn id(&self) -> ObjectId { - self.id.into() - } - - fn interface(&self) -> Interface { - Interface::WlShmPool - } - fn num_requests(&self) -> u32 { RESIZE + 1 } } + +simple_add_obj!(WlShmPool); diff --git a/src/ifs/wl_subcompositor/mod.rs b/src/ifs/wl_subcompositor/mod.rs index 7e2e94ab..ac2d1328 100644 --- a/src/ifs/wl_subcompositor/mod.rs +++ b/src/ifs/wl_subcompositor/mod.rs @@ -3,7 +3,7 @@ mod types; use crate::client::Client; use crate::globals::{Global, GlobalName}; use crate::ifs::wl_surface::wl_subsurface::WlSubsurface; -use crate::object::{Interface, Object, ObjectId}; +use crate::object::{Interface, Object}; use crate::utils::buffd::MsgParser; use std::rc::Rc; pub use types::*; @@ -20,7 +20,7 @@ pub struct WlSubcompositorGlobal { name: GlobalName, } -pub struct WlSubcompositorObj { +pub struct WlSubcompositor { id: WlSubcompositorId, client: Rc, } @@ -36,7 +36,7 @@ impl WlSubcompositorGlobal { client: &Rc, _version: u32, ) -> Result<(), WlSubcompositorError> { - let obj = Rc::new(WlSubcompositorObj { + let obj = Rc::new(WlSubcompositor { id, client: client.clone(), }); @@ -45,7 +45,7 @@ impl WlSubcompositorGlobal { } } -impl WlSubcompositorObj { +impl WlSubcompositor { fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> { let _req: Destroy = self.client.parse(self, parser)?; self.client.remove_obj(self)?; @@ -54,26 +54,13 @@ impl WlSubcompositorObj { fn get_subsurface(&self, parser: MsgParser<'_, '_>) -> Result<(), GetSubsurfaceError> { let req: GetSubsurface = self.client.parse(self, parser)?; - let surface = self.client.get_surface(req.surface)?; - let parent = self.client.get_surface(req.parent)?; + let surface = self.client.lookup(req.surface)?; + let parent = self.client.lookup(req.parent)?; let subsurface = Rc::new(WlSubsurface::new(req.id, &surface, &parent)); self.client.add_client_obj(&subsurface)?; subsurface.install()?; Ok(()) } - - fn handle_request_( - self: &Rc, - request: u32, - parser: MsgParser<'_, '_>, - ) -> Result<(), WlSubcompositorError> { - match request { - DESTROY => self.destroy(parser)?, - GET_SUBSURFACE => self.get_subsurface(parser)?, - _ => unreachable!(), - } - Ok(()) - } } bind!(WlSubcompositorGlobal); @@ -96,18 +83,19 @@ impl Global for WlSubcompositorGlobal { } } -handle_request!(WlSubcompositorObj); +simple_add_global!(WlSubcompositorGlobal); -impl Object for WlSubcompositorObj { - fn id(&self) -> ObjectId { - self.id.into() - } +object_base! { + WlSubcompositor, WlSubcompositorError; - fn interface(&self) -> Interface { - Interface::WlSubcompositor - } + DESTROY => destroy, + GET_SUBSURFACE => get_subsurface, +} +impl Object for WlSubcompositor { fn num_requests(&self) -> u32 { GET_SUBSURFACE + 1 } } + +simple_add_obj!(WlSubcompositor); diff --git a/src/ifs/wl_surface/mod.rs b/src/ifs/wl_surface/mod.rs index 1349834b..1e73a174 100644 --- a/src/ifs/wl_surface/mod.rs +++ b/src/ifs/wl_surface/mod.rs @@ -13,13 +13,11 @@ use crate::ifs::wl_seat::{NodeSeatState, WlSeatGlobal}; use crate::ifs::wl_surface::cursor::CursorSurface; use crate::ifs::wl_surface::wl_subsurface::WlSubsurface; use crate::ifs::wl_surface::xdg_surface::{XdgSurface, XdgSurfaceRole}; -use crate::object::{Interface, Object, ObjectId}; +use crate::object::Object; use crate::pixman::Region; use crate::rect::Rect; use crate::render::Renderer; -use crate::tree::{ - Node, NodeId, -}; +use crate::tree::{Node, NodeId}; use crate::utils::buffd::{MsgParser, MsgParserError}; use crate::utils::clonecell::CloneCell; use crate::utils::linkedlist::LinkedList; @@ -351,7 +349,7 @@ impl WlSurface { fn attach(self: &Rc, parser: MsgParser<'_, '_>) -> Result<(), AttachError> { let req: Attach = self.parse(parser)?; let buf = if req.buffer.is_some() { - Some((req.x, req.y, self.client.get_buffer(req.buffer)?)) + Some((req.x, req.y, self.client.lookup(req.buffer)?)) } else { None }; @@ -375,7 +373,7 @@ impl WlSurface { fn set_opaque_region(&self, parser: MsgParser<'_, '_>) -> Result<(), SetOpaqueRegionError> { let region: SetOpaqueRegion = self.parse(parser)?; let region = if region.region.is_some() { - Some(self.client.get_region(region.region)?.region()) + Some(self.client.lookup(region.region)?.region()) } else { None }; @@ -386,7 +384,7 @@ impl WlSurface { fn set_input_region(&self, parser: MsgParser<'_, '_>) -> Result<(), SetInputRegionError> { let req: SetInputRegion = self.parse(parser)?; let region = if req.region.is_some() { - Some(self.client.get_region(req.region)?.region()) + Some(self.client.lookup(req.region)?.region()) } else { None }; @@ -491,27 +489,6 @@ impl WlSurface { Ok(()) } - fn handle_request_( - self: &Rc, - request: u32, - parser: MsgParser<'_, '_>, - ) -> Result<(), WlSurfaceError> { - match request { - DESTROY => self.destroy(parser)?, - ATTACH => self.attach(parser)?, - DAMAGE => self.damage(parser)?, - FRAME => self.frame(parser)?, - SET_OPAQUE_REGION => self.set_opaque_region(parser)?, - SET_INPUT_REGION => self.set_input_region(parser)?, - COMMIT => self.commit(parser)?, - SET_BUFFER_TRANSFORM => self.set_buffer_transform(parser)?, - SET_BUFFER_SCALE => self.set_buffer_scale(parser)?, - DAMAGE_BUFFER => self.damage_buffer(parser)?, - _ => unreachable!(), - } - Ok(()) - } - fn find_surface_at(self: &Rc, x: i32, y: i32) -> Option<(Rc, i32, i32)> { let buffer = match self.buffer.get() { Some(b) => b, @@ -556,17 +533,22 @@ impl WlSurface { } } -handle_request!(WlSurface); +object_base! { + WlSurface, WlSurfaceError; + + DESTROY => destroy, + ATTACH => attach, + DAMAGE => damage, + FRAME => frame, + SET_OPAQUE_REGION => set_opaque_region, + SET_INPUT_REGION => set_input_region, + COMMIT => commit, + SET_BUFFER_TRANSFORM => set_buffer_transform, + SET_BUFFER_SCALE => set_buffer_scale, + DAMAGE_BUFFER => damage_buffer, +} impl Object for WlSurface { - fn id(&self) -> ObjectId { - self.id.into() - } - - fn interface(&self) -> Interface { - Interface::WlSurface - } - fn num_requests(&self) -> u32 { DAMAGE_BUFFER + 1 } @@ -582,6 +564,8 @@ impl Object for WlSurface { } } +dedicated_add_obj!(WlSurface, WlSurfaceId, surfaces); + tree_id!(SurfaceNodeId); impl Node for WlSurface { fn id(&self) -> NodeId { diff --git a/src/ifs/wl_surface/wl_subsurface/mod.rs b/src/ifs/wl_surface/wl_subsurface/mod.rs index 8fead62b..285b7d53 100644 --- a/src/ifs/wl_surface/wl_subsurface/mod.rs +++ b/src/ifs/wl_surface/wl_subsurface/mod.rs @@ -4,7 +4,7 @@ use crate::ifs::wl_surface::{ CommitAction, CommitContext, StackElement, SurfaceExt, SurfaceRole, WlSurface, WlSurfaceError, WlSurfaceId, }; -use crate::object::{Interface, Object, ObjectId}; +use crate::object::Object; use crate::rect::Rect; use crate::utils::buffd::MsgParser; use crate::utils::linkedlist::LinkedNode; @@ -237,41 +237,27 @@ impl WlSubsurface { self.update_sync(false); Ok(()) } - - fn handle_request_( - self: &Rc, - request: u32, - parser: MsgParser<'_, '_>, - ) -> Result<(), WlSubsurfaceError> { - match request { - DESTROY => self.destroy(parser)?, - SET_POSITION => self.set_position(parser)?, - PLACE_ABOVE => self.place_above(parser)?, - PLACE_BELOW => self.place_below(parser)?, - SET_SYNC => self.set_sync(parser)?, - SET_DESYNC => self.set_desync(parser)?, - _ => unreachable!(), - } - Ok(()) - } } -handle_request!(WlSubsurface); +object_base! { + WlSubsurface, WlSubsurfaceError; + + DESTROY => destroy, + SET_POSITION => set_position, + PLACE_ABOVE => place_above, + PLACE_BELOW => place_below, + SET_SYNC => set_sync, + SET_DESYNC => set_desync, +} impl Object for WlSubsurface { - fn id(&self) -> ObjectId { - self.id.into() - } - - fn interface(&self) -> Interface { - Interface::WlSubsurface - } - fn num_requests(&self) -> u32 { SET_DESYNC + 1 } } +simple_add_obj!(WlSubsurface); + impl SurfaceExt for WlSubsurface { fn pre_commit(self: Rc, ctx: CommitContext) -> Result { if ctx == CommitContext::RootCommit && self.sync() { diff --git a/src/ifs/wl_surface/xdg_surface/mod.rs b/src/ifs/wl_surface/xdg_surface/mod.rs index 9413e66a..756d25d5 100644 --- a/src/ifs/wl_surface/xdg_surface/mod.rs +++ b/src/ifs/wl_surface/xdg_surface/mod.rs @@ -10,8 +10,8 @@ use crate::ifs::wl_surface::xdg_surface::xdg_toplevel::XdgToplevel; use crate::ifs::wl_surface::{ CommitAction, CommitContext, SurfaceExt, SurfaceRole, WlSurface, WlSurfaceError, }; -use crate::ifs::xdg_wm_base::XdgWmBaseObj; -use crate::object::{Interface, Object, ObjectId}; +use crate::ifs::xdg_wm_base::XdgWmBase; +use crate::object::Object; use crate::rect::Rect; use crate::tree::{FindTreeResult, FoundNode, Node, WorkspaceNode}; use crate::utils::buffd::MsgParser; @@ -58,7 +58,7 @@ id!(XdgSurfaceId); pub struct XdgSurface { id: XdgSurfaceId, - base: Rc, + base: Rc, role: Cell, pub surface: Rc, requested_serial: NumCell, @@ -102,7 +102,7 @@ trait XdgSurfaceExt { } impl XdgSurface { - pub fn new(wm_base: &Rc, id: XdgSurfaceId, surface: &Rc) -> Self { + pub fn new(wm_base: &Rc, id: XdgSurfaceId, surface: &Rc) -> Self { Self { id, base: wm_base.clone(), @@ -254,9 +254,9 @@ impl XdgSurface { self.set_role(XdgSurfaceRole::XdgPopup)?; let mut parent = None; if req.parent.is_some() { - parent = Some(self.surface.client.get_xdg_surface(req.parent)?); + parent = Some(self.surface.client.lookup(req.parent)?); } - let positioner = self.surface.client.get_xdg_positioner(req.positioner)?; + let positioner = self.surface.client.lookup(req.positioner)?; if self.ext.get().is_some() { self.surface.client.protocol_error( &**self, @@ -295,22 +295,6 @@ impl XdgSurface { Ok(()) } - fn handle_request_( - self: &Rc, - request: u32, - parser: MsgParser<'_, '_>, - ) -> Result<(), XdgSurfaceError> { - match request { - DESTROY => self.destroy(parser)?, - GET_TOPLEVEL => self.get_toplevel(parser)?, - GET_POPUP => self.get_popup(parser)?, - SET_WINDOW_GEOMETRY => self.set_window_geometry(parser)?, - ACK_CONFIGURE => self.ack_configure(parser)?, - _ => unreachable!(), - } - Ok(()) - } - fn update_extents(&self) { let old_extents = self.extents.get(); let mut new_extents = self.surface.extents.get(); @@ -348,17 +332,17 @@ impl XdgSurface { } } -handle_request!(XdgSurface); +object_base! { + XdgSurface, XdgSurfaceError; + + DESTROY => destroy, + GET_TOPLEVEL => get_toplevel, + GET_POPUP => get_popup, + SET_WINDOW_GEOMETRY => set_window_geometry, + ACK_CONFIGURE => ack_configure, +} impl Object for XdgSurface { - fn id(&self) -> ObjectId { - self.id.into() - } - - fn interface(&self) -> Interface { - Interface::XdgSurface - } - fn num_requests(&self) -> u32 { ACK_CONFIGURE + 1 } @@ -368,6 +352,8 @@ impl Object for XdgSurface { } } +dedicated_add_obj!(XdgSurface, XdgSurfaceId, xdg_surfaces); + impl SurfaceExt for XdgSurface { fn pre_commit(self: Rc, _ctx: CommitContext) -> Result { { diff --git a/src/ifs/wl_surface/xdg_surface/xdg_popup/mod.rs b/src/ifs/wl_surface/xdg_surface/xdg_popup/mod.rs index 18bbadab..4b7f6c42 100644 --- a/src/ifs/wl_surface/xdg_surface/xdg_popup/mod.rs +++ b/src/ifs/wl_surface/xdg_surface/xdg_popup/mod.rs @@ -6,7 +6,7 @@ use crate::fixed::Fixed; use crate::ifs::wl_seat::{NodeSeatState, WlSeatGlobal}; use crate::ifs::wl_surface::xdg_surface::{XdgSurface, XdgSurfaceError, XdgSurfaceExt}; use crate::ifs::xdg_positioner::{XdgPositioned, XdgPositioner, CA}; -use crate::object::{Interface, Object, ObjectId}; +use crate::object::Object; use crate::rect::Rect; use crate::render::Renderer; use crate::tree::{FindTreeResult, FoundNode, Node, NodeId, WorkspaceNode}; @@ -208,12 +208,7 @@ impl XdgPopup { fn reposition(self: &Rc, parser: MsgParser<'_, '_>) -> Result<(), RepositionError> { let req: Reposition = self.xdg.surface.client.parse(&**self, parser)?; - *self.pos.borrow_mut() = self - .xdg - .surface - .client - .get_xdg_positioner(req.positioner)? - .value(); + *self.pos.borrow_mut() = self.xdg.surface.client.lookup(req.positioner)?.value(); if let Some(parent) = self.parent.get() { self.update_position(&parent)?; let rel = self.relative_position.get(); @@ -234,7 +229,7 @@ impl XdgPopup { } } -handle_request! { +object_base! { XdgPopup, XdgPopupError; DESTROY => destroy, @@ -243,14 +238,6 @@ handle_request! { } impl Object for XdgPopup { - fn id(&self) -> ObjectId { - self.id.into() - } - - fn interface(&self) -> Interface { - Interface::XdgPopup - } - fn num_requests(&self) -> u32 { let last_req = match self.xdg.base.version { 0..=2 => GRAB, @@ -267,6 +254,8 @@ impl Object for XdgPopup { } } +simple_add_obj!(XdgPopup); + impl Node for XdgPopup { fn id(&self) -> NodeId { self.node_id.into() diff --git a/src/ifs/wl_surface/xdg_surface/xdg_toplevel/mod.rs b/src/ifs/wl_surface/xdg_surface/xdg_toplevel/mod.rs index c50d9517..c8c927e9 100644 --- a/src/ifs/wl_surface/xdg_surface/xdg_toplevel/mod.rs +++ b/src/ifs/wl_surface/xdg_surface/xdg_toplevel/mod.rs @@ -7,7 +7,7 @@ use crate::cursor::KnownCursor; use crate::fixed::Fixed; use crate::ifs::wl_seat::{NodeSeatState, WlSeatGlobal}; use crate::ifs::wl_surface::xdg_surface::{XdgSurface, XdgSurfaceError, XdgSurfaceExt}; -use crate::object::{Interface, Object, ObjectId}; +use crate::object::Object; use crate::rect::Rect; use crate::render::Renderer; use crate::tree::{ContainerNode, FindTreeResult}; @@ -200,7 +200,7 @@ impl XdgToplevel { let req: SetParent = self.xdg.surface.client.parse(self, parser)?; let mut parent = None; if req.parent.is_some() { - parent = Some(self.xdg.surface.client.get_xdg_toplevel(req.parent)?); + parent = Some(self.xdg.surface.client.lookup(req.parent)?); } self.parent.set(parent); Ok(()) @@ -226,7 +226,7 @@ impl XdgToplevel { fn move_(&self, parser: MsgParser<'_, '_>) -> Result<(), MoveError> { let req: Move = self.xdg.surface.client.parse(self, parser)?; - let seat = self.xdg.surface.client.get_wl_seat(req.seat)?; + let seat = self.xdg.surface.client.lookup(req.seat)?; if let Some(parent) = self.parent_node.get() { if let Some(float) = parent.into_float() { seat.move_(&float); @@ -301,31 +301,6 @@ impl XdgToplevel { Ok(()) } - fn handle_request_( - &self, - request: u32, - parser: MsgParser<'_, '_>, - ) -> Result<(), XdgToplevelError> { - match request { - DESTROY => self.destroy(parser)?, - SET_PARENT => self.set_parent(parser)?, - SET_TITLE => self.set_title(parser)?, - SET_APP_ID => self.set_app_id(parser)?, - SHOW_WINDOW_MENU => self.show_window_menu(parser)?, - MOVE => self.move_(parser)?, - RESIZE => self.resize(parser)?, - SET_MAX_SIZE => self.set_max_size(parser)?, - SET_MIN_SIZE => self.set_min_size(parser)?, - SET_MAXIMIZED => self.set_maximized(parser)?, - UNSET_MAXIMIZED => self.unset_maximized(parser)?, - SET_FULLSCREEN => self.set_fullscreen(parser)?, - UNSET_FULLSCREEN => self.unset_fullscreen(parser)?, - SET_MINIMIZED => self.set_minimized(parser)?, - _ => unreachable!(), - } - Ok(()) - } - fn map_child(self: &Rc, parent: &XdgToplevel) { let workspace = match parent.xdg.workspace.get() { Some(w) => w, @@ -412,17 +387,26 @@ impl XdgToplevel { } } -handle_request!(XdgToplevel); +object_base! { + XdgToplevel, XdgToplevelError; + + DESTROY => destroy, + SET_PARENT => set_parent, + SET_TITLE => set_title, + SET_APP_ID => set_app_id, + SHOW_WINDOW_MENU => show_window_menu, + MOVE => move_, + RESIZE => resize, + SET_MAX_SIZE => set_max_size, + SET_MIN_SIZE => set_min_size, + SET_MAXIMIZED => set_maximized, + UNSET_MAXIMIZED => unset_maximized, + SET_FULLSCREEN => set_fullscreen, + UNSET_FULLSCREEN => unset_fullscreen, + SET_MINIMIZED => set_minimized, +} impl Object for XdgToplevel { - fn id(&self) -> ObjectId { - self.id.into() - } - - fn interface(&self) -> Interface { - Interface::XdgToplevel - } - fn num_requests(&self) -> u32 { SET_MINIMIZED + 1 } @@ -437,6 +421,8 @@ impl Object for XdgToplevel { } } +dedicated_add_obj!(XdgToplevel, XdgToplevelId, xdg_toplevel); + impl Node for XdgToplevel { fn id(&self) -> NodeId { self.node_id.into() diff --git a/src/ifs/xdg_positioner/mod.rs b/src/ifs/xdg_positioner/mod.rs index d52ffb58..44a99cd5 100644 --- a/src/ifs/xdg_positioner/mod.rs +++ b/src/ifs/xdg_positioner/mod.rs @@ -1,8 +1,8 @@ mod types; use crate::client::Client; -use crate::ifs::xdg_wm_base::XdgWmBaseObj; -use crate::object::{Interface, Object, ObjectId}; +use crate::ifs::xdg_wm_base::XdgWmBase; +use crate::object::Object; use crate::rect::Rect; use crate::utils::buffd::MsgParser; use bitflags::bitflags; @@ -78,7 +78,7 @@ id!(XdgPositionerId); pub struct XdgPositioner { id: XdgPositionerId, - base: Rc, + base: Rc, client: Rc, position: RefCell, } @@ -152,7 +152,7 @@ impl XdgPositioned { } impl XdgPositioner { - pub fn new(base: &Rc, id: XdgPositionerId, client: &Rc) -> Self { + pub fn new(base: &Rc, id: XdgPositionerId, client: &Rc) -> Self { Self { id, client: client.clone(), @@ -277,40 +277,24 @@ impl XdgPositioner { self.position.borrow_mut().parent_serial = req.serial; Ok(()) } - - fn handle_request_( - &self, - request: u32, - parser: MsgParser<'_, '_>, - ) -> Result<(), XdgPositionerError> { - match request { - DESTROY => self.destroy(parser)?, - SET_SIZE => self.set_size(parser)?, - SET_ANCHOR_RECT => self.set_anchor_rect(parser)?, - SET_ANCHOR => self.set_anchor(parser)?, - SET_GRAVITY => self.set_gravity(parser)?, - SET_CONSTRAINT_ADJUSTMENT => self.set_constraint_adjustment(parser)?, - SET_OFFSET => self.set_offset(parser)?, - SET_REACTIVE => self.set_reactive(parser)?, - SET_PARENT_SIZE => self.set_parent_size(parser)?, - SET_PARENT_CONFIGURE => self.set_parent_configure(parser)?, - _ => unreachable!(), - } - Ok(()) - } } -handle_request!(XdgPositioner); +object_base! { + XdgPositioner, XdgPositionerError; + + DESTROY => destroy, + SET_SIZE => set_size, + SET_ANCHOR_RECT => set_anchor_rect, + SET_ANCHOR => set_anchor, + SET_GRAVITY => set_gravity, + SET_CONSTRAINT_ADJUSTMENT => set_constraint_adjustment, + SET_OFFSET => set_offset, + SET_REACTIVE => set_reactive, + SET_PARENT_SIZE => set_parent_size, + SET_PARENT_CONFIGURE => set_parent_configure, +} impl Object for XdgPositioner { - fn id(&self) -> ObjectId { - self.id.into() - } - - fn interface(&self) -> Interface { - Interface::XdgPositioner - } - fn num_requests(&self) -> u32 { if self.base.version < 3 { SET_OFFSET + 1 @@ -319,3 +303,5 @@ impl Object for XdgPositioner { } } } + +dedicated_add_obj!(XdgPositioner, XdgPositionerId, xdg_positioners); diff --git a/src/ifs/xdg_wm_base/mod.rs b/src/ifs/xdg_wm_base/mod.rs index 4fe08112..9ec410a2 100644 --- a/src/ifs/xdg_wm_base/mod.rs +++ b/src/ifs/xdg_wm_base/mod.rs @@ -4,7 +4,7 @@ use crate::client::Client; use crate::globals::{Global, GlobalName}; use crate::ifs::wl_surface::xdg_surface::{XdgSurface, XdgSurfaceId}; use crate::ifs::xdg_positioner::XdgPositioner; -use crate::object::{Interface, Object, ObjectId}; +use crate::object::{Interface, Object}; use crate::utils::buffd::MsgParser; use crate::utils::copyhashmap::CopyHashMap; use std::rc::Rc; @@ -35,7 +35,7 @@ pub struct XdgWmBaseGlobal { name: GlobalName, } -pub struct XdgWmBaseObj { +pub struct XdgWmBase { id: XdgWmBaseId, client: Rc, pub version: u32, @@ -53,7 +53,7 @@ impl XdgWmBaseGlobal { client: &Rc, version: u32, ) -> Result<(), XdgWmBaseError> { - let obj = Rc::new(XdgWmBaseObj { + let obj = Rc::new(XdgWmBase { id, client: client.clone(), version, @@ -64,7 +64,7 @@ impl XdgWmBaseGlobal { } } -impl XdgWmBaseObj { +impl XdgWmBase { fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> { let _req: Destroy = self.client.parse(self, parser)?; if !self.surfaces.is_empty() { @@ -97,7 +97,7 @@ impl XdgWmBaseObj { parser: MsgParser<'_, '_>, ) -> Result<(), GetXdgSurfaceError> { let req: GetXdgSurface = self.client.parse(&**self, parser)?; - let surface = self.client.get_surface(req.surface)?; + let surface = self.client.lookup(req.surface)?; let xdg_surface = Rc::new(XdgSurface::new(self, req.id, &surface)); self.client.add_client_obj(&xdg_surface)?; xdg_surface.install()?; @@ -109,21 +109,6 @@ impl XdgWmBaseObj { let _req: Pong = self.client.parse(self, parser)?; Ok(()) } - - fn handle_request_( - self: &Rc, - request: u32, - parser: MsgParser<'_, '_>, - ) -> Result<(), XdgWmBaseError> { - match request { - DESTROY => self.destroy(parser)?, - CREATE_POSITIONER => self.create_positioner(parser)?, - GET_XDG_SURFACE => self.get_xdg_surface(parser)?, - PONG => self.pong(parser)?, - _ => unreachable!(), - } - Ok(()) - } } bind!(XdgWmBaseGlobal); @@ -146,17 +131,20 @@ impl Global for XdgWmBaseGlobal { } } -handle_request!(XdgWmBaseObj); +simple_add_global!(XdgWmBaseGlobal); -impl Object for XdgWmBaseObj { - fn id(&self) -> ObjectId { - self.id.into() - } +object_base! { + XdgWmBase, XdgWmBaseError; - fn interface(&self) -> Interface { - Interface::XdgWmBase - } + DESTROY => destroy, + CREATE_POSITIONER => create_positioner, + GET_XDG_SURFACE => get_xdg_surface, + PONG => pong, +} +dedicated_add_obj!(XdgWmBase, XdgWmBaseId, xdg_wm_bases); + +impl Object for XdgWmBase { fn num_requests(&self) -> u32 { PONG + 1 } diff --git a/src/ifs/xdg_wm_base/types.rs b/src/ifs/xdg_wm_base/types.rs index 4f3cc8c2..d97473fe 100644 --- a/src/ifs/xdg_wm_base/types.rs +++ b/src/ifs/xdg_wm_base/types.rs @@ -2,7 +2,7 @@ use crate::client::{ClientError, EventFormatter, RequestParser}; use crate::ifs::wl_surface::xdg_surface::{XdgSurfaceError, XdgSurfaceId}; use crate::ifs::wl_surface::WlSurfaceId; use crate::ifs::xdg_positioner::XdgPositionerId; -use crate::ifs::xdg_wm_base::{XdgWmBaseObj, PING}; +use crate::ifs::xdg_wm_base::{XdgWmBase, PING}; use crate::object::Object; use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError}; use std::fmt::{Debug, Formatter}; @@ -133,7 +133,7 @@ impl Debug for Pong { } pub(super) struct Ping { - pub obj: Rc, + pub obj: Rc, pub serial: u32, } impl EventFormatter for Ping { diff --git a/src/ifs/zwp_linux_buffer_params_v1/mod.rs b/src/ifs/zwp_linux_buffer_params_v1/mod.rs index ca22049f..8b772220 100644 --- a/src/ifs/zwp_linux_buffer_params_v1/mod.rs +++ b/src/ifs/zwp_linux_buffer_params_v1/mod.rs @@ -2,8 +2,8 @@ use crate::client::DynEventFormatter; use crate::drm::dma::{DmaBuf, DmaBufPlane}; use crate::drm::INVALID_MODIFIER; use crate::ifs::wl_buffer::{WlBuffer, WlBufferId}; -use crate::ifs::zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1Obj; -use crate::object::{Interface, Object, ObjectId}; +use crate::ifs::zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1; +use crate::object::Object; use crate::utils::buffd::MsgParser; use crate::ErrorFmt; use ahash::AHashMap; @@ -34,13 +34,13 @@ const MAX_PLANE: u32 = 3; pub struct ZwpLinuxBufferParamsV1 { id: ZwpLinuxBufferParamsV1Id, - parent: Rc, + parent: Rc, planes: RefCell>, used: Cell, } impl ZwpLinuxBufferParamsV1 { - pub fn new(id: ZwpLinuxBufferParamsV1Id, parent: &Rc) -> Self { + pub fn new(id: ZwpLinuxBufferParamsV1Id, parent: &Rc) -> Self { Self { id, parent: parent.clone(), @@ -168,35 +168,21 @@ impl ZwpLinuxBufferParamsV1 { )?; Ok(()) } - - fn handle_request_( - self: &Rc, - request: u32, - parser: MsgParser<'_, '_>, - ) -> Result<(), ZwpLinuxBufferParamsV1Error> { - match request { - DESTROY => self.destroy(parser)?, - ADD => self.add(parser)?, - CREATE => self.create(parser)?, - CREATE_IMMED => self.create_immed(parser)?, - _ => unreachable!(), - } - Ok(()) - } } -handle_request!(ZwpLinuxBufferParamsV1); +object_base! { + ZwpLinuxBufferParamsV1, ZwpLinuxBufferParamsV1Error; + + DESTROY => destroy, + ADD => add, + CREATE => create, + CREATE_IMMED => create_immed, +} impl Object for ZwpLinuxBufferParamsV1 { - fn id(&self) -> ObjectId { - self.id.into() - } - - fn interface(&self) -> Interface { - Interface::ZwpLinuxBufferParamsV1 - } - fn num_requests(&self) -> u32 { CREATE_IMMED + 1 } } + +simple_add_obj!(ZwpLinuxBufferParamsV1); diff --git a/src/ifs/zwp_linux_dmabuf_v1/mod.rs b/src/ifs/zwp_linux_dmabuf_v1/mod.rs index c5af831a..ae974ce4 100644 --- a/src/ifs/zwp_linux_dmabuf_v1/mod.rs +++ b/src/ifs/zwp_linux_dmabuf_v1/mod.rs @@ -2,7 +2,7 @@ use crate::client::{Client, DynEventFormatter}; use crate::drm::INVALID_MODIFIER; use crate::globals::{Global, GlobalName}; use crate::ifs::zwp_linux_buffer_params_v1::ZwpLinuxBufferParamsV1; -use crate::object::{Interface, Object, ObjectId}; +use crate::object::{Interface, Object}; use crate::utils::buffd::MsgParser; use std::rc::Rc; pub use types::*; @@ -32,7 +32,7 @@ impl ZwpLinuxDmabufV1Global { client: &Rc, version: u32, ) -> Result<(), ZwpLinuxDmabufV1Error> { - let obj = Rc::new(ZwpLinuxDmabufV1Obj { + let obj = Rc::new(ZwpLinuxDmabufV1 { id, client: client.clone(), _version: version, @@ -73,13 +73,15 @@ impl Global for ZwpLinuxDmabufV1Global { } } -pub struct ZwpLinuxDmabufV1Obj { +simple_add_global!(ZwpLinuxDmabufV1Global); + +pub struct ZwpLinuxDmabufV1 { id: ZwpLinuxDmabufV1Id, pub client: Rc, _version: u32, } -impl ZwpLinuxDmabufV1Obj { +impl ZwpLinuxDmabufV1 { fn format(self: &Rc, format: u32) -> DynEventFormatter { Box::new(Format { obj: self.clone(), @@ -107,33 +109,19 @@ impl ZwpLinuxDmabufV1Obj { self.client.add_client_obj(¶ms)?; Ok(()) } - - fn handle_request_( - self: &Rc, - request: u32, - parser: MsgParser<'_, '_>, - ) -> Result<(), ZwpLinuxDmabufV1Error> { - match request { - DESTROY => self.destroy(parser)?, - CREATE_PARAMS => self.create_params(parser)?, - _ => unreachable!(), - } - Ok(()) - } } -handle_request!(ZwpLinuxDmabufV1Obj); +object_base! { + ZwpLinuxDmabufV1, ZwpLinuxDmabufV1Error; -impl Object for ZwpLinuxDmabufV1Obj { - fn id(&self) -> ObjectId { - self.id.into() - } - - fn interface(&self) -> Interface { - Interface::ZwpLinuxDmabufV1 - } + DESTROY => destroy, + CREATE_PARAMS => create_params, +} +impl Object for ZwpLinuxDmabufV1 { fn num_requests(&self) -> u32 { CREATE_PARAMS + 1 } } + +simple_add_obj!(ZwpLinuxDmabufV1); diff --git a/src/ifs/zwp_linux_dmabuf_v1/types.rs b/src/ifs/zwp_linux_dmabuf_v1/types.rs index 69ece504..5c0d4bd6 100644 --- a/src/ifs/zwp_linux_dmabuf_v1/types.rs +++ b/src/ifs/zwp_linux_dmabuf_v1/types.rs @@ -1,6 +1,6 @@ use crate::client::{ClientError, EventFormatter, RequestParser}; use crate::ifs::zwp_linux_buffer_params_v1::ZwpLinuxBufferParamsV1Id; -use crate::ifs::zwp_linux_dmabuf_v1::{ZwpLinuxDmabufV1Obj, FORMAT, MODIFIER}; +use crate::ifs::zwp_linux_dmabuf_v1::{ZwpLinuxDmabufV1, FORMAT, MODIFIER}; use crate::object::Object; use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError}; use std::fmt::{Debug, Formatter}; @@ -67,7 +67,7 @@ impl Debug for CreateParams { } pub(super) struct Format { - pub obj: Rc, + pub obj: Rc, pub format: u32, } impl EventFormatter for Format { @@ -85,7 +85,7 @@ impl Debug for Format { } pub(super) struct Modifier { - pub obj: Rc, + pub obj: Rc, pub format: u32, pub modifier: u64, } diff --git a/src/ifs/zwp_primary_selection_device_manager_v1/mod.rs b/src/ifs/zwp_primary_selection_device_manager_v1/mod.rs new file mode 100644 index 00000000..36752253 --- /dev/null +++ b/src/ifs/zwp_primary_selection_device_manager_v1/mod.rs @@ -0,0 +1,109 @@ +mod types; + +use crate::client::Client; +use crate::globals::{Global, GlobalName}; +use crate::ifs::zwp_primary_selection_device_v1::ZwpPrimarySelectionDeviceV1; +use crate::ifs::zwp_primary_selection_source_v1::ZwpPrimarySelectionSourceV1; +use crate::object::{Interface, Object}; +use crate::utils::buffd::MsgParser; +use std::rc::Rc; +pub use types::*; + +const CREATE_SOURCE: u32 = 0; +const GET_DEVICE: u32 = 1; +const DESTROY: u32 = 2; + +id!(ZwpPrimarySelectionDeviceManagerV1Id); + +pub struct ZwpPrimarySelectionDeviceManagerV1Global { + name: GlobalName, +} + +pub struct ZwpPrimarySelectionDeviceManagerV1 { + pub id: ZwpPrimarySelectionDeviceManagerV1Id, + pub client: Rc, + pub version: u32, +} + +impl ZwpPrimarySelectionDeviceManagerV1Global { + pub fn new(name: GlobalName) -> Self { + Self { name } + } + + fn bind_( + self: Rc, + id: ZwpPrimarySelectionDeviceManagerV1Id, + client: &Rc, + version: u32, + ) -> Result<(), ZwpPrimarySelectionDeviceManagerV1Error> { + let obj = Rc::new(ZwpPrimarySelectionDeviceManagerV1 { + id, + client: client.clone(), + version, + }); + client.add_client_obj(&obj)?; + Ok(()) + } +} + +impl ZwpPrimarySelectionDeviceManagerV1 { + fn create_source(&self, parser: MsgParser<'_, '_>) -> Result<(), CreateSourceError> { + let req: CreateSource = self.client.parse(self, parser)?; + let res = Rc::new(ZwpPrimarySelectionSourceV1::new(req.id, &self.client)); + self.client.add_client_obj(&res)?; + Ok(()) + } + + fn get_data_device(self: &Rc, parser: MsgParser<'_, '_>) -> Result<(), GetDeviceError> { + let req: GetDevice = self.client.parse(&**self, parser)?; + let seat = self.client.lookup(req.seat)?; + let dev = Rc::new(ZwpPrimarySelectionDeviceV1::new(req.id, self, &seat)); + seat.add_primary_selection_device(&dev); + self.client.add_client_obj(&dev)?; + Ok(()) + } + + fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> { + let _req: Destroy = self.client.parse(self, parser)?; + self.client.remove_obj(self)?; + Ok(()) + } +} + +bind!(ZwpPrimarySelectionDeviceManagerV1Global); + +impl Global for ZwpPrimarySelectionDeviceManagerV1Global { + fn name(&self) -> GlobalName { + self.name + } + + fn singleton(&self) -> bool { + true + } + + fn interface(&self) -> Interface { + Interface::ZwpPrimarySelectionDeviceManagerV1 + } + + fn version(&self) -> u32 { + 1 + } +} + +simple_add_global!(ZwpPrimarySelectionDeviceManagerV1Global); + +object_base! { + ZwpPrimarySelectionDeviceManagerV1, ZwpPrimarySelectionDeviceManagerV1Error; + + CREATE_SOURCE => create_source, + GET_DEVICE => get_data_device, + DESTROY => destroy, +} + +impl Object for ZwpPrimarySelectionDeviceManagerV1 { + fn num_requests(&self) -> u32 { + DESTROY + 1 + } +} + +simple_add_obj!(ZwpPrimarySelectionDeviceManagerV1); diff --git a/src/ifs/zwp_primary_selection_device_manager_v1/types.rs b/src/ifs/zwp_primary_selection_device_manager_v1/types.rs new file mode 100644 index 00000000..0b8fe58e --- /dev/null +++ b/src/ifs/zwp_primary_selection_device_manager_v1/types.rs @@ -0,0 +1,96 @@ +use crate::client::{ClientError, RequestParser}; +use crate::ifs::wl_seat::WlSeatId; +use crate::ifs::zwp_primary_selection_device_v1::ZwpPrimarySelectionDeviceV1Id; +use crate::ifs::zwp_primary_selection_source_v1::ZwpPrimarySelectionSourceV1Id; +use crate::utils::buffd::{MsgParser, MsgParserError}; +use std::fmt::{Debug, Formatter}; +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum ZwpPrimarySelectionDeviceManagerV1Error { + #[error(transparent)] + ClientError(Box), + #[error("Could not process `destroy` request")] + DestroyError(#[from] DestroyError), + #[error("Could not process `create_source` request")] + CreateSourceError(#[from] CreateSourceError), + #[error("Could not process `get_device` request")] + GetDeviceError(#[from] GetDeviceError), +} +efrom!(ZwpPrimarySelectionDeviceManagerV1Error, ClientError); + +#[derive(Debug, Error)] +pub enum DestroyError { + #[error("Parsing failed")] + ParseFailed(#[source] Box), + #[error(transparent)] + ClientError(Box), +} +efrom!(DestroyError, ParseFailed, MsgParserError); +efrom!(DestroyError, ClientError); + +#[derive(Debug, Error)] +pub enum CreateSourceError { + #[error("Parsing failed")] + ParseFailed(#[source] Box), + #[error(transparent)] + ClientError(Box), +} +efrom!(CreateSourceError, ParseFailed, MsgParserError); +efrom!(CreateSourceError, ClientError); + +#[derive(Debug, Error)] +pub enum GetDeviceError { + #[error("Parsing failed")] + ParseFailed(#[source] Box), + #[error(transparent)] + ClientError(Box), +} +efrom!(GetDeviceError, ParseFailed, MsgParserError); +efrom!(GetDeviceError, ClientError); + +pub(super) struct CreateSource { + pub id: ZwpPrimarySelectionSourceV1Id, +} +impl RequestParser<'_> for CreateSource { + fn parse(parser: &mut MsgParser<'_, '_>) -> Result { + Ok(Self { + id: parser.object()?, + }) + } +} +impl Debug for CreateSource { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "create_source(id: {})", self.id) + } +} + +pub(super) struct GetDevice { + pub id: ZwpPrimarySelectionDeviceV1Id, + pub seat: WlSeatId, +} +impl RequestParser<'_> for GetDevice { + fn parse(parser: &mut MsgParser<'_, '_>) -> Result { + Ok(Self { + id: parser.object()?, + seat: parser.object()?, + }) + } +} +impl Debug for GetDevice { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "get_device(id: {}, seat: {})", self.id, self.seat,) + } +} + +pub(super) struct Destroy; +impl RequestParser<'_> for Destroy { + fn parse(_parser: &mut MsgParser<'_, '_>) -> Result { + Ok(Self) + } +} +impl Debug for Destroy { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "destroy()") + } +} diff --git a/src/ifs/zwp_primary_selection_device_v1/mod.rs b/src/ifs/zwp_primary_selection_device_v1/mod.rs new file mode 100644 index 00000000..fd8d340a --- /dev/null +++ b/src/ifs/zwp_primary_selection_device_v1/mod.rs @@ -0,0 +1,89 @@ +mod types; + +use crate::client::DynEventFormatter; +use crate::ifs::wl_seat::WlSeat; +use crate::ifs::zwp_primary_selection_device_manager_v1::ZwpPrimarySelectionDeviceManagerV1; +use crate::ifs::zwp_primary_selection_offer_v1::ZwpPrimarySelectionOfferV1Id; +use crate::object::Object; +use crate::utils::buffd::MsgParser; +use std::rc::Rc; +pub use types::*; + +const SET_SELECTION: u32 = 0; +const DESTROY: u32 = 1; + +const DATA_OFFER: u32 = 0; +const SELECTION: u32 = 1; + +id!(ZwpPrimarySelectionDeviceV1Id); + +pub struct ZwpPrimarySelectionDeviceV1 { + pub id: ZwpPrimarySelectionDeviceV1Id, + pub manager: Rc, + seat: Rc, +} + +impl ZwpPrimarySelectionDeviceV1 { + pub fn new( + id: ZwpPrimarySelectionDeviceV1Id, + manager: &Rc, + seat: &Rc, + ) -> Self { + Self { + id, + manager: manager.clone(), + seat: seat.clone(), + } + } + + pub fn data_offer(self: &Rc, id: ZwpPrimarySelectionOfferV1Id) -> DynEventFormatter { + Box::new(DataOffer { + obj: self.clone(), + id, + }) + } + + pub fn selection(self: &Rc, id: ZwpPrimarySelectionOfferV1Id) -> DynEventFormatter { + Box::new(Selection { + obj: self.clone(), + id, + }) + } + + fn set_selection(&self, parser: MsgParser<'_, '_>) -> Result<(), SetSelectionError> { + let req: SetSelection = self.manager.client.parse(self, parser)?; + let src = if req.source.is_none() { + None + } else { + Some(self.manager.client.lookup(req.source)?) + }; + self.seat.global.set_primary_selection(src)?; + Ok(()) + } + + fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> { + let _req: Destroy = self.manager.client.parse(self, parser)?; + self.seat.remove_primary_selection_device(self); + self.manager.client.remove_obj(self)?; + Ok(()) + } +} + +object_base! { + ZwpPrimarySelectionDeviceV1, ZwpPrimarySelectionDeviceV1Error; + + SET_SELECTION => set_selection, + DESTROY => destroy, +} + +impl Object for ZwpPrimarySelectionDeviceV1 { + fn num_requests(&self) -> u32 { + DESTROY + 1 + } + + fn break_loops(&self) { + self.seat.remove_primary_selection_device(self); + } +} + +simple_add_obj!(ZwpPrimarySelectionDeviceV1); diff --git a/src/ifs/zwp_primary_selection_device_v1/types.rs b/src/ifs/zwp_primary_selection_device_v1/types.rs new file mode 100644 index 00000000..e37b5f9b --- /dev/null +++ b/src/ifs/zwp_primary_selection_device_v1/types.rs @@ -0,0 +1,117 @@ +use crate::client::{ClientError, EventFormatter, RequestParser}; +use crate::ifs::zwp_primary_selection_device_v1::{ + ZwpPrimarySelectionDeviceV1, DATA_OFFER, SELECTION, +}; +use crate::ifs::zwp_primary_selection_offer_v1::ZwpPrimarySelectionOfferV1Id; +use crate::ifs::zwp_primary_selection_source_v1::{ + ZwpPrimarySelectionSourceV1Error, ZwpPrimarySelectionSourceV1Id, +}; +use crate::object::Object; +use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError}; +use std::fmt::{Debug, Formatter}; +use std::rc::Rc; +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum ZwpPrimarySelectionDeviceV1Error { + #[error(transparent)] + ClientError(Box), + #[error("Could not process `set_selection` request")] + SetSelectionError(#[from] SetSelectionError), + #[error("Could not process `destroy` request")] + DestroyError(#[from] DestroyError), +} +efrom!(ZwpPrimarySelectionDeviceV1Error, ClientError); + +#[derive(Debug, Error)] +pub enum SetSelectionError { + #[error("Parsing failed")] + ParseFailed(#[source] Box), + #[error(transparent)] + ClientError(Box), + #[error(transparent)] + ZwpPrimarySelectionSourceV1Error(Box), +} +efrom!(SetSelectionError, ParseFailed, MsgParserError); +efrom!(SetSelectionError, ClientError); +efrom!(SetSelectionError, ZwpPrimarySelectionSourceV1Error); + +#[derive(Debug, Error)] +pub enum DestroyError { + #[error("Parsing failed")] + ParseFailed(#[source] Box), + #[error(transparent)] + ClientError(Box), +} +efrom!(DestroyError, ParseFailed, MsgParserError); +efrom!(DestroyError, ClientError); + +pub(super) struct SetSelection { + pub source: ZwpPrimarySelectionSourceV1Id, + pub serial: u32, +} +impl RequestParser<'_> for SetSelection { + fn parse(parser: &mut MsgParser<'_, '_>) -> Result { + Ok(Self { + source: parser.object()?, + serial: parser.uint()?, + }) + } +} +impl Debug for SetSelection { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "set_selection(source: {}, serial: {})", + self.source, self.serial, + ) + } +} + +pub(super) struct Destroy; +impl RequestParser<'_> for Destroy { + fn parse(_parser: &mut MsgParser<'_, '_>) -> Result { + Ok(Self) + } +} +impl Debug for Destroy { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "destroy()") + } +} + +pub(super) struct DataOffer { + pub obj: Rc, + pub id: ZwpPrimarySelectionOfferV1Id, +} +impl EventFormatter for DataOffer { + fn format(self: Box, fmt: &mut MsgFormatter<'_>) { + fmt.header(self.obj.id, DATA_OFFER).object(self.id); + } + fn obj(&self) -> &dyn Object { + &*self.obj + } +} +impl Debug for DataOffer { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "data_offer(id: {})", self.id) + } +} + +pub(super) struct Selection { + pub obj: Rc, + pub id: ZwpPrimarySelectionOfferV1Id, +} +impl EventFormatter for Selection { + fn format(self: Box, fmt: &mut MsgFormatter<'_>) { + fmt.header(self.obj.id, SELECTION).object(self.id); + } + fn obj(&self) -> &dyn Object { + &*self.obj + } +} +impl Debug for Selection { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "selection(id: {})", self.id) + } +} diff --git a/src/ifs/zwp_primary_selection_offer_v1/mod.rs b/src/ifs/zwp_primary_selection_offer_v1/mod.rs new file mode 100644 index 00000000..c818085f --- /dev/null +++ b/src/ifs/zwp_primary_selection_offer_v1/mod.rs @@ -0,0 +1,103 @@ +mod types; + +use crate::client::{Client, DynEventFormatter}; +use crate::ifs::wl_seat::WlSeatGlobal; +use crate::ifs::zwp_primary_selection_source_v1::ZwpPrimarySelectionSourceV1; +use crate::object::Object; +use crate::utils::buffd::MsgParser; +use crate::utils::clonecell::CloneCell; +use std::ops::Deref; +use std::rc::Rc; +pub use types::*; + +const RECEIVE: u32 = 0; +const DESTROY: u32 = 1; + +const OFFER: u32 = 0; + +id!(ZwpPrimarySelectionOfferV1Id); + +pub struct ZwpPrimarySelectionOfferV1 { + pub id: ZwpPrimarySelectionOfferV1Id, + pub client: Rc, + pub source: CloneCell>>, +} + +impl ZwpPrimarySelectionOfferV1 { + pub fn create( + client: &Rc, + src: &Rc, + seat: &Rc, + ) -> Option> { + let id = match client.new_id() { + Ok(id) => id, + Err(e) => { + client.error(e); + return None; + } + }; + let slf = Rc::new(Self { + id, + client: client.clone(), + source: CloneCell::new(Some(src.clone())), + }); + let mt = src.mime_types.borrow_mut(); + seat.for_each_primary_selection_device(0, client.id, |device| { + client.event(device.data_offer(slf.id)); + for mt in mt.deref() { + client.event(slf.offer(mt)); + } + client.event(device.selection(id)); + }); + client.add_server_obj(&slf); + Some(slf) + } + + pub fn offer(self: &Rc, mime_type: &str) -> DynEventFormatter { + Box::new(Offer { + obj: self.clone(), + mime_type: mime_type.to_string(), + }) + } + + fn receive(&self, parser: MsgParser<'_, '_>) -> Result<(), ReceiveError> { + let req: Receive = self.client.parse(self, parser)?; + if let Some(src) = self.source.get() { + src.client.event(src.send(req.mime_type, req.fd)); + src.client.flush(); + } + Ok(()) + } + + fn disconnect(&self) { + if let Some(src) = self.source.set(None) { + src.clear_offer(); + } + } + + fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> { + let _req: Destroy = self.client.parse(self, parser)?; + self.disconnect(); + self.client.remove_obj(self)?; + Ok(()) + } +} + +object_base! { + ZwpPrimarySelectionOfferV1, ZwpPrimarySelectionOfferV1Error; + + RECEIVE => receive, + DESTROY => destroy, +} + +impl Object for ZwpPrimarySelectionOfferV1 { + fn num_requests(&self) -> u32 { + DESTROY + 1 + } + + fn break_loops(&self) { + self.disconnect(); + } +} + +simple_add_obj!(ZwpPrimarySelectionOfferV1); diff --git a/src/ifs/zwp_primary_selection_offer_v1/types.rs b/src/ifs/zwp_primary_selection_offer_v1/types.rs new file mode 100644 index 00000000..7d204997 --- /dev/null +++ b/src/ifs/zwp_primary_selection_offer_v1/types.rs @@ -0,0 +1,92 @@ +use crate::client::{ClientError, EventFormatter, RequestParser}; +use crate::ifs::zwp_primary_selection_offer_v1::{ZwpPrimarySelectionOfferV1, OFFER}; +use crate::object::Object; +use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError}; +use std::fmt::{Debug, Formatter}; +use std::rc::Rc; +use thiserror::Error; +use uapi::OwnedFd; + +#[derive(Debug, Error)] +pub enum ZwpPrimarySelectionOfferV1Error { + #[error(transparent)] + ClientError(Box), + #[error("Could not process `receive` request")] + ReceiveError(#[from] ReceiveError), + #[error("Could not process `destroy` request")] + DestroyError(#[from] DestroyError), +} +efrom!(ZwpPrimarySelectionOfferV1Error, ClientError); + +#[derive(Debug, Error)] +pub enum ReceiveError { + #[error("Parsing failed")] + ParseFailed(#[source] Box), + #[error(transparent)] + ClientError(Box), +} +efrom!(ReceiveError, ParseFailed, MsgParserError); +efrom!(ReceiveError, ClientError); + +#[derive(Debug, Error)] +pub enum DestroyError { + #[error("Parsing failed")] + ParseFailed(#[source] Box), + #[error(transparent)] + ClientError(Box), +} +efrom!(DestroyError, ParseFailed, MsgParserError); +efrom!(DestroyError, ClientError); + +pub(super) struct Receive<'a> { + pub mime_type: &'a str, + pub fd: OwnedFd, +} +impl<'a> RequestParser<'a> for Receive<'a> { + fn parse(parser: &mut MsgParser<'_, 'a>) -> Result { + Ok(Self { + mime_type: parser.str()?, + fd: parser.fd()?, + }) + } +} +impl Debug for Receive<'_> { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "receive(mime_type: {:?}, fd: {})", + self.mime_type, + self.fd.raw() + ) + } +} + +pub(super) struct Destroy; +impl RequestParser<'_> for Destroy { + fn parse(_parser: &mut MsgParser<'_, '_>) -> Result { + Ok(Self) + } +} +impl Debug for Destroy { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "destroy()") + } +} + +pub(super) struct Offer { + pub obj: Rc, + pub mime_type: String, +} +impl EventFormatter for Offer { + fn format(self: Box, fmt: &mut MsgFormatter<'_>) { + fmt.header(self.obj.id, OFFER).string(&self.mime_type); + } + fn obj(&self) -> &dyn Object { + &*self.obj + } +} +impl Debug for Offer { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "offer(mime_type: {:?})", self.mime_type) + } +} diff --git a/src/ifs/zwp_primary_selection_source_v1/mod.rs b/src/ifs/zwp_primary_selection_source_v1/mod.rs new file mode 100644 index 00000000..982fe507 --- /dev/null +++ b/src/ifs/zwp_primary_selection_source_v1/mod.rs @@ -0,0 +1,142 @@ +mod types; + +use crate::client::{Client, DynEventFormatter}; +use crate::ifs::wl_seat::WlSeatGlobal; +use crate::ifs::zwp_primary_selection_offer_v1::ZwpPrimarySelectionOfferV1; +use crate::object::Object; +use crate::utils::buffd::MsgParser; +use crate::utils::clonecell::CloneCell; +use ahash::AHashSet; +use std::cell::RefCell; +use std::rc::Rc; +pub use types::*; +use uapi::OwnedFd; + +const OFFER: u32 = 0; +const DESTROY: u32 = 1; + +const SEND: u32 = 0; +const CANCELLED: u32 = 1; + +id!(ZwpPrimarySelectionSourceV1Id); + +pub struct ZwpPrimarySelectionSourceV1 { + pub id: ZwpPrimarySelectionSourceV1Id, + pub client: Rc, + pub mime_types: RefCell>, + seat: CloneCell>>, + offer: CloneCell>>, +} + +impl ZwpPrimarySelectionSourceV1 { + pub fn new(id: ZwpPrimarySelectionSourceV1Id, client: &Rc) -> Self { + Self { + id, + client: client.clone(), + mime_types: RefCell::new(Default::default()), + seat: Default::default(), + offer: Default::default(), + } + } + + pub fn attach(&self, seat: &Rc) -> Result<(), ZwpPrimarySelectionSourceV1Error> { + if self.seat.get().is_some() { + return Err(ZwpPrimarySelectionSourceV1Error::AlreadyAttached); + } + self.seat.set(Some(seat.clone())); + Ok(()) + } + + pub fn detach(self: &Rc) { + self.seat.set(None); + if let Some(offer) = self.offer.set(None) { + offer.source.set(None); + } + self.client.event(self.cancelled()); + self.client.flush(); + } + + pub fn create_offer(self: &Rc, client: &Rc) { + let seat = match self.seat.get() { + Some(a) => a, + _ => { + log::error!("Trying to create an offer from a unattached data source"); + return; + } + }; + let offer = ZwpPrimarySelectionOfferV1::create(client, self, &seat); + let old = self.offer.set(offer); + if let Some(offer) = old { + offer.source.set(None); + } + } + + pub fn clear_offer(&self) { + self.offer.take(); + } + + pub fn cancelled(self: &Rc) -> DynEventFormatter { + Box::new(Cancelled { obj: self.clone() }) + } + + pub fn send(self: &Rc, mime_type: &str, fd: OwnedFd) -> DynEventFormatter { + Box::new(Send { + obj: self.clone(), + mime_type: mime_type.to_string(), + fd: Rc::new(fd), + }) + } + + fn offer(&self, parser: MsgParser<'_, '_>) -> Result<(), OfferError> { + let req: Offer = self.client.parse(self, parser)?; + if self + .mime_types + .borrow_mut() + .insert(req.mime_type.to_string()) + { + if let Some(offer) = self.offer.get() { + offer.client.event(offer.offer(req.mime_type)); + } + } + Ok(()) + } + + fn disconnect(&self) { + if let Some(offer) = self.offer.take() { + offer.source.set(None); + } + if let Some(seat) = self.seat.get() { + let _ = seat.set_primary_selection(None); + } + } + + fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> { + let _req: Destroy = self.client.parse(self, parser)?; + self.disconnect(); + self.client.remove_obj(self)?; + Ok(()) + } +} + +object_base! { + ZwpPrimarySelectionSourceV1, ZwpPrimarySelectionSourceV1Error; + + OFFER => offer, + DESTROY => destroy, +} + +impl Object for ZwpPrimarySelectionSourceV1 { + fn num_requests(&self) -> u32 { + DESTROY + 1 + } + + fn break_loops(&self) { + self.disconnect(); + } +} + +dedicated_add_obj!( + ZwpPrimarySelectionSourceV1, + ZwpPrimarySelectionSourceV1Id, + zwp_primary_selection_source +); diff --git a/src/ifs/zwp_primary_selection_source_v1/types.rs b/src/ifs/zwp_primary_selection_source_v1/types.rs new file mode 100644 index 00000000..250b9e8d --- /dev/null +++ b/src/ifs/zwp_primary_selection_source_v1/types.rs @@ -0,0 +1,112 @@ +use crate::client::{ClientError, EventFormatter, RequestParser}; +use crate::ifs::zwp_primary_selection_source_v1::{ZwpPrimarySelectionSourceV1, CANCELLED, SEND}; +use crate::object::Object; +use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError}; +use std::fmt::{Debug, Formatter}; +use std::rc::Rc; +use thiserror::Error; +use uapi::OwnedFd; + +#[derive(Debug, Error)] +pub enum ZwpPrimarySelectionSourceV1Error { + #[error(transparent)] + ClientError(Box), + #[error("Could not process `offer` request")] + OfferError(#[from] OfferError), + #[error("Could not process `destroy` request")] + DestroyError(#[from] DestroyError), + #[error("The data source is already attached")] + AlreadyAttached, +} +efrom!(ZwpPrimarySelectionSourceV1Error, ClientError); + +#[derive(Debug, Error)] +pub enum OfferError { + #[error("Parsing failed")] + ParseFailed(#[source] Box), + #[error(transparent)] + ClientError(Box), +} +efrom!(OfferError, ParseFailed, MsgParserError); +efrom!(OfferError, ClientError); + +#[derive(Debug, Error)] +pub enum DestroyError { + #[error("Parsing failed")] + ParseFailed(#[source] Box), + #[error(transparent)] + ClientError(Box), +} +efrom!(DestroyError, ParseFailed, MsgParserError); +efrom!(DestroyError, ClientError); + +pub(super) struct Offer<'a> { + pub mime_type: &'a str, +} +impl<'a> RequestParser<'a> for Offer<'a> { + fn parse(parser: &mut MsgParser<'_, 'a>) -> Result { + Ok(Self { + mime_type: parser.str()?, + }) + } +} +impl Debug for Offer<'_> { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "offer(mime_type: {:?})", self.mime_type) + } +} + +pub(super) struct Destroy; +impl RequestParser<'_> for Destroy { + fn parse(_parser: &mut MsgParser<'_, '_>) -> Result { + Ok(Self) + } +} +impl Debug for Destroy { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "destroy()",) + } +} + +pub(super) struct Send { + pub obj: Rc, + pub mime_type: String, + pub fd: Rc, +} +impl EventFormatter for Send { + fn format(self: Box, fmt: &mut MsgFormatter<'_>) { + fmt.header(self.obj.id, SEND) + .string(&self.mime_type) + .fd(self.fd); + } + fn obj(&self) -> &dyn Object { + &*self.obj + } +} +impl Debug for Send { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "send(mime_type: {:?}, fd: {})", + self.mime_type, + self.fd.raw() + ) + } +} + +pub(super) struct Cancelled { + pub obj: Rc, +} +impl EventFormatter for Cancelled { + fn format(self: Box, fmt: &mut MsgFormatter<'_>) { + fmt.header(self.obj.id, CANCELLED); + } + fn obj(&self) -> &dyn Object { + &*self.obj + } +} +impl Debug for Cancelled { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "cancelled()") + } +} diff --git a/src/ifs/zxdg_decoration_manager_v1/mod.rs b/src/ifs/zxdg_decoration_manager_v1/mod.rs index 498563ad..91fd4b59 100644 --- a/src/ifs/zxdg_decoration_manager_v1/mod.rs +++ b/src/ifs/zxdg_decoration_manager_v1/mod.rs @@ -1,7 +1,7 @@ use crate::client::Client; use crate::globals::{Global, GlobalName}; use crate::ifs::zxdg_toplevel_decoration_v1::ZxdgToplevelDecorationV1; -use crate::object::{Interface, Object, ObjectId}; +use crate::object::{Interface, Object}; use crate::utils::buffd::MsgParser; use std::rc::Rc; pub use types::*; @@ -27,7 +27,7 @@ impl ZxdgDecorationManagerV1Global { client: &Rc, version: u32, ) -> Result<(), ZxdgDecorationManagerV1Error> { - let obj = Rc::new(ZxdgDecorationManagerV1Obj { + let obj = Rc::new(ZxdgDecorationManagerV1 { id, client: client.clone(), _version: version, @@ -57,13 +57,15 @@ impl Global for ZxdgDecorationManagerV1Global { } } -pub struct ZxdgDecorationManagerV1Obj { +simple_add_global!(ZxdgDecorationManagerV1Global); + +pub struct ZxdgDecorationManagerV1 { id: ZxdgDecorationManagerV1Id, client: Rc, _version: u32, } -impl ZxdgDecorationManagerV1Obj { +impl ZxdgDecorationManagerV1 { fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> { let _req: Destroy = self.client.parse(self, parser)?; self.client.remove_obj(self)?; @@ -75,39 +77,25 @@ impl ZxdgDecorationManagerV1Obj { parser: MsgParser<'_, '_>, ) -> Result<(), GetToplevelDecorationError> { let req: GetToplevelDecoration = self.client.parse(self, parser)?; - let tl = self.client.get_xdg_toplevel(req.toplevel)?; + let tl = self.client.lookup(req.toplevel)?; let obj = Rc::new(ZxdgToplevelDecorationV1::new(req.id, &self.client, &tl)); self.client.add_client_obj(&obj)?; obj.send_configure(); Ok(()) } - - fn handle_request_( - self: &Rc, - request: u32, - parser: MsgParser<'_, '_>, - ) -> Result<(), ZxdgDecorationManagerV1Error> { - match request { - DESTROY => self.destroy(parser)?, - GET_TOPLEVEL_DECORATION => self.get_toplevel_decoration(parser)?, - _ => unreachable!(), - } - Ok(()) - } } -handle_request!(ZxdgDecorationManagerV1Obj); +object_base! { + ZxdgDecorationManagerV1, ZxdgDecorationManagerV1Error; -impl Object for ZxdgDecorationManagerV1Obj { - fn id(&self) -> ObjectId { - self.id.into() - } - - fn interface(&self) -> Interface { - Interface::ZxdgDecorationManagerV1 - } + DESTROY => destroy, + GET_TOPLEVEL_DECORATION => get_toplevel_decoration, +} +impl Object for ZxdgDecorationManagerV1 { fn num_requests(&self) -> u32 { GET_TOPLEVEL_DECORATION + 1 } } + +simple_add_obj!(ZxdgDecorationManagerV1); diff --git a/src/ifs/zxdg_toplevel_decoration_v1/mod.rs b/src/ifs/zxdg_toplevel_decoration_v1/mod.rs index 829edbea..cde85696 100644 --- a/src/ifs/zxdg_toplevel_decoration_v1/mod.rs +++ b/src/ifs/zxdg_toplevel_decoration_v1/mod.rs @@ -2,7 +2,7 @@ mod types; use crate::client::{Client, DynEventFormatter}; use crate::ifs::wl_surface::xdg_surface::xdg_toplevel::{Decoration, XdgToplevel}; -use crate::object::{Interface, Object, ObjectId}; +use crate::object::Object; use crate::utils::buffd::MsgParser; use std::rc::Rc; pub use types::*; @@ -70,34 +70,20 @@ impl ZxdgToplevelDecorationV1 { self.send_configure(); Ok(()) } - - fn handle_request_( - self: &Rc, - request: u32, - parser: MsgParser<'_, '_>, - ) -> Result<(), ZxdgToplevelDecorationV1Error> { - match request { - DESTROY => self.destroy(parser)?, - SET_MODE => self.set_mode(parser)?, - UNSET_MODE => self.unset_mode(parser)?, - _ => unreachable!(), - } - Ok(()) - } } -handle_request!(ZxdgToplevelDecorationV1); +object_base! { + ZxdgToplevelDecorationV1, ZxdgToplevelDecorationV1Error; + + DESTROY => destroy, + SET_MODE => set_mode, + UNSET_MODE => unset_mode, +} impl Object for ZxdgToplevelDecorationV1 { - fn id(&self) -> ObjectId { - self.id.into() - } - - fn interface(&self) -> Interface { - Interface::ZxdgToplevelDecorationV1 - } - fn num_requests(&self) -> u32 { UNSET_MODE + 1 } } + +simple_add_obj!(ZxdgToplevelDecorationV1); diff --git a/src/macros.rs b/src/macros.rs index 83ec8843..2edbead6 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -11,21 +11,14 @@ macro_rules! efrom { }; } -macro_rules! handle_request { - ($oname:ty) => { - impl crate::object::ObjectHandleRequest for $oname { - fn handle_request( - self: std::rc::Rc, - request: u32, - parser: crate::utils::buffd::MsgParser<'_, '_>, - ) -> Result<(), crate::client::ClientError> { - self.handle_request_(request, parser)?; - Ok(()) +macro_rules! object_base { + ($oname:ident, $ename:ty; $($code:ident => $f:ident,)*) => { + impl crate::object::ObjectBase for $oname { + fn id(&self) -> crate::object::ObjectId { + self.id.into() } - } - }; - ($oname:ty, $ename:ty; $($code:ident => $f:ident,)*) => { - impl crate::object::ObjectHandleRequest for $oname { + + #[allow(unused_variables, unreachable_code)] fn handle_request( self: std::rc::Rc, request: u32, @@ -44,9 +37,24 @@ macro_rules! handle_request { } Ok(()) } - handle_request(self, request, parser)?; + if let Err(e) = handle_request(self, request, parser) { + return Err(crate::client::ClientError::ObjectError(e.into())); + } Ok(()) } + + fn interface(&self) -> crate::object::Interface { + crate::object::Interface::$oname + } + } + + impl From<$ename> for crate::client::ObjectError { + fn from(v: $ename) -> Self { + Self { + interface: crate::object::Interface::$oname, + error: Box::new(v), + } + } } }; } @@ -59,7 +67,7 @@ macro_rules! bind { client: &'a std::rc::Rc, id: crate::object::ObjectId, version: u32, - ) -> Result<(), crate::globals::GlobalError> { + ) -> Result<(), crate::globals::GlobalsError> { self.bind_(id.into(), client, version)?; Ok(()) } @@ -235,3 +243,50 @@ macro_rules! tree_id { } }; } + +macro_rules! dedicated_add_obj { + ($oname:ident, $idname:ident, $field:ident) => { + impl crate::client::WaylandObject for $oname { + fn add(self: Rc, client: &crate::client::Client) { + client.objects.$field.set(self.id.into(), self); + } + fn remove(&self, client: &crate::client::Client) { + client.objects.$field.remove(&self.id.into()); + } + } + + impl crate::client::WaylandObjectLookup for $idname { + type Object = $oname; + const INTERFACE: crate::object::Interface = crate::object::Interface::$oname; + + fn lookup(client: &crate::client::Client, id: Self) -> Option> { + client.objects.$field.get(&id) + } + } + }; +} + +macro_rules! simple_add_obj { + ($ty:ty) => { + impl crate::client::WaylandObject for $ty {} + }; +} + +macro_rules! simple_add_global { + ($ty:ty) => { + impl crate::globals::WaylandGlobal for $ty {} + }; +} + +macro_rules! dedicated_add_global { + ($oname:ident, $field:ident) => { + impl crate::globals::WaylandGlobal for $oname { + fn add(self: Rc, globals: &crate::globals::Globals) { + globals.$field.set(self.name(), self); + } + fn remove(&self, globals: &crate::globals::Globals) { + globals.$field.remove(&self.name()); + } + } + }; +} diff --git a/src/object.rs b/src/object.rs index e5c77dc5..b697ab96 100644 --- a/src/object.rs +++ b/src/object.rs @@ -24,17 +24,17 @@ impl Display for ObjectId { } } -pub trait ObjectHandleRequest { +pub trait ObjectBase { + fn id(&self) -> ObjectId; fn handle_request( self: Rc, request: u32, parser: MsgParser<'_, '_>, ) -> Result<(), ClientError>; + fn interface(&self) -> Interface; } -pub trait Object: ObjectHandleRequest + 'static { - fn id(&self) -> ObjectId; - fn interface(&self) -> Interface; +pub trait Object: ObjectBase + 'static { fn num_requests(&self) -> u32; fn break_loops(&self) {} } @@ -73,6 +73,10 @@ pub enum Interface { ZxdgToplevelDecorationV1, OrgKdeKwinServerDecorationManager, OrgKdeKwinServerDecoration, + ZwpPrimarySelectionDeviceManagerV1, + ZwpPrimarySelectionDeviceV1, + ZwpPrimarySelectionSourceV1, + ZwpPrimarySelectionOfferV1, } impl Interface { @@ -112,6 +116,12 @@ impl Interface { "org_kde_kwin_server_decoration_manager" } Interface::OrgKdeKwinServerDecoration => "org_kde_kwin_server_decoration", + Interface::ZwpPrimarySelectionDeviceManagerV1 => { + "zwp_primary_selection_device_manager_v1" + } + Interface::ZwpPrimarySelectionDeviceV1 => "zwp_primary_selection_device_v1", + Interface::ZwpPrimarySelectionSourceV1 => "zwp_primary_selection_source_v1", + Interface::ZwpPrimarySelectionOfferV1 => "zwp_primary_selection_offer_v1", } } } diff --git a/src/sighand.rs b/src/sighand.rs index b32031be..fd763d3f 100644 --- a/src/sighand.rs +++ b/src/sighand.rs @@ -47,7 +47,7 @@ struct Sighand { } impl EventLoopDispatcher for Sighand { - fn dispatch(self: Rc, events: i32) -> Result<(), Box> { + fn dispatch(self: Rc, events: i32) -> Result<(), Box> { if events & (c::EPOLLERR | c::EPOLLHUP) != 0 { return Err(Box::new(SighandError::ErrorEvent)); } diff --git a/src/state.rs b/src/state.rs index 428ee862..257816fb 100644 --- a/src/state.rs +++ b/src/state.rs @@ -3,7 +3,7 @@ use crate::backend::{BackendEvent, OutputId, OutputIds, SeatId, SeatIds}; use crate::client::{Client, Clients}; use crate::cursor::ServerCursors; use crate::event_loop::EventLoop; -use crate::globals::{AddGlobal, Globals}; +use crate::globals::{GlobalsError, Globals, WaylandGlobal}; use crate::ifs::wl_output::WlOutputGlobal; use crate::ifs::wl_seat::WlSeatGlobal; use crate::ifs::wl_surface::NoneSurfaceExt; @@ -61,13 +61,14 @@ impl State { self.render_ctx.set(Some(ctx.clone())); } - pub fn add_global(&self, global: &Rc) - where - Globals: AddGlobal, - { + pub fn add_global(&self, global: &Rc) { self.globals.add_global(self, global) } + pub fn remove_global(&self, global: &T) -> Result<(), GlobalsError> { + self.globals.remove(self, global) + } + pub fn tree_changed(&self) { if self.tree_changed_sent.replace(true) { return; diff --git a/src/tasks/output.rs b/src/tasks/output.rs index 8a515b57..a3939381 100644 --- a/src/tasks/output.rs +++ b/src/tasks/output.rs @@ -60,7 +60,7 @@ impl OutputHandler { ae.triggered().await; } self.state.outputs.remove(&self.output.id()); - let _ = self.state.globals.remove(&self.state, name); + let _ = self.state.remove_global(&*global); self.state .output_handlers .borrow_mut() diff --git a/src/tasks/seat.rs b/src/tasks/seat.rs index 02eecbc5..ba0ab712 100644 --- a/src/tasks/seat.rs +++ b/src/tasks/seat.rs @@ -46,7 +46,7 @@ impl SeatHandler { ae.triggered().await; } global.set_cursor(None); - let _ = self.state.globals.remove(&self.state, name); + let _ = self.state.remove_global(&*global); self.state.seats.borrow_mut().remove(&self.seat.id()); } } diff --git a/src/wheel.rs b/src/wheel.rs index eadd2a47..9fe6cab4 100644 --- a/src/wheel.rs +++ b/src/wheel.rs @@ -28,7 +28,7 @@ pub enum WheelError { } pub trait WheelDispatcher { - fn dispatch(self: Rc) -> Result<(), Box>; + fn dispatch(self: Rc) -> Result<(), Box>; } #[derive(Debug, Eq, PartialEq, Ord, PartialOrd)] @@ -172,10 +172,7 @@ struct WheelWrapper { } impl EventLoopDispatcher for WheelWrapper { - fn dispatch( - self: Rc, - events: i32, - ) -> Result<(), Box> { + fn dispatch(self: Rc, events: i32) -> Result<(), Box> { if events & (c::EPOLLERR | c::EPOLLHUP) != 0 { return Err(Box::new(WheelError::ErrorEvent)); } @@ -241,7 +238,7 @@ struct PeriodicDispatcher { } impl EventLoopDispatcher for PeriodicDispatcher { - fn dispatch(self: Rc, events: i32) -> Result<(), Box> { + fn dispatch(self: Rc, events: i32) -> Result<(), Box> { if events & (c::EPOLLERR | c::EPOLLHUP) != 0 { return Err(Box::new(WheelError::ErrorEvent)); } diff --git a/todo.md b/todo.md index 809b5da9..151939e8 100644 --- a/todo.md +++ b/todo.md @@ -10,7 +10,6 @@ - Float moving - Highlighting active - dnd -- clipboard - primary selection - presentation time - viewporter @@ -19,3 +18,4 @@ # done - Container resizing +- clipboard