feat(wayland): try set role modularization

This commit is contained in:
Nova
2025-09-11 15:53:31 -07:00
parent 4bc71b01cb
commit 7e53db3d33
3 changed files with 38 additions and 35 deletions

View File

@@ -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>(surface) else {
return Ok(());
};
surface.try_set_role(client, SurfaceRole::Cursor).await?;
self.cursor_surface.lock().await.replace(surface);
Ok(())
}

View File

@@ -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<Surface> = 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<SurfaceState>> {
self.state.lock()

View File

@@ -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<ObjectId>,
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