From 7e53db3d3339461cb9c485da37b41d09bcbcf8e5 Mon Sep 17 00:00:00 2001 From: Nova Date: Thu, 11 Sep 2025 15:53:31 -0700 Subject: [PATCH] feat(wayland): try set role modularization --- src/wayland/core/pointer.rs | 4 ++++ src/wayland/core/surface.rs | 30 ++++++++++++++++++++++++++-- src/wayland/xdg/surface.rs | 39 ++++++------------------------------- 3 files changed, 38 insertions(+), 35 deletions(-) diff --git a/src/wayland/core/pointer.rs b/src/wayland/core/pointer.rs index 3474289..30a645a 100644 --- a/src/wayland/core/pointer.rs +++ b/src/wayland/core/pointer.rs @@ -11,6 +11,8 @@ use waynest::{ wire::ObjectId, }; +use super::surface::SurfaceRole; + #[derive(Dispatcher)] pub struct Pointer { pub id: ObjectId, @@ -208,6 +210,8 @@ impl WlPointer for Pointer { let Some(surface) = client.get::(surface) else { return Ok(()); }; + + surface.try_set_role(client, SurfaceRole::Cursor).await?; self.cursor_surface.lock().await.replace(surface); Ok(()) } diff --git a/src/wayland/core/surface.rs b/src/wayland/core/surface.rs index 79ddcd4..f4fa2c9 100644 --- a/src/wayland/core/surface.rs +++ b/src/wayland/core/surface.rs @@ -26,7 +26,7 @@ use std::sync::{Arc, OnceLock, Weak}; use tokio::task::LocalSet; use waynest::{ server::{ - Client, Dispatcher, Result, + self, Client, Dispatcher, Result, protocol::{ core::wayland::{wl_output::Transform, wl_surface::*}, stable::presentation_time::wp_presentation_feedback::{Kind, WpPresentationFeedback}, @@ -37,7 +37,7 @@ use waynest::{ pub static WL_SURFACE_REGISTRY: Registry = Registry::new(); -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum SurfaceRole { Cursor, Subsurface, @@ -129,6 +129,32 @@ impl Surface { } } + pub async fn try_set_role(&self, client: &mut Client, role: SurfaceRole) -> Result<()> { + 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( + "Surface has an incompatible role".to_string(), + )) + } + } + None => { + let _ = self.role.set(SurfaceRole::XdgPopup); + Ok(()) + } + } + } + #[tracing::instrument(level = "debug", skip_all)] pub fn pending_state(&self) -> parking_lot::MutexGuard<'_, DoubleBuffer> { self.state.lock() diff --git a/src/wayland/xdg/surface.rs b/src/wayland/xdg/surface.rs index 94665da..ffa38c0 100644 --- a/src/wayland/xdg/surface.rs +++ b/src/wayland/xdg/surface.rs @@ -59,23 +59,9 @@ impl XdgSurface for Surface { ), ); - // Check if the surface already has an XDG role - match self.wl_surface.role.get() { - Some(SurfaceRole::XdgToplevel) => (), - None => { - let _ = self.wl_surface.role.set(SurfaceRole::XdgToplevel); - } - _ => { - return client - .protocol_error( - sender_id, - toplevel_id, - 1, // XDG_WM_BASE_ERROR_ROLE - "Surface has a non-XDG role".to_string(), - ) - .await; - } - } + self.wl_surface + .try_set_role(client, SurfaceRole::XdgToplevel) + .await?; toplevel.reconfigure(client).await?; @@ -114,22 +100,9 @@ impl XdgSurface for Surface { parent: Option, positioner: ObjectId, ) -> Result<()> { - match self.wl_surface.role.get() { - Some(SurfaceRole::XdgPopup) => (), - None => { - let _ = self.wl_surface.role.set(SurfaceRole::XdgPopup); - } - _ => { - return client - .protocol_error( - sender_id, - popup_id, - 1, // XDG_WM_BASE_ERROR_ROLE - "Surface has an incomparible role".to_string(), - ) - .await; - } - } + self.wl_surface + .try_set_role(client, SurfaceRole::XdgPopup) + .await?; let Some(parent) = parent else { return client