fix(corner-radius): properly handle no value, and use geometry

This commit is contained in:
Ashley Wulber 2025-09-25 12:53:14 -04:00 committed by Victoria Brekenfeld
parent 6f93b8774d
commit 2873d6b27e
5 changed files with 52 additions and 42 deletions

View file

@ -127,10 +127,10 @@ impl CosmicSurface {
}
}
pub fn corner_radius(&self) -> Option<[u8; 4]> {
pub fn corner_radius(&self, geometry_size: Size<i32, Logical>) -> Option<[u8; 4]> {
self.wl_surface().and_then(|surface| {
with_states(&surface, |s| {
let d = s
with_states(&surface, |states| {
let d = states
.data_map
.get::<Mutex<Weak<CosmicCornerRadiusToplevelV1>>>()?;
let guard = d.lock().unwrap();
@ -141,16 +141,18 @@ impl CosmicSurface {
let guard = corners.lock().unwrap();
let size = <CosmicSurface as SpaceElement>::geometry(self).size;
// guard against corner radius being too large, potentially disconnecting the outline
let half_min_dim = u8::try_from(size.w.min(size.h) / 2).unwrap_or(u8::MAX);
let half_min_dim =
u8::try_from(geometry_size.w.min(geometry_size.h) / 2).unwrap_or(u8::MAX);
Some([
guard.top_right.min(half_min_dim),
guard.bottom_right.min(half_min_dim),
guard.top_left.min(half_min_dim),
guard.bottom_left.min(half_min_dim),
])
guard.corners.map(|corners| {
[
corners.top_right.min(half_min_dim),
corners.bottom_right.min(half_min_dim),
corners.top_left.min(half_min_dim),
corners.bottom_left.min(half_min_dim),
]
})
})
})
}

View file

@ -111,7 +111,7 @@ impl MoveGrabState {
let active_window_hint = crate::theme::active_window_hint(theme);
let radius = self
.window()
.corner_radius()
.corner_radius(window_geo.size)
.unwrap_or([self.indicator_thickness; 4]);
let focus_element = if self.indicator_thickness > 0 {

View file

@ -1591,7 +1591,7 @@ impl FloatingLayout {
let active_window_hint = crate::theme::active_window_hint(theme);
let radius = elem
.active_window()
.corner_radius()
.corner_radius(geometry.size.as_logical())
.unwrap_or([indicator_thickness; 4]);
if indicator_thickness > 0 {
let element = IndicatorShader::focus_element(

View file

@ -5017,7 +5017,7 @@ where
}));
let radius = mapped
.active_window()
.corner_radius()
.corner_radius(geo.size.as_logical())
.unwrap_or([indicator_thickness; 4]);
if is_minimizing && indicator_thickness > 0 {
elements.push(CosmicMappedRenderElement::FocusIndicator(
@ -5288,7 +5288,9 @@ where
)
.unwrap();
let radius = window.corner_radius().unwrap_or([indicator_thickness; 4]);
let radius = window
.corner_radius(swap_geo.size.as_logical())
.unwrap_or([indicator_thickness; 4]);
swap_elements.push(CosmicMappedRenderElement::FocusIndicator(
IndicatorShader::focus_element(
renderer,
@ -5369,7 +5371,7 @@ where
let radius = match data {
Data::Mapped { mapped, .. } => mapped
.active_window()
.corner_radius()
.corner_radius(geo.size.as_logical())
.unwrap_or([indicator_thickness; 4]),
_ => [1; 4],
};

View file

@ -108,10 +108,7 @@ where
cosmic_corner_radius_manager_v1::Request::GetCornerRadius { id, toplevel } => {
let data = Mutex::new(CornerRadiusInternal {
toplevel: toplevel.downgrade(),
top_left: 0,
top_right: 0,
bottom_right: 0,
bottom_left: 0,
corners: None,
});
let instance = data_init.init(id, data);
@ -151,7 +148,7 @@ where
+ 'static,
{
fn request(
_state: &mut D,
state: &mut D,
_client: &Client,
resource: &cosmic_corner_radius_toplevel_v1::CosmicCornerRadiusToplevelV1,
request: <cosmic_corner_radius_toplevel_v1::CosmicCornerRadiusToplevelV1 as Resource>::Request,
@ -161,8 +158,11 @@ where
) {
match request {
cosmic_corner_radius_toplevel_v1::Request::Destroy => {
// TODO do we want to unset it after it is destroyed or just leave it?
_state.unset_corner_radius(resource, data);
let mut guard = data.lock().unwrap();
guard.corners = None;
drop(guard);
state.unset_corner_radius(resource, data);
}
cosmic_corner_radius_toplevel_v1::Request::SetRadius {
top_left,
@ -170,20 +170,18 @@ where
bottom_right,
bottom_left,
} => {
{
let mut guard = data.lock().unwrap();
guard.set_corner_radius(
top_left as u8,
top_right as u8,
bottom_right as u8,
bottom_left as u8,
);
}
let mut guard = data.lock().unwrap();
guard.set_corner_radius(top_left, top_right, bottom_right, bottom_left);
drop(guard);
_state.set_corner_radius(resource, data);
state.set_corner_radius(resource, data);
}
cosmic_corner_radius_toplevel_v1::Request::UnsetRadius => {
_state.unset_corner_radius(resource, data);
let mut guard = data.lock().unwrap();
guard.corners = None;
drop(guard);
state.unset_corner_radius(resource, data);
}
_ => unimplemented!(),
}
@ -195,6 +193,11 @@ pub type CornerRadiusData = Mutex<CornerRadiusInternal>;
#[derive(Debug)]
pub struct CornerRadiusInternal {
pub toplevel: Weak<XdgToplevel>,
pub corners: Option<Corners>,
}
#[derive(Debug, Copy, Clone)]
pub struct Corners {
pub top_left: u8,
pub top_right: u8,
pub bottom_right: u8,
@ -204,15 +207,18 @@ pub struct CornerRadiusInternal {
impl CornerRadiusInternal {
fn set_corner_radius(
&mut self,
top_left: u8,
top_right: u8,
bottom_right: u8,
bottom_left: u8,
top_left: u32,
top_right: u32,
bottom_right: u32,
bottom_left: u32,
) {
self.top_left = top_left;
self.top_right = top_right;
self.bottom_right = bottom_right;
self.bottom_left = bottom_left;
let corners = Corners {
top_left: top_left.clamp(u8::MIN as u32, u8::MAX as u32) as u8,
top_right: top_right.clamp(u8::MIN as u32, u8::MAX as u32) as u8,
bottom_right: bottom_right.clamp(u8::MIN as u32, u8::MAX as u32) as u8,
bottom_left: bottom_left.clamp(u8::MIN as u32, u8::MAX as u32) as u8,
};
self.corners = Some(corners);
}
}