diff --git a/src/client/mod.rs b/src/client/mod.rs index 624e0eaa..003f6930 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -7,21 +7,22 @@ use crate::ifs::wl_region::{WlRegion, WlRegionError}; use crate::ifs::wl_registry::{WlRegistry, WlRegistryError}; use crate::ifs::wl_shm::{WlShmError, WlShmObj}; use crate::ifs::wl_shm_pool::{WlShmPool, WlShmPoolError}; -use crate::ifs::wl_subcompositor::WlSubcompositorObj; +use crate::ifs::wl_subcompositor::{WlSubcompositorError, WlSubcompositorObj}; +use crate::ifs::wl_surface::wl_subsurface::{WlSubsurface, WlSubsurfaceError}; use crate::ifs::wl_surface::{WlSurface, WlSurfaceError}; use crate::ifs::xdg_wm_base::XdgWmBaseObj; use crate::object::{Object, ObjectId, WL_DISPLAY_ID}; use crate::state::State; -use crate::utils::buffd::{BufFdError, WlFormatter, WlParser, WlParserError}; -use crate::utils::copyhashmap::CopyHashMap; +use crate::utils::buffd::{BufFdError, MsgFormatter, MsgParser, MsgParserError}; use crate::utils::numcell::NumCell; use crate::utils::oneshot::{oneshot, OneshotTx}; use crate::utils::queue::AsyncQueue; use ahash::AHashMap; use anyhow::anyhow; -use std::cell::{Cell, RefMut}; +use std::cell::{Cell, RefCell, RefMut}; use std::fmt::{Debug, Display, Formatter}; use std::future::Future; +use std::mem; use std::rc::Rc; use thiserror::Error; use uapi::OwnedFd; @@ -51,8 +52,10 @@ pub enum ClientError { ClientDoesNotExist(ClientId), #[error("There is no region with id {0}")] RegionDoesNotExist(ObjectId), + #[error("There is no surface with id {0}")] + SurfaceDoesNotExist(ObjectId), #[error("Cannot parse the message")] - ParserError(#[source] Box), + ParserError(#[source] Box), #[error("Server tried to allocate more than 0x1_00_00_00 ids")] TooManyIds, #[error("The server object id is out of bounds")] @@ -79,11 +82,15 @@ pub enum ClientError { 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("Object {0} is not a display")] NotADisplay(ObjectId), } -efrom!(ClientError, ParserError, WlParserError); +efrom!(ClientError, ParserError, MsgParserError); efrom!(ClientError, WlDisplayError, WlDisplayError); efrom!(ClientError, WlRegistryError, WlRegistryError); efrom!(ClientError, WlSurfaceError, WlSurfaceError); @@ -91,6 +98,8 @@ efrom!(ClientError, WlCompositorError, WlCompositorError); efrom!(ClientError, WlShmError, WlShmError); efrom!(ClientError, WlShmPoolError, WlShmPoolError); efrom!(ClientError, WlRegionError, WlRegionError); +efrom!(ClientError, WlSubsurfaceError, WlSubsurfaceError); +efrom!(ClientError, WlSubcompositorError, WlSubcompositorError); impl ClientError { fn peer_closed(&self) -> bool { @@ -112,16 +121,16 @@ impl Display for ClientId { pub struct Clients { next_client_id: NumCell, - clients: CopyHashMap>, - shutdown_clients: CopyHashMap>, + clients: RefCell>, + shutdown_clients: RefCell>, } impl Clients { pub fn new() -> Self { Self { next_client_id: NumCell::new(1), - clients: CopyHashMap::new(), - shutdown_clients: CopyHashMap::new(), + clients: Default::default(), + shutdown_clients: Default::default(), } } @@ -130,7 +139,8 @@ impl Clients { } pub fn get(&self, id: ClientId) -> Result, ClientError> { - match self.clients.get(&id) { + let clients = self.clients.borrow(); + match clients.get(&id) { Some(c) => Ok(c.data.clone()), _ => Err(ClientError::ClientDoesNotExist(id)), } @@ -155,29 +165,29 @@ impl Clients { data.objects .add_client_object(Rc::new(WlDisplay::new(&data))) .expect(""); - let client = Rc::new(ClientHolder { + let client = ClientHolder { _handler: global.eng.spawn(tasks::client(data.clone(), recv)), data, - }); - self.clients.set(client.data.id, client.clone()); + }; + self.clients.borrow_mut().insert(client.data.id, client); log::info!("Client {} connected", id); Ok(()) } pub fn kill(&self, client: ClientId) { log::info!("Removing client {}", client.0); - if self.clients.remove(&client).is_none() { - self.shutdown_clients.remove(&client); + if self.clients.borrow_mut().remove(&client).is_none() { + self.shutdown_clients.borrow_mut().remove(&client); } } pub fn shutdown(&self, client_id: ClientId) { - if let Some(client) = self.clients.remove(&client_id) { + if let Some(client) = self.clients.borrow_mut().remove(&client_id) { log::info!("Shutting down client {}", client.data.id.0); client.data.shutdown.replace(None).unwrap().send(()); client.data.events.push(WlEvent::Shutdown); client.data.shutdown_sent.set(true); - self.shutdown_clients.set(client_id, client); + self.shutdown_clients.borrow_mut().insert(client_id, client); } } @@ -185,13 +195,20 @@ impl Clients { where B: FnMut(&Rc), { - let clients = self.clients.lock(); + let clients = self.clients.borrow(); for client in clients.values() { f(&client.data); } } } +impl Drop for Clients { + fn drop(&mut self) { + let _clients1 = mem::take(&mut *self.clients.borrow_mut()); + let _clients2 = mem::take(&mut *self.shutdown_clients.borrow_mut()); + } +} + struct ClientHolder { data: Rc, _handler: SpawnedFuture<()>, @@ -204,14 +221,14 @@ impl Drop for ClientHolder { } pub trait EventFormatter: Debug { - fn format(self: Box, fmt: &mut WlFormatter<'_>); + fn format(self: Box, fmt: &mut MsgFormatter<'_>); fn obj(&self) -> &dyn Object; } pub type DynEventFormatter = Box; pub trait RequestParser<'a>: Debug + Sized { - fn parse(parser: &mut WlParser<'_, 'a>) -> Result; + fn parse(parser: &mut MsgParser<'_, 'a>) -> Result; } enum WlEvent { @@ -261,8 +278,8 @@ impl Client { pub fn parse<'a, R: RequestParser<'a>>( &self, obj: &impl Object, - mut parser: WlParser<'_, 'a>, - ) -> Result { + mut parser: MsgParser<'_, 'a>, + ) -> Result { let res = R::parse(&mut parser)?; parser.eof()?; log::trace!( @@ -313,6 +330,13 @@ impl Client { } } + pub fn get_surface(&self, id: ObjectId) -> Result, ClientError> { + match self.objects.surfaces.get(&id) { + Some(r) => Ok(r), + _ => Err(ClientError::SurfaceDoesNotExist(id)), + } + } + fn simple_add_obj(&self, obj: &Rc, client: bool) -> Result<(), ClientError> { if client { self.objects.add_client_object(obj.clone()) @@ -332,6 +356,17 @@ impl Client { pub fn lock_registries(&self) -> RefMut>> { self.objects.registries() } + + pub fn log_event(&self, event: &dyn EventFormatter) { + let obj = event.obj(); + log::trace!( + "Client {} <= {}@{}.{:?}", + self.id, + obj.interface().name(), + obj.id(), + event, + ); + } } pub trait AddObj { @@ -371,6 +406,7 @@ simple_add_obj!(WlRegistry); simple_add_obj!(WlShmObj); simple_add_obj!(WlShmPool); simple_add_obj!(WlSubcompositorObj); +simple_add_obj!(WlSubsurface); simple_add_obj!(XdgWmBaseObj); macro_rules! dedicated_add_obj { diff --git a/src/client/objects.rs b/src/client/objects.rs index 758244ae..014b1c9e 100644 --- a/src/client/objects.rs +++ b/src/client/objects.rs @@ -32,7 +32,14 @@ impl Objects { } pub fn destroy(&self) { + { + let mut surfaces = self.surfaces.lock(); + for surface in surfaces.values_mut() { + surface.break_loops(); + } + } self.registry.clear(); + self.regions.clear(); self.registries.clear(); self.surfaces.clear(); } diff --git a/src/client/tasks.rs b/src/client/tasks.rs index e6e8a203..c21e9be1 100644 --- a/src/client/tasks.rs +++ b/src/client/tasks.rs @@ -1,6 +1,6 @@ use crate::client::{Client, ClientError, WlEvent}; use crate::object::ObjectId; -use crate::utils::buffd::{BufFdIn, BufFdOut, WlFormatter, WlParser}; +use crate::utils::buffd::{BufFdIn, BufFdOut, MsgFormatter, MsgParser}; use crate::utils::oneshot::OneshotRx; use crate::utils::vec_ext::VecExt; use anyhow::anyhow; @@ -69,7 +69,7 @@ async fn receive(data: Rc) { data_buf.set_len(len); } // log::trace!("{:x?}", data_buf); - let parser = WlParser::new(&mut buf, &data_buf[..]); + let parser = MsgParser::new(&mut buf, &data_buf[..]); if let Err(e) = obj.handle_request(request, parser).await { return Err(ClientError::RequestError(Box::new(e))); } @@ -112,16 +112,9 @@ async fn send(data: Rc) { } WlEvent::Event(e) => { if log::log_enabled!(log::Level::Trace) { - let obj = e.obj(); - log::trace!( - "Client {} <= {}@{}.{:?}", - data.id, - obj.interface().name(), - obj.id(), - e - ); + data.log_event(&*e); } - e.format(&mut WlFormatter::new(&mut buf)); + e.format(&mut MsgFormatter::new(&mut buf)); if buf.needs_flush() { buf.flush().await?; flush_requested = false; diff --git a/src/ifs/wl_callback/mod.rs b/src/ifs/wl_callback/mod.rs index e9e5a7b5..eac41fe8 100644 --- a/src/ifs/wl_callback/mod.rs +++ b/src/ifs/wl_callback/mod.rs @@ -2,7 +2,7 @@ mod types; use crate::client::{ClientError, DynEventFormatter}; use crate::object::{Interface, Object, ObjectId}; -use crate::utils::buffd::WlParser; +use crate::utils::buffd::MsgParser; use std::rc::Rc; use types::*; @@ -24,7 +24,7 @@ impl WlCallback { async fn handle_request_( &self, _request: u32, - _parser: WlParser<'_, '_>, + _parser: MsgParser<'_, '_>, ) -> Result<(), ClientError> { unreachable!(); } diff --git a/src/ifs/wl_callback/types.rs b/src/ifs/wl_callback/types.rs index 95132169..6e02ec63 100644 --- a/src/ifs/wl_callback/types.rs +++ b/src/ifs/wl_callback/types.rs @@ -1,7 +1,7 @@ use crate::client::EventFormatter; use crate::ifs::wl_callback::{WlCallback, DONE}; use crate::object::Object; -use crate::utils::buffd::WlFormatter; +use crate::utils::buffd::MsgFormatter; use std::fmt::{Debug, Formatter}; use std::rc::Rc; @@ -9,7 +9,7 @@ pub(super) struct Done { pub obj: Rc, } impl EventFormatter for Done { - fn format(self: Box, fmt: &mut WlFormatter<'_>) { + fn format(self: Box, fmt: &mut MsgFormatter<'_>) { fmt.header(self.obj.id, DONE).uint(0); } fn obj(&self) -> &dyn Object { diff --git a/src/ifs/wl_compositor/mod.rs b/src/ifs/wl_compositor/mod.rs index 3cf16ca9..cdfbce10 100644 --- a/src/ifs/wl_compositor/mod.rs +++ b/src/ifs/wl_compositor/mod.rs @@ -5,7 +5,7 @@ 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::utils::buffd::WlParser; +use crate::utils::buffd::MsgParser; use std::rc::Rc; pub use types::*; @@ -46,14 +46,14 @@ impl WlCompositorGlobal { } impl WlCompositorObj { - async fn create_surface(&self, parser: WlParser<'_, '_>) -> Result<(), CreateSurfaceError> { + async 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)); self.client.add_client_obj(&surface)?; Ok(()) } - async fn create_region(&self, parser: WlParser<'_, '_>) -> Result<(), CreateRegionError> { + async fn create_region(&self, parser: MsgParser<'_, '_>) -> Result<(), CreateRegionError> { let region: CreateRegion = self.client.parse(self, parser)?; let region = Rc::new(WlRegion::new(region.id, &self.client)); self.client.add_client_obj(®ion)?; @@ -63,7 +63,7 @@ impl WlCompositorObj { async fn handle_request_( &self, request: u32, - parser: WlParser<'_, '_>, + parser: MsgParser<'_, '_>, ) -> Result<(), WlCompositorError> { match request { CREATE_SURFACE => self.create_surface(parser).await?, diff --git a/src/ifs/wl_compositor/types.rs b/src/ifs/wl_compositor/types.rs index 57ff263c..5b4fe530 100644 --- a/src/ifs/wl_compositor/types.rs +++ b/src/ifs/wl_compositor/types.rs @@ -1,6 +1,6 @@ use crate::client::{ClientError, RequestParser}; use crate::object::ObjectId; -use crate::utils::buffd::{WlParser, WlParserError}; +use crate::utils::buffd::{MsgParser, MsgParserError}; use std::fmt::{Debug, Formatter}; use thiserror::Error; @@ -21,30 +21,30 @@ efrom!(WlCompositorError, CreateRegionError, CreateRegionError); #[derive(Debug, Error)] pub enum CreateSurfaceError { #[error("Parsing failed")] - ParseFailed(#[source] Box), + ParseFailed(#[source] Box), #[error(transparent)] ClientError(Box), } -efrom!(CreateSurfaceError, ParseFailed, WlParserError); +efrom!(CreateSurfaceError, ParseFailed, MsgParserError); efrom!(CreateSurfaceError, ClientError, ClientError); #[derive(Debug, Error)] pub enum CreateRegionError { #[error("Parsing failed")] - ParseFailed(#[source] Box), + ParseFailed(#[source] Box), #[error(transparent)] ClientError(Box), } -efrom!(CreateRegionError, ParseFailed, WlParserError); +efrom!(CreateRegionError, ParseFailed, MsgParserError); efrom!(CreateRegionError, ClientError, ClientError); pub(super) struct CreateSurface { pub id: ObjectId, } impl RequestParser<'_> for CreateSurface { - fn parse(parser: &mut WlParser<'_, '_>) -> Result { + fn parse(parser: &mut MsgParser<'_, '_>) -> Result { Ok(Self { id: parser.object()?, }) @@ -60,7 +60,7 @@ pub(super) struct CreateRegion { pub id: ObjectId, } impl RequestParser<'_> for CreateRegion { - fn parse(parser: &mut WlParser<'_, '_>) -> Result { + fn parse(parser: &mut MsgParser<'_, '_>) -> Result { Ok(Self { id: parser.object()?, }) diff --git a/src/ifs/wl_display/mod.rs b/src/ifs/wl_display/mod.rs index 12ed592f..604f7da4 100644 --- a/src/ifs/wl_display/mod.rs +++ b/src/ifs/wl_display/mod.rs @@ -4,7 +4,7 @@ use crate::client::{AddObj, Client, ClientError, DynEventFormatter}; use crate::ifs::wl_callback::WlCallback; use crate::ifs::wl_registry::WlRegistry; use crate::object::{Interface, Object, ObjectId, WL_DISPLAY_ID}; -use crate::utils::buffd::WlParser; +use crate::utils::buffd::MsgParser; use std::rc::Rc; pub use types::*; @@ -33,7 +33,7 @@ impl WlDisplay { async fn handle_request_( &self, request: u32, - parser: WlParser<'_, '_>, + parser: MsgParser<'_, '_>, ) -> Result<(), WlDisplayError> { match request { SYNC => self.sync(parser).await?, @@ -43,7 +43,7 @@ impl WlDisplay { Ok(()) } - async fn sync(&self, parser: WlParser<'_, '_>) -> Result<(), SyncError> { + async fn sync(&self, parser: MsgParser<'_, '_>) -> Result<(), SyncError> { let sync: Sync = self.client.parse(self, parser)?; let cb = Rc::new(WlCallback::new(sync.callback)); self.client.add_client_obj(&cb)?; @@ -52,7 +52,7 @@ impl WlDisplay { Ok(()) } - async fn get_registry(&self, parser: WlParser<'_, '_>) -> Result<(), GetRegistryError> { + async fn get_registry(&self, parser: MsgParser<'_, '_>) -> Result<(), GetRegistryError> { let gr: GetRegistry = self.client.parse(self, parser)?; let registry = Rc::new(WlRegistry::new(gr.registry, &self.client)); self.client.add_client_obj(®istry)?; diff --git a/src/ifs/wl_display/types.rs b/src/ifs/wl_display/types.rs index c7fb4335..22ca5685 100644 --- a/src/ifs/wl_display/types.rs +++ b/src/ifs/wl_display/types.rs @@ -2,7 +2,7 @@ use crate::client::{ClientError, EventFormatter, RequestParser}; use crate::globals::GlobalError; use crate::ifs::wl_display::{WlDisplay, DELETE_ID, ERROR}; use crate::object::{Object, ObjectId, WL_DISPLAY_ID}; -use crate::utils::buffd::{WlFormatter, WlParser, WlParserError}; +use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError}; use std::fmt::{Debug, Formatter}; use std::rc::Rc; use thiserror::Error; @@ -21,33 +21,33 @@ efrom!(WlDisplayError, SyncError, SyncError); #[derive(Debug, Error)] pub enum GetRegistryError { #[error("Parsing failed")] - ParseFailed(#[source] Box), + ParseFailed(#[source] Box), #[error(transparent)] ClientError(Box), #[error("An error occurred while processing globals")] GlobalError(#[source] Box), } -efrom!(GetRegistryError, ParseFailed, WlParserError); +efrom!(GetRegistryError, ParseFailed, MsgParserError); efrom!(GetRegistryError, GlobalError, GlobalError); efrom!(GetRegistryError, ClientError, ClientError); #[derive(Debug, Error)] pub enum SyncError { #[error("Parsing failed")] - ParseFailed(#[source] Box), + ParseFailed(#[source] Box), #[error(transparent)] ClientError(Box), } -efrom!(SyncError, ParseFailed, WlParserError); +efrom!(SyncError, ParseFailed, MsgParserError); efrom!(SyncError, ClientError, ClientError); pub(super) struct GetRegistry { pub registry: ObjectId, } impl RequestParser<'_> for GetRegistry { - fn parse(parser: &mut WlParser<'_, '_>) -> Result { + fn parse(parser: &mut MsgParser<'_, '_>) -> Result { Ok(Self { registry: parser.object()?, }) @@ -63,7 +63,7 @@ pub(super) struct Sync { pub callback: ObjectId, } impl RequestParser<'_> for Sync { - fn parse(parser: &mut WlParser<'_, '_>) -> Result { + fn parse(parser: &mut MsgParser<'_, '_>) -> Result { Ok(Self { callback: parser.object()?, }) @@ -80,7 +80,7 @@ pub(super) struct DeleteId { pub id: ObjectId, } impl EventFormatter for DeleteId { - fn format(self: Box, fmt: &mut WlFormatter<'_>) { + fn format(self: Box, fmt: &mut MsgFormatter<'_>) { fmt.header(WL_DISPLAY_ID, DELETE_ID).object(self.id); } fn obj(&self) -> &dyn Object { @@ -100,7 +100,7 @@ pub(super) struct Error { pub message: String, } impl EventFormatter for Error { - fn format(self: Box, fmt: &mut WlFormatter<'_>) { + fn format(self: Box, fmt: &mut MsgFormatter<'_>) { fmt.header(WL_DISPLAY_ID, ERROR) .object(self.object_id) .uint(self.code) diff --git a/src/ifs/wl_region/mod.rs b/src/ifs/wl_region/mod.rs index 2a2c21ee..b7525b2b 100644 --- a/src/ifs/wl_region/mod.rs +++ b/src/ifs/wl_region/mod.rs @@ -3,7 +3,7 @@ mod types; use crate::client::{AddObj, Client}; use crate::object::{Interface, Object, ObjectId}; use crate::pixman::Region; -use crate::utils::buffd::WlParser; +use crate::utils::buffd::MsgParser; use std::cell::RefCell; use std::rc::Rc; pub use types::*; @@ -31,13 +31,13 @@ impl WlRegion { self.rect.borrow().clone() } - async fn destroy(&self, parser: WlParser<'_, '_>) -> Result<(), DestroyError> { + async fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> { let _destroy: Destroy = self.client.parse(self, parser)?; self.client.remove_obj(self).await?; Ok(()) } - async fn add(&self, parser: WlParser<'_, '_>) -> Result<(), AddError> { + async fn add(&self, parser: MsgParser<'_, '_>) -> Result<(), AddError> { let add: Add = self.client.parse(self, parser)?; if add.width < 0 || add.height < 0 { return Err(AddError::NegativeExtents); @@ -47,7 +47,7 @@ impl WlRegion { Ok(()) } - async fn subtract(&self, parser: WlParser<'_, '_>) -> Result<(), SubtractError> { + async fn subtract(&self, parser: MsgParser<'_, '_>) -> Result<(), SubtractError> { let subtract: Subtract = self.client.parse(self, parser)?; if subtract.width < 0 || subtract.height < 0 { return Err(SubtractError::NegativeExtents); @@ -65,7 +65,7 @@ impl WlRegion { async fn handle_request_( &self, request: u32, - parser: WlParser<'_, '_>, + parser: MsgParser<'_, '_>, ) -> Result<(), WlRegionError> { match request { DESTROY => self.destroy(parser).await?, diff --git a/src/ifs/wl_region/types.rs b/src/ifs/wl_region/types.rs index 90f7053c..6debb393 100644 --- a/src/ifs/wl_region/types.rs +++ b/src/ifs/wl_region/types.rs @@ -1,5 +1,5 @@ use crate::client::{ClientError, RequestParser}; -use crate::utils::buffd::{WlParser, WlParserError}; +use crate::utils::buffd::{MsgParser, MsgParserError}; use std::fmt::{Debug, Formatter}; use thiserror::Error; @@ -16,34 +16,34 @@ pub enum WlRegionError { #[derive(Debug, Error)] pub enum DestroyError { #[error("Parsing failed")] - ParseFailed(#[source] Box), + ParseFailed(#[source] Box), #[error(transparent)] ClientError(Box), } -efrom!(DestroyError, ParseFailed, WlParserError); +efrom!(DestroyError, ParseFailed, MsgParserError); efrom!(DestroyError, ClientError, ClientError); #[derive(Debug, Error)] pub enum AddError { #[error("Parsing failed")] - ParseFailed(#[source] Box), + ParseFailed(#[source] Box), #[error("width and/or height are negative")] NegativeExtents, } -efrom!(AddError, ParseFailed, WlParserError); +efrom!(AddError, ParseFailed, MsgParserError); #[derive(Debug, Error)] pub enum SubtractError { #[error("Parsing failed")] - ParseFailed(#[source] Box), + ParseFailed(#[source] Box), #[error("width and/or height are negative")] NegativeExtents, } -efrom!(SubtractError, ParseFailed, WlParserError); +efrom!(SubtractError, ParseFailed, MsgParserError); pub(super) struct Destroy; impl RequestParser<'_> for Destroy { - fn parse(_parser: &mut WlParser<'_, '_>) -> Result { + fn parse(_parser: &mut MsgParser<'_, '_>) -> Result { Ok(Self) } } @@ -60,7 +60,7 @@ pub(super) struct Add { pub height: i32, } impl RequestParser<'_> for Add { - fn parse(parser: &mut WlParser<'_, '_>) -> Result { + fn parse(parser: &mut MsgParser<'_, '_>) -> Result { Ok(Self { x: parser.int()?, y: parser.int()?, @@ -86,7 +86,7 @@ pub(super) struct Subtract { pub height: i32, } impl RequestParser<'_> for Subtract { - fn parse(parser: &mut WlParser<'_, '_>) -> Result { + fn parse(parser: &mut MsgParser<'_, '_>) -> Result { Ok(Self { x: parser.int()?, y: parser.int()?, diff --git a/src/ifs/wl_registry/mod.rs b/src/ifs/wl_registry/mod.rs index e4ca5e0b..0132c8a5 100644 --- a/src/ifs/wl_registry/mod.rs +++ b/src/ifs/wl_registry/mod.rs @@ -3,7 +3,7 @@ mod types; use crate::client::{Client, DynEventFormatter}; use crate::globals::{Global, GlobalName}; use crate::object::{Interface, Object, ObjectId}; -use crate::utils::buffd::WlParser; +use crate::utils::buffd::MsgParser; use std::rc::Rc; pub use types::*; @@ -39,7 +39,7 @@ impl WlRegistry { }) } - async fn bind(&self, parser: WlParser<'_, '_>) -> Result<(), BindError> { + async fn bind(&self, parser: MsgParser<'_, '_>) -> Result<(), BindError> { let bind: Bind = self.client.parse(self, parser)?; let global = self.client.state.globals.get(bind.name)?; if global.interface().name() != bind.interface { @@ -64,7 +64,7 @@ impl WlRegistry { async fn handle_request_( &self, request: u32, - parser: WlParser<'_, '_>, + parser: MsgParser<'_, '_>, ) -> Result<(), WlRegistryError> { match request { BIND => self.bind(parser).await?, diff --git a/src/ifs/wl_registry/types.rs b/src/ifs/wl_registry/types.rs index 1d8c6e6e..0c6a448b 100644 --- a/src/ifs/wl_registry/types.rs +++ b/src/ifs/wl_registry/types.rs @@ -2,7 +2,7 @@ use crate::client::{EventFormatter, RequestParser}; use crate::globals::{Global, GlobalError, GlobalName}; use crate::ifs::wl_registry::{WlRegistry, GLOBAL, GLOBAL_REMOVE}; use crate::object::{Interface, Object, ObjectId}; -use crate::utils::buffd::{WlFormatter, WlParser, WlParserError}; +use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError}; use std::fmt::{Debug, Formatter}; use std::rc::Rc; use thiserror::Error; @@ -18,7 +18,7 @@ efrom!(WlRegistryError, BindError, BindError); #[derive(Debug, Error)] pub enum BindError { #[error("Parsing failed")] - ParseError(#[source] Box), + ParseError(#[source] Box), #[error(transparent)] GlobalError(Box), #[error("Tried to bind to global {} of type {} using interface {}", .0.name, .0.interface.name(), .0.actual)] @@ -42,7 +42,7 @@ pub struct VersionError { pub actual: u32, } -efrom!(BindError, ParseError, WlParserError); +efrom!(BindError, ParseError, MsgParserError); efrom!(BindError, GlobalError, GlobalError); pub(super) struct GlobalE { @@ -50,7 +50,7 @@ pub(super) struct GlobalE { pub global: Rc, } impl EventFormatter for GlobalE { - fn format(self: Box, fmt: &mut WlFormatter<'_>) { + fn format(self: Box, fmt: &mut MsgFormatter<'_>) { fmt.header(self.obj.id, GLOBAL) .uint(self.global.name().raw()) .string(self.global.interface().name()) @@ -77,7 +77,7 @@ pub(super) struct GlobalRemove { pub name: GlobalName, } impl EventFormatter for GlobalRemove { - fn format(self: Box, fmt: &mut WlFormatter<'_>) { + fn format(self: Box, fmt: &mut MsgFormatter<'_>) { fmt.header(self.obj.id, GLOBAL_REMOVE).uint(self.name.raw()); } fn obj(&self) -> &dyn Object { @@ -97,7 +97,7 @@ pub(super) struct Bind<'a> { pub version: u32, } impl<'a> RequestParser<'a> for Bind<'a> { - fn parse(parser: &mut WlParser<'_, 'a>) -> Result { + fn parse(parser: &mut MsgParser<'_, 'a>) -> Result { Ok(Self { name: parser.global()?, interface: parser.string()?, diff --git a/src/ifs/wl_shm/mod.rs b/src/ifs/wl_shm/mod.rs index 72e54789..ac1f90c8 100644 --- a/src/ifs/wl_shm/mod.rs +++ b/src/ifs/wl_shm/mod.rs @@ -4,7 +4,7 @@ use crate::client::{AddObj, Client}; use crate::globals::{Global, GlobalName}; use crate::ifs::wl_shm_pool::WlShmPool; use crate::object::{Interface, Object, ObjectId}; -use crate::utils::buffd::WlParser; +use crate::utils::buffd::MsgParser; use std::rc::Rc; pub use types::*; @@ -52,7 +52,7 @@ impl WlShmGlobal { } impl WlShmObj { - async fn create_pool(&self, parser: WlParser<'_, '_>) -> Result<(), CreatePoolError> { + async fn create_pool(&self, parser: MsgParser<'_, '_>) -> Result<(), CreatePoolError> { let create: CreatePool = self.client.parse(self, parser)?; if create.size < 0 { return Err(CreatePoolError::NegativeSize); @@ -70,7 +70,7 @@ impl WlShmObj { async fn handle_request_( &self, request: u32, - parser: WlParser<'_, '_>, + parser: MsgParser<'_, '_>, ) -> Result<(), WlShmError> { match request { CREATE_POOL => self.create_pool(parser).await?, diff --git a/src/ifs/wl_shm/types.rs b/src/ifs/wl_shm/types.rs index 9f1b082b..4a44994f 100644 --- a/src/ifs/wl_shm/types.rs +++ b/src/ifs/wl_shm/types.rs @@ -2,7 +2,7 @@ use crate::client::{ClientError, EventFormatter, RequestParser}; use crate::ifs::wl_shm::{Format, WlShmObj, FORMAT}; use crate::ifs::wl_shm_pool::WlShmPoolError; use crate::object::{Object, ObjectId}; -use crate::utils::buffd::{WlFormatter, WlParser, WlParserError}; +use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError}; use std::fmt::{Debug, Formatter}; use std::rc::Rc; use thiserror::Error; @@ -20,7 +20,7 @@ efrom!(WlShmError, ClientError, ClientError); #[derive(Debug, Error)] pub enum CreatePoolError { #[error("Parsing failed")] - ParseError(#[source] Box), + ParseError(#[source] Box), #[error("The passed size is negative")] NegativeSize, #[error(transparent)] @@ -28,7 +28,7 @@ pub enum CreatePoolError { #[error(transparent)] ClientError(Box), } -efrom!(CreatePoolError, ParseError, WlParserError); +efrom!(CreatePoolError, ParseError, MsgParserError); efrom!(CreatePoolError, WlShmPoolError, WlShmPoolError); efrom!(CreatePoolError, ClientError, ClientError); @@ -38,7 +38,7 @@ pub(super) struct CreatePool { pub size: i32, } impl RequestParser<'_> for CreatePool { - fn parse(parser: &mut WlParser<'_, '_>) -> Result { + fn parse(parser: &mut MsgParser<'_, '_>) -> Result { Ok(Self { id: parser.object()?, fd: parser.fd()?, @@ -63,7 +63,7 @@ pub(super) struct FormatE { pub format: Format, } impl EventFormatter for FormatE { - fn format(self: Box, fmt: &mut WlFormatter<'_>) { + fn format(self: Box, fmt: &mut MsgFormatter<'_>) { fmt.header(self.obj.id, FORMAT).uint(self.format.uint()); } fn obj(&self) -> &dyn Object { diff --git a/src/ifs/wl_shm_pool/mod.rs b/src/ifs/wl_shm_pool/mod.rs index 415fdb69..68a3201d 100644 --- a/src/ifs/wl_shm_pool/mod.rs +++ b/src/ifs/wl_shm_pool/mod.rs @@ -3,7 +3,7 @@ mod types; use crate::client::{AddObj, Client}; use crate::clientmem::ClientMem; use crate::object::{Interface, Object, ObjectId}; -use crate::utils::buffd::WlParser; +use crate::utils::buffd::MsgParser; use std::cell::RefCell; use std::rc::Rc; pub use types::*; @@ -35,18 +35,18 @@ impl WlShmPool { }) } - async fn create_buffer(&self, parser: WlParser<'_, '_>) -> Result<(), CreateBufferError> { + async fn create_buffer(&self, parser: MsgParser<'_, '_>) -> Result<(), CreateBufferError> { let create: CreateBuffer = self.client.parse(self, parser)?; Ok(()) } - async fn destroy(&self, parser: WlParser<'_, '_>) -> Result<(), DestroyError> { + async fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> { let _destroy: Destroy = self.client.parse(self, parser)?; self.client.remove_obj(self).await?; Ok(()) } - async fn resize(&self, parser: WlParser<'_, '_>) -> Result<(), ResizeError> { + async fn resize(&self, parser: MsgParser<'_, '_>) -> Result<(), ResizeError> { let resize: Resize = self.client.parse(self, parser)?; let mut mem = self.mem.borrow_mut(); if resize.size < 0 { @@ -62,7 +62,7 @@ impl WlShmPool { async fn handle_request_( &self, request: u32, - parser: WlParser<'_, '_>, + parser: MsgParser<'_, '_>, ) -> Result<(), WlShmPoolError> { match request { CREATE_BUFFER => self.create_buffer(parser).await?, diff --git a/src/ifs/wl_shm_pool/types.rs b/src/ifs/wl_shm_pool/types.rs index 3d26830d..4b1e5578 100644 --- a/src/ifs/wl_shm_pool/types.rs +++ b/src/ifs/wl_shm_pool/types.rs @@ -1,7 +1,7 @@ use crate::client::{ClientError, RequestParser}; use crate::clientmem::ClientMemError; use crate::object::ObjectId; -use crate::utils::buffd::{WlParser, WlParserError}; +use crate::utils::buffd::{MsgParser, MsgParserError}; use std::fmt::{Debug, Formatter}; use thiserror::Error; @@ -24,27 +24,27 @@ efrom!(WlShmPoolError, ClientMemError, ClientMemError); #[derive(Debug, Error)] pub enum CreateBufferError { #[error("Parsing failed")] - ParseError(#[source] Box), + ParseError(#[source] Box), #[error(transparent)] ClientError(Box), } -efrom!(CreateBufferError, ParseError, WlParserError); +efrom!(CreateBufferError, ParseError, MsgParserError); efrom!(CreateBufferError, ClientError, ClientError); #[derive(Debug, Error)] pub enum DestroyError { #[error("Parsing failed")] - ParseError(#[source] Box), + ParseError(#[source] Box), #[error(transparent)] ClientError(Box), } -efrom!(DestroyError, ParseError, WlParserError); +efrom!(DestroyError, ParseError, MsgParserError); efrom!(DestroyError, ClientError, ClientError); #[derive(Debug, Error)] pub enum ResizeError { #[error("Parsing failed")] - ParseError(#[source] Box), + ParseError(#[source] Box), #[error("Tried to shrink the pool")] CannotShrink, #[error("Requested size is negative")] @@ -52,7 +52,7 @@ pub enum ResizeError { #[error(transparent)] ClientMemError(Box), } -efrom!(ResizeError, ParseError, WlParserError); +efrom!(ResizeError, ParseError, MsgParserError); efrom!(ResizeError, ClientMemError, ClientMemError); pub(super) struct CreateBuffer { @@ -64,7 +64,7 @@ pub(super) struct CreateBuffer { pub format: u32, } impl RequestParser<'_> for CreateBuffer { - fn parse(parser: &mut WlParser<'_, '_>) -> Result { + fn parse(parser: &mut MsgParser<'_, '_>) -> Result { Ok(Self { id: parser.object()?, offset: parser.int()?, @@ -87,7 +87,7 @@ impl Debug for CreateBuffer { pub(super) struct Destroy; impl RequestParser<'_> for Destroy { - fn parse(_parser: &mut WlParser<'_, '_>) -> Result { + fn parse(_parser: &mut MsgParser<'_, '_>) -> Result { Ok(Self) } } @@ -101,7 +101,7 @@ pub(super) struct Resize { pub size: i32, } impl RequestParser<'_> for Resize { - fn parse(parser: &mut WlParser<'_, '_>) -> Result { + fn parse(parser: &mut MsgParser<'_, '_>) -> Result { Ok(Self { size: parser.int()?, }) diff --git a/src/ifs/wl_subcompositor/mod.rs b/src/ifs/wl_subcompositor/mod.rs index d39a514d..c9d5566b 100644 --- a/src/ifs/wl_subcompositor/mod.rs +++ b/src/ifs/wl_subcompositor/mod.rs @@ -1,12 +1,18 @@ mod types; -use crate::client::{AddObj, Client, ClientError}; +use crate::client::{AddObj, Client}; use crate::globals::{Global, GlobalName}; +use crate::ifs::wl_surface::wl_subsurface::WlSubsurface; use crate::object::{Interface, Object, ObjectId}; -use crate::utils::buffd::WlParser; +use crate::utils::buffd::MsgParser; use std::rc::Rc; pub use types::*; +const DESTROY: u32 = 0; +const GET_SUBSURFACE: u32 = 1; + +const BAD_SURFACE: u32 = 0; + pub struct WlSubcompositorGlobal { name: GlobalName, } @@ -14,6 +20,7 @@ pub struct WlSubcompositorGlobal { pub struct WlSubcompositorObj { global: Rc, id: ObjectId, + client: Rc, } impl WlSubcompositorGlobal { @@ -24,22 +31,47 @@ impl WlSubcompositorGlobal { async fn bind_( self: Rc, id: ObjectId, - client: &Client, + client: &Rc, _version: u32, ) -> Result<(), WlSubcompositorError> { - let obj = Rc::new(WlSubcompositorObj { global: self, id }); + let obj = Rc::new(WlSubcompositorObj { + global: self, + id, + client: client.clone(), + }); client.add_client_obj(&obj)?; Ok(()) } } impl WlSubcompositorObj { + async fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> { + let _req: Destroy = self.client.parse(self, parser)?; + self.client.remove_obj(self).await?; + Ok(()) + } + + async 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 subsurface = Rc::new(WlSubsurface::new(req.id, &surface)); + self.client.add_client_obj(&subsurface)?; + subsurface.install(&parent)?; + Ok(()) + } + async fn handle_request_( - &self, + self: &Rc, request: u32, - parser: WlParser<'_, '_>, - ) -> Result<(), ClientError> { - unreachable!(); + parser: MsgParser<'_, '_>, + ) -> Result<(), WlSubcompositorError> { + match request { + DESTROY => self.destroy(parser).await?, + GET_SUBSURFACE => self.get_subsurface(parser).await?, + _ => unreachable!(), + } + Ok(()) } } @@ -75,6 +107,6 @@ impl Object for WlSubcompositorObj { } fn num_requests(&self) -> u32 { - 0 + GET_SUBSURFACE + 1 } } diff --git a/src/ifs/wl_subcompositor/types.rs b/src/ifs/wl_subcompositor/types.rs index 82b9511d..20c34487 100644 --- a/src/ifs/wl_subcompositor/types.rs +++ b/src/ifs/wl_subcompositor/types.rs @@ -1,10 +1,76 @@ -use crate::client::ClientError; +use crate::client::{ClientError, RequestParser}; +use crate::ifs::wl_surface::wl_subsurface::WlSubsurfaceError; +use crate::object::ObjectId; +use crate::utils::buffd::{MsgParser, MsgParserError}; +use std::fmt::{Debug, Formatter}; use thiserror::Error; #[derive(Debug, Error)] pub enum WlSubcompositorError { #[error(transparent)] ClientError(Box), + #[error("Could not process `destroy` request")] + DestroyError(#[from] DestroyError), + #[error("Could not process `get_subsurface` request")] + GetSubsurfaceError(#[from] GetSubsurfaceError), +} +efrom!(WlSubcompositorError, ClientError, ClientError); + +#[derive(Debug, Error)] +pub enum DestroyError { + #[error("Parsing failed")] + ParseFailed(#[source] Box), + #[error(transparent)] + ClientError(Box), +} +efrom!(DestroyError, ParseFailed, MsgParserError); +efrom!(DestroyError, ClientError, ClientError); + +#[derive(Debug, Error)] +pub enum GetSubsurfaceError { + #[error("Parsing failed")] + ParseFailed(#[source] Box), + #[error(transparent)] + ClientError(Box), + #[error(transparent)] + SubsurfaceError(Box), +} +efrom!(GetSubsurfaceError, ParseFailed, MsgParserError); +efrom!(GetSubsurfaceError, ClientError, ClientError); +efrom!(GetSubsurfaceError, SubsurfaceError, WlSubsurfaceError); + +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()") + } } -efrom!(WlSubcompositorError, ClientError, ClientError); +pub(super) struct GetSubsurface { + pub id: ObjectId, + pub surface: ObjectId, + pub parent: ObjectId, +} +impl RequestParser<'_> for GetSubsurface { + fn parse(parser: &mut MsgParser<'_, '_>) -> Result { + Ok(Self { + id: parser.object()?, + surface: parser.object()?, + parent: parser.object()?, + }) + } +} +impl Debug for GetSubsurface { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "get_subsurface(id: {}, surface: {}, parent: {})", + self.id, self.surface, self.parent, + ) + } +} diff --git a/src/ifs/wl_surface/mod.rs b/src/ifs/wl_surface/mod.rs index aa90ad38..e3a96aef 100644 --- a/src/ifs/wl_surface/mod.rs +++ b/src/ifs/wl_surface/mod.rs @@ -1,10 +1,13 @@ mod types; +pub mod wl_subsurface; use crate::client::{Client, RequestParser}; +use crate::ifs::wl_surface::wl_subsurface::WlSubsurface; use crate::object::{Interface, Object, ObjectId}; use crate::pixman::Region; -use crate::utils::buffd::{WlParser, WlParserError}; -use std::cell::Cell; +use crate::utils::buffd::{MsgParser, MsgParserError}; +use ahash::AHashMap; +use std::cell::{Cell, RefCell}; use std::rc::Rc; pub use types::*; @@ -26,10 +29,19 @@ const INVALID_SCALE: u32 = 0; const INVALID_TRANSFORM: u32 = 1; const INVALID_SIZE: u32 = 2; +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum SurfaceType { + None, + Subsurface, +} + pub struct WlSurface { id: ObjectId, client: Rc, + ty: Cell, pending: PendingState, + children: RefCell>>, + subsurface_data: RefCell>>, } #[derive(Default)] @@ -38,45 +50,82 @@ struct PendingState { input_region: Cell>, } +struct SubsurfaceData { + subsurface: Rc, + parent: Rc, + sync_requested: bool, + sync_ancestor: bool, + pending: bool, +} + +#[derive(Default)] +struct ParentData { + subsurfaces: AHashMap>, + pending_subsurfaces: AHashMap>, +} + impl WlSurface { pub fn new(id: ObjectId, client: &Rc) -> Self { Self { id, client: client.clone(), + ty: Cell::new(SurfaceType::None), pending: Default::default(), + children: Default::default(), + subsurface_data: Default::default(), + } + } + + pub fn break_loops(&self) { + *self.children.borrow_mut() = None; + *self.subsurface_data.borrow_mut() = None; + } + + pub fn get_root(self: &Rc) -> Rc { + let mut root = self.clone(); + loop { + let tmp = root; + let data = tmp.subsurface_data.borrow(); + match data.as_ref() { + Some(d) => root = d.parent.clone(), + None => { + drop(data); + return tmp; + } + } } } fn parse<'a, T: RequestParser<'a>>( &self, - parser: WlParser<'_, 'a>, - ) -> Result { + parser: MsgParser<'_, 'a>, + ) -> Result { self.client.parse(self, parser) } - async fn destroy(&self, parser: WlParser<'_, '_>) -> Result<(), DestroyError> { + async fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> { let destroy: Destroy = self.parse(parser)?; Ok(()) } - async fn attach(&self, parser: WlParser<'_, '_>) -> Result<(), AttachError> { + async fn attach(&self, parser: MsgParser<'_, '_>) -> Result<(), AttachError> { let attach: Attach = self.parse(parser)?; Ok(()) } - async fn damage(&self, parser: WlParser<'_, '_>) -> Result<(), DamageError> { + async fn damage(&self, parser: MsgParser<'_, '_>) -> Result<(), DamageError> { let damage: Damage = self.parse(parser)?; Ok(()) } - async fn frame(&self, parser: WlParser<'_, '_>) -> Result<(), FrameError> { + async fn frame(&self, parser: MsgParser<'_, '_>) -> Result<(), FrameError> { let frame: Frame = self.parse(parser)?; Ok(()) } async fn set_opaque_region( &self, - parser: WlParser<'_, '_>, + parser: MsgParser<'_, '_>, ) -> Result<(), SetOpaqueRegionError> { let region: SetOpaqueRegion = self.parse(parser)?; let region = self.client.get_region(region.region)?; @@ -84,32 +133,32 @@ impl WlSurface { Ok(()) } - async fn set_input_region(&self, parser: WlParser<'_, '_>) -> Result<(), SetInputRegionError> { + async fn set_input_region(&self, parser: MsgParser<'_, '_>) -> Result<(), SetInputRegionError> { let region: SetInputRegion = self.parse(parser)?; let region = self.client.get_region(region.region)?; self.pending.input_region.set(Some(region.region())); Ok(()) } - async fn commit(&self, parser: WlParser<'_, '_>) -> Result<(), CommitError> { + async fn commit(&self, parser: MsgParser<'_, '_>) -> Result<(), CommitError> { let commit: Commit = self.parse(parser)?; Ok(()) } async fn set_buffer_transform( &self, - parser: WlParser<'_, '_>, + parser: MsgParser<'_, '_>, ) -> Result<(), SetBufferTransformError> { let transform: SetBufferTransform = self.parse(parser)?; Ok(()) } - async fn set_buffer_scale(&self, parser: WlParser<'_, '_>) -> Result<(), SetBufferScaleError> { + async fn set_buffer_scale(&self, parser: MsgParser<'_, '_>) -> Result<(), SetBufferScaleError> { let scale: SetBufferScale = self.parse(parser)?; Ok(()) } - async fn damage_buffer(&self, parser: WlParser<'_, '_>) -> Result<(), DamageBufferError> { + async fn damage_buffer(&self, parser: MsgParser<'_, '_>) -> Result<(), DamageBufferError> { let damage: DamageBuffer = self.parse(parser)?; Ok(()) } @@ -117,7 +166,7 @@ impl WlSurface { async fn handle_request_( &self, request: u32, - parser: WlParser<'_, '_>, + parser: MsgParser<'_, '_>, ) -> Result<(), WlSurfaceError> { match request { DESTROY => self.destroy(parser).await?, diff --git a/src/ifs/wl_surface/types.rs b/src/ifs/wl_surface/types.rs index 019e3a92..066c1970 100644 --- a/src/ifs/wl_surface/types.rs +++ b/src/ifs/wl_surface/types.rs @@ -1,6 +1,6 @@ use crate::client::{ClientError, RequestParser}; use crate::object::ObjectId; -use crate::utils::buffd::{WlParser, WlParserError}; +use crate::utils::buffd::{MsgParser, MsgParserError}; use std::fmt::{Debug, Formatter}; use thiserror::Error; @@ -45,82 +45,82 @@ efrom!(WlSurfaceError, DamageBufferError, DamageBufferError); #[derive(Debug, Error)] pub enum DestroyError { #[error("Parsing failed")] - ParseFailed(#[source] Box), + ParseFailed(#[source] Box), } -efrom!(DestroyError, ParseFailed, WlParserError); +efrom!(DestroyError, ParseFailed, MsgParserError); #[derive(Debug, Error)] pub enum AttachError { #[error("Parsing failed")] - ParseFailed(#[source] Box), + ParseFailed(#[source] Box), } -efrom!(AttachError, ParseFailed, WlParserError); +efrom!(AttachError, ParseFailed, MsgParserError); #[derive(Debug, Error)] pub enum DamageError { #[error("Parsing failed")] - ParseFailed(#[source] Box), + ParseFailed(#[source] Box), } -efrom!(DamageError, ParseFailed, WlParserError); +efrom!(DamageError, ParseFailed, MsgParserError); #[derive(Debug, Error)] pub enum FrameError { #[error("Parsing failed")] - ParseFailed(#[source] Box), + ParseFailed(#[source] Box), } -efrom!(FrameError, ParseFailed, WlParserError); +efrom!(FrameError, ParseFailed, MsgParserError); #[derive(Debug, Error)] pub enum SetOpaqueRegionError { #[error("Parsing failed")] - ParseFailed(#[source] Box), + ParseFailed(#[source] Box), #[error(transparent)] ClientError(Box), } -efrom!(SetOpaqueRegionError, ParseFailed, WlParserError); +efrom!(SetOpaqueRegionError, ParseFailed, MsgParserError); efrom!(SetOpaqueRegionError, ClientError, ClientError); #[derive(Debug, Error)] pub enum SetInputRegionError { #[error("Parsing failed")] - ParseFailed(#[source] Box), + ParseFailed(#[source] Box), #[error(transparent)] ClientError(Box), } -efrom!(SetInputRegionError, ParseFailed, WlParserError); +efrom!(SetInputRegionError, ParseFailed, MsgParserError); efrom!(SetInputRegionError, ClientError, ClientError); #[derive(Debug, Error)] pub enum CommitError { #[error("Parsing failed")] - ParseFailed(#[source] Box), + ParseFailed(#[source] Box), } -efrom!(CommitError, ParseFailed, WlParserError); +efrom!(CommitError, ParseFailed, MsgParserError); #[derive(Debug, Error)] pub enum SetBufferTransformError { #[error("Parsing failed")] - ParseFailed(#[source] Box), + ParseFailed(#[source] Box), } -efrom!(SetBufferTransformError, ParseFailed, WlParserError); +efrom!(SetBufferTransformError, ParseFailed, MsgParserError); #[derive(Debug, Error)] pub enum SetBufferScaleError { #[error("Parsing failed")] - ParseFailed(#[source] Box), + ParseFailed(#[source] Box), } -efrom!(SetBufferScaleError, ParseFailed, WlParserError); +efrom!(SetBufferScaleError, ParseFailed, MsgParserError); #[derive(Debug, Error)] pub enum DamageBufferError { #[error("Parsing failed")] - ParseFailed(#[source] Box), + ParseFailed(#[source] Box), } -efrom!(DamageBufferError, ParseFailed, WlParserError); +efrom!(DamageBufferError, ParseFailed, MsgParserError); pub(super) struct Destroy; impl RequestParser<'_> for Destroy { - fn parse(_parser: &mut WlParser<'_, '_>) -> Result { + fn parse(_parser: &mut MsgParser<'_, '_>) -> Result { Ok(Self) } } @@ -136,7 +136,7 @@ pub(super) struct Attach { pub y: i32, } impl RequestParser<'_> for Attach { - fn parse(parser: &mut WlParser<'_, '_>) -> Result { + fn parse(parser: &mut MsgParser<'_, '_>) -> Result { Ok(Self { buffer: parser.object()?, x: parser.int()?, @@ -161,7 +161,7 @@ pub(super) struct Damage { pub height: i32, } impl RequestParser<'_> for Damage { - fn parse(parser: &mut WlParser<'_, '_>) -> Result { + fn parse(parser: &mut MsgParser<'_, '_>) -> Result { Ok(Self { x: parser.int()?, y: parser.int()?, @@ -184,7 +184,7 @@ pub(super) struct Frame { pub callback: ObjectId, } impl RequestParser<'_> for Frame { - fn parse(parser: &mut WlParser<'_, '_>) -> Result { + fn parse(parser: &mut MsgParser<'_, '_>) -> Result { Ok(Self { callback: parser.object()?, }) @@ -200,7 +200,7 @@ pub(super) struct SetOpaqueRegion { pub region: ObjectId, } impl RequestParser<'_> for SetOpaqueRegion { - fn parse(parser: &mut WlParser<'_, '_>) -> Result { + fn parse(parser: &mut MsgParser<'_, '_>) -> Result { Ok(Self { region: parser.object()?, }) @@ -216,7 +216,7 @@ pub(super) struct SetInputRegion { pub region: ObjectId, } impl RequestParser<'_> for SetInputRegion { - fn parse(parser: &mut WlParser<'_, '_>) -> Result { + fn parse(parser: &mut MsgParser<'_, '_>) -> Result { Ok(Self { region: parser.object()?, }) @@ -230,7 +230,7 @@ impl Debug for SetInputRegion { pub(super) struct Commit; impl RequestParser<'_> for Commit { - fn parse(_parser: &mut WlParser<'_, '_>) -> Result { + fn parse(_parser: &mut MsgParser<'_, '_>) -> Result { Ok(Self) } } @@ -244,7 +244,7 @@ pub(super) struct SetBufferTransform { pub transform: i32, } impl RequestParser<'_> for SetBufferTransform { - fn parse(parser: &mut WlParser<'_, '_>) -> Result { + fn parse(parser: &mut MsgParser<'_, '_>) -> Result { Ok(Self { transform: parser.int()?, }) @@ -260,7 +260,7 @@ pub(super) struct SetBufferScale { pub scale: i32, } impl RequestParser<'_> for SetBufferScale { - fn parse(parser: &mut WlParser<'_, '_>) -> Result { + fn parse(parser: &mut MsgParser<'_, '_>) -> Result { Ok(Self { scale: parser.int()?, }) @@ -279,7 +279,7 @@ pub(super) struct DamageBuffer { pub height: i32, } impl RequestParser<'_> for DamageBuffer { - fn parse(parser: &mut WlParser<'_, '_>) -> Result { + fn parse(parser: &mut MsgParser<'_, '_>) -> Result { Ok(Self { x: parser.int()?, y: parser.int()?, diff --git a/src/ifs/wl_surface/wl_subsurface/mod.rs b/src/ifs/wl_surface/wl_subsurface/mod.rs new file mode 100644 index 00000000..581cd740 --- /dev/null +++ b/src/ifs/wl_surface/wl_subsurface/mod.rs @@ -0,0 +1,132 @@ +mod types; + +use crate::ifs::wl_surface::{SubsurfaceData, SurfaceType, WlSurface}; +use crate::object::{Interface, Object, ObjectId}; +use crate::utils::buffd::MsgParser; +use std::rc::Rc; +pub use types::*; + +const DESTROY: u32 = 0; +const SET_POSITION: u32 = 1; +const PLACE_ABOVE: u32 = 2; +const PLACE_BELOW: u32 = 3; +const SET_SYNC: u32 = 4; +const SET_DESYNC: u32 = 5; + +const BAD_SURFACE: u32 = 0; + +pub struct WlSubsurface { + id: ObjectId, + surface: Rc, +} + +impl WlSubsurface { + pub fn new(id: ObjectId, surface: &Rc) -> Self { + Self { + id, + surface: surface.clone(), + } + } + + pub fn install(self: &Rc, parent: &Rc) -> Result<(), WlSubsurfaceError> { + let old_ty = self.surface.ty.get(); + if !matches!(old_ty, SurfaceType::None | SurfaceType::Subsurface) { + return Err(WlSubsurfaceError::IncompatibleType(self.surface.id, old_ty)); + } + self.surface.ty.set(SurfaceType::Subsurface); + let mut data = self.surface.subsurface_data.borrow_mut(); + if data.is_some() { + return Err(WlSubsurfaceError::AlreadyAttached(self.surface.id)); + } + if self.surface.id == parent.id { + return Err(WlSubsurfaceError::OwnParent(self.surface.id)); + } + if self.surface.id == parent.get_root().id { + return Err(WlSubsurfaceError::Ancestor(self.surface.id, parent.id)); + } + let mut sync_ancestor = false; + { + let data = parent.subsurface_data.borrow(); + if let Some(data) = data.as_ref() { + sync_ancestor = data.sync_requested || data.sync_ancestor; + } + } + *data = Some(Box::new(SubsurfaceData { + subsurface: self.clone(), + parent: parent.clone(), + sync_requested: false, + sync_ancestor, + pending: true, + })); + { + let mut data = parent.children.borrow_mut(); + let data = data.get_or_insert_with(|| Default::default()); + data.pending_subsurfaces + .insert(self.surface.id, self.surface.clone()); + } + Ok(()) + } + + async fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> { + let _req: Destroy = self.surface.client.parse(self, parser)?; + Ok(()) + } + + async fn set_position(&self, parser: MsgParser<'_, '_>) -> Result<(), SetPositionError> { + let req: SetPosition = self.surface.client.parse(self, parser)?; + Ok(()) + } + + async fn place_above(&self, parser: MsgParser<'_, '_>) -> Result<(), PlaceAboveError> { + let req: PlaceAbove = self.surface.client.parse(self, parser)?; + Ok(()) + } + + async fn place_below(&self, parser: MsgParser<'_, '_>) -> Result<(), PlaceBelowError> { + let req: PlaceBelow = self.surface.client.parse(self, parser)?; + Ok(()) + } + + async fn set_sync(&self, parser: MsgParser<'_, '_>) -> Result<(), SetSyncError> { + let _req: SetSync = self.surface.client.parse(self, parser)?; + Ok(()) + } + + async fn set_desync(&self, parser: MsgParser<'_, '_>) -> Result<(), SetDesyncError> { + let _req: SetDesync = self.surface.client.parse(self, parser)?; + Ok(()) + } + + async fn handle_request_( + &self, + request: u32, + parser: MsgParser<'_, '_>, + ) -> Result<(), WlSubsurfaceError> { + match request { + DESTROY => self.destroy(parser).await?, + SET_POSITION => self.set_position(parser).await?, + PLACE_ABOVE => self.place_above(parser).await?, + PLACE_BELOW => self.place_below(parser).await?, + SET_SYNC => self.set_sync(parser).await?, + SET_DESYNC => self.set_desync(parser).await?, + _ => unreachable!(), + } + Ok(()) + } +} + +handle_request!(WlSubsurface); + +impl Object for WlSubsurface { + fn id(&self) -> ObjectId { + self.id + } + + fn interface(&self) -> Interface { + Interface::WlSubsurface + } + + fn num_requests(&self) -> u32 { + SET_DESYNC + 1 + } +} diff --git a/src/ifs/wl_surface/wl_subsurface/types.rs b/src/ifs/wl_surface/wl_subsurface/types.rs new file mode 100644 index 00000000..dbe376d8 --- /dev/null +++ b/src/ifs/wl_surface/wl_subsurface/types.rs @@ -0,0 +1,158 @@ +use crate::client::{RequestParser}; +use crate::ifs::wl_surface::SurfaceType; +use crate::object::ObjectId; +use crate::utils::buffd::{MsgParser, MsgParserError}; +use std::fmt::{Debug, Formatter}; +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum WlSubsurfaceError { + #[error("Could not process `destroy` request")] + DestroyError(#[from] DestroyError), + #[error("Could not process `set_position` request")] + SetPosition(#[from] SetPositionError), + #[error("Could not process `place_above` request")] + PlaceAbove(#[from] PlaceAboveError), + #[error("Could not process `place_below` request")] + PlaceBelow(#[from] PlaceBelowError), + #[error("Could not process `set_sync` request")] + SetSync(#[from] SetSyncError), + #[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, SurfaceType), + #[error("Surface {0} already has an attached `wl_subsurface`")] + AlreadyAttached(ObjectId), + #[error("Surface {0} cannot be made its own parent")] + OwnParent(ObjectId), + #[error("Surface {0} cannot be made a subsurface of {1} because it's an ancestor of {1}")] + Ancestor(ObjectId, ObjectId), +} + +#[derive(Debug, Error)] +pub enum DestroyError { + #[error("Parsing failed")] + ParseFailed(#[source] Box), +} +efrom!(DestroyError, ParseFailed, MsgParserError); + +#[derive(Debug, Error)] +pub enum SetPositionError { + #[error("Parsing failed")] + ParseFailed(#[source] Box), +} +efrom!(SetPositionError, ParseFailed, MsgParserError); + +#[derive(Debug, Error)] +pub enum PlaceAboveError { + #[error("Parsing failed")] + ParseFailed(#[source] Box), +} +efrom!(PlaceAboveError, ParseFailed, MsgParserError); + +#[derive(Debug, Error)] +pub enum PlaceBelowError { + #[error("Parsing failed")] + ParseFailed(#[source] Box), +} +efrom!(PlaceBelowError, ParseFailed, MsgParserError); + +#[derive(Debug, Error)] +pub enum SetSyncError { + #[error("Parsing failed")] + ParseFailed(#[source] Box), +} +efrom!(SetSyncError, ParseFailed, MsgParserError); + +#[derive(Debug, Error)] +pub enum SetDesyncError { + #[error("Parsing failed")] + ParseFailed(#[source] Box), +} +efrom!(SetDesyncError, ParseFailed, MsgParserError); + +pub(in crate::ifs) 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(in crate::ifs) struct SetPosition { + pub x: i32, + pub y: i32, +} +impl RequestParser<'_> for SetPosition { + fn parse(parser: &mut MsgParser<'_, '_>) -> Result { + Ok(Self { + x: parser.int()?, + y: parser.int()?, + }) + } +} +impl Debug for SetPosition { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "set_position(x: {}, y: {})", self.x, self.y) + } +} + +pub(in crate::ifs) struct PlaceAbove { + pub sibling: ObjectId, +} +impl RequestParser<'_> for PlaceAbove { + fn parse(parser: &mut MsgParser<'_, '_>) -> Result { + Ok(Self { + sibling: parser.object()?, + }) + } +} +impl Debug for PlaceAbove { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "place_above(sibling: {})", self.sibling,) + } +} + +pub(in crate::ifs) struct PlaceBelow { + pub sibling: ObjectId, +} +impl RequestParser<'_> for PlaceBelow { + fn parse(parser: &mut MsgParser<'_, '_>) -> Result { + Ok(Self { + sibling: parser.object()?, + }) + } +} +impl Debug for PlaceBelow { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "place_below(sibling: {})", self.sibling,) + } +} + +pub(in crate::ifs) struct SetSync; +impl RequestParser<'_> for SetSync { + fn parse(_parser: &mut MsgParser<'_, '_>) -> Result { + Ok(Self) + } +} +impl Debug for SetSync { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "set_sync()") + } +} + +pub(in crate::ifs) struct SetDesync; +impl RequestParser<'_> for SetDesync { + fn parse(_parser: &mut MsgParser<'_, '_>) -> Result { + Ok(Self) + } +} +impl Debug for SetDesync { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "set_desync()") + } +} diff --git a/src/ifs/xdg_wm_base/mod.rs b/src/ifs/xdg_wm_base/mod.rs index 3a07b430..0ec4d2d5 100644 --- a/src/ifs/xdg_wm_base/mod.rs +++ b/src/ifs/xdg_wm_base/mod.rs @@ -3,7 +3,7 @@ mod types; use crate::client::{AddObj, Client, ClientError}; use crate::globals::{Global, GlobalName}; use crate::object::{Interface, Object, ObjectId}; -use crate::utils::buffd::WlParser; +use crate::utils::buffd::MsgParser; use std::rc::Rc; pub use types::*; @@ -42,7 +42,7 @@ impl XdgWmBaseObj { async fn handle_request_( &self, request: u32, - parser: WlParser<'_, '_>, + parser: MsgParser<'_, '_>, ) -> Result<(), ClientError> { unreachable!(); } diff --git a/src/macros.rs b/src/macros.rs index 1515bb02..5c121eb3 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -12,9 +12,9 @@ macro_rules! handle_request { ($oname:ty) => { impl crate::object::ObjectHandleRequest for $oname { fn handle_request<'a>( - &'a self, + self: std::rc::Rc, request: u32, - parser: crate::utils::buffd::WlParser<'a, 'a>, + parser: crate::utils::buffd::MsgParser<'a, 'a>, ) -> std::pin::Pin< Box> + 'a>, > { diff --git a/src/object.rs b/src/object.rs index 91cd97f4..4d74f16c 100644 --- a/src/object.rs +++ b/src/object.rs @@ -1,6 +1,6 @@ use crate::client::ClientError; use crate::ifs::wl_display::WlDisplay; -use crate::utils::buffd::WlParser; +use crate::utils::buffd::MsgParser; use std::fmt::{Display, Formatter}; use std::future::Future; use std::pin::Pin; @@ -29,9 +29,9 @@ impl Display for ObjectId { pub trait ObjectHandleRequest { fn handle_request<'a>( - &'a self, + self: Rc, request: u32, - parser: WlParser<'a, 'a>, + parser: MsgParser<'a, 'a>, ) -> Pin> + 'a>>; } @@ -55,6 +55,7 @@ pub enum Interface { WlSubcompositor, XdgWmBase, WlSurface, + WlSubsurface, WlRegion, } @@ -69,6 +70,7 @@ impl Interface { Interface::WlSubcompositor => "wl_subcompositor", Interface::XdgWmBase => "xdg_wm_base", Interface::WlSurface => "wl_surface", + Interface::WlSubsurface => "wl_subsurface", Interface::WlShmPool => "wl_shm_pool", Interface::WlRegion => "wl_region", } diff --git a/src/utils/buffd/wl_formatter.rs b/src/utils/buffd/formatter.rs similarity index 95% rename from src/utils/buffd/wl_formatter.rs rename to src/utils/buffd/formatter.rs index 1e3299aa..256831d2 100644 --- a/src/utils/buffd/wl_formatter.rs +++ b/src/utils/buffd/formatter.rs @@ -4,13 +4,13 @@ use std::mem; use std::mem::MaybeUninit; use uapi::OwnedFd; -pub struct WlFormatter<'a> { +pub struct MsgFormatter<'a> { buf: &'a mut BufFdOut, pos: usize, fds: Vec, } -impl<'a> WlFormatter<'a> { +impl<'a> MsgFormatter<'a> { pub fn new(buf: &'a mut BufFdOut) -> Self { Self { pos: buf.out_pos, @@ -59,7 +59,7 @@ impl<'a> WlFormatter<'a> { } } -impl<'a> Drop for WlFormatter<'a> { +impl<'a> Drop for MsgFormatter<'a> { fn drop(&mut self) { assert!(self.buf.out_pos - self.pos >= 8); assert_eq!(self.pos % 4, 0); diff --git a/src/utils/buffd/mod.rs b/src/utils/buffd/mod.rs index b0a348f6..db387fe9 100644 --- a/src/utils/buffd/mod.rs +++ b/src/utils/buffd/mod.rs @@ -1,14 +1,14 @@ use crate::async_engine::AsyncError; pub use buf_in::BufFdIn; pub use buf_out::BufFdOut; +pub use formatter::MsgFormatter; +pub use parser::{MsgParser, MsgParserError}; use thiserror::Error; -pub use wl_formatter::WlFormatter; -pub use wl_parser::{WlParser, WlParserError}; mod buf_in; mod buf_out; -mod wl_formatter; -mod wl_parser; +mod formatter; +mod parser; #[derive(Debug, Error)] pub enum BufFdError { diff --git a/src/utils/buffd/wl_parser.rs b/src/utils/buffd/parser.rs similarity index 66% rename from src/utils/buffd/wl_parser.rs rename to src/utils/buffd/parser.rs index d74abb92..7cf3437a 100644 --- a/src/utils/buffd/wl_parser.rs +++ b/src/utils/buffd/parser.rs @@ -5,7 +5,7 @@ use thiserror::Error; use uapi::OwnedFd; #[derive(Debug, Error)] -pub enum WlParserError { +pub enum MsgParserError { #[error("The message ended unexpectedly")] UnexpectedEof, #[error("The message contained a non-utf8 string")] @@ -18,13 +18,13 @@ pub enum WlParserError { TrailingData, } -pub struct WlParser<'a, 'b> { +pub struct MsgParser<'a, 'b> { buf: &'a mut BufFdIn, pos: usize, data: &'b [u8], } -impl<'a, 'b> WlParser<'a, 'b> { +impl<'a, 'b> MsgParser<'a, 'b> { pub fn new(buf: &'a mut BufFdIn, data: &'b [u32]) -> Self { Self { buf, @@ -33,61 +33,61 @@ impl<'a, 'b> WlParser<'a, 'b> { } } - pub fn int(&mut self) -> Result { + pub fn int(&mut self) -> Result { if self.data.len() - self.pos < 4 { - return Err(WlParserError::UnexpectedEof); + return Err(MsgParserError::UnexpectedEof); } let res = unsafe { *(self.data.as_ptr().add(self.pos) as *const i32) }; self.pos += 4; Ok(res) } - pub fn uint(&mut self) -> Result { + pub fn uint(&mut self) -> Result { self.int().map(|i| i as u32) } - pub fn object(&mut self) -> Result { + pub fn object(&mut self) -> Result { self.int().map(|i| ObjectId::from_raw(i as u32)) } - pub fn global(&mut self) -> Result { + pub fn global(&mut self) -> Result { self.int().map(|i| GlobalName::from_raw(i as u32)) } - pub fn fixed(&mut self) -> Result { + pub fn fixed(&mut self) -> Result { self.int().map(|i| i as f64 / 256.0) } - pub fn string(&mut self) -> Result<&'b str, WlParserError> { + pub fn string(&mut self) -> Result<&'b str, MsgParserError> { let len = self.uint()? as usize; if len == 0 { - return Err(WlParserError::EmptyString); + return Err(MsgParserError::EmptyString); } let cap = (len + 3) & !3; if cap > self.data.len() - self.pos { - return Err(WlParserError::UnexpectedEof); + return Err(MsgParserError::UnexpectedEof); } let s = &self.data[self.pos..self.pos + len - 1]; let s = match std::str::from_utf8(s) { Ok(s) => s, - _ => return Err(WlParserError::NonUtf8), + _ => return Err(MsgParserError::NonUtf8), }; self.pos += cap; Ok(s) } - pub fn fd(&mut self) -> Result { + pub fn fd(&mut self) -> Result { match self.buf.get_fd() { Ok(fd) => Ok(fd), - _ => Err(WlParserError::MissingFd), + _ => Err(MsgParserError::MissingFd), } } - pub fn eof(&self) -> Result<(), WlParserError> { + pub fn eof(&self) -> Result<(), MsgParserError> { if self.pos == self.data.len() { Ok(()) } else { - Err(WlParserError::TrailingData) + Err(MsgParserError::TrailingData) } } }