From 24beda4a4a4a86b1b31ff52f2d445aa55a04ca4f Mon Sep 17 00:00:00 2001 From: Nova Date: Sun, 3 Aug 2025 15:43:51 -0700 Subject: [PATCH] fix(wayland): protocol error --- src/wayland/dmabuf/buffer_params.rs | 26 +++++++++++++++++++------- src/wayland/dmabuf/mod.rs | 9 ++------- src/wayland/mod.rs | 19 ++++++++++++------- src/wayland/util.rs | 29 +++++++++++++++++++++++++++-- 4 files changed, 60 insertions(+), 23 deletions(-) diff --git a/src/wayland/dmabuf/buffer_params.rs b/src/wayland/dmabuf/buffer_params.rs index f6628bb..40e1180 100644 --- a/src/wayland/dmabuf/buffer_params.rs +++ b/src/wayland/dmabuf/buffer_params.rs @@ -12,7 +12,7 @@ use waynest::{ server::{ Client, Dispatcher, Result, protocol::stable::linux_dmabuf_v1::zwp_linux_buffer_params_v1::{ - Flags, ZwpLinuxBufferParamsV1, + Error, Flags, ZwpLinuxBufferParamsV1, }, }, wire::ObjectId, @@ -129,7 +129,7 @@ impl ZwpLinuxBufferParamsV1 for BufferParams { async fn create_immed( &self, client: &mut Client, - _sender_id: ObjectId, + sender_id: ObjectId, buffer_id: ObjectId, width: i32, height: i32, @@ -138,15 +138,27 @@ impl ZwpLinuxBufferParamsV1 for BufferParams { ) -> Result<()> { // TODO: terminate client on fail, or send a fail event or something // Create the buffer with DMA-BUF backing using self as the backing - _ = DmabufBacking::from_params( + match DmabufBacking::from_params( client.get::(self.id).unwrap(), [width as u32, height as u32].into(), DrmFourcc::try_from(format).unwrap(), flags, - ) - .inspect_err(|e| tracing::error!("Failed to import dmabuf because {e}")) - .map(|backing| Buffer::new(client, buffer_id, BufferBacking::Dmabuf(backing))); - + ) { + Ok(backing) => { + 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}"); + } + } Ok(()) } } diff --git a/src/wayland/dmabuf/mod.rs b/src/wayland/dmabuf/mod.rs index b7758d8..ba2c9a6 100644 --- a/src/wayland/dmabuf/mod.rs +++ b/src/wayland/dmabuf/mod.rs @@ -15,10 +15,7 @@ use vulkano::format::FormatFeatures; use waynest::{ server::{ Client, Dispatcher, Error, Result, - protocol::{ - core::wayland::wl_display::WlDisplay, - stable::linux_dmabuf_v1::zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1, - }, + protocol::stable::linux_dmabuf_v1::zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1, }, wire::ObjectId, }; @@ -146,9 +143,7 @@ impl ZwpLinuxDmabufV1 for Dmabuf { ) -> Result<()> { if self.version < 3 { client - .display() - .error( - client, + .protocol_error( sender_id, id, 71, diff --git a/src/wayland/mod.rs b/src/wayland/mod.rs index dc935c8..cc85711 100644 --- a/src/wayland/mod.rs +++ b/src/wayland/mod.rs @@ -110,6 +110,7 @@ pub fn get_free_wayland_socket_path() -> Option<(PathBuf, FlockLock)> { } pub enum Message { + Disconnect, Frame(Arc), ReleaseBuffer(Arc), CloseToplevel(Arc), @@ -200,8 +201,9 @@ impl WaylandClient { async fn handle_render_message( client: &mut server::Client, message: Message, - ) -> Result<(), waynest::server::Error> { + ) -> Result { match message { + Message::Disconnect => return Ok(true), Message::Frame(callback) => { let serial = client.next_event_serial(); callback.done(client, callback.0, serial).await?; @@ -211,25 +213,28 @@ impl WaylandClient { .delete_id(client, ObjectId::DISPLAY, callback.0.as_raw()) .await?; client.remove(callback.0); - Ok(()) } - Message::ReleaseBuffer(buffer) => buffer.release(client, buffer.id).await, - Message::CloseToplevel(toplevel) => toplevel.close(client, toplevel.id).await, + Message::ReleaseBuffer(buffer) => { + buffer.release(client, buffer.id).await?; + } + Message::CloseToplevel(toplevel) => { + toplevel.close(client, toplevel.id).await?; + } Message::ResizeToplevel { toplevel, size } => { toplevel.set_size(size); - toplevel.reconfigure(client).await + toplevel.reconfigure(client).await?; } Message::SetToplevelVisualActive { toplevel, active } => { toplevel.set_activated(active); - toplevel.reconfigure(client).await + toplevel.reconfigure(client).await?; } Message::Seat(seat_message) => { if let Some(seat) = client.get::(ObjectId::DISPLAY).unwrap().seat.get() { seat.handle_message(client, seat_message).await?; } - Ok(()) } } + Ok(false) } } impl Drop for WaylandClient { diff --git a/src/wayland/util.rs b/src/wayland/util.rs index c971697..5a15d8a 100644 --- a/src/wayland/util.rs +++ b/src/wayland/util.rs @@ -1,12 +1,22 @@ #![allow(unused)] -use super::{MessageSink, display::Display}; +use super::{Message, MessageSink, display::Display}; use std::{fmt::Debug, sync::Arc}; -use waynest::{server::Client, wire::ObjectId}; +use waynest::{ + server::{Client, Result, protocol::core::wayland::wl_display::WlDisplay}, + wire::ObjectId, +}; 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<()>; } impl ClientExt for Client { fn message_sink(&self) -> MessageSink { @@ -19,6 +29,21 @@ impl ClientExt for Client { fn display(&self) -> Arc { 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(()) + } } #[derive(Debug, Default)]