fix(corner-radius): post protocol errors

This commit is contained in:
Ashley Wulber 2025-09-26 10:10:49 -04:00 committed by Victoria Brekenfeld
parent 242e465d42
commit 819887e298
2 changed files with 79 additions and 21 deletions

View file

@ -1,9 +1,12 @@
use cosmic_protocols::corner_radius::v1::server::cosmic_corner_radius_toplevel_v1;
use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel;
use smithay::wayland::shell::xdg::ToplevelSurface;
use smithay::reexports::wayland_server::Resource;
use smithay::wayland::compositor::{add_pre_commit_hook, with_states};
use smithay::wayland::shell::xdg::{SurfaceCachedState, ToplevelSurface};
use crate::wayland::protocols::corner_radius::{
delegate_corner_radius, CornerRadiusData, CornerRadiusHandler, CornerRadiusState,
delegate_corner_radius, CacheableCorners, CornerRadiusData, CornerRadiusHandler,
CornerRadiusState,
};
use crate::state::State;
@ -39,6 +42,45 @@ impl CornerRadiusHandler for State {
tracing::warn!("Failed to force redraw for corner radius reset.");
}
}
fn add_corners(
&mut self,
toplevel: &xdg_toplevel::XdgToplevel,
toplevel_obj: cosmic_corner_radius_toplevel_v1::CosmicCornerRadiusToplevelV1,
) {
if let Some(surface) = self.toplevel_from_resource(&toplevel) {
add_pre_commit_hook::<Self, _>(surface.wl_surface(), move |_, _dh, surface| {
let corner_radii_too_big = with_states(surface, |surface_data| {
let corners = surface_data
.cached_state
.get::<CacheableCorners>()
.pending()
.clone();
surface_data
.cached_state
.get::<SurfaceCachedState>()
.pending()
.geometry
.zip(corners.0.as_ref())
.is_some_and(|(geo, corners)| {
let half_min_dim =
u8::try_from(geo.size.w.min(geo.size.h) / 2).unwrap_or(u8::MAX);
corners.top_right > half_min_dim
|| corners.top_left > half_min_dim
|| corners.bottom_right > half_min_dim
|| corners.bottom_left > half_min_dim
})
});
if corner_radii_too_big {
toplevel_obj.post_error(
cosmic_corner_radius_toplevel_v1::Error::RadiusTooLarge as u32,
format!("{toplevel_obj:?} corner radius too large"),
);
}
});
}
}
}
fn force_redraw(state: &mut State, data: &CornerRadiusData) -> Option<()> {

View file

@ -45,6 +45,11 @@ impl CornerRadiusState {
}
pub trait CornerRadiusHandler {
fn add_corners(
&mut self,
toplevel: &XdgToplevel,
toplevel_obj: cosmic_corner_radius_toplevel_v1::CosmicCornerRadiusToplevelV1,
);
fn corner_radius_state(&mut self) -> &mut CornerRadiusState;
fn toplevel_from_resource(&mut self, toplevel: &XdgToplevel) -> Option<ToplevelSurface>;
fn set_corner_radius(
@ -111,7 +116,8 @@ where
toplevel: toplevel.downgrade(),
corners: None,
});
let _ = data_init.init(id, data);
let obj = data_init.init(id, data);
state.add_corners(&toplevel, obj);
}
_ => unimplemented!(),
}
@ -151,12 +157,16 @@ where
cosmic_corner_radius_toplevel_v1::Request::Destroy => {
let mut guard = data.lock().unwrap();
guard.corners = None;
if let Some(surface) = guard
.toplevel
.upgrade()
.ok()
.and_then(|toplevel| state.toplevel_from_resource(&toplevel))
{
let Ok(toplevel) = guard.toplevel.upgrade() else {
resource.post_error(
cosmic_corner_radius_toplevel_v1::Error::ToplevelDestroyed as u32,
format!("{:?} No toplevel found", resource),
);
return;
};
if let Some(surface) = state.toplevel_from_resource(&toplevel) {
with_states(surface.wl_surface(), |s| {
let mut cached = s.cached_state.get::<CacheableCorners>();
let pending = cached.pending();
@ -175,12 +185,15 @@ where
} => {
let mut guard = data.lock().unwrap();
guard.set_corner_radius(top_left, top_right, bottom_right, bottom_left);
if let Some(surface) = guard
.toplevel
.upgrade()
.ok()
.and_then(|toplevel| state.toplevel_from_resource(&toplevel))
{
let Ok(toplevel) = guard.toplevel.upgrade() else {
resource.post_error(
cosmic_corner_radius_toplevel_v1::Error::ToplevelDestroyed as u32,
format!("{:?} No toplevel found", resource),
);
return;
};
if let Some(surface) = state.toplevel_from_resource(&toplevel) {
with_states(surface.wl_surface(), |s| {
let mut cached = s.cached_state.get::<CacheableCorners>();
let pending = cached.pending();
@ -194,12 +207,15 @@ where
cosmic_corner_radius_toplevel_v1::Request::UnsetRadius => {
let mut guard = data.lock().unwrap();
guard.corners = None;
if let Some(surface) = guard
.toplevel
.upgrade()
.ok()
.and_then(|toplevel| state.toplevel_from_resource(&toplevel))
{
let Ok(toplevel) = guard.toplevel.upgrade() else {
resource.post_error(
cosmic_corner_radius_toplevel_v1::Error::ToplevelDestroyed as u32,
format!("{:?} No toplevel found", resource),
);
return;
};
if let Some(surface) = state.toplevel_from_resource(&toplevel) {
with_states(surface.wl_surface(), |s| {
let mut cached = s.cached_state.get::<CacheableCorners>();
let pending = cached.pending();