Skip to content

Commit 819887e

Browse files
wash2Drakulix
authored andcommitted
fix(corner-radius): post protocol errors
1 parent 242e465 commit 819887e

File tree

2 files changed

+79
-21
lines changed

2 files changed

+79
-21
lines changed

src/wayland/handlers/corner_radius.rs

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
use cosmic_protocols::corner_radius::v1::server::cosmic_corner_radius_toplevel_v1;
22
use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel;
3-
use smithay::wayland::shell::xdg::ToplevelSurface;
3+
use smithay::reexports::wayland_server::Resource;
4+
use smithay::wayland::compositor::{add_pre_commit_hook, with_states};
5+
use smithay::wayland::shell::xdg::{SurfaceCachedState, ToplevelSurface};
46

57
use crate::wayland::protocols::corner_radius::{
6-
delegate_corner_radius, CornerRadiusData, CornerRadiusHandler, CornerRadiusState,
8+
delegate_corner_radius, CacheableCorners, CornerRadiusData, CornerRadiusHandler,
9+
CornerRadiusState,
710
};
811

912
use crate::state::State;
@@ -39,6 +42,45 @@ impl CornerRadiusHandler for State {
3942
tracing::warn!("Failed to force redraw for corner radius reset.");
4043
}
4144
}
45+
46+
fn add_corners(
47+
&mut self,
48+
toplevel: &xdg_toplevel::XdgToplevel,
49+
toplevel_obj: cosmic_corner_radius_toplevel_v1::CosmicCornerRadiusToplevelV1,
50+
) {
51+
if let Some(surface) = self.toplevel_from_resource(&toplevel) {
52+
add_pre_commit_hook::<Self, _>(surface.wl_surface(), move |_, _dh, surface| {
53+
let corner_radii_too_big = with_states(surface, |surface_data| {
54+
let corners = surface_data
55+
.cached_state
56+
.get::<CacheableCorners>()
57+
.pending()
58+
.clone();
59+
surface_data
60+
.cached_state
61+
.get::<SurfaceCachedState>()
62+
.pending()
63+
.geometry
64+
.zip(corners.0.as_ref())
65+
.is_some_and(|(geo, corners)| {
66+
let half_min_dim =
67+
u8::try_from(geo.size.w.min(geo.size.h) / 2).unwrap_or(u8::MAX);
68+
corners.top_right > half_min_dim
69+
|| corners.top_left > half_min_dim
70+
|| corners.bottom_right > half_min_dim
71+
|| corners.bottom_left > half_min_dim
72+
})
73+
});
74+
75+
if corner_radii_too_big {
76+
toplevel_obj.post_error(
77+
cosmic_corner_radius_toplevel_v1::Error::RadiusTooLarge as u32,
78+
format!("{toplevel_obj:?} corner radius too large"),
79+
);
80+
}
81+
});
82+
}
83+
}
4284
}
4385

4486
fn force_redraw(state: &mut State, data: &CornerRadiusData) -> Option<()> {

src/wayland/protocols/corner_radius.rs

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ impl CornerRadiusState {
4545
}
4646

4747
pub trait CornerRadiusHandler {
48+
fn add_corners(
49+
&mut self,
50+
toplevel: &XdgToplevel,
51+
toplevel_obj: cosmic_corner_radius_toplevel_v1::CosmicCornerRadiusToplevelV1,
52+
);
4853
fn corner_radius_state(&mut self) -> &mut CornerRadiusState;
4954
fn toplevel_from_resource(&mut self, toplevel: &XdgToplevel) -> Option<ToplevelSurface>;
5055
fn set_corner_radius(
@@ -111,7 +116,8 @@ where
111116
toplevel: toplevel.downgrade(),
112117
corners: None,
113118
});
114-
let _ = data_init.init(id, data);
119+
let obj = data_init.init(id, data);
120+
state.add_corners(&toplevel, obj);
115121
}
116122
_ => unimplemented!(),
117123
}
@@ -151,12 +157,16 @@ where
151157
cosmic_corner_radius_toplevel_v1::Request::Destroy => {
152158
let mut guard = data.lock().unwrap();
153159
guard.corners = None;
154-
if let Some(surface) = guard
155-
.toplevel
156-
.upgrade()
157-
.ok()
158-
.and_then(|toplevel| state.toplevel_from_resource(&toplevel))
159-
{
160+
161+
let Ok(toplevel) = guard.toplevel.upgrade() else {
162+
resource.post_error(
163+
cosmic_corner_radius_toplevel_v1::Error::ToplevelDestroyed as u32,
164+
format!("{:?} No toplevel found", resource),
165+
);
166+
return;
167+
};
168+
169+
if let Some(surface) = state.toplevel_from_resource(&toplevel) {
160170
with_states(surface.wl_surface(), |s| {
161171
let mut cached = s.cached_state.get::<CacheableCorners>();
162172
let pending = cached.pending();
@@ -175,12 +185,15 @@ where
175185
} => {
176186
let mut guard = data.lock().unwrap();
177187
guard.set_corner_radius(top_left, top_right, bottom_right, bottom_left);
178-
if let Some(surface) = guard
179-
.toplevel
180-
.upgrade()
181-
.ok()
182-
.and_then(|toplevel| state.toplevel_from_resource(&toplevel))
183-
{
188+
let Ok(toplevel) = guard.toplevel.upgrade() else {
189+
resource.post_error(
190+
cosmic_corner_radius_toplevel_v1::Error::ToplevelDestroyed as u32,
191+
format!("{:?} No toplevel found", resource),
192+
);
193+
return;
194+
};
195+
196+
if let Some(surface) = state.toplevel_from_resource(&toplevel) {
184197
with_states(surface.wl_surface(), |s| {
185198
let mut cached = s.cached_state.get::<CacheableCorners>();
186199
let pending = cached.pending();
@@ -194,12 +207,15 @@ where
194207
cosmic_corner_radius_toplevel_v1::Request::UnsetRadius => {
195208
let mut guard = data.lock().unwrap();
196209
guard.corners = None;
197-
if let Some(surface) = guard
198-
.toplevel
199-
.upgrade()
200-
.ok()
201-
.and_then(|toplevel| state.toplevel_from_resource(&toplevel))
202-
{
210+
let Ok(toplevel) = guard.toplevel.upgrade() else {
211+
resource.post_error(
212+
cosmic_corner_radius_toplevel_v1::Error::ToplevelDestroyed as u32,
213+
format!("{:?} No toplevel found", resource),
214+
);
215+
return;
216+
};
217+
218+
if let Some(surface) = state.toplevel_from_resource(&toplevel) {
203219
with_states(surface.wl_surface(), |s| {
204220
let mut cached = s.cached_state.get::<CacheableCorners>();
205221
let pending = cached.pending();

0 commit comments

Comments
 (0)