diff --git a/Cargo.lock b/Cargo.lock index 644364a..ec474d1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2215,6 +2215,41 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" +[[package]] +name = "darling" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.104", +] + +[[package]] +name = "darling_macro" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.104", +] + [[package]] name = "dashmap" version = "6.1.0" @@ -2494,7 +2529,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.60.2", ] [[package]] @@ -3211,6 +3246,12 @@ dependencies = [ "tracing", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "image" version = "0.25.6" @@ -5072,7 +5113,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.4.15", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -5085,7 +5126,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.11.0", - "windows-sys 0.52.0", + "windows-sys 0.60.2", ] [[package]] @@ -5502,6 +5543,8 @@ dependencies = [ "tracy-client", "vulkano", "waynest", + "waynest-protocols", + "waynest-server", "wgpu-hal", "xkbcommon-rs", "zbus", @@ -5694,7 +5737,7 @@ dependencies = [ "getrandom 0.3.3", "once_cell", "rustix 1.1.2", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -6543,34 +6586,56 @@ dependencies = [ [[package]] name = "waynest" -version = "0.0.26" -source = "git+https://github.com/verdiwm/waynest.git?branch=codec-test#d03960abdd585d923cb068297487932511d997cb" +version = "0.1.0" +source = "git+https://github.com/verdiwm/waynest.git#cbbc19ed20ba5610fcc5577375d6b743d615da31" dependencies = [ - "async-trait", - "bitflags 2.9.4", "bytes", "futures-core", "futures-sink", - "futures-util", "pin-project-lite", "rustix 1.1.2", - "thiserror 2.0.16", "tokio", - "tokio-stream", "tokio-util", - "tracing", - "waynest-macros", ] [[package]] name = "waynest-macros" -version = "0.0.26" -source = "git+https://github.com/verdiwm/waynest.git?branch=codec-test#d03960abdd585d923cb068297487932511d997cb" +version = "0.1.0" +source = "git+https://github.com/verdiwm/waynest.git#cbbc19ed20ba5610fcc5577375d6b743d615da31" dependencies = [ + "darling", "quote", "syn 2.0.104", ] +[[package]] +name = "waynest-protocols" +version = "0.1.0" +source = "git+https://github.com/verdiwm/waynest.git#cbbc19ed20ba5610fcc5577375d6b743d615da31" +dependencies = [ + "bitflags 2.9.4", + "futures-core", + "futures-sink", + "futures-util", + "tracing", + "waynest", +] + +[[package]] +name = "waynest-server" +version = "0.1.0" +source = "git+https://github.com/verdiwm/waynest.git#cbbc19ed20ba5610fcc5577375d6b743d615da31" +dependencies = [ + "async-trait", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tokio-stream", + "waynest", + "waynest-macros", +] + [[package]] name = "web-sys" version = "0.3.77" @@ -6719,7 +6784,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 353a8dc..f0933fd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,8 @@ path = "src/main.rs" default = ["wayland"] wayland = [ "dep:waynest", + "dep:waynest-protocols", + "dep:waynest-server", "dep:tokio-stream", "dep:memmap2", "dep:drm-fourcc", @@ -145,12 +147,14 @@ xkbcommon-rs = "0.1.0" cosmic-text = "0.14.2" # Wayland -waynest = { git = "https://github.com/verdiwm/waynest.git", branch="codec-test", features = [ +waynest = { git = "https://github.com/verdiwm/waynest.git", default-features = false, optional = true } +waynest-protocols = { git = "https://github.com/verdiwm/waynest.git", features = [ "server", "stable", "mesa", "tracing", ], default-features = false, optional = true } +waynest-server = { git = "https://github.com/verdiwm/waynest.git", default-features = false, optional = true } tokio-stream = { version = "0.1.17", optional = true } memmap2 = { version = "0.9.5", optional = true } drm-fourcc = { version = "2.2.0", optional = true } diff --git a/src/core/error.rs b/src/core/error.rs index 33071f9..2d11138 100644 --- a/src/core/error.rs +++ b/src/core/error.rs @@ -29,8 +29,6 @@ pub enum ServerError { #[error("Reader error: {0}")] ReaderError(#[from] ReaderError), #[cfg(feature = "wayland")] - #[error("Wayland error: {0}")] - WaylandError(waynest::server::Error), #[error("Aspect {} does not exist for node", 0.to_string())] NoAspect(TypeId), #[error("{0}")] diff --git a/src/wayland/core/buffer.rs b/src/wayland/core/buffer.rs index 5210919..eb35124 100644 --- a/src/wayland/core/buffer.rs +++ b/src/wayland/core/buffer.rs @@ -1,5 +1,5 @@ -use crate::wayland::Message; use crate::wayland::dmabuf::buffer_backing::DmabufBacking; +use crate::wayland::{Client, Message, WaylandResult}; use crate::wayland::{MessageSink, core::shm_buffer_backing::ShmBufferBacking, util::ClientExt}; use bevy::{ asset::{Assets, Handle}, @@ -8,11 +8,9 @@ use bevy::{ use bevy_dmabuf::import::ImportedDmatexs; use mint::Vector2; use std::sync::Arc; -pub use waynest::server::protocol::core::wayland::wl_buffer::*; -use waynest::{ - server::{Client, Dispatcher, Result}, - wire::ObjectId, -}; +use waynest::ObjectId; +pub use waynest_protocols::server::core::wayland::wl_buffer::*; +use waynest_server::RequestDispatcher; #[derive(Debug)] pub struct BufferUsage { @@ -41,7 +39,8 @@ pub enum BufferBacking { Dmabuf(DmabufBacking), } -#[derive(Debug, Dispatcher)] +#[derive(Debug, RequestDispatcher)] +#[waynest(error = crate::wayland::WaylandError)] pub struct Buffer { pub id: ObjectId, backing: BufferBacking, @@ -98,8 +97,10 @@ impl Buffer { } impl WlBuffer for Buffer { + type Connection = crate::wayland::Client; + /// https://wayland.app/protocols/wayland#wl_buffer:request:destroy - async fn destroy(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { + async fn destroy(&self, _client: &mut Client, _sender_id: ObjectId) -> WaylandResult<()> { tracing::info!("Destroying buffer {:?}", self.id); Ok(()) } diff --git a/src/wayland/core/callback.rs b/src/wayland/core/callback.rs index 195bc34..d347fb0 100644 --- a/src/wayland/core/callback.rs +++ b/src/wayland/core/callback.rs @@ -1,10 +1,11 @@ -pub use waynest::server::protocol::core::wayland::wl_callback::*; -use waynest::{ - server::{Dispatcher, Result}, - wire::ObjectId, -}; +use waynest::ObjectId; +pub use waynest_protocols::server::core::wayland::wl_callback::*; +use waynest_server::RequestDispatcher; -#[derive(Debug, Dispatcher, Clone)] +#[derive(Debug, RequestDispatcher, Clone)] +#[waynest(error = crate::wayland::WaylandError)] pub struct Callback(pub ObjectId); /// https://wayland.app/protocols/wayland#wl_callback -impl WlCallback for Callback {} +impl WlCallback for Callback { + type Connection = crate::wayland::Client; +} diff --git a/src/wayland/core/compositor.rs b/src/wayland/core/compositor.rs index cd145f6..8fb518d 100644 --- a/src/wayland/core/compositor.rs +++ b/src/wayland/core/compositor.rs @@ -1,24 +1,24 @@ use super::surface::WL_SURFACE_REGISTRY; +use crate::wayland::{WaylandResult, WaylandError}; use crate::wayland::{core::surface::Surface, util::ClientExt}; -pub use waynest::server::protocol::core::wayland::wl_compositor::*; -use waynest::{ - server::{ - Client, Dispatcher, Result, - protocol::core::wayland::{wl_region::WlRegion, wl_surface::WlSurface}, - }, - wire::ObjectId, -}; +use waynest::ObjectId; +use waynest_protocols::server::core::wayland::wl_surface::WlSurface; +pub use waynest_protocols::server::core::wayland::{wl_compositor::*, wl_region::*}; +use waynest_server::RequestDispatcher; -#[derive(Debug, Dispatcher, Default)] +#[derive(Debug, waynest_server::RequestDispatcher, Default)] +#[waynest(error = WaylandError)] pub struct Compositor; impl WlCompositor for Compositor { + type Connection = crate::wayland::Client; + /// https://wayland.app/protocols/wayland#wl_compositor:request:create_surface async fn create_surface( &self, - client: &mut Client, + client: &mut Self::Connection, _sender_id: ObjectId, id: ObjectId, - ) -> Result<()> { + ) -> WaylandResult<()> { let surface = client.insert(id, Surface::new(client, id)); if let Some(output) = client.display().output.get() { surface.enter(client, id, output.id).await?; @@ -31,46 +31,49 @@ impl WlCompositor for Compositor { /// https://wayland.app/protocols/wayland#wl_compositor:request:create_region async fn create_region( &self, - client: &mut Client, + client: &mut Self::Connection, _sender_id: ObjectId, id: ObjectId, - ) -> Result<()> { + ) -> WaylandResult<()> { client.insert(id, Region::default()); Ok(()) } } -#[derive(Debug, Dispatcher, Default)] +#[derive(Debug, RequestDispatcher, Default)] +#[waynest(error = WaylandError)] pub struct Region {} impl WlRegion for Region { + type Connection = crate::wayland::Client; + /// https://wayland.app/protocols/wayland#wl_region:request:add async fn add( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, _x: i32, _y: i32, _width: i32, _height: i32, - ) -> Result<()> { + ) -> WaylandResult<()> { Ok(()) } /// https://wayland.app/protocols/wayland#wl_region:request:subtract async fn subtract( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, _x: i32, _y: i32, _width: i32, _height: i32, - ) -> Result<()> { + ) -> WaylandResult<()> { Ok(()) } /// https://wayland.app/protocols/wayland#wl_region:request:destroy - async fn destroy(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { + async fn destroy(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> { Ok(()) } } diff --git a/src/wayland/core/data_device.rs b/src/wayland/core/data_device.rs index 2b57971..87519f7 100644 --- a/src/wayland/core/data_device.rs +++ b/src/wayland/core/data_device.rs @@ -1,26 +1,24 @@ +use crate::wayland::{Client, WaylandResult}; use std::os::fd::OwnedFd; -use waynest::{ - server::{ - Client, Dispatcher, Result, - protocol::core::wayland::{ - wl_data_device::*, wl_data_device_manager::*, wl_data_offer::WlDataOffer, - wl_data_source::*, - }, - }, - wire::ObjectId, +use waynest::ObjectId; +use waynest_protocols::server::core::wayland::{ + wl_data_device::*, wl_data_device_manager::*, wl_data_offer::WlDataOffer, wl_data_source::*, }; // TODO: actually implement this -#[derive(Debug, Dispatcher)] +#[derive(Debug, waynest_server::RequestDispatcher)] +#[waynest(error = crate::wayland::WaylandError)] pub struct DataDeviceManager; impl WlDataDeviceManager for DataDeviceManager { + type Connection = Client; + async fn create_data_source( &self, - client: &mut Client, + client: &mut Self::Connection, _sender_id: ObjectId, id: ObjectId, - ) -> Result<()> { + ) -> WaylandResult<()> { client.insert(id, DataSource); Ok(()) } @@ -31,116 +29,125 @@ impl WlDataDeviceManager for DataDeviceManager { _sender_id: ObjectId, id: ObjectId, _seat: ObjectId, - ) -> Result<()> { + ) -> WaylandResult<()> { client.insert(id, DataDevice); Ok(()) } } -#[derive(Debug, Dispatcher)] +#[derive(Debug, waynest_server::RequestDispatcher)] +#[waynest(error = crate::wayland::WaylandError)] pub struct DataSource; impl WlDataSource for DataSource { + type Connection = Client; + async fn send( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, _mime_type: String, _fd: OwnedFd, - ) -> Result<()> { + ) -> WaylandResult<()> { Ok(()) } async fn offer( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, _mime_type: String, - ) -> Result<()> { + ) -> WaylandResult<()> { Ok(()) } - async fn destroy(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { + async fn destroy(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> { Ok(()) } async fn set_actions( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, _dnd_actions: DndAction, - ) -> Result<()> { + ) -> WaylandResult<()> { Ok(()) } } -#[derive(Debug, Dispatcher)] +#[derive(Debug, waynest_server::RequestDispatcher)] +#[waynest(error = crate::wayland::WaylandError)] pub struct DataDevice; impl WlDataDevice for DataDevice { + type Connection = Client; + async fn start_drag( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, _source: Option, _origin: ObjectId, _icon: Option, _serial: u32, - ) -> Result<()> { + ) -> WaylandResult<()> { Ok(()) } async fn set_selection( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, _source: Option, _serial: u32, - ) -> Result<()> { + ) -> WaylandResult<()> { Ok(()) } - async fn release(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { + async fn release(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> { Ok(()) } } -#[derive(Debug, Dispatcher)] +#[derive(Debug, waynest_server::RequestDispatcher)] +#[waynest(error = crate::wayland::WaylandError)] pub struct DataOffer; impl WlDataOffer for DataOffer { + type Connection = Client; + async fn accept( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, _serial: u32, _mime_type: Option, - ) -> Result<()> { + ) -> WaylandResult<()> { Ok(()) } async fn receive( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, _mime_type: String, _fd: OwnedFd, - ) -> Result<()> { + ) -> WaylandResult<()> { Ok(()) } - async fn destroy(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { + async fn destroy(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> { Ok(()) } - async fn finish(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { + async fn finish(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> { Ok(()) } async fn set_actions( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, _dnd_actions: DndAction, _preferred_action: DndAction, - ) -> Result<()> { + ) -> WaylandResult<()> { Ok(()) } } diff --git a/src/wayland/core/keyboard.rs b/src/wayland/core/keyboard.rs index 99d1888..e9d1935 100644 --- a/src/wayland/core/keyboard.rs +++ b/src/wayland/core/keyboard.rs @@ -1,6 +1,6 @@ use crate::{ nodes::items::panel::KEYMAPS, - wayland::{core::surface::Surface, util::ClientExt}, + wayland::{Client, WaylandResult, core::surface::Surface, util::ClientExt}, }; use dashmap::{DashMap, DashSet}; use memfd::MemfdOptions; @@ -15,11 +15,8 @@ use std::{ sync::{Arc, Weak}, }; use tokio::sync::Mutex; -pub use waynest::server::protocol::core::wayland::wl_keyboard::*; -use waynest::{ - server::{Client, Dispatcher, Result}, - wire::ObjectId, -}; +use waynest::ObjectId; +pub use waynest_protocols::server::core::wayland::wl_keyboard::*; #[derive(Default)] struct ModifierState { @@ -69,7 +66,8 @@ impl ModifierState { } } -#[derive(Dispatcher)] +#[derive(waynest_server::RequestDispatcher)] +#[waynest(error = crate::wayland::WaylandError)] pub struct Keyboard { pub id: ObjectId, focused_surface: Mutex>, @@ -89,10 +87,9 @@ impl Keyboard { } } - async fn send_keymap(&self, client: &mut Client, keymap: &[u8]) -> Result<()> { + async fn send_keymap(&self, client: &mut Client, keymap: &[u8]) -> WaylandResult<()> { let mut file = MemfdOptions::default() - .create("stardust-keymap") - .map_err(|e| waynest::server::Error::Custom(e.to_string()))? + .create("stardust-keymap")? .into_file(); file.set_len(keymap.len() as u64)?; file.write_all(keymap)?; @@ -121,7 +118,7 @@ impl Keyboard { keymap_id: u64, key: u32, pressed: bool, - ) -> Result<()> { + ) -> WaylandResult<()> { // KEYMAP UPDATES { let mut old_keymap_id = self.current_keymap_id.lock().await; @@ -224,7 +221,7 @@ impl Keyboard { Ok(()) } - pub async fn reset(&self, client: &mut Client) -> Result<()> { + pub async fn reset(&self, client: &mut Client) -> WaylandResult<()> { let mut modifier_state = self.modifier_state.lock().await; modifier_state.pressed_keys.clear(); modifier_state.mods_depressed = 0; @@ -247,8 +244,10 @@ impl Keyboard { } impl WlKeyboard for Keyboard { + type Connection = Client; + /// https://wayland.app/protocols/wayland#wl_keyboard:request:release - async fn release(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { + async fn release(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> { Ok(()) } } diff --git a/src/wayland/core/output.rs b/src/wayland/core/output.rs index 8d77e1f..ff0f04d 100644 --- a/src/wayland/core/output.rs +++ b/src/wayland/core/output.rs @@ -1,17 +1,15 @@ -use waynest::{ - server::{Client, Dispatcher, Result}, - wire::ObjectId, -}; +use crate::wayland::{Client, WaylandResult}; +use waynest::ObjectId; +pub use waynest_protocols::server::core::wayland::wl_output::*; -pub use waynest::server::protocol::core::wayland::wl_output::*; - -#[derive(Debug, Dispatcher)] +#[derive(Debug, waynest_server::RequestDispatcher)] +#[waynest(error = crate::wayland::WaylandError)] pub struct Output { pub id: ObjectId, pub version: u32, } impl Output { - pub async fn advertise_outputs(&self, client: &mut Client) -> Result<()> { + pub async fn advertise_outputs(&self, client: &mut Client) -> WaylandResult<()> { self.geometry( client, self.id, @@ -46,8 +44,10 @@ impl Output { } } impl WlOutput for Output { + type Connection = Client; + /// https://wayland.app/protocols/wayland#wl_output:request:release - async fn release(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { + async fn release(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> { Ok(()) } } diff --git a/src/wayland/core/pointer.rs b/src/wayland/core/pointer.rs index 30a645a..8136625 100644 --- a/src/wayland/core/pointer.rs +++ b/src/wayland/core/pointer.rs @@ -1,19 +1,18 @@ +use super::surface::SurfaceRole; use crate::nodes::items::panel::Geometry; -use crate::wayland::core::{seat::fixed_from_f32, surface::Surface}; +use crate::wayland::core::surface::Surface; +use crate::wayland::{Client, WaylandResult}; use mint::Vector2; use std::sync::Arc; use std::sync::Weak; use tokio::sync::Mutex; use tracing; -pub use waynest::server::protocol::core::wayland::wl_pointer::*; -use waynest::{ - server::{Client, Dispatcher, Result}, - wire::ObjectId, -}; +use waynest::ObjectId; -use super::surface::SurfaceRole; +pub use waynest_protocols::server::core::wayland::wl_pointer::*; -#[derive(Dispatcher)] +#[derive(waynest_server::RequestDispatcher)] +#[waynest(error = crate::wayland::WaylandError)] pub struct Pointer { pub id: ObjectId, version: u32, @@ -35,7 +34,7 @@ impl Pointer { client: &mut Client, surface: Arc, position: Vector2, - ) -> Result<()> { + ) -> WaylandResult<()> { tracing::debug!( "Handling pointer motion at ({}, {})", position.x, @@ -65,8 +64,8 @@ impl Pointer { self.id, serial, surface.id, - fixed_from_f32(position.x), - fixed_from_f32(position.y), + (position.x as f64).into(), + (position.y as f64).into(), ) .await?; @@ -80,8 +79,8 @@ impl Pointer { client, self.id, 0, // time - fixed_from_f32(position.x), - fixed_from_f32(position.y), + (position.x as f64).into(), + (position.y as f64).into(), ) .await?; if self.version >= 5 { @@ -97,7 +96,7 @@ impl Pointer { surface: Arc, button: u32, pressed: bool, - ) -> Result<()> { + ) -> WaylandResult<()> { tracing::debug!( "Handling pointer button {} {} on surface {:?}", button, @@ -126,7 +125,7 @@ impl Pointer { _surface: Arc, scroll_distance: Option>, scroll_steps: Option>, - ) -> Result<()> { + ) -> WaylandResult<()> { tracing::debug!( "Handling pointer scroll: distance={:?}, steps={:?}", scroll_distance, @@ -138,7 +137,7 @@ impl Pointer { self.id, 0, // time Axis::HorizontalScroll, - fixed_from_f32(distance.x), + (distance.x as f64).into(), ) .await?; self.axis( @@ -146,7 +145,7 @@ impl Pointer { self.id, 0, // time Axis::VerticalScroll, - fixed_from_f32(distance.y), + (distance.y as f64).into(), ) .await?; } @@ -162,7 +161,7 @@ impl Pointer { Ok(()) } - pub async fn reset(&self, client: &mut Client) -> Result<()> { + pub async fn reset(&self, client: &mut Client) -> WaylandResult<()> { let mut focused = self.focused_surface.lock().await; if let Some(old_surface) = focused.upgrade() { let serial = client.next_event_serial(); @@ -179,16 +178,18 @@ impl Pointer { } impl WlPointer for Pointer { + type Connection = crate::wayland::Client; + /// https://wayland.app/protocols/wayland#wl_pointer:request:set_cursor async fn set_cursor( &self, - client: &mut Client, + client: &mut Self::Connection, _sender_id: ObjectId, _serial: u32, surface: Option, hotspot_x: i32, hotspot_y: i32, - ) -> Result<()> { + ) -> WaylandResult<()> { if let Some(focused_surface) = self.focused_surface.lock().await.upgrade() && let Some(panel_item) = focused_surface.panel_item.lock().upgrade() { @@ -211,13 +212,19 @@ impl WlPointer for Pointer { return Ok(()); }; - surface.try_set_role(client, SurfaceRole::Cursor).await?; + surface + .try_set_role(SurfaceRole::Cursor, Error::Role) + .await?; self.cursor_surface.lock().await.replace(surface); Ok(()) } /// https://wayland.app/protocols/wayland#wl_pointer:request:release - async fn release(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { + async fn release( + &self, + _client: &mut Self::Connection, + _sender_id: ObjectId, + ) -> WaylandResult<()> { Ok(()) } } diff --git a/src/wayland/core/seat.rs b/src/wayland/core/seat.rs index dae74fc..4c24c03 100644 --- a/src/wayland/core/seat.rs +++ b/src/wayland/core/seat.rs @@ -1,10 +1,11 @@ +use crate::wayland::Client; +use crate::wayland::WaylandResult; use crate::wayland::core::{keyboard::Keyboard, pointer::Pointer, surface::Surface, touch::Touch}; use mint::Vector2; use std::sync::Arc; use std::sync::OnceLock; -pub use waynest::server::protocol::core::wayland::wl_seat::*; -use waynest::server::{Client, Dispatcher, Result}; -use waynest::wire::{Fixed, ObjectId}; +use waynest::ObjectId; +pub use waynest_protocols::server::core::wayland::wl_seat::*; #[derive(Debug)] pub enum SeatMessage { @@ -43,11 +44,8 @@ pub enum SeatMessage { Reset, } -pub fn fixed_from_f32(f: f32) -> Fixed { - unsafe { Fixed::from_raw((f * 256.0).round() as u32) } -} - -#[derive(Default, Dispatcher)] +#[derive(Default, waynest_server::RequestDispatcher)] +#[waynest(error = crate::wayland::WaylandError)] pub struct Seat { version: u32, pointer: OnceLock>, @@ -56,7 +54,7 @@ pub struct Seat { } impl Seat { - pub async fn new(client: &mut Client, id: ObjectId, version: u32) -> Result { + pub async fn new(client: &mut Client, id: ObjectId, version: u32) -> WaylandResult { let seat = Self { version, pointer: OnceLock::new(), @@ -76,7 +74,11 @@ impl Seat { Ok(seat) } - pub async fn handle_message(&self, client: &mut Client, message: SeatMessage) -> Result<()> { + pub async fn handle_message( + &self, + client: &mut Client, + message: SeatMessage, + ) -> WaylandResult<()> { match message { SeatMessage::PointerMotion { surface, position } => { if let Some(pointer) = self.pointer.get() { @@ -160,13 +162,15 @@ impl Seat { } } impl WlSeat for Seat { + type Connection = crate::wayland::Client; + /// https://wayland.app/protocols/wayland#wl_seat:request:get_pointer async fn get_pointer( &self, - client: &mut Client, + client: &mut Self::Connection, _sender_id: ObjectId, id: ObjectId, - ) -> Result<()> { + ) -> WaylandResult<()> { let pointer = client.insert(id, Pointer::new(id, self.version)); let _ = self.pointer.set(pointer); Ok(()) @@ -175,10 +179,10 @@ impl WlSeat for Seat { /// https://wayland.app/protocols/wayland#wl_seat:request:get_keyboard async fn get_keyboard( &self, - client: &mut Client, + client: &mut Self::Connection, _sender_id: ObjectId, id: ObjectId, - ) -> Result<()> { + ) -> WaylandResult<()> { tracing::info!("Getting keyboard"); let keyboard = client.insert(id, Keyboard::new(id)); let _ = self.keyboard.set(keyboard); @@ -188,17 +192,21 @@ impl WlSeat for Seat { /// https://wayland.app/protocols/wayland#wl_seat:request:get_touch async fn get_touch( &self, - client: &mut Client, + client: &mut Self::Connection, _sender_id: ObjectId, id: ObjectId, - ) -> Result<()> { + ) -> WaylandResult<()> { let touch = client.insert(id, Touch(id)); let _ = self.touch.set(touch); Ok(()) } /// https://wayland.app/protocols/wayland#wl_seat:request:release - async fn release(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { + async fn release( + &self, + _client: &mut Self::Connection, + _sender_id: ObjectId, + ) -> WaylandResult<()> { Ok(()) } } diff --git a/src/wayland/core/shm.rs b/src/wayland/core/shm.rs index 602ddbd..7a0fef9 100644 --- a/src/wayland/core/shm.rs +++ b/src/wayland/core/shm.rs @@ -1,16 +1,13 @@ +use crate::wayland::{Client, WaylandResult, core::shm_pool::ShmPool}; use std::os::fd::OwnedFd; +use waynest::ObjectId; +pub use waynest_protocols::server::core::wayland::wl_shm::*; -use crate::wayland::core::shm_pool::ShmPool; -pub use waynest::server::protocol::core::wayland::wl_shm::*; -use waynest::{ - server::{Client, Dispatcher, Result}, - wire::ObjectId, -}; - -#[derive(Debug, Dispatcher, Default)] +#[derive(Debug, waynest_server::RequestDispatcher, Default)] +#[waynest(error = crate::wayland::WaylandError)] pub struct Shm; impl Shm { - pub async fn advertise_formats(&self, client: &mut Client, sender_id: ObjectId) -> Result<()> { + pub async fn advertise_formats(&self, client: &mut Client, sender_id: ObjectId) -> WaylandResult<()> { self.format(client, sender_id, Format::Argb8888).await?; self.format(client, sender_id, Format::Xrgb8888).await?; @@ -18,22 +15,24 @@ impl Shm { } } impl WlShm for Shm { + type Connection = crate::wayland::Client; + /// https://wayland.app/protocols/wayland#wl_shm:request:create_pool async fn create_pool( &self, - client: &mut Client, + client: &mut Self::Connection, _sender_id: ObjectId, pool_id: ObjectId, fd: OwnedFd, size: i32, - ) -> Result<()> { + ) -> WaylandResult<()> { client.insert(pool_id, ShmPool::new(fd, size)?); Ok(()) } /// https://wayland.app/protocols/wayland#wl_shm:request:release - async fn release(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { + async fn release(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> { Ok(()) } } diff --git a/src/wayland/core/shm_buffer_backing.rs b/src/wayland/core/shm_buffer_backing.rs index 2641809..6307247 100644 --- a/src/wayland/core/shm_buffer_backing.rs +++ b/src/wayland/core/shm_buffer_backing.rs @@ -33,7 +33,7 @@ use vulkano::{ }, sync::GpuFuture, }; -use waynest::server::protocol::core::wayland::wl_shm::Format; +use waynest_protocols::server::core::wayland::wl_shm::Format; /// Parameters for a shared memory buffer pub struct ShmBufferBacking { diff --git a/src/wayland/core/shm_pool.rs b/src/wayland/core/shm_pool.rs index 69a4234..328c315 100644 --- a/src/wayland/core/shm_pool.rs +++ b/src/wayland/core/shm_pool.rs @@ -1,25 +1,24 @@ +use super::shm_buffer_backing::ShmBufferBacking; +use crate::wayland::{ + Client, WaylandResult, + core::buffer::{Buffer, BufferBacking}, +}; use memmap2::{MmapOptions, RemapOptions}; use parking_lot::{Mutex, MutexGuard, RawMutex, lock_api::MappedMutexGuard}; use std::os::fd::{IntoRawFd, OwnedFd}; -use waynest::{ - server::{Client, Dispatcher, Result, protocol::core::wayland::wl_shm::Format}, - wire::ObjectId, -}; +use waynest::ObjectId; +use waynest_protocols::server::core::wayland::wl_shm::Format; +pub use waynest_protocols::server::core::wayland::wl_shm_pool::*; -use crate::wayland::core::buffer::{Buffer, BufferBacking}; - -pub use waynest::server::protocol::core::wayland::wl_shm_pool::*; - -use super::shm_buffer_backing::ShmBufferBacking; - -#[derive(Debug, Dispatcher)] +#[derive(Debug, waynest_server::RequestDispatcher)] +#[waynest(error = crate::wayland::WaylandError)] pub struct ShmPool { inner: Mutex, } impl ShmPool { #[tracing::instrument(level = "debug", skip_all)] - pub fn new(fd: OwnedFd, size: i32) -> Result { + pub fn new(fd: OwnedFd, size: i32) -> WaylandResult { let map = unsafe { MmapOptions::new() .len(size as usize) @@ -38,11 +37,13 @@ impl ShmPool { } impl WlShmPool for ShmPool { + type Connection = Client; + /// https://wayland.app/protocols/wayland#wl_shm_pool:request:create_buffer #[tracing::instrument(level = "debug", skip_all)] async fn create_buffer( &self, - client: &mut Client, + client: &mut Self::Connection, sender_id: ObjectId, id: ObjectId, offset: i32, @@ -50,7 +51,7 @@ impl WlShmPool for ShmPool { height: i32, stride: i32, format: Format, - ) -> Result<()> { + ) -> WaylandResult<()> { let params = ShmBufferBacking::new( client.get::(sender_id).unwrap(), offset as usize, @@ -65,7 +66,12 @@ impl WlShmPool for ShmPool { /// https://wayland.app/protocols/wayland#wl_shm_pool:request:resize #[tracing::instrument(level = "debug", skip_all)] - async fn resize(&self, _client: &mut Client, _sender_id: ObjectId, size: i32) -> Result<()> { + async fn resize( + &self, + _client: &mut Self::Connection, + _sender_id: ObjectId, + size: i32, + ) -> WaylandResult<()> { let mut inner = self.inner.lock(); unsafe { inner.remap(size as usize, RemapOptions::new().may_move(true))? }; Ok(()) @@ -73,7 +79,7 @@ impl WlShmPool for ShmPool { /// https://wayland.app/protocols/wayland#wl_shm_pool:request:destroy #[tracing::instrument(level = "debug", skip_all)] - async fn destroy(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { + async fn destroy(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> { Ok(()) } } diff --git a/src/wayland/core/surface.rs b/src/wayland/core/surface.rs index 83ab610..1c1e5e6 100644 --- a/src/wayland/core/surface.rs +++ b/src/wayland/core/surface.rs @@ -7,7 +7,7 @@ use crate::{ items::panel::{Geometry, PanelItem, SurfaceId}, }, wayland::{ - Message, MessageSink, + Client, Message, MessageSink, WaylandError, WaylandResult, core::buffer::BufferUsage, presentation::{MonotonicTimestamp, PresentationFeedback}, util::{ClientExt, DoubleBuffer}, @@ -22,16 +22,14 @@ use bevy::{ use bevy_dmabuf::import::ImportedDmatexs; use mint::Vector2; use parking_lot::Mutex; -use std::sync::{Arc, OnceLock, Weak}; -use waynest::{ - server::{ - self, Client, Dispatcher, Result, - protocol::{ - core::wayland::{wl_output::Transform, wl_surface::*}, - stable::presentation_time::wp_presentation_feedback::{Kind, WpPresentationFeedback}, - }, - }, - wire::ObjectId, +use std::{ + fmt::Display, + sync::{Arc, OnceLock, Weak}, +}; +use waynest::ObjectId; +use waynest_protocols::server::{ + core::wayland::{wl_output::Transform, wl_surface::*}, + stable::presentation_time::wp_presentation_feedback::{Kind, WpPresentationFeedback}, }; pub static WL_SURFACE_REGISTRY: Registry = Registry::new(); @@ -43,6 +41,16 @@ pub enum SurfaceRole { XdgToplevel, XdgPopup, } +impl Display for SurfaceRole { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + SurfaceRole::Cursor => f.write_str("SurfaceRole::Cursor"), + SurfaceRole::Subsurface => f.write_str("SurfaceRole::Subsurface"), + SurfaceRole::XdgToplevel => f.write_str("SurfaceRole::XdgToplevel"), + SurfaceRole::XdgPopup => f.write_str("SurfaceRole::XdgPopup"), + } + } +} #[derive(Debug, Clone)] pub struct BufferState { @@ -81,7 +89,8 @@ impl SurfaceState { // if returning false, don't run this callback again... just remove it pub type OnCommitCallback = Box bool + Send + Sync>; -#[derive(Dispatcher)] +#[derive(waynest_server::RequestDispatcher)] +#[waynest(error = crate::wayland::WaylandError)] pub struct Surface { pub id: ObjectId, pub surface_id: OnceLock, @@ -130,24 +139,21 @@ impl Surface { } } - pub async fn try_set_role(&self, client: &mut Client, role: SurfaceRole) -> Result<()> { + pub async fn try_set_role( + &self, + role: SurfaceRole, + role_error: impl Into, + ) -> WaylandResult<()> { match self.role.get().cloned() { Some(current_role) => { if current_role == role { Ok(()) } else { - client - .protocol_error( - self.id, - self.id, - 1, // XDG_WM_BASE_ERROR_ROLE - "Surface has an incomparible role".to_string(), - ) - .await?; - Err(server::Error::Custom(format!( - "Surface {} has role {current_role:?} but tried to set to {role:?}", - self.id - ))) + Err(WaylandError::Fatal { + object_id: self.id, + code: role_error.into(), + message: "Surface has an incomparible role", + }) } } None => { @@ -248,7 +254,7 @@ impl Surface { // .map(|b| [b.size.x as u32, b.size.y as u32].into()) // } - // pub async fn release_old_buffer(&self, client: &mut Client) -> Result<()> { + // pub async fn release_old_buffer(&self, client: &mut Self::Connection) -> Result<()> { // let (old_buffer, object) = { // let lock = self.state.lock(); @@ -291,7 +297,7 @@ impl Surface { client: &mut Client, display_timestamp: MonotonicTimestamp, refresh_cycle: u64, - ) -> Result<()> { + ) -> WaylandResult<()> { let feedbacks = self .presentation_feedback .lock() @@ -325,16 +331,18 @@ impl Surface { } } impl WlSurface for Surface { + type Connection = crate::wayland::Client; + /// https://wayland.app/protocols/wayland#wl_surface:request:attach #[tracing::instrument(level = "debug", skip_all)] async fn attach( &self, - client: &mut Client, + client: &mut Self::Connection, _sender_id: ObjectId, buffer: Option, _x: i32, _y: i32, - ) -> Result<()> { + ) -> WaylandResult<()> { self.state.lock().pending.buffer = buffer.and_then(|b| { let buffer = client.get::(b)?; let mut usage = Some(BufferUsage::new(client, &buffer)); @@ -350,13 +358,13 @@ impl WlSurface for Surface { #[tracing::instrument(level = "debug", skip_all)] async fn damage( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, _x: i32, _y: i32, _width: i32, _height: i32, - ) -> Result<()> { + ) -> WaylandResult<()> { Ok(()) } @@ -364,10 +372,10 @@ impl WlSurface for Surface { #[tracing::instrument(level = "debug", skip_all)] async fn frame( &self, - client: &mut Client, + client: &mut Self::Connection, _sender_id: ObjectId, callback_id: ObjectId, - ) -> Result<()> { + ) -> WaylandResult<()> { let callback = client.insert(callback_id, Callback(callback_id)); self.state.lock().pending.frame_callbacks.push(callback); Ok(()) @@ -377,10 +385,10 @@ impl WlSurface for Surface { #[tracing::instrument(level = "debug", skip_all)] async fn set_opaque_region( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, _region: Option, - ) -> Result<()> { + ) -> WaylandResult<()> { // nothing we can really do to repaint behind this so ignore it Ok(()) } @@ -389,17 +397,21 @@ impl WlSurface for Surface { #[tracing::instrument(level = "debug", skip_all)] async fn set_input_region( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, _region: Option, - ) -> Result<()> { + ) -> WaylandResult<()> { // too complicated to implement this for now so who the hell cares Ok(()) } /// https://wayland.app/protocols/wayland#wl_surface:request:commit #[tracing::instrument(level = "debug", skip_all)] - async fn commit(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { + async fn commit( + &self, + _client: &mut Self::Connection, + _sender_id: ObjectId, + ) -> WaylandResult<()> { // we want the upload to complete before we give the image to bevy let buffer_option = self .state_lock() @@ -428,10 +440,10 @@ impl WlSurface for Surface { #[tracing::instrument(level = "debug", skip_all)] async fn set_buffer_transform( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, _transform: Transform, - ) -> Result<()> { + ) -> WaylandResult<()> { // we just don't have the output transform or fullscreen at all so this optimization is never needed Ok(()) } @@ -440,10 +452,10 @@ impl WlSurface for Surface { #[tracing::instrument(level = "debug", skip_all)] async fn set_buffer_scale( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, scale: i32, - ) -> Result<()> { + ) -> WaylandResult<()> { self.state.lock().pending.density = scale as f32; Ok(()) } @@ -452,13 +464,13 @@ impl WlSurface for Surface { #[tracing::instrument(level = "debug", skip_all)] async fn damage_buffer( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, _x: i32, _y: i32, _width: i32, _height: i32, - ) -> Result<()> { + ) -> WaylandResult<()> { Ok(()) } @@ -466,17 +478,21 @@ impl WlSurface for Surface { #[tracing::instrument(level = "debug", skip_all)] async fn offset( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, _x: i32, _y: i32, - ) -> Result<()> { + ) -> WaylandResult<()> { Ok(()) } /// https://wayland.app/protocols/wayland#wl_surface:request:destroy #[tracing::instrument(level = "debug", skip_all)] - async fn destroy(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { + async fn destroy( + &self, + _client: &mut Self::Connection, + _sender_id: ObjectId, + ) -> WaylandResult<()> { Ok(()) } } diff --git a/src/wayland/core/touch.rs b/src/wayland/core/touch.rs index 619fa0d..a8bd9e5 100644 --- a/src/wayland/core/touch.rs +++ b/src/wayland/core/touch.rs @@ -1,15 +1,11 @@ -use crate::wayland::core::surface::Surface; +use crate::wayland::{Client, WaylandResult, core::surface::Surface}; use mint::Vector2; use std::sync::Arc; -pub use waynest::server::protocol::core::wayland::wl_touch::*; -use waynest::{ - server::{Client, Dispatcher, Result}, - wire::ObjectId, -}; +use waynest::ObjectId; +pub use waynest_protocols::server::core::wayland::wl_touch::*; -use super::seat::fixed_from_f32; - -#[derive(Debug, Dispatcher)] +#[derive(Debug, waynest_server::RequestDispatcher)] +#[waynest(error = crate::wayland::WaylandError)] pub struct Touch(pub ObjectId); impl Touch { pub async fn handle_touch_down( @@ -18,7 +14,7 @@ impl Touch { surface: Arc, id: u32, position: Vector2, - ) -> Result<()> { + ) -> WaylandResult<()> { let serial = client.next_event_serial(); self.down( client, @@ -27,8 +23,8 @@ impl Touch { 0, surface.id, id as i32, - fixed_from_f32(position.x), - fixed_from_f32(position.y), + (position.x as f64).into(), + (position.y as f64).into(), ) .await?; self.frame(client, self.0).await @@ -39,37 +35,39 @@ impl Touch { client: &mut Client, id: u32, position: Vector2, - ) -> Result<()> { + ) -> WaylandResult<()> { self.motion( client, self.0, 0, id as i32, - fixed_from_f32(position.x), - fixed_from_f32(position.y), + (position.x as f64).into(), + (position.y as f64).into(), ) .await?; self.frame(client, self.0).await } - pub async fn handle_touch_up(&self, client: &mut Client, id: u32) -> Result<()> { + pub async fn handle_touch_up(&self, client: &mut Client, id: u32) -> WaylandResult<()> { let serial = client.next_event_serial(); self.up(client, self.0, serial, 0, id as i32).await?; self.frame(client, self.0).await } - pub async fn reset(&self, client: &mut Client) -> Result<()> { + pub async fn reset(&self, client: &mut Client) -> WaylandResult<()> { self.frame(client, self.0).await } } impl WlTouch for Touch { + type Connection = crate::wayland::Client; + /// https://wayland.app/protocols/wayland#wl_touch:request:release async fn release( &self, - _client: &mut waynest::server::Client, - _sender_id: waynest::wire::ObjectId, - ) -> Result<()> { + _client: &mut Self::Connection, + _sender_id: ObjectId, + ) -> WaylandResult<()> { Ok(()) } } diff --git a/src/wayland/display.rs b/src/wayland/display.rs index f61a980..b8c8340 100644 --- a/src/wayland/display.rs +++ b/src/wayland/display.rs @@ -1,7 +1,7 @@ #![allow(unused)] use crate::wayland::{ - MessageSink, + MessageSink, WaylandResult, core::{ callback::{Callback, WlCallback}, output::Output, @@ -14,13 +14,11 @@ use std::{ sync::{Arc, OnceLock}, time::Instant, }; -pub use waynest::server::protocol::core::wayland::wl_display::*; -use waynest::{ - server::{Client, Dispatcher, Result}, - wire::ObjectId, -}; +use waynest::ObjectId; +pub use waynest_protocols::server::core::wayland::wl_display::*; -#[derive(Dispatcher)] +#[derive(waynest_server::RequestDispatcher)] +#[waynest(error = crate::wayland::WaylandError)] pub struct Display { pub message_sink: MessageSink, pub pid: Option, @@ -45,13 +43,15 @@ impl Display { } } impl WlDisplay for Display { + type Connection = crate::wayland::Client; + /// https://wayland.app/protocols/wayland#wl_display:request:sync async fn sync( &self, - client: &mut Client, + client: &mut Self::Connection, sender_id: ObjectId, callback_id: ObjectId, - ) -> Result<()> { + ) -> WaylandResult<()> { let serial = client.next_event_serial(); Callback(callback_id) .done(client, callback_id, serial) @@ -65,10 +65,10 @@ impl WlDisplay for Display { /// https://wayland.app/protocols/wayland#wl_display:request:get_registry async fn get_registry( &self, - client: &mut Client, + client: &mut Self::Connection, _sender_id: ObjectId, registry_id: ObjectId, - ) -> Result<()> { + ) -> WaylandResult<()> { let registry = client.insert(registry_id, Registry); registry.advertise_globals(client, registry_id).await?; diff --git a/src/wayland/dmabuf/buffer_backing.rs b/src/wayland/dmabuf/buffer_backing.rs index 08ff23c..4dcfb0b 100644 --- a/src/wayland/dmabuf/buffer_backing.rs +++ b/src/wayland/dmabuf/buffer_backing.rs @@ -14,7 +14,7 @@ use drm_fourcc::DrmFourcc; use mint::Vector2; use parking_lot::Mutex; use std::sync::{Arc, OnceLock}; -use waynest::server::protocol::stable::linux_dmabuf_v1::zwp_linux_buffer_params_v1::Flags; +use waynest_protocols::server::stable::linux_dmabuf_v1::zwp_linux_buffer_params_v1::Flags; /// Parameters for a shared memory buffer pub struct DmabufBacking { diff --git a/src/wayland/dmabuf/buffer_params.rs b/src/wayland/dmabuf/buffer_params.rs index 40e1180..824782e 100644 --- a/src/wayland/dmabuf/buffer_params.rs +++ b/src/wayland/dmabuf/buffer_params.rs @@ -1,5 +1,6 @@ use super::buffer_backing::DmabufBacking; use crate::wayland::{ + Client, WaylandError, WaylandResult, core::buffer::{Buffer, BufferBacking}, util::ClientExt, }; @@ -8,14 +9,9 @@ use drm_fourcc::DrmFourcc; use parking_lot::Mutex; use rustc_hash::FxHashMap; use std::os::fd::{AsRawFd, OwnedFd}; -use waynest::{ - server::{ - Client, Dispatcher, Result, - protocol::stable::linux_dmabuf_v1::zwp_linux_buffer_params_v1::{ - Error, Flags, ZwpLinuxBufferParamsV1, - }, - }, - wire::ObjectId, +use waynest::ObjectId; +use waynest_protocols::server::stable::linux_dmabuf_v1::zwp_linux_buffer_params_v1::{ + Error, Flags, ZwpLinuxBufferParamsV1, }; /// Parameters for creating a DMA-BUF-based wl_buffer @@ -23,7 +19,8 @@ use waynest::{ /// This is a temporary object that collects dmabufs and other parameters /// that together form a single logical buffer. The object may eventually /// create one wl_buffer unless cancelled by destroying it. -#[derive(Debug, Dispatcher)] +#[derive(Debug, waynest_server::RequestDispatcher)] +#[waynest(error = crate::wayland::WaylandError)] pub struct BufferParams { pub id: ObjectId, pub(super) planes: Mutex>, @@ -41,7 +38,13 @@ impl BufferParams { } impl ZwpLinuxBufferParamsV1 for BufferParams { - async fn destroy(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { + type Connection = Client; + + async fn destroy( + &self, + _client: &mut Self::Connection, + _sender_id: ObjectId, + ) -> WaylandResult<()> { tracing::info!("Destroying BufferParams {:?}", self.id); Ok(()) } @@ -49,7 +52,7 @@ impl ZwpLinuxBufferParamsV1 for BufferParams { #[tracing::instrument(level = "debug", skip_all)] async fn add( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, fd: OwnedFd, plane_idx: u32, @@ -57,7 +60,7 @@ impl ZwpLinuxBufferParamsV1 for BufferParams { stride: u32, modifier_hi: u32, modifier_lo: u32, - ) -> Result<()> { + ) -> WaylandResult<()> { let fd_num = fd.as_raw_fd(); tracing::info!( "Adding plane {} with fd {} to BufferParams {:?}", @@ -75,7 +78,7 @@ impl ZwpLinuxBufferParamsV1 for BufferParams { plane_idx, self.id ); - return Err(waynest::server::Error::MissingObject(self.id)); + return Err(crate::wayland::WaylandError::MissingObject(self.id)); } // Create plane with the provided parameters @@ -94,13 +97,13 @@ impl ZwpLinuxBufferParamsV1 for BufferParams { #[tracing::instrument(level = "debug", skip_all)] async fn create( &self, - client: &mut Client, + client: &mut Self::Connection, _sender_id: ObjectId, width: i32, height: i32, format: u32, flags: Flags, - ) -> Result<()> { + ) -> WaylandResult<()> { tracing::info!("Creating buffer from BufferParams {:?}", self.id); // Create the buffer with DMA-BUF backing using self as the backing let size = [width as u32, height as u32].into(); @@ -128,14 +131,14 @@ impl ZwpLinuxBufferParamsV1 for BufferParams { #[tracing::instrument(level = "debug", skip_all)] async fn create_immed( &self, - client: &mut Client, - sender_id: ObjectId, + client: &mut Self::Connection, + _sender_id: ObjectId, buffer_id: ObjectId, width: i32, height: i32, format: u32, flags: Flags, - ) -> Result<()> { + ) -> WaylandResult<()> { // TODO: terminate client on fail, or send a fail event or something // Create the buffer with DMA-BUF backing using self as the backing match DmabufBacking::from_params( @@ -148,15 +151,12 @@ impl ZwpLinuxBufferParamsV1 for BufferParams { Buffer::new(client, buffer_id, BufferBacking::Dmabuf(backing)); } Err(e) => { - client - .protocol_error( - sender_id, - buffer_id, - Error::Incomplete as u32, - format!("Failed to import dmabuf because {e}"), - ) - .await?; tracing::error!("Failed to import dmabuf because {e}"); + return Err(WaylandError::Fatal { + object_id: buffer_id, + code: Error::Incomplete as u32, + message: "Failed to import dmabuf", + }); } } Ok(()) diff --git a/src/wayland/dmabuf/feedback.rs b/src/wayland/dmabuf/feedback.rs index adc2231..63d58e5 100644 --- a/src/wayland/dmabuf/feedback.rs +++ b/src/wayland/dmabuf/feedback.rs @@ -1,26 +1,22 @@ use super::Dmabuf; -use crate::wayland::vulkano_data::VULKANO_CONTEXT; +use crate::wayland::{Client, WaylandResult, vulkano_data::VULKANO_CONTEXT}; use memfd::MemfdOptions; use std::{ io::Write, os::fd::{FromRawFd, IntoRawFd, OwnedFd}, sync::Arc, }; -use waynest::{ - server::{ - Client, Dispatcher, Result, - protocol::stable::linux_dmabuf_v1::zwp_linux_dmabuf_feedback_v1::{ - TrancheFlags, ZwpLinuxDmabufFeedbackV1, - }, - }, - wire::ObjectId, +use waynest::ObjectId; +use waynest_protocols::server::stable::linux_dmabuf_v1::zwp_linux_dmabuf_feedback_v1::{ + TrancheFlags, ZwpLinuxDmabufFeedbackV1, }; -#[derive(Debug, Dispatcher)] +#[derive(Debug, waynest_server::RequestDispatcher)] +#[waynest(error = crate::wayland::WaylandError)] pub struct DmabufFeedback(pub Arc); impl DmabufFeedback { #[tracing::instrument(level = "debug", skip_all)] - pub async fn send_params(&self, client: &mut Client, sender_id: ObjectId) -> Result<()> { + pub async fn send_params(&self, client: &mut Client, sender_id: ObjectId) -> WaylandResult<()> { let num_formats = self.0.formats.len(); // Send format table first self.send_format_table(client, sender_id).await?; @@ -63,16 +59,18 @@ impl DmabufFeedback { } #[tracing::instrument(level = "debug", skip_all)] - pub async fn send_format_table(&self, client: &mut Client, sender_id: ObjectId) -> Result<()> { + pub async fn send_format_table( + &self, + client: &mut Client, + sender_id: ObjectId, + ) -> WaylandResult<()> { // Format + modifier pair (16 bytes): // - format: u32 // - padding: 4 bytes // - modifier: u64 let size = self.0.formats.len() as u32 * 16u32; // Create a temporary file for the format table - let mfd = MemfdOptions::default() - .create("stardustxr-format-table") - .map_err(|e| waynest::server::Error::Custom(e.to_string()))?; + let mfd = MemfdOptions::default().create("stardustxr-format-table")?; mfd.as_file().set_len(size as u64)?; @@ -96,7 +94,13 @@ impl DmabufFeedback { } impl ZwpLinuxDmabufFeedbackV1 for DmabufFeedback { - async fn destroy(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { + type Connection = crate::wayland::Client; + + async fn destroy( + &self, + _client: &mut Self::Connection, + _sender_id: ObjectId, + ) -> WaylandResult<()> { Ok(()) } } diff --git a/src/wayland/dmabuf/mod.rs b/src/wayland/dmabuf/mod.rs index df4151a..83f0ede 100644 --- a/src/wayland/dmabuf/mod.rs +++ b/src/wayland/dmabuf/mod.rs @@ -2,10 +2,11 @@ pub mod buffer_backing; pub mod buffer_params; pub mod feedback; -use std::sync::LazyLock; - -use super::{util::ClientExt, vulkano_data::VULKANO_CONTEXT}; -use crate::core::registry::Registry; +use super::vulkano_data::VULKANO_CONTEXT; +use crate::{ + core::registry::Registry, + wayland::{Client, WaylandError, WaylandResult}, +}; use bevy_dmabuf::{ format_mapping::{drm_fourcc_to_vk_format, vk_format_to_srgb}, wgpu_init::vulkan_to_wgpu, @@ -14,14 +15,10 @@ use buffer_params::BufferParams; use drm_fourcc::DrmFourcc; use feedback::DmabufFeedback; use rustc_hash::FxHashSet; +use std::sync::LazyLock; use vulkano::format::FormatFeatures; -use waynest::{ - server::{ - Client, Dispatcher, Error, Result, - protocol::stable::linux_dmabuf_v1::zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1, - }, - wire::ObjectId, -}; +use waynest::ObjectId; +use waynest_protocols::server::stable::linux_dmabuf_v1::zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1; pub static DMABUF_FORMATS: LazyLock> = LazyLock::new(|| { let vk = VULKANO_CONTEXT.wait(); @@ -76,7 +73,8 @@ pub static DMABUF_FORMATS: LazyLock> = LazyLock::new(|| { /// - Coherency for read access in dmabuf data /// - Proper lifetime management of dmabuf file descriptors /// - Safe handling of buffer attachments -#[derive(Debug, Dispatcher)] +#[derive(Debug, waynest_server::RequestDispatcher)] +#[waynest(error = crate::wayland::WaylandError)] pub struct Dmabuf { // Track supported formats and modifiers // formats: Mutex>, @@ -88,7 +86,7 @@ pub struct Dmabuf { impl Dmabuf { /// Create a new DMA-BUF interface instance - pub async fn new(client: &mut Client, id: ObjectId, version: u32) -> Result { + pub async fn new(client: &mut Client, id: ObjectId, version: u32) -> WaylandResult { let dmabuf = Self { active_params: Registry::new(), version, @@ -122,17 +120,23 @@ impl Dmabuf { } impl ZwpLinuxDmabufV1 for Dmabuf { - async fn destroy(&self, _client: &mut Client, sender_id: ObjectId) -> Result<()> { + type Connection = crate::wayland::Client; + + async fn destroy( + &self, + _client: &mut Self::Connection, + sender_id: ObjectId, + ) -> WaylandResult<()> { self.remove_params(sender_id); Ok(()) } async fn create_params( &self, - client: &mut Client, + client: &mut Self::Connection, _sender_id: ObjectId, params_id: ObjectId, - ) -> Result<()> { + ) -> WaylandResult<()> { // Create new buffer parameters object let params = client.insert(params_id, BufferParams::new(params_id)); self.active_params.add_raw(¶ms); @@ -141,20 +145,16 @@ impl ZwpLinuxDmabufV1 for Dmabuf { async fn get_default_feedback( &self, - client: &mut Client, + client: &mut Self::Connection, sender_id: ObjectId, id: ObjectId, - ) -> Result<()> { + ) -> WaylandResult<()> { if self.version < 3 { - client - .protocol_error( - sender_id, - id, - 71, - "Can't call get_default_feedback on version < 4 of dmabuf".into(), - ) - .await?; - return Err(Error::Custom("Protocol error".into())); + return Err(WaylandError::Fatal { + object_id: id, + code: 71, + message: "Can't call get_default_feedback on version < 4 of dmabuf", + }); } // Create feedback object for default (non-surface-specific) settings let feedback = client.insert(id, DmabufFeedback(client.get::(sender_id).unwrap())); @@ -164,11 +164,11 @@ impl ZwpLinuxDmabufV1 for Dmabuf { async fn get_surface_feedback( &self, - client: &mut Client, + client: &mut Self::Connection, sender_id: ObjectId, id: ObjectId, _surface: ObjectId, - ) -> Result<()> { + ) -> WaylandResult<()> { // Create feedback object for surface-specific settings // Note: Surface-specific feedback could be optimized based on the surface's // requirements, but for now we use the same feedback as default diff --git a/src/wayland/mesa_drm.rs b/src/wayland/mesa_drm.rs index 2a4d03b..506a52d 100644 --- a/src/wayland/mesa_drm.rs +++ b/src/wayland/mesa_drm.rs @@ -1,4 +1,5 @@ use crate::wayland::{ + Client, WaylandResult, core::buffer::{Buffer, BufferBacking}, dmabuf::{DMABUF_FORMATS, buffer_backing::DmabufBacking}, vulkano_data::VULKANO_CONTEXT, @@ -6,17 +7,16 @@ use crate::wayland::{ use bevy_dmabuf::dmatex::{Dmatex, DmatexPlane, Resolution}; use rustc_hash::FxHashSet; use std::os::fd::OwnedFd; -use waynest::{ - server::{Client, Dispatcher, Result, protocol::mesa::drm::wl_drm::*}, - wire::ObjectId, -}; +use waynest::ObjectId; +use waynest_protocols::server::mesa::drm::wl_drm::*; -#[derive(Debug, Dispatcher, Default)] +#[derive(Debug, waynest_server::RequestDispatcher, Default)] +#[waynest(error = crate::wayland::WaylandError)] pub struct MesaDrm { version: u32, } impl MesaDrm { - pub async fn new(client: &mut Client, id: ObjectId, version: u32) -> Result { + pub async fn new(client: &mut Client, id: ObjectId, version: u32) -> WaylandResult { let drm = MesaDrm { version }; let path = { @@ -46,13 +46,20 @@ impl MesaDrm { } } impl WlDrm for MesaDrm { - async fn authenticate(&self, client: &mut Client, sender_id: ObjectId, _id: u32) -> Result<()> { + type Connection = Client; + + async fn authenticate( + &self, + client: &mut Self::Connection, + sender_id: ObjectId, + _id: u32, + ) -> WaylandResult<()> { self.authenticated(client, sender_id).await } async fn create_buffer( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, _id: ObjectId, _name: u32, @@ -60,14 +67,14 @@ impl WlDrm for MesaDrm { _height: i32, _stride: u32, _format: u32, - ) -> Result<()> { + ) -> WaylandResult<()> { tracing::error!("Tried to create non-prime wl_drm buffer!"); Ok(()) } async fn create_planar_buffer( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, _id: ObjectId, _name: u32, @@ -80,14 +87,14 @@ impl WlDrm for MesaDrm { _stride1: i32, _offset2: i32, _stride2: i32, - ) -> Result<()> { + ) -> WaylandResult<()> { tracing::error!("Tried to create non-prime wl_drm buffer!"); Ok(()) } async fn create_prime_buffer( &self, - client: &mut Client, + client: &mut Self::Connection, _sender_id: ObjectId, buffer_id: ObjectId, name: OwnedFd, @@ -100,7 +107,7 @@ impl WlDrm for MesaDrm { _stride1: i32, _offset2: i32, _stride2: i32, - ) -> Result<()> { + ) -> WaylandResult<()> { // TODO: actual error checking let _ = DmabufBacking::new(Dmatex { diff --git a/src/wayland/mod.rs b/src/wayland/mod.rs index 78b296b..2992afa 100644 --- a/src/wayland/mod.rs +++ b/src/wayland/mod.rs @@ -9,18 +9,14 @@ mod viewporter; mod vulkano_data; mod xdg; +use crate::core::error::ServerError; use crate::core::registry::OwnedRegistry; use crate::nodes::drawable::model::ModelNodeSystemSet; use crate::wayland::core::seat::SeatMessage; use crate::wayland::core::surface::Surface; use crate::wayland::presentation::MonotonicTimestamp; -use crate::{ - BevyMaterial, - core::{ - error::{Result, ServerError}, - task, - }, -}; +use crate::wayland::util::ClientExt; +use crate::{BevyMaterial, core::task}; use bevy::app::{App, Plugin, Update}; use bevy::ecs::schedule::IntoScheduleConfigs; use bevy::ecs::system::{Local, Res, ResMut}; @@ -37,11 +33,11 @@ use core::{buffer::Buffer, callback::Callback, surface::WL_SURFACE_REGISTRY}; use display::Display; use mint::Vector2; use std::fs::File; +use std::io::ErrorKind; use std::mem::MaybeUninit; use std::time::Duration; use std::{ - fs, - io::{self, ErrorKind}, + io, path::PathBuf, sync::{Arc, OnceLock}, }; @@ -49,24 +45,37 @@ use tokio::{net::UnixStream, sync::mpsc, task::AbortHandle}; use tokio_stream::StreamExt; use tracing::{debug_span, instrument}; use vulkano_data::setup_vulkano_context; -use waynest::{ - server::{ - self, - protocol::{ - core::wayland::{wl_buffer::WlBuffer, wl_callback::WlCallback, wl_display::WlDisplay}, - stable::xdg_shell::xdg_toplevel::XdgToplevel, - }, - }, - wire::{DecodeError, ObjectId}, -}; +use waynest::ObjectId; +use waynest_protocols::server::core::wayland::wl_display::WlDisplay; +use waynest_server::{Connection, Listener}; use xdg::toplevel::Toplevel; pub static WAYLAND_DISPLAY: OnceLock = OnceLock::new(); -impl From for ServerError { - fn from(err: waynest::server::Error) -> Self { - ServerError::WaylandError(err) - } +#[derive(thiserror::Error, Debug)] +pub enum WaylandError { + // #[error("Listener error: {0}")] + // Listener(#[from] waynest_server::ListenerError), + #[error("I/O error: {0}")] + Io(#[from] io::Error), + #[error("Decode error: {0}")] + DecodeError(#[from] waynest::ProtocolError), + #[error("Client requested unknown global: {0}")] + UnknownGlobal(u32), + #[error("No object found with ID {0}")] + MissingObject(ObjectId), + #[error("Fatal error on object {object_id} with code {code}: {message}")] + Fatal { + object_id: ObjectId, + code: u32, + message: &'static str, + }, + #[error("Memfd error: {0}")] + MemfdError(#[from] memfd::Error), + #[error("Dmabuf import error: {0}")] + DmabufImport(#[from] bevy_dmabuf::import::ImportError), + #[error("Server error: {0}")] + Server(#[from] ServerError), } pub fn get_free_wayland_socket_path() -> Option<(PathBuf, File)> { @@ -93,7 +102,7 @@ pub fn get_free_wayland_socket_path() -> Option<(PathBuf, File)> { Ok(_) => continue, // Active compositor found - skip Err(e) if e.kind() == ErrorKind::ConnectionRefused => { // Stale socket - safe to remove since we hold the lock - let _ = fs::remove_file(&socket_path); + let _ = std::fs::remove_file(&socket_path); } Err(_) => continue, // Transient error - conservative skip } @@ -106,8 +115,10 @@ pub fn get_free_wayland_socket_path() -> Option<(PathBuf, File)> { None // Exhausted all conventional display numbers } +pub type WaylandResult = std::result::Result; +pub type Client = waynest_server::Connection; + pub enum Message { - Disconnect, Frame(Vec>), ReleaseBuffer(Arc), CloseToplevel(Arc), @@ -135,26 +146,25 @@ struct WaylandClient { abort_handle: AbortHandle, } impl WaylandClient { - pub fn from_stream(socket: UnixStream) -> Result { + pub fn from_stream(socket: UnixStream) -> WaylandResult { let pid = socket.peer_cred().ok().and_then(|c| c.pid()); - let mut client = server::Client::new(socket)?; + let mut client = Connection::new(socket)?; let (message_sink, message_source) = mpsc::unbounded_channel(); client.insert(ObjectId::DISPLAY, Display::new(message_sink, pid)); - let abort_handle = task::new( - || "wayland client", - Self::handle_client_messages(client, message_source), - )? - .abort_handle(); + let abort_handle = + tokio::task::spawn(Self::dispatch_loop(client, message_source)).abort_handle(); Ok(WaylandClient { abort_handle }) } - async fn handle_client_messages( - mut client: server::Client, + + async fn dispatch_loop( + mut client: Client, mut render_message_rx: mpsc::UnboundedReceiver, - ) -> Result<()> { + ) -> WaylandResult<()> { loop { tokio::select! { + biased; // send all queued up messages msg = render_message_rx.recv() => { if let Some(msg) = msg { @@ -162,49 +172,32 @@ impl WaylandClient { } } // handle the next message - msg = client.next_message() => { - match msg { - Ok(Some(mut msg)) => { - if let Err(e) = client.handle_message(&mut msg).await { - tracing::error!("Wayland: Error handling message: {:?}", e); - break; - } - } - Err(e) => { - // wayland clients really aren't nice when disconnecting properly, are they? :p - if let server::Error::Decode(DecodeError::IoError(e)) = &e && e.kind() == io::ErrorKind::ConnectionReset { - if let Some(pid) = client.get::(ObjectId::DISPLAY).and_then(|d| d.pid) { - tracing::info!("Wayland: Client with pid: {pid} disconnected from server"); - } else { - tracing::info!("Wayland: Unknown client disconnected from server"); - } - break; - } - tracing::error!("Wayland: Error reading message: {:?}", e); - break; - } - Ok(None) => { - if let Some(pid) = client.get::(ObjectId::DISPLAY).and_then(|d| d.pid) { - tracing::info!("Wayland: Client with pid: {pid} disconnected from server"); - } else { - tracing::info!("Wayland: Unknown client disconnected from server"); - } - // Message stream ended - break; + msg = client.try_next() => { + if let Some(mut msg) = msg? && + let Err(e) = client + .get_raw(msg.object_id()) + .ok_or(WaylandError::MissingObject(msg.object_id()))? + .dispatch_request(&mut client, msg.object_id(), &mut msg) + .await + { + if let WaylandError::Fatal { object_id, code, message } = e { + client.display().error(&mut client, ObjectId::DISPLAY, object_id, code, message.to_string()).await?; } + tracing::error!("Wayland: {e}"); + return Err(e); } } - } + }; } - Ok(()) } - async fn handle_render_message( - client: &mut server::Client, - message: Message, - ) -> Result { + async fn handle_render_message(client: &mut Client, message: Message) -> WaylandResult<()> { + use waynest_protocols::server::core::wayland::wl_buffer::WlBuffer; + use waynest_protocols::server::core::wayland::wl_callback::WlCallback; + use waynest_protocols::server::core::wayland::wl_display::WlDisplay; + use waynest_protocols::server::stable::xdg_shell::xdg_toplevel::XdgToplevel; + match message { - Message::Disconnect => return Ok(true), Message::Frame(callbacks) => { let now = rustix::time::clock_gettime(rustix::time::ClockId::Monotonic); let now = Duration::new(now.tv_sec as u64, now.tv_nsec as u32); @@ -251,7 +244,7 @@ impl WaylandClient { .await?; } } - Ok(false) + Ok(()) } } impl Drop for WaylandClient { @@ -266,16 +259,15 @@ pub struct Wayland { abort_handle: AbortHandle, } impl Wayland { - pub fn new() -> Result { - let (socket_path, _lockfile) = - get_free_wayland_socket_path().ok_or(ServerError::WaylandError( - waynest::server::Error::IoError(std::io::ErrorKind::AddrNotAvailable.into()), - ))?; + pub fn new() -> color_eyre::eyre::Result { + let (socket_path, _lockfile) = get_free_wayland_socket_path().ok_or(WaylandError::Io( + std::io::ErrorKind::AddrNotAvailable.into(), + ))?; let _ = WAYLAND_DISPLAY.set(socket_path.clone()); - let listener = - server::Listener::new_with_path(&socket_path).map_err(ServerError::WaylandError)?; + let listener = waynest_server::Listener::new_with_path(&socket_path)?; + let _ = WAYLAND_DISPLAY.set(listener.socket_path().to_path_buf()); let abort_handle = task::new(|| "wayland loop", Self::handle_wayland_loop(listener))?.abort_handle(); @@ -285,7 +277,7 @@ impl Wayland { abort_handle, }) } - async fn handle_wayland_loop(mut listener: server::Listener) -> Result<()> { + async fn handle_wayland_loop(mut listener: Listener) -> WaylandResult<()> { let mut clients = Vec::new(); loop { if let Ok(Some(stream)) = listener.try_next().await { diff --git a/src/wayland/presentation.rs b/src/wayland/presentation.rs index 4bea67c..81a912b 100644 --- a/src/wayland/presentation.rs +++ b/src/wayland/presentation.rs @@ -1,15 +1,10 @@ -use rustix::fs::Timespec; -use waynest::{ - server::{ - Client, Dispatcher, Result, - protocol::stable::presentation_time::{ - wp_presentation::WpPresentation, wp_presentation_feedback::WpPresentationFeedback, - }, - }, - wire::ObjectId, -}; - +use crate::wayland::WaylandResult; use crate::wayland::core::surface::Surface; +use rustix::fs::Timespec; +use waynest::ObjectId; +use waynest_protocols::server::stable::presentation_time::{ + wp_presentation::*, wp_presentation_feedback::*, +}; #[derive(Clone, Copy, Debug)] pub struct MonotonicTimestamp { @@ -37,20 +32,23 @@ impl From for MonotonicTimestamp { } } -#[derive(Debug, Dispatcher)] +#[derive(Debug, waynest_server::RequestDispatcher)] +#[waynest(error = crate::wayland::WaylandError)] pub struct Presentation; impl WpPresentation for Presentation { - async fn destroy(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { + type Connection = crate::wayland::Client; + + async fn destroy(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> { Ok(()) } async fn feedback( &self, - client: &mut Client, + client: &mut Self::Connection, _sender_id: ObjectId, surface: ObjectId, id: ObjectId, - ) -> Result<()> { + ) -> WaylandResult<()> { let Some(surface) = client.get::(surface) else { tracing::error!("unable to get surface#{surface}"); return Ok(()); @@ -62,6 +60,9 @@ impl WpPresentation for Presentation { } } -#[derive(Debug, Dispatcher)] +#[derive(Debug, waynest_server::RequestDispatcher)] +#[waynest(error = crate::wayland::WaylandError)] pub struct PresentationFeedback(pub ObjectId); -impl WpPresentationFeedback for PresentationFeedback {} +impl WpPresentationFeedback for PresentationFeedback { + type Connection = crate::wayland::Client; +} diff --git a/src/wayland/registry.rs b/src/wayland/registry.rs index 11bc46d..ca8ebd9 100644 --- a/src/wayland/registry.rs +++ b/src/wayland/registry.rs @@ -1,4 +1,6 @@ +use crate::wayland::{Client, WaylandResult}; use crate::wayland::{ + WaylandError, core::{ compositor::{Compositor, WlCompositor}, data_device::DataDeviceManager, @@ -13,20 +15,15 @@ use crate::wayland::{ viewporter::Viewporter, xdg::wm_base::{WmBase, XdgWmBase}, }; -use waynest::{ - server::{ - Client, Dispatcher, Error, Result, - protocol::{ - core::wayland::{wl_data_device_manager::WlDataDeviceManager, wl_registry::*}, - mesa::drm::wl_drm::WlDrm, - stable::{ - linux_dmabuf_v1::zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1, - presentation_time::wp_presentation::WpPresentation, - viewporter::wp_viewporter::WpViewporter, - }, - }, +use waynest::{NewId, ObjectId}; +use waynest_protocols::server::{ + core::wayland::{wl_data_device_manager::WlDataDeviceManager, wl_registry::*}, + mesa::drm::wl_drm::WlDrm, + stable::{ + linux_dmabuf_v1::zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1, + presentation_time::wp_presentation::WpPresentation, + viewporter::wp_viewporter::WpViewporter, }, - wire::{NewId, ObjectId}, }; struct RegistryGlobals; @@ -43,11 +40,16 @@ impl RegistryGlobals { pub const VIEWPORTER: u32 = 9; } -#[derive(Debug, Dispatcher, Default)] +#[derive(Debug, waynest_server::RequestDispatcher, Default)] +#[waynest(error = crate::wayland::WaylandError)] pub struct Registry; impl Registry { - pub async fn advertise_globals(&self, client: &mut Client, sender_id: ObjectId) -> Result<()> { + pub async fn advertise_globals( + &self, + client: &mut Client, + sender_id: ObjectId, + ) -> WaylandResult<()> { self.global( client, sender_id, @@ -143,13 +145,15 @@ impl Registry { } impl WlRegistry for Registry { + type Connection = crate::wayland::Client; + async fn bind( &self, - client: &mut Client, + client: &mut Self::Connection, _sender_id: ObjectId, name: u32, new_id: NewId, - ) -> Result<()> { + ) -> WaylandResult<()> { match name { RegistryGlobals::COMPOSITOR => { tracing::info!("Binding compositor"); @@ -217,7 +221,7 @@ impl WlRegistry for Registry { } id => { tracing::error!(id, "Wayland: failed to bind to registry global"); - return Err(Error::MissingObject(unsafe { ObjectId::from_raw(name) })); + return Err(WaylandError::UnknownGlobal(name)); } } diff --git a/src/wayland/util.rs b/src/wayland/util.rs index b551fcf..3b1815d 100644 --- a/src/wayland/util.rs +++ b/src/wayland/util.rs @@ -1,22 +1,16 @@ #![allow(unused)] use super::{Message, MessageSink, display::Display}; +use crate::wayland::{Client, WaylandError, WaylandResult}; use std::{fmt::Debug, sync::Arc}; -use waynest::{ - server::{Client, Result, protocol::core::wayland::wl_display::WlDisplay}, - wire::ObjectId, -}; +use waynest::ObjectId; +use waynest_protocols::server::core::wayland::wl_display::WlDisplay; +use waynest_server::RequestDispatcher; pub trait ClientExt { fn message_sink(&self) -> MessageSink; fn display(&self) -> Arc; - async fn protocol_error( - &mut self, - sender_id: ObjectId, - object_id: ObjectId, - code: u32, - message: String, - ) -> Result<()>; + fn try_get(&self, id: ObjectId) -> WaylandResult>; } impl ClientExt for Client { fn message_sink(&self) -> MessageSink { @@ -30,19 +24,8 @@ impl ClientExt for Client { self.get::(ObjectId::DISPLAY).unwrap() } - async fn protocol_error( - &mut self, - sender_id: ObjectId, - object_id: ObjectId, - code: u32, - message: String, - ) -> Result<()> { - self.display() - .error(self, sender_id, object_id, code, message) - .await?; - let _ = self.message_sink().send(Message::Disconnect); - - Ok(()) + fn try_get(&self, id: ObjectId) -> WaylandResult> { + self.get::(id).ok_or(WaylandError::MissingObject(id)) } } diff --git a/src/wayland/viewporter.rs b/src/wayland/viewporter.rs index e989c9a..796be7b 100644 --- a/src/wayland/viewporter.rs +++ b/src/wayland/viewporter.rs @@ -1,35 +1,37 @@ -use waynest::{ - server::{Client, Dispatcher, Result}, - wire::{Fixed, ObjectId}, -}; - -pub use waynest::server::protocol::stable::viewporter::wp_viewport::*; -pub use waynest::server::protocol::stable::viewporter::wp_viewporter::*; +use crate::wayland::WaylandResult; +use waynest::Fixed; +use waynest::ObjectId; +pub use waynest_protocols::server::stable::viewporter::wp_viewport::*; +pub use waynest_protocols::server::stable::viewporter::wp_viewporter::*; // This is a barebones/stub no-op implementation of wp_viewporter to make xwayland apps work -#[derive(Debug, Dispatcher, Default)] +#[derive(Debug, waynest_server::RequestDispatcher, Default)] +#[waynest(error = crate::wayland::WaylandError)] pub struct Viewporter; impl WpViewporter for Viewporter { - async fn destroy(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { + type Connection = crate::wayland::Client; + + async fn destroy(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> { Ok(()) } async fn get_viewport( &self, - client: &mut Client, + client: &mut Self::Connection, _sender_id: ObjectId, id: ObjectId, surface_id: ObjectId, - ) -> Result<()> { + ) -> WaylandResult<()> { let viewport = Viewport::new(id, surface_id); client.insert(id, viewport); Ok(()) } } -#[derive(Debug, Dispatcher)] +#[derive(Debug, waynest_server::RequestDispatcher)] +#[waynest(error = crate::wayland::WaylandError)] pub struct Viewport { _id: ObjectId, _surface_id: ObjectId, @@ -45,29 +47,31 @@ impl Viewport { } impl WpViewport for Viewport { - async fn destroy(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { + type Connection = crate::wayland::Client; + + async fn destroy(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> { Ok(()) } async fn set_source( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, _x: Fixed, _y: Fixed, _width: Fixed, _height: Fixed, - ) -> Result<()> { + ) -> WaylandResult<()> { Ok(()) } async fn set_destination( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, _width: i32, _height: i32, - ) -> Result<()> { + ) -> WaylandResult<()> { Ok(()) } } diff --git a/src/wayland/xdg/popup.rs b/src/wayland/xdg/popup.rs index 29473a3..e2a3c02 100644 --- a/src/wayland/xdg/popup.rs +++ b/src/wayland/xdg/popup.rs @@ -3,15 +3,15 @@ use super::{ surface::Surface, }; use crate::nodes::items::panel::SurfaceId; +use crate::wayland::WaylandResult; use parking_lot::Mutex; use rand::Rng; use std::sync::Arc; -use waynest::{ - server::{Client, Dispatcher, Result, protocol::stable::xdg_shell::xdg_popup::XdgPopup}, - wire::ObjectId, -}; +use waynest::ObjectId; +use waynest_protocols::server::stable::xdg_shell::xdg_popup::XdgPopup; -#[derive(Debug, Dispatcher)] +#[derive(Debug, waynest_server::RequestDispatcher)] +#[waynest(error = crate::wayland::WaylandError)] pub struct Popup { version: u32, pub surface: Arc, @@ -33,25 +33,27 @@ impl Popup { } } impl XdgPopup for Popup { + type Connection = crate::wayland::Client; + /// https://wayland.app/protocols/xdg-shell#xdg_popup:request:grab async fn grab( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, _seat: ObjectId, _serial: u32, - ) -> Result<()> { + ) -> WaylandResult<()> { Ok(()) } /// https://wayland.app/protocols/xdg-shell#xdg_popup:request:reposition async fn reposition( &self, - client: &mut Client, + client: &mut Self::Connection, sender_id: ObjectId, positioner: ObjectId, token: u32, - ) -> Result<()> { + ) -> WaylandResult<()> { let positioner = client.get::(positioner).unwrap(); let positioner_data = positioner.data(); *self.positioner_data.lock() = positioner_data; @@ -80,7 +82,7 @@ impl XdgPopup for Popup { } /// https://wayland.app/protocols/xdg-shell#xdg_popup:request:destroy - async fn destroy(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { + async fn destroy(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> { Ok(()) } } diff --git a/src/wayland/xdg/positioner.rs b/src/wayland/xdg/positioner.rs index 8e00e8b..09dff80 100644 --- a/src/wayland/xdg/positioner.rs +++ b/src/wayland/xdg/positioner.rs @@ -1,15 +1,8 @@ -use crate::nodes::items::panel::Geometry; +use crate::{nodes::items::panel::Geometry, wayland::WaylandResult}; use mint::Vector2; use parking_lot::Mutex; -use waynest::{ - server::{ - Client, Dispatcher, Result, - protocol::stable::xdg_shell::xdg_positioner::{ - Anchor, ConstraintAdjustment, Gravity, XdgPositioner, - }, - }, - wire::ObjectId, -}; +use waynest::ObjectId; +use waynest_protocols::server::stable::xdg_shell::xdg_positioner::*; #[derive(Debug, Clone, Copy)] pub struct PositionerData { @@ -133,7 +126,8 @@ impl Default for PositionerData { } } -#[derive(Debug, Dispatcher)] +#[derive(Debug, waynest_server::RequestDispatcher)] +#[waynest(error = crate::wayland::WaylandError)] pub struct Positioner { data: Mutex, } @@ -150,13 +144,15 @@ impl Positioner { } } impl XdgPositioner for Positioner { + type Connection = crate::wayland::Client; + async fn set_size( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, _width: i32, _height: i32, - ) -> Result<()> { + ) -> WaylandResult<()> { let mut data = self.data.lock(); data.size = [_width.max(0) as u32, _height.max(0) as u32].into(); data.reactive = true; @@ -165,13 +161,13 @@ impl XdgPositioner for Positioner { async fn set_anchor_rect( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, _x: i32, _y: i32, _width: i32, _height: i32, - ) -> Result<()> { + ) -> WaylandResult<()> { let mut data = self.data.lock(); data.anchor_rect.origin = [_x, _y].into(); data.anchor_rect.size = [_width.max(0) as u32, _height.max(0) as u32].into(); @@ -181,10 +177,10 @@ impl XdgPositioner for Positioner { async fn set_anchor( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, _anchor: Anchor, - ) -> Result<()> { + ) -> WaylandResult<()> { let mut data = self.data.lock(); data.anchor = _anchor; Ok(()) @@ -192,10 +188,10 @@ impl XdgPositioner for Positioner { async fn set_gravity( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, gravity: Gravity, - ) -> Result<()> { + ) -> WaylandResult<()> { let mut data = self.data.lock(); data.gravity = gravity; Ok(()) @@ -203,10 +199,10 @@ impl XdgPositioner for Positioner { async fn set_constraint_adjustment( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, _constraint_adjustment: ConstraintAdjustment, - ) -> Result<()> { + ) -> WaylandResult<()> { let mut data = self.data.lock(); data.constraint_adjustment = _constraint_adjustment; Ok(()) @@ -214,28 +210,32 @@ impl XdgPositioner for Positioner { async fn set_offset( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, _x: i32, _y: i32, - ) -> Result<()> { + ) -> WaylandResult<()> { let mut data = self.data.lock(); data.offset.x += _x; data.offset.y += _y; Ok(()) } - async fn set_reactive(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { + async fn set_reactive( + &self, + _client: &mut Self::Connection, + _sender_id: ObjectId, + ) -> WaylandResult<()> { Ok(()) } async fn set_parent_size( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, _parent_width: i32, _parent_height: i32, - ) -> Result<()> { + ) -> WaylandResult<()> { let mut data = self.data.lock(); data.parent_size.x = _parent_width.max(0) as u32; data.parent_size.y = _parent_height.max(0) as u32; @@ -244,14 +244,18 @@ impl XdgPositioner for Positioner { async fn set_parent_configure( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, _serial: u32, - ) -> Result<()> { + ) -> WaylandResult<()> { Ok(()) } - async fn destroy(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { + async fn destroy( + &self, + _client: &mut Self::Connection, + _sender_id: ObjectId, + ) -> WaylandResult<()> { Ok(()) } } diff --git a/src/wayland/xdg/surface.rs b/src/wayland/xdg/surface.rs index 6a64ef7..94fc6ac 100644 --- a/src/wayland/xdg/surface.rs +++ b/src/wayland/xdg/surface.rs @@ -1,17 +1,17 @@ use super::{popup::Popup, positioner::Positioner, toplevel::MappedInner}; use crate::nodes::items::panel::{ChildInfo, SurfaceId}; -use crate::wayland::Message; -use crate::wayland::util::ClientExt; -use crate::wayland::{core::surface::SurfaceRole, display::Display, xdg::toplevel::Toplevel}; -use std::sync::Arc; -use waynest::server::protocol::stable::xdg_shell::xdg_popup::XdgPopup; -pub use waynest::server::protocol::stable::xdg_shell::xdg_surface::*; -use waynest::{ - server::{Client, Dispatcher, Result}, - wire::ObjectId, +use crate::wayland::{Client, WaylandError}; +use crate::wayland::{ + Message, WaylandResult, core::surface::SurfaceRole, display::Display, util::ClientExt, + xdg::toplevel::Toplevel, }; +use std::sync::Arc; +use waynest::ObjectId; +use waynest_protocols::server::stable::xdg_shell::xdg_popup::XdgPopup; +pub use waynest_protocols::server::stable::xdg_shell::xdg_surface::*; -#[derive(Debug, Dispatcher)] +#[derive(Debug, waynest_server::RequestDispatcher)] +#[waynest(error = crate::wayland::WaylandError)] pub struct Surface { id: ObjectId, version: u32, @@ -32,25 +32,31 @@ impl Surface { } } - pub async fn reconfigure(&self, client: &mut Client) -> Result<()> { + pub async fn reconfigure(&self, client: &mut Client) -> WaylandResult<()> { let serial = client.next_event_serial(); self.configure(client, self.id, serial).await } } impl XdgSurface for Surface { + type Connection = crate::wayland::Client; + /// https://wayland.app/protocols/xdg-shell#xdg_surface:request:destroy - async fn destroy(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { + async fn destroy( + &self, + _client: &mut Self::Connection, + _sender_id: ObjectId, + ) -> WaylandResult<()> { Ok(()) } /// https://wayland.app/protocols/xdg-shell#xdg_surface:request:get_toplevel async fn get_toplevel( &self, - client: &mut Client, + client: &mut Self::Connection, sender_id: ObjectId, toplevel_id: ObjectId, - ) -> Result<()> { + ) -> WaylandResult<()> { let toplevel = client.insert( toplevel_id, Toplevel::new( @@ -61,7 +67,7 @@ impl XdgSurface for Surface { ); self.wl_surface - .try_set_role(client, SurfaceRole::XdgToplevel) + .try_set_role(SurfaceRole::XdgToplevel, Error::AlreadyConstructed) .await?; let toplevel_weak = Arc::downgrade(&toplevel); @@ -100,35 +106,29 @@ impl XdgSurface for Surface { /// https://wayland.app/protocols/xdg-shell#xdg_surface:request:get_popup async fn get_popup( &self, - client: &mut Client, + client: &mut Self::Connection, sender_id: ObjectId, popup_id: ObjectId, parent: Option, positioner: ObjectId, - ) -> Result<()> { + ) -> WaylandResult<()> { self.wl_surface - .try_set_role(client, SurfaceRole::XdgPopup) + .try_set_role(SurfaceRole::XdgPopup, Error::AlreadyConstructed) .await?; let Some(parent) = parent else { - return client - .protocol_error( - sender_id, - popup_id, - 3, // INVALID_POPUP_PARENT - "Parent surface does not have an XDG role".to_string(), - ) - .await; + return Err(WaylandError::Fatal { + object_id: popup_id, + code: 3, + message: "Parent surface does not have an XDG role", + }); }; let Some(parent) = client.get::(parent) else { - return client - .protocol_error( - sender_id, - popup_id, - 3, // INVALID_POPUP_PARENT - "Parent surface does not exist".to_string(), - ) - .await; + return Err(WaylandError::Fatal { + object_id: popup_id, + code: 3, + message: "Parent surface does not exist", + }); }; *self.wl_surface.panel_item.lock() = parent.wl_surface.panel_item.lock().clone(); let positioner = client.get::(positioner).unwrap(); @@ -192,13 +192,13 @@ impl XdgSurface for Surface { /// https://wayland.app/protocols/xdg-shell#xdg_surface:request:set_window_geometry async fn set_window_geometry( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, _x: i32, _y: i32, _width: i32, _height: i32, - ) -> Result<()> { + ) -> WaylandResult<()> { // we're gonna delegate literally all the window management // to 3D stuff sooo we don't care, maximized is the floating state Ok(()) @@ -207,10 +207,10 @@ impl XdgSurface for Surface { /// https://wayland.app/protocols/xdg-shell#xdg_surface:request:ack_configure async fn ack_configure( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, _serial: u32, - ) -> Result<()> { + ) -> WaylandResult<()> { self.configured .store(true, std::sync::atomic::Ordering::SeqCst); Ok(()) diff --git a/src/wayland/xdg/toplevel.rs b/src/wayland/xdg/toplevel.rs index efcf478..706a4bb 100644 --- a/src/wayland/xdg/toplevel.rs +++ b/src/wayland/xdg/toplevel.rs @@ -4,16 +4,16 @@ use crate::{ Node, items::panel::{PanelItem, SurfaceId}, }, - wayland::core::{seat::Seat, surface::Surface}, + wayland::{ + Client, WaylandResult, + core::{seat::Seat, surface::Surface}, + }, }; use mint::Vector2; use parking_lot::Mutex; use std::sync::Arc; -pub use waynest::server::protocol::stable::xdg_shell::xdg_toplevel::*; -use waynest::{ - server::{Client, Dispatcher, Result}, - wire::ObjectId, -}; +use waynest::ObjectId; +pub use waynest_protocols::server::stable::xdg_shell::xdg_toplevel::*; #[derive(Debug)] pub struct MappedInner { @@ -54,7 +54,8 @@ impl Default for ToplevelData { } } -#[derive(Debug, Dispatcher)] +#[derive(Debug, waynest_server::RequestDispatcher)] +#[waynest(error = crate::wayland::WaylandError)] pub struct Toplevel { pub id: ObjectId, xdg_surface: Arc, @@ -115,7 +116,7 @@ impl Toplevel { clamped } - pub async fn reconfigure(&self, client: &mut Client) -> Result<()> { + pub async fn reconfigure(&self, client: &mut Client) -> WaylandResult<()> { let data = self.data.lock().clone(); // Use the explicitly set size, applying constraints @@ -152,12 +153,14 @@ impl Toplevel { } } impl XdgToplevel for Toplevel { + type Connection = crate::wayland::Client; + async fn set_parent( &self, - client: &mut Client, + client: &mut Self::Connection, _sender_id: ObjectId, parent: Option, - ) -> Result<()> { + ) -> WaylandResult<()> { // Handle case where parent is specified if let Some(parent) = parent { // Per spec: parent must be another xdg_toplevel surface @@ -188,64 +191,64 @@ impl XdgToplevel for Toplevel { async fn set_title( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, title: String, - ) -> Result<()> { + ) -> WaylandResult<()> { self.data.lock().title.replace(title); Ok(()) } async fn set_app_id( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, app_id: String, - ) -> Result<()> { + ) -> WaylandResult<()> { self.data.lock().app_id.replace(app_id); Ok(()) } async fn show_window_menu( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, _seat: ObjectId, _serial: u32, _x: i32, _y: i32, - ) -> Result<()> { + ) -> WaylandResult<()> { Ok(()) } async fn r#move( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, _seat: ObjectId, _serial: u32, - ) -> Result<()> { + ) -> WaylandResult<()> { Ok(()) } async fn resize( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, _seat: ObjectId, _serial: u32, _edges: ResizeEdge, - ) -> Result<()> { + ) -> WaylandResult<()> { Ok(()) } async fn set_max_size( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, width: i32, height: i32, - ) -> Result<()> { + ) -> WaylandResult<()> { self.wl_surface().state_lock().pending.max_size = if width == 0 && height == 0 { None } else { @@ -256,13 +259,12 @@ impl XdgToplevel for Toplevel { async fn set_min_size( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, width: i32, height: i32, - ) -> Result<()> { - self.xdg_surface.wl_surface.state_lock().pending.min_size = if width == 0 && height == 0 - { + ) -> WaylandResult<()> { + self.xdg_surface.wl_surface.state_lock().pending.min_size = if width == 0 && height == 0 { None } else { Some([width as u32, height as u32].into()) @@ -270,32 +272,52 @@ impl XdgToplevel for Toplevel { Ok(()) } - async fn set_maximized(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { + async fn set_maximized( + &self, + _client: &mut Self::Connection, + _sender_id: ObjectId, + ) -> WaylandResult<()> { Ok(()) } - async fn unset_maximized(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { + async fn unset_maximized( + &self, + _client: &mut Self::Connection, + _sender_id: ObjectId, + ) -> WaylandResult<()> { Ok(()) } async fn set_fullscreen( &self, - _client: &mut Client, + _client: &mut Self::Connection, _sender_id: ObjectId, _output: Option, - ) -> Result<()> { + ) -> WaylandResult<()> { Ok(()) } - async fn unset_fullscreen(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { + async fn unset_fullscreen( + &self, + _client: &mut Self::Connection, + _sender_id: ObjectId, + ) -> WaylandResult<()> { Ok(()) } - async fn set_minimized(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { + async fn set_minimized( + &self, + _client: &mut Self::Connection, + _sender_id: ObjectId, + ) -> WaylandResult<()> { Ok(()) } - async fn destroy(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { + async fn destroy( + &self, + _client: &mut Self::Connection, + _sender_id: ObjectId, + ) -> WaylandResult<()> { self.mapped.lock().take(); Ok(()) } diff --git a/src/wayland/xdg/wm_base.rs b/src/wayland/xdg/wm_base.rs index 6b2153c..be7d182 100644 --- a/src/wayland/xdg/wm_base.rs +++ b/src/wayland/xdg/wm_base.rs @@ -1,54 +1,51 @@ use super::positioner::Positioner; -use crate::wayland::{core::surface::SurfaceRole, util::ClientExt, xdg::surface::Surface}; -pub use waynest::server::protocol::stable::xdg_shell::xdg_wm_base::*; -use waynest::{ - server::{Client, Dispatcher, Result}, - wire::ObjectId, -}; +use crate::wayland::{WaylandError, WaylandResult, util::ClientExt, xdg::surface::Surface}; -#[derive(Debug, Dispatcher, Default)] +use waynest::ObjectId; +pub use waynest_protocols::server::stable::xdg_shell::xdg_wm_base::*; + +#[derive(Debug, waynest_server::RequestDispatcher, Default)] +#[waynest(error = crate::wayland::WaylandError)] pub struct WmBase { pub version: u32, } impl XdgWmBase for WmBase { - async fn destroy(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { + type Connection = crate::wayland::Client; + + async fn destroy( + &self, + _client: &mut Self::Connection, + _sender_id: ObjectId, + ) -> WaylandResult<()> { Ok(()) } async fn create_positioner( &self, - client: &mut Client, + client: &mut Self::Connection, _sender_id: ObjectId, id: ObjectId, - ) -> Result<()> { + ) -> WaylandResult<()> { client.insert(id, Positioner::default()); Ok(()) } async fn get_xdg_surface( &self, - client: &mut Client, - sender_id: ObjectId, + client: &mut Self::Connection, + _sender_id: ObjectId, xdg_surface_id: ObjectId, wl_surface_id: ObjectId, - ) -> Result<()> { - let wl_surface = client - .get::(wl_surface_id) - .ok_or(waynest::server::Error::Custom( - "can't get wayland surface id".to_string(), - ))?; + ) -> WaylandResult<()> { + let wl_surface = client.try_get::(wl_surface_id)?; match wl_surface.role.get() { - Some(SurfaceRole::XdgToplevel | SurfaceRole::XdgPopup) => (), None => (), - _ => { - client - .protocol_error( - sender_id, - xdg_surface_id, - 0, - "invalid surface role".to_string(), - ) - .await? + Some(_) => { + return Err(WaylandError::Fatal { + object_id: wl_surface_id, + code: Error::Role as u32, + message: "Wayland surface has role", + }); } }; let xdg_surface = Surface::new(xdg_surface_id, self.version, wl_surface); @@ -57,7 +54,12 @@ impl XdgWmBase for WmBase { Ok(()) } - async fn pong(&self, _client: &mut Client, _sender_id: ObjectId, _serial: u32) -> Result<()> { + async fn pong( + &self, + _client: &mut Self::Connection, + _sender_id: ObjectId, + _serial: u32, + ) -> WaylandResult<()> { Ok(()) } }