From cbbc41a463e437bc8c0995c30db07d600a433997 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Tue, 4 Jan 2022 15:30:21 +0100 Subject: [PATCH] autocommit 2022-01-04 15:30:21 CET --- Cargo.lock | 21 ++++ Cargo.toml | 1 + src/client/mod.rs | 48 +++++--- src/client/objects.rs | 44 +++---- src/format.rs | 3 + src/ifs/mod.rs | 3 + src/ifs/wl_buffer/mod.rs | 91 ++++++++++++++ src/ifs/wl_buffer/types.rs | 56 +++++++++ src/ifs/wl_callback/mod.rs | 8 +- src/ifs/wl_compositor/mod.rs | 8 +- src/ifs/wl_compositor/types.rs | 7 +- src/ifs/wl_display/mod.rs | 2 +- src/ifs/wl_display/types.rs | 6 +- src/ifs/wl_output/mod.rs | 1 + src/ifs/wl_region/mod.rs | 8 +- src/ifs/wl_registry/mod.rs | 8 +- src/ifs/wl_seat/mod.rs | 1 + src/ifs/wl_shm/mod.rs | 8 +- src/ifs/wl_shm/types.rs | 6 +- src/ifs/wl_shm_pool/mod.rs | 28 ++++- src/ifs/wl_shm_pool/types.rs | 11 +- src/ifs/wl_subcompositor/mod.rs | 8 +- src/ifs/wl_subcompositor/types.rs | 10 +- src/ifs/wl_surface/mod.rs | 95 ++++++++++++--- src/ifs/wl_surface/types.rs | 11 +- src/ifs/wl_surface/wl_subsurface/mod.rs | 14 ++- src/ifs/wl_surface/wl_subsurface/types.rs | 31 +++-- src/ifs/wl_surface/xdg_surface/mod.rs | 114 ++++++++++++++++-- src/ifs/wl_surface/xdg_surface/types.rs | 31 +++-- .../wl_surface/xdg_surface/xdg_popup/mod.rs | 25 +++- .../wl_surface/xdg_surface/xdg_popup/types.rs | 8 +- .../xdg_surface/xdg_toplevel/mod.rs | 15 ++- .../xdg_surface/xdg_toplevel/types.rs | 70 ++++++++--- src/ifs/xdg_positioner/mod.rs | 8 +- src/ifs/xdg_wm_base/mod.rs | 25 ++-- src/ifs/xdg_wm_base/types.rs | 12 +- src/macros.rs | 48 +++++++- src/object.rs | 5 + src/utils/buffd/formatter.rs | 8 +- src/utils/buffd/parser.rs | 7 +- 40 files changed, 725 insertions(+), 189 deletions(-) create mode 100644 src/ifs/wl_buffer/mod.rs create mode 100644 src/ifs/wl_buffer/types.rs create mode 100644 src/ifs/wl_output/mod.rs create mode 100644 src/ifs/wl_seat/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 3d33a90f..491f4442 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -212,6 +212,7 @@ dependencies = [ "thiserror", "uapi", "waker-fn", + "xcb-dl", ] [[package]] @@ -226,6 +227,16 @@ version = "0.2.112" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" +[[package]] +name = "libloading" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afe203d669ec979b7128619bae5a63b7b42e9203c1b29146079ee05e2f604b52" +dependencies = [ + "cfg-if 1.0.0", + "winapi", +] + [[package]] name = "log" version = "0.4.14" @@ -440,3 +451,13 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "xcb-dl" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ce37e57249f12cbdf43844a3c9b3162f528ec27a1dc1dd7c6f46826063f51e8" +dependencies = [ + "libc", + "libloading", +] diff --git a/Cargo.toml b/Cargo.toml index 50a94f78..336f0cbe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,3 +23,4 @@ waker-fn = "1.1.0" num-traits = "0.2.14" num-derive = "0.3.3" bitflags = "1.3.2" +xcb-dl = "0.2.0" diff --git a/src/client/mod.rs b/src/client/mod.rs index d9a2304b..bc2e5226 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -3,16 +3,16 @@ use crate::client::objects::Objects; use crate::ifs::wl_callback::WlCallback; use crate::ifs::wl_compositor::{WlCompositorError, WlCompositorObj}; use crate::ifs::wl_display::{WlDisplay, WlDisplayError}; -use crate::ifs::wl_region::{WlRegion, WlRegionError}; -use crate::ifs::wl_registry::{WlRegistry, WlRegistryError}; +use crate::ifs::wl_region::{WlRegion, WlRegionError, WlRegionId}; +use crate::ifs::wl_registry::{WlRegistry, WlRegistryError, WlRegistryId}; use crate::ifs::wl_shm::{WlShmError, WlShmObj}; use crate::ifs::wl_shm_pool::{WlShmPool, WlShmPoolError}; use crate::ifs::wl_subcompositor::{WlSubcompositorError, WlSubcompositorObj}; use crate::ifs::wl_surface::wl_subsurface::{WlSubsurface, WlSubsurfaceError}; -use crate::ifs::wl_surface::xdg_surface::xdg_popup::XdgPopupError; -use crate::ifs::wl_surface::xdg_surface::xdg_toplevel::XdgToplevelError; -use crate::ifs::wl_surface::xdg_surface::{XdgSurface, XdgSurfaceError}; -use crate::ifs::wl_surface::{WlSurface, WlSurfaceError}; +use crate::ifs::wl_surface::xdg_surface::xdg_popup::{XdgPopup, XdgPopupError}; +use crate::ifs::wl_surface::xdg_surface::xdg_toplevel::{XdgToplevel, XdgToplevelError}; +use crate::ifs::wl_surface::xdg_surface::{XdgSurface, XdgSurfaceError, XdgSurfaceId}; +use crate::ifs::wl_surface::{WlSurface, WlSurfaceError, WlSurfaceId}; use crate::ifs::xdg_positioner::{XdgPositioner, XdgPositionerError}; use crate::ifs::xdg_wm_base::{XdgWmBaseError, XdgWmBaseObj}; use crate::object::{Object, ObjectId, WL_DISPLAY_ID}; @@ -30,6 +30,7 @@ use std::mem; use std::rc::Rc; use thiserror::Error; use uapi::OwnedFd; +use crate::ifs::wl_buffer::{WlBuffer, WlBufferError}; mod objects; mod tasks; @@ -54,10 +55,12 @@ pub enum ClientError { OutBufferOverflow, #[error("The requested client {0} does not exist")] ClientDoesNotExist(ClientId), - #[error("There is no region with id {0}")] - RegionDoesNotExist(ObjectId), - #[error("There is no surface with id {0}")] - SurfaceDoesNotExist(ObjectId), + #[error("There is no wl_region with id {0}")] + RegionDoesNotExist(WlRegionId), + #[error("There is no wl_surface with id {0}")] + SurfaceDoesNotExist(WlSurfaceId), + #[error("There is no xdg_surface with id {0}")] + XdgSurfaceDoesNotExist(XdgSurfaceId), #[error("Cannot parse the message")] ParserError(#[source] Box), #[error("Server tried to allocate more than 0x1_00_00_00 ids")] @@ -100,6 +103,8 @@ pub enum ClientError { 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("Object {0} is not a display")] NotADisplay(ObjectId), } @@ -119,6 +124,7 @@ efrom!(ClientError, XdgPositionerError, XdgPositionerError); efrom!(ClientError, XdgWmBaseError, XdgWmBaseError); efrom!(ClientError, XdgToplevelError, XdgToplevelError); efrom!(ClientError, XdgPopupError, XdgPopupError); +efrom!(ClientError, WlBufferError, WlBufferError); impl ClientError { fn peer_closed(&self) -> bool { @@ -353,20 +359,27 @@ impl Client { Ok(()) } - pub fn get_region(&self, id: ObjectId) -> Result, ClientError> { + 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: ObjectId) -> Result, ClientError> { + 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)), + } + } + fn simple_add_obj(&self, obj: &Rc, client: bool) -> Result<(), ClientError> { if client { self.objects.add_client_object(obj.clone()) @@ -383,7 +396,7 @@ impl Client { self.objects.remove_obj(self, id) } - pub fn lock_registries(&self) -> RefMut>> { + pub fn lock_registries(&self) -> RefMut>> { self.objects.registries() } @@ -438,7 +451,9 @@ simple_add_obj!(WlShmPool); simple_add_obj!(WlSubcompositorObj); simple_add_obj!(WlSubsurface); simple_add_obj!(XdgPositioner); -simple_add_obj!(XdgSurface); +simple_add_obj!(XdgToplevel); +simple_add_obj!(XdgPopup); +simple_add_obj!(WlBuffer); macro_rules! dedicated_add_obj { ($ty:ty, $field:ident) => { @@ -447,11 +462,11 @@ macro_rules! dedicated_add_obj { fn add_obj(&self, obj: &Rc<$ty>, client: bool) -> Result<(), ClientError> { self.simple_add_obj(obj, client)?; - self.objects.$field.set(obj.id(), obj.clone()); + self.objects.$field.set(obj.id().into(), obj.clone()); Ok(()) } fn remove_obj<'a>(&'a self, obj: &'a $ty) -> Self::RemoveObj<'a> { - self.objects.$field.remove(&obj.id()); + self.objects.$field.remove(&obj.id().into()); self.simple_remove_obj(obj.id()) } } @@ -461,3 +476,4 @@ macro_rules! dedicated_add_obj { dedicated_add_obj!(WlRegion, regions); dedicated_add_obj!(WlSurface, surfaces); dedicated_add_obj!(XdgWmBaseObj, xdg_wm_bases); +dedicated_add_obj!(XdgSurface, xdg_surfaces); diff --git a/src/client/objects.rs b/src/client/objects.rs index b7a31153..9e27f8a2 100644 --- a/src/client/objects.rs +++ b/src/client/objects.rs @@ -1,23 +1,25 @@ use crate::client::{Client, ClientError}; use crate::ifs::wl_display::WlDisplay; -use crate::ifs::wl_region::WlRegion; -use crate::ifs::wl_registry::WlRegistry; -use crate::ifs::wl_surface::WlSurface; +use crate::ifs::wl_region::{WlRegion, WlRegionId}; +use crate::ifs::wl_registry::{WlRegistry, WlRegistryId}; +use crate::ifs::wl_surface::xdg_surface::{XdgSurface, XdgSurfaceId}; +use crate::ifs::wl_surface::{WlSurface, WlSurfaceId}; +use crate::ifs::xdg_wm_base::{XdgWmBaseId, XdgWmBaseObj}; use crate::object::{Object, ObjectId}; use crate::utils::copyhashmap::CopyHashMap; use ahash::AHashMap; use std::cell::{RefCell, RefMut}; use std::mem; use std::rc::Rc; -use crate::ifs::xdg_wm_base::XdgWmBaseObj; pub struct Objects { pub display: RefCell>>, registry: CopyHashMap>, - registries: CopyHashMap>, - pub surfaces: CopyHashMap>, - pub regions: CopyHashMap>, - pub xdg_wm_bases: CopyHashMap>, + registries: CopyHashMap>, + pub surfaces: CopyHashMap>, + pub xdg_surfaces: CopyHashMap>, + pub regions: CopyHashMap>, + pub xdg_wm_bases: CopyHashMap>, ids: RefCell>, } @@ -31,6 +33,7 @@ impl Objects { registry: Default::default(), registries: Default::default(), surfaces: Default::default(), + xdg_surfaces: Default::default(), regions: Default::default(), xdg_wm_bases: Default::default(), ids: RefCell::new(vec![]), @@ -39,25 +42,24 @@ impl Objects { pub fn destroy(&self) { { - let mut surfaces = self.surfaces.lock(); - for surface in surfaces.values_mut() { - surface.break_loops(); - } - } - { - let mut xdg_wm_bases = self.xdg_wm_bases.lock(); - for xdg_wm_base in xdg_wm_bases.values_mut() { - xdg_wm_base.break_loops(); + let mut registry = self.registry.lock(); + for obj in registry.values_mut() { + obj.break_loops(); } + registry.clear(); } *self.display.borrow_mut() = None; - self.registry.clear(); self.regions.clear(); self.registries.clear(); self.surfaces.clear(); + self.xdg_wm_bases.clear(); + self.xdg_surfaces.clear(); } - fn id(&self, client_data: &Client) -> Result { + fn id(&self, client_data: &Client) -> Result + where + ObjectId: Into, + { const MAX_ID_OFFSET: u32 = u32::MAX - MIN_SERVER_ID; let offset = self.id_offset(); if offset > MAX_ID_OFFSET { @@ -68,7 +70,7 @@ impl Objects { ); return Err(ClientError::TooManyIds); } - Ok(ObjectId::from_raw(MIN_SERVER_ID + offset)) + Ok(ObjectId::from_raw(MIN_SERVER_ID + offset).into()) } pub fn get_obj(&self, id: ObjectId) -> Result, ClientError> { @@ -123,7 +125,7 @@ impl Objects { Ok(()) } - pub fn registries(&self) -> RefMut>> { + pub fn registries(&self) -> RefMut>> { self.registries.lock() } diff --git a/src/format.rs b/src/format.rs index a12ad5f1..4d586694 100644 --- a/src/format.rs +++ b/src/format.rs @@ -4,6 +4,7 @@ use ahash::AHashMap; pub struct Format { pub id: u32, pub name: &'static str, + pub bpp: u32, } pub fn formats() -> AHashMap { @@ -22,10 +23,12 @@ static FORMATS: &[Format] = &[ Format { id: 0, name: "argb8888", + bpp: 4, }, Format { id: 1, name: "xrgb8888", + bpp: 4, }, // Format { // id: fourcc_code('C', '8', ' ', ' '), diff --git a/src/ifs/mod.rs b/src/ifs/mod.rs index daabcaef..6a41934a 100644 --- a/src/ifs/mod.rs +++ b/src/ifs/mod.rs @@ -1,8 +1,11 @@ +pub mod wl_buffer; pub mod wl_callback; pub mod wl_compositor; pub mod wl_display; +pub mod wl_output; pub mod wl_region; pub mod wl_registry; +pub mod wl_seat; pub mod wl_shm; pub mod wl_shm_pool; pub mod wl_subcompositor; diff --git a/src/ifs/wl_buffer/mod.rs b/src/ifs/wl_buffer/mod.rs new file mode 100644 index 00000000..e19307c4 --- /dev/null +++ b/src/ifs/wl_buffer/mod.rs @@ -0,0 +1,91 @@ +mod types; + +use std::cell::RefCell; +use crate::client::{AddObj, Client}; +use crate::clientmem::ClientMem; +use crate::format::Format; +use crate::object::{Interface, Object, ObjectId}; +use std::rc::Rc; +pub use types::*; +use crate::utils::buffd::MsgParser; + +const DESTROY: u32 = 0; + +const RELEASE: u32 = 0; + +id!(WlBufferId); + +pub struct WlBuffer { + id: WlBufferId, + client: Rc, + offset: usize, + width: u32, + height: u32, + stride: u32, + format: &'static Format, + mem: RefCell>>, +} + +impl WlBuffer { + pub fn new( + id: WlBufferId, + client: &Rc, + offset: usize, + width: u32, + height: u32, + stride: u32, + format: &'static Format, + mem: &Rc, + ) -> Result { + let bytes = stride as u64 * height as u64; + let required = bytes + offset as u64; + if required > mem.len() as u64 { + return Err(WlBufferError::OutOfBounds); + } + let min_row_size = width as u64 * format.bpp as u64; + if (stride as u64) < min_row_size { + return Err(WlBufferError::StrideTooSmall); + } + Ok(Self { + id, + client: client.clone(), + offset, + width, + height, + stride, + format, + mem: RefCell::new(Some(mem.clone())), + }) + } + + async fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> { + let _req: Destroy = self.client.parse(self, parser)?; + *self.mem.borrow_mut() = None; + self.client.remove_obj(self).await?; + Ok(()) + } + + async fn handle_request_(&self, request: u32, parser: MsgParser<'_, '_>) -> Result<(), WlBufferError> { + match request { + DESTROY => self.destroy(parser).await?, + _ => unreachable!(), + } + Ok(()) + } +} + +handle_request!(WlBuffer); + +impl Object for WlBuffer { + fn id(&self) -> ObjectId { + self.id.into() + } + + fn interface(&self) -> Interface { + Interface::WlBuffer + } + + fn num_requests(&self) -> u32 { + DESTROY + 1 + } +} diff --git a/src/ifs/wl_buffer/types.rs b/src/ifs/wl_buffer/types.rs new file mode 100644 index 00000000..cf7cbf66 --- /dev/null +++ b/src/ifs/wl_buffer/types.rs @@ -0,0 +1,56 @@ +use std::fmt::{Debug, Formatter}; +use std::rc::Rc; +use thiserror::Error; +use crate::client::{ClientError, EventFormatter, RequestParser}; +use crate::ifs::wl_buffer::{RELEASE, WlBuffer}; +use crate::object::Object; +use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError}; + +#[derive(Debug, Error)] +pub enum WlBufferError { + #[error("The requested memory region is out of bounds for the pool")] + OutOfBounds, + #[error("The stride does not fit all pixels in a row")] + StrideTooSmall, + #[error("Could not handle a `destroy` request")] + DestroyError(#[from] DestroyError), +} + +#[derive(Debug, Error)] +pub enum DestroyError { + #[error("Parsing failed")] + ParseFailed(#[source] Box), + #[error(transparent)] + ClientError(Box), +} +efrom!(DestroyError, ParseFailed, MsgParserError); +efrom!(DestroyError, ClientError, ClientError); + +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 Release { + pub obj: Rc, +} +impl EventFormatter for Release { + fn format(self: Box, fmt: &mut MsgFormatter<'_>) { + fmt.header(self.obj.id, RELEASE); + } + fn obj(&self) -> &dyn Object { + &*self.obj + } +} +impl Debug for Release { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "release()") + } +} diff --git a/src/ifs/wl_callback/mod.rs b/src/ifs/wl_callback/mod.rs index eac41fe8..c00bdfd4 100644 --- a/src/ifs/wl_callback/mod.rs +++ b/src/ifs/wl_callback/mod.rs @@ -8,12 +8,14 @@ use types::*; const DONE: u32 = 0; +id!(WlCallbackId); + pub struct WlCallback { - id: ObjectId, + id: WlCallbackId, } impl WlCallback { - pub fn new(id: ObjectId) -> Self { + pub fn new(id: WlCallbackId) -> Self { Self { id } } @@ -34,7 +36,7 @@ handle_request!(WlCallback); impl Object for WlCallback { fn id(&self) -> ObjectId { - self.id + self.id.into() } fn interface(&self) -> Interface { diff --git a/src/ifs/wl_compositor/mod.rs b/src/ifs/wl_compositor/mod.rs index cdfbce10..0fb4a5a2 100644 --- a/src/ifs/wl_compositor/mod.rs +++ b/src/ifs/wl_compositor/mod.rs @@ -12,13 +12,15 @@ pub use types::*; const CREATE_SURFACE: u32 = 0; const CREATE_REGION: u32 = 1; +id!(WlCompositorId); + pub struct WlCompositorGlobal { name: GlobalName, } pub struct WlCompositorObj { global: Rc, - id: ObjectId, + id: WlCompositorId, client: Rc, version: u32, } @@ -30,7 +32,7 @@ impl WlCompositorGlobal { async fn bind_( self: Rc, - id: ObjectId, + id: WlCompositorId, client: &Rc, version: u32, ) -> Result<(), WlCompositorError> { @@ -98,7 +100,7 @@ handle_request!(WlCompositorObj); impl Object for WlCompositorObj { fn id(&self) -> ObjectId { - self.id + self.id.into() } fn interface(&self) -> Interface { diff --git a/src/ifs/wl_compositor/types.rs b/src/ifs/wl_compositor/types.rs index 5b4fe530..7d8c73bd 100644 --- a/src/ifs/wl_compositor/types.rs +++ b/src/ifs/wl_compositor/types.rs @@ -1,5 +1,6 @@ use crate::client::{ClientError, RequestParser}; -use crate::object::ObjectId; +use crate::ifs::wl_region::WlRegionId; +use crate::ifs::wl_surface::WlSurfaceId; use crate::utils::buffd::{MsgParser, MsgParserError}; use std::fmt::{Debug, Formatter}; use thiserror::Error; @@ -41,7 +42,7 @@ efrom!(CreateRegionError, ParseFailed, MsgParserError); efrom!(CreateRegionError, ClientError, ClientError); pub(super) struct CreateSurface { - pub id: ObjectId, + pub id: WlSurfaceId, } impl RequestParser<'_> for CreateSurface { fn parse(parser: &mut MsgParser<'_, '_>) -> Result { @@ -57,7 +58,7 @@ impl Debug for CreateSurface { } pub(super) struct CreateRegion { - pub id: ObjectId, + pub id: WlRegionId, } impl RequestParser<'_> for CreateRegion { fn parse(parser: &mut MsgParser<'_, '_>) -> Result { diff --git a/src/ifs/wl_display/mod.rs b/src/ifs/wl_display/mod.rs index 194ecd64..5f6da1a2 100644 --- a/src/ifs/wl_display/mod.rs +++ b/src/ifs/wl_display/mod.rs @@ -45,7 +45,7 @@ impl WlDisplay { async fn sync(&self, parser: MsgParser<'_, '_>) -> Result<(), SyncError> { let sync: Sync = self.client.parse(self, parser)?; - let cb = Rc::new(WlCallback::new(sync.callback)); + let cb = Rc::new(WlCallback::new(sync.callback.into())); self.client.add_client_obj(&cb)?; self.client.event(cb.done()).await?; self.client.remove_obj(&*cb).await?; diff --git a/src/ifs/wl_display/types.rs b/src/ifs/wl_display/types.rs index 22ca5685..01d7418e 100644 --- a/src/ifs/wl_display/types.rs +++ b/src/ifs/wl_display/types.rs @@ -1,6 +1,8 @@ use crate::client::{ClientError, EventFormatter, RequestParser}; use crate::globals::GlobalError; +use crate::ifs::wl_callback::WlCallbackId; use crate::ifs::wl_display::{WlDisplay, DELETE_ID, ERROR}; +use crate::ifs::wl_registry::WlRegistryId; use crate::object::{Object, ObjectId, WL_DISPLAY_ID}; use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError}; use std::fmt::{Debug, Formatter}; @@ -44,7 +46,7 @@ efrom!(SyncError, ParseFailed, MsgParserError); efrom!(SyncError, ClientError, ClientError); pub(super) struct GetRegistry { - pub registry: ObjectId, + pub registry: WlRegistryId, } impl RequestParser<'_> for GetRegistry { fn parse(parser: &mut MsgParser<'_, '_>) -> Result { @@ -60,7 +62,7 @@ impl Debug for GetRegistry { } pub(super) struct Sync { - pub callback: ObjectId, + pub callback: WlCallbackId, } impl RequestParser<'_> for Sync { fn parse(parser: &mut MsgParser<'_, '_>) -> Result { diff --git a/src/ifs/wl_output/mod.rs b/src/ifs/wl_output/mod.rs new file mode 100644 index 00000000..65845678 --- /dev/null +++ b/src/ifs/wl_output/mod.rs @@ -0,0 +1 @@ +id!(WlOutputId); diff --git a/src/ifs/wl_region/mod.rs b/src/ifs/wl_region/mod.rs index b7525b2b..090f3c45 100644 --- a/src/ifs/wl_region/mod.rs +++ b/src/ifs/wl_region/mod.rs @@ -12,14 +12,16 @@ const DESTROY: u32 = 0; const ADD: u32 = 1; const SUBTRACT: u32 = 2; +id!(WlRegionId); + pub struct WlRegion { - id: ObjectId, + id: WlRegionId, client: Rc, rect: RefCell, } impl WlRegion { - pub fn new(id: ObjectId, client: &Rc) -> Self { + pub fn new(id: WlRegionId, client: &Rc) -> Self { Self { id, client: client.clone(), @@ -81,7 +83,7 @@ handle_request!(WlRegion); impl Object for WlRegion { fn id(&self) -> ObjectId { - self.id + self.id.into() } fn interface(&self) -> Interface { diff --git a/src/ifs/wl_registry/mod.rs b/src/ifs/wl_registry/mod.rs index 0132c8a5..32e642f9 100644 --- a/src/ifs/wl_registry/mod.rs +++ b/src/ifs/wl_registry/mod.rs @@ -12,13 +12,15 @@ const BIND: u32 = 0; const GLOBAL: u32 = 0; const GLOBAL_REMOVE: u32 = 1; +id!(WlRegistryId); + pub struct WlRegistry { - id: ObjectId, + id: WlRegistryId, client: Rc, } impl WlRegistry { - pub fn new(id: ObjectId, client: &Rc) -> Self { + pub fn new(id: WlRegistryId, client: &Rc) -> Self { Self { id, client: client.clone(), @@ -78,7 +80,7 @@ handle_request!(WlRegistry); impl Object for WlRegistry { fn id(&self) -> ObjectId { - self.id + self.id.into() } fn interface(&self) -> Interface { diff --git a/src/ifs/wl_seat/mod.rs b/src/ifs/wl_seat/mod.rs new file mode 100644 index 00000000..5fbd737d --- /dev/null +++ b/src/ifs/wl_seat/mod.rs @@ -0,0 +1 @@ +id!(WlSeatId); diff --git a/src/ifs/wl_shm/mod.rs b/src/ifs/wl_shm/mod.rs index ba8a9e27..15527bc1 100644 --- a/src/ifs/wl_shm/mod.rs +++ b/src/ifs/wl_shm/mod.rs @@ -12,13 +12,15 @@ const CREATE_POOL: u32 = 0; const FORMAT: u32 = 0; +id!(WlShmId); + pub struct WlShmGlobal { name: GlobalName, } pub struct WlShmObj { global: Rc, - id: ObjectId, + id: WlShmId, client: Rc, } @@ -29,7 +31,7 @@ impl WlShmGlobal { async fn bind_( self: Rc, - id: ObjectId, + id: WlShmId, client: &Rc, _version: u32, ) -> Result<(), WlShmError> { @@ -104,7 +106,7 @@ handle_request!(WlShmObj); impl Object for WlShmObj { fn id(&self) -> ObjectId { - self.id + self.id.into() } fn interface(&self) -> Interface { diff --git a/src/ifs/wl_shm/types.rs b/src/ifs/wl_shm/types.rs index c89ca10a..7251d38a 100644 --- a/src/ifs/wl_shm/types.rs +++ b/src/ifs/wl_shm/types.rs @@ -1,8 +1,8 @@ use crate::client::{ClientError, EventFormatter, RequestParser}; use crate::format::Format; use crate::ifs::wl_shm::{WlShmObj, FORMAT}; -use crate::ifs::wl_shm_pool::WlShmPoolError; -use crate::object::{Object, ObjectId}; +use crate::ifs::wl_shm_pool::{WlShmPoolError, WlShmPoolId}; +use crate::object::Object; use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError}; use std::fmt::{Debug, Formatter}; use std::rc::Rc; @@ -34,7 +34,7 @@ efrom!(CreatePoolError, WlShmPoolError, WlShmPoolError); efrom!(CreatePoolError, ClientError, ClientError); pub(super) struct CreatePool { - pub id: ObjectId, + pub id: WlShmPoolId, pub fd: OwnedFd, pub size: i32, } diff --git a/src/ifs/wl_shm_pool/mod.rs b/src/ifs/wl_shm_pool/mod.rs index 2e15dba3..d6aadaa2 100644 --- a/src/ifs/wl_shm_pool/mod.rs +++ b/src/ifs/wl_shm_pool/mod.rs @@ -2,6 +2,7 @@ mod types; use crate::client::{AddObj, Client}; use crate::clientmem::ClientMem; +use crate::ifs::wl_buffer::WlBuffer; use crate::object::{Interface, Object, ObjectId}; use crate::utils::buffd::MsgParser; use std::cell::RefCell; @@ -13,8 +14,10 @@ const CREATE_BUFFER: u32 = 0; const DESTROY: u32 = 1; const RESIZE: u32 = 2; +id!(WlShmPoolId); + pub struct WlShmPool { - id: ObjectId, + id: WlShmPoolId, client: Rc, fd: OwnedFd, mem: RefCell>, @@ -22,7 +25,7 @@ pub struct WlShmPool { impl WlShmPool { pub fn new( - id: ObjectId, + id: WlShmPoolId, client: &Rc, fd: OwnedFd, len: usize, @@ -37,6 +40,25 @@ impl WlShmPool { async fn create_buffer(&self, parser: MsgParser<'_, '_>) -> Result<(), CreateBufferError> { let req: CreateBuffer = self.client.parse(self, parser)?; + let format = match self.client.state.formats.get(&req.format) { + Some(f) => *f, + _ => return Err(CreateBufferError::InvalidFormat(req.format)), + }; + if req.height < 0 || req.width < 0 || req.stride < 0 || req.offset < 0 { + return Err(CreateBufferError::NegativeParameters); + } + let mem = self.mem.borrow(); + let buffer = Rc::new(WlBuffer::new( + req.id, + &self.client, + req.offset as usize, + req.width as u32, + req.height as u32, + req.stride as u32, + format, + &mem, + )?); + self.client.add_client_obj(&buffer)?; Ok(()) } @@ -78,7 +100,7 @@ handle_request!(WlShmPool); impl Object for WlShmPool { fn id(&self) -> ObjectId { - self.id + self.id.into() } fn interface(&self) -> Interface { diff --git a/src/ifs/wl_shm_pool/types.rs b/src/ifs/wl_shm_pool/types.rs index 4b1e5578..bb2786ca 100644 --- a/src/ifs/wl_shm_pool/types.rs +++ b/src/ifs/wl_shm_pool/types.rs @@ -1,6 +1,6 @@ use crate::client::{ClientError, RequestParser}; use crate::clientmem::ClientMemError; -use crate::object::ObjectId; +use crate::ifs::wl_buffer::{WlBufferError, WlBufferId}; use crate::utils::buffd::{MsgParser, MsgParserError}; use std::fmt::{Debug, Formatter}; use thiserror::Error; @@ -27,9 +27,16 @@ pub enum CreateBufferError { ParseError(#[source] Box), #[error(transparent)] ClientError(Box), + #[error("Format {0} is not supported")] + InvalidFormat(u32), + #[error("All parameters in a create_buffer request must be non-negative")] + NegativeParameters, + #[error(transparent)] + WlBufferError(Box), } efrom!(CreateBufferError, ParseError, MsgParserError); efrom!(CreateBufferError, ClientError, ClientError); +efrom!(CreateBufferError, WlBufferError, WlBufferError); #[derive(Debug, Error)] pub enum DestroyError { @@ -56,7 +63,7 @@ efrom!(ResizeError, ParseError, MsgParserError); efrom!(ResizeError, ClientMemError, ClientMemError); pub(super) struct CreateBuffer { - pub id: ObjectId, + pub id: WlBufferId, pub offset: i32, pub width: i32, pub height: i32, diff --git a/src/ifs/wl_subcompositor/mod.rs b/src/ifs/wl_subcompositor/mod.rs index 651e8da9..4fffbad5 100644 --- a/src/ifs/wl_subcompositor/mod.rs +++ b/src/ifs/wl_subcompositor/mod.rs @@ -13,13 +13,15 @@ const GET_SUBSURFACE: u32 = 1; const BAD_SURFACE: u32 = 0; +id!(WlSubcompositorId); + pub struct WlSubcompositorGlobal { name: GlobalName, } pub struct WlSubcompositorObj { global: Rc, - id: ObjectId, + id: WlSubcompositorId, client: Rc, } @@ -30,7 +32,7 @@ impl WlSubcompositorGlobal { async fn bind_( self: Rc, - id: ObjectId, + id: WlSubcompositorId, client: &Rc, _version: u32, ) -> Result<(), WlSubcompositorError> { @@ -99,7 +101,7 @@ handle_request!(WlSubcompositorObj); impl Object for WlSubcompositorObj { fn id(&self) -> ObjectId { - self.id + self.id.into() } fn interface(&self) -> Interface { diff --git a/src/ifs/wl_subcompositor/types.rs b/src/ifs/wl_subcompositor/types.rs index 20c34487..2f5049a5 100644 --- a/src/ifs/wl_subcompositor/types.rs +++ b/src/ifs/wl_subcompositor/types.rs @@ -1,6 +1,6 @@ use crate::client::{ClientError, RequestParser}; -use crate::ifs::wl_surface::wl_subsurface::WlSubsurfaceError; -use crate::object::ObjectId; +use crate::ifs::wl_surface::wl_subsurface::{WlSubsurfaceError, WlSubsurfaceId}; +use crate::ifs::wl_surface::WlSurfaceId; use crate::utils::buffd::{MsgParser, MsgParserError}; use std::fmt::{Debug, Formatter}; use thiserror::Error; @@ -52,9 +52,9 @@ impl Debug for Destroy { } pub(super) struct GetSubsurface { - pub id: ObjectId, - pub surface: ObjectId, - pub parent: ObjectId, + pub id: WlSubsurfaceId, + pub surface: WlSurfaceId, + pub parent: WlSurfaceId, } impl RequestParser<'_> for GetSubsurface { fn parse(parser: &mut MsgParser<'_, '_>) -> Result { diff --git a/src/ifs/wl_surface/mod.rs b/src/ifs/wl_surface/mod.rs index 54e94823..f171829e 100644 --- a/src/ifs/wl_surface/mod.rs +++ b/src/ifs/wl_surface/mod.rs @@ -4,15 +4,18 @@ pub mod xdg_surface; use crate::client::{AddObj, Client, RequestParser}; 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; +use crate::ifs::wl_surface::xdg_surface::XdgSurface; use crate::object::{Interface, Object, ObjectId}; use crate::pixman::Region; use crate::utils::buffd::{MsgParser, MsgParserError}; +use crate::utils::copyhashmap::CopyHashMap; use crate::utils::linkedlist::{LinkedList, Node}; use ahash::AHashMap; use std::cell::{Cell, RefCell}; use std::rc::Rc; pub use types::*; -use crate::ifs::wl_surface::xdg_surface::XdgSurface; const DESTROY: u32 = 0; const ATTACH: u32 = 1; @@ -32,6 +35,8 @@ const INVALID_SCALE: u32 = 0; const INVALID_TRANSFORM: u32 = 1; const INVALID_SIZE: u32 = 2; +id!(WlSurfaceId); + #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum SurfaceRole { None, @@ -50,7 +55,7 @@ impl SurfaceRole { } pub struct WlSurface { - id: ObjectId, + id: WlSurfaceId, client: Rc, role: Cell, pending: PendingState, @@ -78,21 +83,44 @@ struct PendingState { struct XdgSurfaceData { xdg_surface: Rc, + committed: bool, role: XdgSurfaceRole, + role_data: XdgSurfaceRoleData, + popups: CopyHashMap>, } +#[derive(Copy, Clone, Debug, Eq, PartialEq)] enum XdgSurfaceRole { + None, + Popup, + Toplevel, +} + +impl XdgSurfaceRole { + fn is_compatible(self, role: XdgSurfaceRole) -> bool { + self == XdgSurfaceRole::None || self == role + } +} + +enum XdgSurfaceRoleData { None, Popup(XdgPopupData), Toplevel(XdgToplevelData), } -struct XdgPopupData { +impl XdgSurfaceRoleData { + fn is_some(&self) -> bool { + !matches!(self, XdgSurfaceRoleData::None) + } +} +struct XdgPopupData { + popup: Rc, + parent: Option>, } struct XdgToplevelData { - + toplevel: Rc, } struct SubsurfaceData { @@ -114,7 +142,7 @@ struct PendingSubsurfaceData { #[derive(Default)] struct ParentData { - subsurfaces: AHashMap>, + subsurfaces: AHashMap>, below: LinkedList, above: LinkedList, } @@ -125,7 +153,7 @@ struct StackElement { } impl WlSurface { - pub fn new(id: ObjectId, client: &Rc) -> Self { + pub fn new(id: WlSurfaceId, client: &Rc) -> Self { Self { id, client: client.clone(), @@ -136,11 +164,6 @@ impl WlSurface { } } - pub fn break_loops(&self) { - *self.children.borrow_mut() = None; - *self.role_data.borrow_mut() = RoleData::None; - } - pub fn get_root(self: &Rc) -> Rc { let mut root = self.clone(); loop { @@ -165,8 +188,47 @@ impl WlSurface { async fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> { let _req: Destroy = self.parse(parser)?; - *self.children.borrow_mut() = None; - *self.role_data.borrow_mut() = RoleData::None; + { + let mut children = self.children.borrow_mut(); + if let Some(children) = &mut *children { + for surface in children.subsurfaces.values() { + *surface.role_data.borrow_mut() = RoleData::None; + } + } + *children = None; + } + { + let mut data = self.role_data.borrow_mut(); + match &mut *data { + RoleData::None => {} + RoleData::Subsurface(ss) => { + let mut children = ss.subsurface.parent.children.borrow_mut(); + if let Some(children) = &mut *children { + children.subsurfaces.remove(&self.id); + } + } + RoleData::XdgSurface(xdg) => { + let children = xdg.popups.lock(); + for child in children.values() { + let mut rd = child.surface.surface.role_data.borrow_mut(); + if let RoleData::XdgSurface(xdg) = &mut *rd { + if let XdgSurfaceRoleData::Popup(p) = &mut xdg.role_data { + p.parent = None; + } + } + } + if let XdgSurfaceRoleData::Popup(p) = &mut xdg.role_data { + if let Some(p) = &p.parent { + let mut rd = p.surface.role_data.borrow_mut(); + if let RoleData::XdgSurface(xdg) = &mut *rd { + xdg.popups.remove(&self.id); + } + } + } + } + } + *data = RoleData::None; + } self.client.remove_obj(self).await?; Ok(()) } @@ -252,7 +314,7 @@ handle_request!(WlSurface); impl Object for WlSurface { fn id(&self) -> ObjectId { - self.id + self.id.into() } fn interface(&self) -> Interface { @@ -262,4 +324,9 @@ impl Object for WlSurface { fn num_requests(&self) -> u32 { DAMAGE_BUFFER + 1 } + + fn break_loops(&self) { + *self.children.borrow_mut() = None; + *self.role_data.borrow_mut() = RoleData::None; + } } diff --git a/src/ifs/wl_surface/types.rs b/src/ifs/wl_surface/types.rs index 09105edd..7f6e829b 100644 --- a/src/ifs/wl_surface/types.rs +++ b/src/ifs/wl_surface/types.rs @@ -1,5 +1,6 @@ use crate::client::{ClientError, RequestParser}; -use crate::object::ObjectId; +use crate::ifs::wl_callback::WlCallbackId; +use crate::ifs::wl_region::WlRegionId; use crate::utils::buffd::{MsgParser, MsgParserError}; use std::fmt::{Debug, Formatter}; use thiserror::Error; @@ -134,7 +135,7 @@ impl Debug for Destroy { } pub(super) struct Attach { - pub buffer: ObjectId, + pub buffer: crate::ifs::wl_buffer::WlBufferId, pub x: i32, pub y: i32, } @@ -184,7 +185,7 @@ impl Debug for Damage { } pub(super) struct Frame { - pub callback: ObjectId, + pub callback: WlCallbackId, } impl RequestParser<'_> for Frame { fn parse(parser: &mut MsgParser<'_, '_>) -> Result { @@ -200,7 +201,7 @@ impl Debug for Frame { } pub(super) struct SetOpaqueRegion { - pub region: ObjectId, + pub region: WlRegionId, } impl RequestParser<'_> for SetOpaqueRegion { fn parse(parser: &mut MsgParser<'_, '_>) -> Result { @@ -216,7 +217,7 @@ impl Debug for SetOpaqueRegion { } pub(super) struct SetInputRegion { - pub region: ObjectId, + pub region: WlRegionId, } impl RequestParser<'_> for SetInputRegion { fn parse(parser: &mut MsgParser<'_, '_>) -> Result { diff --git a/src/ifs/wl_surface/wl_subsurface/mod.rs b/src/ifs/wl_surface/wl_subsurface/mod.rs index 1a8b5bf4..5cc44c50 100644 --- a/src/ifs/wl_surface/wl_subsurface/mod.rs +++ b/src/ifs/wl_surface/wl_subsurface/mod.rs @@ -1,7 +1,9 @@ mod types; use crate::client::AddObj; -use crate::ifs::wl_surface::{RoleData, StackElement, SubsurfaceData, SurfaceRole, WlSurface}; +use crate::ifs::wl_surface::{ + RoleData, StackElement, SubsurfaceData, SurfaceRole, WlSurface, WlSurfaceId, +}; use crate::object::{Interface, Object, ObjectId}; use crate::utils::buffd::MsgParser; use std::cell::Cell; @@ -19,8 +21,10 @@ const BAD_SURFACE: u32 = 0; const MAX_SUBSURFACE_DEPTH: u32 = 100; +id!(WlSubsurfaceId); + pub struct WlSubsurface { - id: ObjectId, + id: WlSubsurfaceId, surface: Rc, pub(super) parent: Rc, } @@ -67,7 +71,7 @@ fn update_children_attach( } impl WlSubsurface { - pub fn new(id: ObjectId, surface: &Rc, parent: &Rc) -> Self { + pub fn new(id: WlSubsurfaceId, surface: &Rc, parent: &Rc) -> Self { Self { id, surface: surface.clone(), @@ -150,7 +154,7 @@ impl WlSubsurface { Ok(()) } - fn place(&self, sibling: ObjectId, above: bool) -> Result<(), PlacementError> { + fn place(&self, sibling: WlSurfaceId, above: bool) -> Result<(), PlacementError> { if sibling == self.surface.id { return Err(PlacementError::AboveSelf(sibling)); } @@ -247,7 +251,7 @@ handle_request!(WlSubsurface); impl Object for WlSubsurface { fn id(&self) -> ObjectId { - self.id + self.id.into() } fn interface(&self) -> Interface { diff --git a/src/ifs/wl_surface/wl_subsurface/types.rs b/src/ifs/wl_surface/wl_subsurface/types.rs index 238b2cf7..932824a5 100644 --- a/src/ifs/wl_surface/wl_subsurface/types.rs +++ b/src/ifs/wl_surface/wl_subsurface/types.rs @@ -1,6 +1,5 @@ use crate::client::{ClientError, RequestParser}; -use crate::ifs::wl_surface::SurfaceRole; -use crate::object::ObjectId; +use crate::ifs::wl_surface::{SurfaceRole, WlSurfaceId}; use crate::utils::buffd::{MsgParser, MsgParserError}; use std::fmt::{Debug, Formatter}; use thiserror::Error; @@ -20,13 +19,13 @@ pub enum WlSubsurfaceError { #[error("Could not process `set_desync` request")] SetDesync(#[from] SetDesyncError), #[error("Surface {0} cannot be assigned the role `Subsurface` because it already has the role `{1:?}`")] - IncompatibleType(ObjectId, SurfaceRole), + IncompatibleType(WlSurfaceId, SurfaceRole), #[error("Surface {0} already has an attached `wl_subsurface`")] - AlreadyAttached(ObjectId), + AlreadyAttached(WlSurfaceId), #[error("Surface {0} cannot be made its own parent")] - OwnParent(ObjectId), + OwnParent(WlSurfaceId), #[error("Surface {0} cannot be made a subsurface of {1} because it's an ancestor of {1}")] - Ancestor(ObjectId, ObjectId), + Ancestor(WlSurfaceId, WlSurfaceId), #[error("Subsurfaces cannot be nested deeper than 100 levels")] MaxDepthExceeded, } @@ -60,9 +59,9 @@ efrom!(PlaceAboveError, ParseFailed, MsgParserError); #[derive(Debug, Error)] pub enum PlacementError { #[error("Cannot place {0} above/below itself")] - AboveSelf(ObjectId), + AboveSelf(WlSurfaceId), #[error("{0} is not a sibling of {1}")] - NotASibling(ObjectId, ObjectId), + NotASibling(WlSurfaceId, WlSurfaceId), } #[derive(Debug, Error)] @@ -88,7 +87,7 @@ pub enum SetDesyncError { } efrom!(SetDesyncError, ParseFailed, MsgParserError); -pub(in crate::ifs) struct Destroy; +pub(super) struct Destroy; impl RequestParser<'_> for Destroy { fn parse(_parser: &mut MsgParser<'_, '_>) -> Result { Ok(Self) @@ -100,7 +99,7 @@ impl Debug for Destroy { } } -pub(in crate::ifs) struct SetPosition { +pub(super) struct SetPosition { pub x: i32, pub y: i32, } @@ -118,8 +117,8 @@ impl Debug for SetPosition { } } -pub(in crate::ifs) struct PlaceAbove { - pub sibling: ObjectId, +pub(super) struct PlaceAbove { + pub sibling: WlSurfaceId, } impl RequestParser<'_> for PlaceAbove { fn parse(parser: &mut MsgParser<'_, '_>) -> Result { @@ -134,8 +133,8 @@ impl Debug for PlaceAbove { } } -pub(in crate::ifs) struct PlaceBelow { - pub sibling: ObjectId, +pub(super) struct PlaceBelow { + pub sibling: WlSurfaceId, } impl RequestParser<'_> for PlaceBelow { fn parse(parser: &mut MsgParser<'_, '_>) -> Result { @@ -150,7 +149,7 @@ impl Debug for PlaceBelow { } } -pub(in crate::ifs) struct SetSync; +pub(super) struct SetSync; impl RequestParser<'_> for SetSync { fn parse(_parser: &mut MsgParser<'_, '_>) -> Result { Ok(Self) @@ -162,7 +161,7 @@ impl Debug for SetSync { } } -pub(in crate::ifs) struct SetDesync; +pub(super) struct SetDesync; impl RequestParser<'_> for SetDesync { fn parse(_parser: &mut MsgParser<'_, '_>) -> Result { Ok(Self) diff --git a/src/ifs/wl_surface/xdg_surface/mod.rs b/src/ifs/wl_surface/xdg_surface/mod.rs index d547780e..b65faf65 100644 --- a/src/ifs/wl_surface/xdg_surface/mod.rs +++ b/src/ifs/wl_surface/xdg_surface/mod.rs @@ -2,13 +2,18 @@ mod types; pub mod xdg_popup; pub mod xdg_toplevel; -use crate::ifs::wl_surface::{RoleData, SurfaceRole, WlSurface, XdgSurfaceData}; +use crate::client::AddObj; +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::{ + RoleData, SurfaceRole, WlSurface, XdgPopupData, XdgSurfaceData, XdgSurfaceRole, + XdgSurfaceRoleData, XdgToplevelData, +}; +use crate::ifs::xdg_wm_base::XdgWmBaseObj; use crate::object::{Interface, Object, ObjectId}; use crate::utils::buffd::MsgParser; use std::rc::Rc; pub use types::*; -use crate::client::AddObj; -use crate::ifs::xdg_wm_base::XdgWmBaseObj; const DESTROY: u32 = 0; const GET_TOPLEVEL: u32 = 1; @@ -22,15 +27,22 @@ const NOT_CONSTRUCTED: u32 = 1; const ALREADY_CONSTRUCTED: u32 = 2; const UNCONFIGURED_BUFFER: u32 = 3; +id!(XdgSurfaceId); + pub struct XdgSurface { - id: ObjectId, + id: XdgSurfaceId, wm_base: Rc, - surface: Rc, + pub(super) surface: Rc, version: u32, } impl XdgSurface { - pub fn new(wm_base: &Rc, id: ObjectId, surface: &Rc, version: u32) -> Self { + pub fn new( + wm_base: &Rc, + id: XdgSurfaceId, + surface: &Rc, + version: u32, + ) -> Self { Self { id, wm_base: wm_base.clone(), @@ -50,25 +62,101 @@ impl XdgSurface { } *data = RoleData::XdgSurface(Box::new(XdgSurfaceData { xdg_surface: self.clone(), + committed: false, + role: XdgSurfaceRole::None, + role_data: XdgSurfaceRoleData::None, + popups: Default::default(), })); Ok(()) } async fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> { let _req: Destroy = self.surface.client.parse(self, parser)?; - *self.surface.role_data.borrow_mut() = RoleData::None; + { + let mut data = self.surface.role_data.borrow_mut(); + if let RoleData::XdgSurface(rd) = &*data { + if rd.role_data.is_some() { + return Err(DestroyError::RoleNotYetDestroyed(self.id)); + } + let children = rd.popups.lock(); + for child in children.values() { + let mut data = child.surface.surface.role_data.borrow_mut(); + if let RoleData::XdgSurface(xdg) = &mut *data { + if let XdgSurfaceRoleData::Popup(p) = &mut xdg.role_data { + p.parent = None; + } + } + } + } + *data = RoleData::None; + } self.wm_base.surfaces.remove(&self.id); self.surface.client.remove_obj(self).await?; Ok(()) } - async fn get_toplevel(&self, parser: MsgParser<'_, '_>) -> Result<(), GetToplevelError> { - let _req: GetToplevel = self.surface.client.parse(self, parser)?; + async fn get_toplevel( + self: &Rc, + parser: MsgParser<'_, '_>, + ) -> Result<(), GetToplevelError> { + let req: GetToplevel = self.surface.client.parse(&**self, parser)?; + let mut data = self.surface.role_data.borrow_mut(); + if let RoleData::XdgSurface(data) = &mut *data { + if !data.role.is_compatible(XdgSurfaceRole::Toplevel) { + return Err(GetToplevelError::IncompatibleRole); + } + if data.role_data.is_some() { + self.surface.client.protocol_error( + &**self, + ALREADY_CONSTRUCTED, + format!( + "wl_surface {} already has an assigned xdg_toplevel", + self.surface.id + ), + ); + return Err(GetToplevelError::AlreadyConstructed); + } + data.role = XdgSurfaceRole::Toplevel; + let toplevel = Rc::new(XdgToplevel::new(req.id, self, self.version)); + self.surface.client.add_client_obj(&toplevel)?; + data.role_data = XdgSurfaceRoleData::Toplevel(XdgToplevelData { toplevel }); + } Ok(()) } - async fn get_popup(&self, parser: MsgParser<'_, '_>) -> Result<(), GetPopupError> { - let _req: GetPopup = self.surface.client.parse(self, parser)?; + async fn get_popup(self: &Rc, parser: MsgParser<'_, '_>) -> Result<(), GetPopupError> { + let req: GetPopup = self.surface.client.parse(&**self, parser)?; + let mut data = self.surface.role_data.borrow_mut(); + if let RoleData::XdgSurface(data) = &mut *data { + let mut parent = None; + if req.parent.is_some() { + parent = Some(self.surface.client.get_xdg_surface(req.parent)?); + } + if !data.role.is_compatible(XdgSurfaceRole::Popup) { + return Err(GetPopupError::IncompatibleRole); + } + if data.role_data.is_some() { + self.surface.client.protocol_error( + &**self, + ALREADY_CONSTRUCTED, + format!( + "wl_surface {} already has an assigned xdg_popup", + self.surface.id + ), + ); + return Err(GetPopupError::AlreadyConstructed); + } + data.role = XdgSurfaceRole::Popup; + let popup = Rc::new(XdgPopup::new(req.id, self, self.version)); + self.surface.client.add_client_obj(&popup)?; + if let Some(parent) = &parent { + let mut data = parent.surface.role_data.borrow_mut(); + if let RoleData::XdgSurface(xdg) = &mut *data { + xdg.popups.set(self.surface.id, popup.clone()); + } + } + data.role_data = XdgSurfaceRoleData::Popup(XdgPopupData { popup, parent }); + } Ok(()) } @@ -86,7 +174,7 @@ impl XdgSurface { } async fn handle_request_( - &self, + self: &Rc, request: u32, parser: MsgParser<'_, '_>, ) -> Result<(), XdgSurfaceError> { @@ -106,7 +194,7 @@ handle_request!(XdgSurface); impl Object for XdgSurface { fn id(&self) -> ObjectId { - self.id + self.id.into() } fn interface(&self) -> Interface { diff --git a/src/ifs/wl_surface/xdg_surface/types.rs b/src/ifs/wl_surface/xdg_surface/types.rs index 18103823..d98f3226 100644 --- a/src/ifs/wl_surface/xdg_surface/types.rs +++ b/src/ifs/wl_surface/xdg_surface/types.rs @@ -1,11 +1,14 @@ use crate::client::{ClientError, EventFormatter, RequestParser}; -use crate::ifs::wl_surface::xdg_surface::{XdgSurface, CONFIGURE}; -use crate::object::{Object, ObjectId}; +use crate::ifs::wl_surface::xdg_surface::xdg_popup::XdgPopupId; +use crate::ifs::wl_surface::xdg_surface::xdg_toplevel::XdgToplevelId; +use crate::ifs::wl_surface::xdg_surface::{XdgSurface, XdgSurfaceId, CONFIGURE}; +use crate::ifs::wl_surface::{SurfaceRole, WlSurfaceId}; +use crate::ifs::xdg_positioner::XdgPositionerId; +use crate::object::Object; use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError}; use std::fmt::{Debug, Formatter}; use std::rc::Rc; use thiserror::Error; -use crate::ifs::wl_surface::SurfaceRole; #[derive(Debug, Error)] pub enum XdgSurfaceError { @@ -20,9 +23,9 @@ pub enum XdgSurfaceError { #[error("Could not process `ack_configure` request")] AckConfigureError(#[from] AckConfigureError), #[error("Surface {0} cannot be turned into a xdg_surface because it already has the role {}", .1.name())] - IncompatibleRole(ObjectId, SurfaceRole), + IncompatibleRole(WlSurfaceId, SurfaceRole), #[error("Surface {0} cannot be turned into a xdg_surface because it already has an attached xdg_surface")] - AlreadyAttached(ObjectId), + AlreadyAttached(WlSurfaceId), } #[derive(Debug, Error)] @@ -31,6 +34,8 @@ pub enum DestroyError { ParseFailed(#[source] Box), #[error(transparent)] ClientError(Box), + #[error("Cannot destroy xdg_surface {0} because it's associated xdg_toplevel/popup is not yet destroyed")] + RoleNotYetDestroyed(XdgSurfaceId), } efrom!(DestroyError, ParseFailed, MsgParserError); efrom!(DestroyError, ClientError, ClientError); @@ -41,6 +46,10 @@ pub enum GetToplevelError { ParseFailed(#[source] Box), #[error(transparent)] ClientError(Box), + #[error("The surface already has a different role")] + IncompatibleRole, + #[error("The surface already has an assigned xdg_toplevel")] + AlreadyConstructed, } efrom!(GetToplevelError, ParseFailed, MsgParserError); efrom!(GetToplevelError, ClientError, ClientError); @@ -51,6 +60,10 @@ pub enum GetPopupError { ParseFailed(#[source] Box), #[error(transparent)] ClientError(Box), + #[error("The surface already has a different role")] + IncompatibleRole, + #[error("The surface already has an assigned xdg_popup")] + AlreadyConstructed, } efrom!(GetPopupError, ParseFailed, MsgParserError); efrom!(GetPopupError, ClientError, ClientError); @@ -88,7 +101,7 @@ impl Debug for Destroy { } pub(super) struct GetToplevel { - pub id: ObjectId, + pub id: XdgToplevelId, } impl RequestParser<'_> for GetToplevel { fn parse(parser: &mut MsgParser<'_, '_>) -> Result { @@ -104,9 +117,9 @@ impl Debug for GetToplevel { } pub(super) struct GetPopup { - pub id: ObjectId, - pub parent: ObjectId, - pub positioner: ObjectId, + pub id: XdgPopupId, + pub parent: XdgSurfaceId, + pub positioner: XdgPositionerId, } impl RequestParser<'_> for GetPopup { fn parse(parser: &mut MsgParser<'_, '_>) -> 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 f1fccc81..cee098e8 100644 --- a/src/ifs/wl_surface/xdg_surface/xdg_popup/mod.rs +++ b/src/ifs/wl_surface/xdg_surface/xdg_popup/mod.rs @@ -1,6 +1,7 @@ mod types; use crate::ifs::wl_surface::xdg_surface::XdgSurface; +use crate::ifs::wl_surface::{RoleData, XdgSurfaceRoleData}; use crate::object::{Interface, Object, ObjectId}; use crate::utils::buffd::MsgParser; use std::rc::Rc; @@ -16,14 +17,16 @@ const REPOSITIONED: u32 = 2; const INVALID_GRAB: u32 = 1; +id!(XdgPopupId); + pub struct XdgPopup { - id: ObjectId, - surface: Rc, + id: XdgPopupId, + pub(in super::super) surface: Rc, version: u32, } impl XdgPopup { - pub fn new(id: ObjectId, surface: &Rc, version: u32) -> Self { + pub fn new(id: XdgPopupId, surface: &Rc, version: u32) -> Self { Self { id, surface: surface.clone(), @@ -33,6 +36,20 @@ impl XdgPopup { async fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> { let _req: Destroy = self.surface.surface.client.parse(self, parser)?; + { + let mut rd = self.surface.surface.role_data.borrow_mut(); + if let RoleData::XdgSurface(xdg) = &mut *rd { + if let XdgSurfaceRoleData::Popup(p) = &xdg.role_data { + if let Some(p) = &p.parent { + let mut rd = p.surface.role_data.borrow_mut(); + if let RoleData::XdgSurface(xdg) = &mut *rd { + xdg.popups.remove(&self.surface.surface.id); + } + } + } + xdg.role_data = XdgSurfaceRoleData::None; + } + } Ok(()) } @@ -65,7 +82,7 @@ handle_request!(XdgPopup); impl Object for XdgPopup { fn id(&self) -> ObjectId { - self.id + self.id.into() } fn interface(&self) -> Interface { diff --git a/src/ifs/wl_surface/xdg_surface/xdg_popup/types.rs b/src/ifs/wl_surface/xdg_surface/xdg_popup/types.rs index 52fe74fd..2c1b426d 100644 --- a/src/ifs/wl_surface/xdg_surface/xdg_popup/types.rs +++ b/src/ifs/wl_surface/xdg_surface/xdg_popup/types.rs @@ -1,8 +1,10 @@ use crate::client::{ClientError, EventFormatter, RequestParser}; +use crate::ifs::wl_seat::WlSeatId; use crate::ifs::wl_surface::xdg_surface::xdg_popup::{ XdgPopup, CONFIGURE, POPUP_DONE, REPOSITIONED, }; -use crate::object::{Object, ObjectId}; +use crate::ifs::xdg_positioner::XdgPositionerId; +use crate::object::Object; use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError}; use std::fmt::{Debug, Formatter}; use std::rc::Rc; @@ -61,7 +63,7 @@ impl Debug for Destroy { } pub(super) struct Grab { - pub seat: ObjectId, + pub seat: WlSeatId, pub serial: u32, } impl RequestParser<'_> for Grab { @@ -79,7 +81,7 @@ impl Debug for Grab { } pub(super) struct Reposition { - pub positioner: ObjectId, + pub positioner: XdgPositionerId, pub token: u32, } impl RequestParser<'_> for Reposition { 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 cf541ff3..20806aac 100644 --- a/src/ifs/wl_surface/xdg_surface/xdg_toplevel/mod.rs +++ b/src/ifs/wl_surface/xdg_surface/xdg_toplevel/mod.rs @@ -1,6 +1,7 @@ mod types; use crate::ifs::wl_surface::xdg_surface::XdgSurface; +use crate::ifs::wl_surface::{RoleData, XdgSurfaceRoleData}; use crate::object::{Interface, Object, ObjectId}; use crate::utils::buffd::MsgParser; use num_derive::FromPrimitive; @@ -47,14 +48,16 @@ const STATE_TILED_RIGHT: u32 = 6; const STATE_TILED_TOP: u32 = 7; const STATE_TILED_BOTTOM: u32 = 8; +id!(XdgToplevelId); + pub struct XdgToplevel { - id: ObjectId, + id: XdgToplevelId, surface: Rc, version: u32, } impl XdgToplevel { - pub fn new(id: ObjectId, surface: &Rc, version: u32) -> Self { + pub fn new(id: XdgToplevelId, surface: &Rc, version: u32) -> Self { Self { id, surface: surface.clone(), @@ -64,6 +67,12 @@ impl XdgToplevel { async fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> { let _req: Destroy = self.surface.surface.client.parse(self, parser)?; + { + let mut rd = self.surface.surface.role_data.borrow_mut(); + if let RoleData::XdgSurface(rd) = &mut *rd { + rd.role_data = XdgSurfaceRoleData::None; + } + } Ok(()) } @@ -165,7 +174,7 @@ handle_request!(XdgToplevel); impl Object for XdgToplevel { fn id(&self) -> ObjectId { - self.id + self.id.into() } fn interface(&self) -> Interface { diff --git a/src/ifs/wl_surface/xdg_surface/xdg_toplevel/types.rs b/src/ifs/wl_surface/xdg_surface/xdg_toplevel/types.rs index c7698994..d9677810 100644 --- a/src/ifs/wl_surface/xdg_surface/xdg_toplevel/types.rs +++ b/src/ifs/wl_surface/xdg_surface/xdg_toplevel/types.rs @@ -1,7 +1,8 @@ use super::CONFIGURE; use crate::client::{ClientError, EventFormatter, RequestParser}; -use crate::ifs::wl_surface::xdg_surface::xdg_toplevel::{XdgToplevel, CLOSE}; -use crate::object::{Object, ObjectId}; +use crate::ifs::wl_seat::WlSeatId; +use crate::ifs::wl_surface::xdg_surface::xdg_toplevel::{XdgToplevel, XdgToplevelId, CLOSE}; +use crate::object::Object; use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError}; use std::fmt::{Debug, Formatter}; use std::rc::Rc; @@ -192,11 +193,13 @@ impl Debug for Destroy { } pub(super) struct SetParent { - pub parent: ObjectId, + pub parent: XdgToplevelId, } impl RequestParser<'_> for SetParent { fn parse(parser: &mut MsgParser<'_, '_>) -> Result { - Ok(Self { parent: parser.object()? }) + Ok(Self { + parent: parser.object()?, + }) } } impl Debug for SetParent { @@ -210,7 +213,9 @@ pub(super) struct SetTitle<'a> { } impl<'a> RequestParser<'a> for SetTitle<'a> { fn parse(parser: &mut MsgParser<'_, 'a>) -> Result { - Ok(Self { title: parser.string()? }) + Ok(Self { + title: parser.string()?, + }) } } impl<'a> Debug for SetTitle<'a> { @@ -224,7 +229,9 @@ pub(super) struct SetAppId<'a> { } impl<'a> RequestParser<'a> for SetAppId<'a> { fn parse(parser: &mut MsgParser<'_, 'a>) -> Result { - Ok(Self { app_id: parser.string()? }) + Ok(Self { + app_id: parser.string()?, + }) } } impl<'a> Debug for SetAppId<'a> { @@ -234,7 +241,7 @@ impl<'a> Debug for SetAppId<'a> { } pub(super) struct ShowWindowMenu { - pub seat: ObjectId, + pub seat: WlSeatId, pub serial: u32, pub x: i32, pub y: i32, @@ -251,17 +258,24 @@ impl RequestParser<'_> for ShowWindowMenu { } impl Debug for ShowWindowMenu { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "show_window_menu(seat: {}, serial: {}, x: {}, y: {})", self.seat, self.serial, self.x, self.y) + write!( + f, + "show_window_menu(seat: {}, serial: {}, x: {}, y: {})", + self.seat, self.serial, self.x, self.y + ) } } pub(super) struct Move { - pub seat: ObjectId, + pub seat: WlSeatId, pub serial: u32, } impl RequestParser<'_> for Move { fn parse(parser: &mut MsgParser<'_, '_>) -> Result { - Ok(Self { seat: parser.object()?, serial: parser.uint()? }) + Ok(Self { + seat: parser.object()?, + serial: parser.uint()?, + }) } } impl Debug for Move { @@ -271,7 +285,7 @@ impl Debug for Move { } pub(super) struct Resize { - pub seat: ObjectId, + pub seat: WlSeatId, pub serial: u32, pub edges: u32, } @@ -286,7 +300,11 @@ impl RequestParser<'_> for Resize { } impl Debug for Resize { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "resize(seat: {}, serial: {}, edges: {})", self.seat, self.serial, self.edges) + write!( + f, + "resize(seat: {}, serial: {}, edges: {})", + self.seat, self.serial, self.edges + ) } } @@ -296,12 +314,19 @@ pub(super) struct SetMaxSize { } impl RequestParser<'_> for SetMaxSize { fn parse(parser: &mut MsgParser<'_, '_>) -> Result { - Ok(Self { width: parser.int()?, height: parser.int()? }) + Ok(Self { + width: parser.int()?, + height: parser.int()?, + }) } } impl Debug for SetMaxSize { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "set_max_size(width: {}, height: {})", self.width, self.height) + write!( + f, + "set_max_size(width: {}, height: {})", + self.width, self.height + ) } } @@ -311,12 +336,19 @@ pub(super) struct SetMinSize { } impl RequestParser<'_> for SetMinSize { fn parse(parser: &mut MsgParser<'_, '_>) -> Result { - Ok(Self { width: parser.int()?, height: parser.int()? }) + Ok(Self { + width: parser.int()?, + height: parser.int()?, + }) } } impl Debug for SetMinSize { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "set_min_size(width: {}, height: {})", self.width, self.height) + write!( + f, + "set_min_size(width: {}, height: {})", + self.width, self.height + ) } } @@ -345,11 +377,13 @@ impl Debug for UnsetMaximized { } pub(super) struct SetFullscreen { - pub output: ObjectId, + pub output: crate::ifs::wl_output::WlOutputId, } impl RequestParser<'_> for SetFullscreen { fn parse(parser: &mut MsgParser<'_, '_>) -> Result { - Ok(Self { output: parser.object()? }) + Ok(Self { + output: parser.object()?, + }) } } impl Debug for SetFullscreen { diff --git a/src/ifs/xdg_positioner/mod.rs b/src/ifs/xdg_positioner/mod.rs index 4e24033f..c638ee37 100644 --- a/src/ifs/xdg_positioner/mod.rs +++ b/src/ifs/xdg_positioner/mod.rs @@ -74,8 +74,10 @@ bitflags! { } } +id!(XdgPositionerId); + pub struct XdgPositioner { - id: ObjectId, + id: XdgPositionerId, client: Rc, version: u32, position: RefCell, @@ -101,7 +103,7 @@ pub struct XdgPositioned { } impl XdgPositioner { - pub fn new(id: ObjectId, client: &Rc, version: u32) -> Self { + pub fn new(id: XdgPositionerId, client: &Rc, version: u32) -> Self { Self { id, client: client.clone(), @@ -256,7 +258,7 @@ handle_request!(XdgPositioner); impl Object for XdgPositioner { fn id(&self) -> ObjectId { - self.id + self.id.into() } fn interface(&self) -> Interface { diff --git a/src/ifs/xdg_wm_base/mod.rs b/src/ifs/xdg_wm_base/mod.rs index 29d33390..a0ade427 100644 --- a/src/ifs/xdg_wm_base/mod.rs +++ b/src/ifs/xdg_wm_base/mod.rs @@ -2,7 +2,7 @@ mod types; use crate::client::{AddObj, Client}; use crate::globals::{Global, GlobalName}; -use crate::ifs::wl_surface::xdg_surface::XdgSurface; +use crate::ifs::wl_surface::xdg_surface::{XdgSurface, XdgSurfaceId}; use crate::ifs::xdg_positioner::XdgPositioner; use crate::object::{Interface, Object, ObjectId}; use crate::utils::buffd::MsgParser; @@ -24,16 +24,18 @@ const INVALID_POPUP_PARENT: u32 = 3; const INVALID_SURFACE_STATE: u32 = 4; const INVALID_POSITIONER: u32 = 5; +id!(XdgWmBaseId); + pub struct XdgWmBaseGlobal { name: GlobalName, } pub struct XdgWmBaseObj { global: Rc, - id: ObjectId, + id: XdgWmBaseId, client: Rc, version: u32, - pub(super) surfaces: CopyHashMap>, + pub(super) surfaces: CopyHashMap>, } impl XdgWmBaseGlobal { @@ -43,7 +45,7 @@ impl XdgWmBaseGlobal { async fn bind_( self: Rc, - id: ObjectId, + id: XdgWmBaseId, client: &Rc, version: u32, ) -> Result<(), XdgWmBaseError> { @@ -60,10 +62,6 @@ impl XdgWmBaseGlobal { } impl XdgWmBaseObj { - pub fn break_loops(&self) { - self.surfaces.clear(); - } - async fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> { let _req: Destroy = self.client.parse(self, parser)?; if !self.surfaces.is_empty() { @@ -91,7 +89,10 @@ impl XdgWmBaseObj { Ok(()) } - async fn get_xdg_surface(self: &Rc, parser: MsgParser<'_, '_>) -> Result<(), GetXdgSurfaceError> { + async fn get_xdg_surface( + self: &Rc, + parser: MsgParser<'_, '_>, + ) -> Result<(), GetXdgSurfaceError> { let req: GetXdgSurface = self.client.parse(&**self, parser)?; let surface = self.client.get_surface(req.surface)?; let xdg_surface = Rc::new(XdgSurface::new(self, req.id, &surface, 3)); @@ -146,7 +147,7 @@ handle_request!(XdgWmBaseObj); impl Object for XdgWmBaseObj { fn id(&self) -> ObjectId { - self.id + self.id.into() } fn interface(&self) -> Interface { @@ -156,4 +157,8 @@ impl Object for XdgWmBaseObj { fn num_requests(&self) -> u32 { PONG + 1 } + + fn break_loops(&self) { + self.surfaces.clear(); + } } diff --git a/src/ifs/xdg_wm_base/types.rs b/src/ifs/xdg_wm_base/types.rs index 9f6a9428..8754da90 100644 --- a/src/ifs/xdg_wm_base/types.rs +++ b/src/ifs/xdg_wm_base/types.rs @@ -1,11 +1,13 @@ 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::object::{Object, ObjectId}; +use crate::object::Object; use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError}; use std::fmt::{Debug, Formatter}; use std::rc::Rc; use thiserror::Error; -use crate::ifs::wl_surface::xdg_surface::XdgSurfaceError; #[derive(Debug, Error)] pub enum XdgWmBaseError { @@ -77,7 +79,7 @@ impl Debug for Destroy { } pub(super) struct CreatePositioner { - pub id: ObjectId, + pub id: XdgPositionerId, } impl RequestParser<'_> for CreatePositioner { fn parse(parser: &mut MsgParser<'_, '_>) -> Result { @@ -93,8 +95,8 @@ impl Debug for CreatePositioner { } pub(super) struct GetXdgSurface { - pub id: ObjectId, - pub surface: ObjectId, + pub id: XdgSurfaceId, + pub surface: WlSurfaceId, } impl RequestParser<'_> for GetXdgSurface { fn parse(parser: &mut MsgParser<'_, '_>) -> Result { diff --git a/src/macros.rs b/src/macros.rs index 5c121eb3..cc2595f4 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -39,10 +39,56 @@ macro_rules! bind { Box> + 'a>, > { Box::pin(async move { - self.bind_(id, client, version).await?; + self.bind_(id.into(), client, version).await?; Ok(()) }) } } }; } + +macro_rules! id { + ($name:ident) => { + #[derive(Debug, Copy, Clone, Hash, Ord, PartialOrd, Eq, PartialEq)] + pub struct $name(u32); + + #[allow(dead_code)] + impl $name { + pub const NONE: Self = $name(0); + + pub fn from_raw(raw: u32) -> Self { + Self(raw) + } + + pub fn raw(self) -> u32 { + self.0 + } + + pub fn is_some(self) -> bool { + self.0 != 0 + } + + pub fn is_none(self) -> bool { + self.0 == 0 + } + } + + impl From for $name { + fn from(f: crate::object::ObjectId) -> Self { + Self(f.raw()) + } + } + + impl From<$name> for crate::object::ObjectId { + fn from(f: $name) -> Self { + crate::object::ObjectId::from_raw(f.0) + } + } + + impl std::fmt::Display for $name { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(&self.0, f) + } + } + }; +} diff --git a/src/object.rs b/src/object.rs index af115f35..2264a369 100644 --- a/src/object.rs +++ b/src/object.rs @@ -11,6 +11,8 @@ pub const WL_DISPLAY_ID: ObjectId = ObjectId(1); pub struct ObjectId(u32); impl ObjectId { + pub const NONE: Self = ObjectId(0); + pub fn from_raw(raw: u32) -> Self { Self(raw) } @@ -38,6 +40,7 @@ pub trait Object: ObjectHandleRequest + 'static { fn id(&self) -> ObjectId; fn interface(&self) -> Interface; fn num_requests(&self) -> u32; + fn break_loops(&self) {} } #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -57,6 +60,7 @@ pub enum Interface { XdgPopup, XdgToplevel, WlRegion, + WlBuffer, } impl Interface { @@ -77,6 +81,7 @@ impl Interface { Interface::XdgPositioner => "xdg_positioner", Interface::XdgPopup => "xdg_popup", Interface::XdgToplevel => "xdg_toplevel", + Interface::WlBuffer => "wl_buffer", } } } diff --git a/src/utils/buffd/formatter.rs b/src/utils/buffd/formatter.rs index 87a45920..bb6e0732 100644 --- a/src/utils/buffd/formatter.rs +++ b/src/utils/buffd/formatter.rs @@ -1,7 +1,7 @@ use crate::object::ObjectId; use crate::utils::buffd::buf_out::{BufFdOut, MsgFds}; use std::mem; -use std::mem::{MaybeUninit}; +use std::mem::MaybeUninit; use uapi::OwnedFd; pub struct MsgFormatter<'a> { @@ -50,11 +50,11 @@ impl<'a> MsgFormatter<'a> { self } - pub fn object(&mut self, obj: ObjectId) -> &mut Self { - self.uint(obj.raw()) + pub fn object>(&mut self, obj: T) -> &mut Self { + self.uint(obj.into().raw()) } - pub fn header(&mut self, obj: ObjectId, event: u32) -> &mut Self { + pub fn header>(&mut self, obj: T, event: u32) -> &mut Self { self.object(obj).uint(event) } diff --git a/src/utils/buffd/parser.rs b/src/utils/buffd/parser.rs index 7cf3437a..1abe5ce8 100644 --- a/src/utils/buffd/parser.rs +++ b/src/utils/buffd/parser.rs @@ -46,8 +46,11 @@ impl<'a, 'b> MsgParser<'a, 'b> { self.int().map(|i| i as u32) } - pub fn object(&mut self) -> Result { - self.int().map(|i| ObjectId::from_raw(i as u32)) + pub fn object(&mut self) -> Result + where + ObjectId: Into, + { + self.int().map(|i| ObjectId::from_raw(i as u32).into()) } pub fn global(&mut self) -> Result {