2025-09-25 09:10:00 -04:00
|
|
|
use cosmic_protocols::corner_radius::v1::server::cosmic_corner_radius_toplevel_v1;
|
|
|
|
|
use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel;
|
2025-09-26 10:10:49 -04:00
|
|
|
use smithay::reexports::wayland_server::Resource;
|
|
|
|
|
use smithay::wayland::compositor::{add_pre_commit_hook, with_states};
|
|
|
|
|
use smithay::wayland::shell::xdg::{SurfaceCachedState, ToplevelSurface};
|
2025-09-24 15:11:16 -04:00
|
|
|
|
|
|
|
|
use crate::wayland::protocols::corner_radius::{
|
2025-09-26 10:10:49 -04:00
|
|
|
delegate_corner_radius, CacheableCorners, CornerRadiusData, CornerRadiusHandler,
|
|
|
|
|
CornerRadiusState,
|
2025-09-24 15:11:16 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
use crate::state::State;
|
|
|
|
|
|
|
|
|
|
impl CornerRadiusHandler for State {
|
2025-09-25 09:10:00 -04:00
|
|
|
fn corner_radius_state(&mut self) -> &mut CornerRadiusState {
|
2025-09-24 15:11:16 -04:00
|
|
|
&mut self.common.corner_radius_state
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn toplevel_from_resource(
|
|
|
|
|
&mut self,
|
2025-09-25 09:10:00 -04:00
|
|
|
toplevel: &xdg_toplevel::XdgToplevel,
|
2025-09-24 15:11:16 -04:00
|
|
|
) -> Option<ToplevelSurface> {
|
|
|
|
|
self.common.xdg_shell_state.get_toplevel(toplevel)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn set_corner_radius(
|
|
|
|
|
&mut self,
|
2025-09-25 09:57:08 -04:00
|
|
|
_: &cosmic_corner_radius_toplevel_v1::CosmicCornerRadiusToplevelV1,
|
|
|
|
|
data: &CornerRadiusData,
|
2025-09-24 15:11:16 -04:00
|
|
|
) {
|
2025-09-25 09:57:08 -04:00
|
|
|
if force_redraw(self, data).is_none() {
|
|
|
|
|
tracing::warn!("Failed to force redraw for corner radius change.");
|
|
|
|
|
}
|
2025-09-24 15:11:16 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn unset_corner_radius(
|
|
|
|
|
&mut self,
|
2025-09-25 09:57:08 -04:00
|
|
|
_: &cosmic_corner_radius_toplevel_v1::CosmicCornerRadiusToplevelV1,
|
|
|
|
|
data: &CornerRadiusData,
|
2025-09-24 15:11:16 -04:00
|
|
|
) {
|
2025-09-25 09:57:08 -04:00
|
|
|
if force_redraw(self, data).is_none() {
|
|
|
|
|
tracing::warn!("Failed to force redraw for corner radius reset.");
|
|
|
|
|
}
|
2025-09-24 15:11:16 -04:00
|
|
|
}
|
2025-09-26 10:10:49 -04:00
|
|
|
|
|
|
|
|
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"),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-09-24 15:11:16 -04:00
|
|
|
}
|
|
|
|
|
|
2025-09-25 09:57:08 -04:00
|
|
|
fn force_redraw(state: &mut State, data: &CornerRadiusData) -> Option<()> {
|
|
|
|
|
let guard = data.lock().unwrap();
|
|
|
|
|
|
|
|
|
|
let toplevel = guard.toplevel.upgrade().ok()?;
|
|
|
|
|
|
|
|
|
|
let surface = state.common.xdg_shell_state.get_toplevel(&toplevel)?;
|
|
|
|
|
|
|
|
|
|
let guard = state.common.shell.read();
|
|
|
|
|
let output = guard.visible_output_for_surface(surface.wl_surface())?;
|
|
|
|
|
|
|
|
|
|
state.backend.schedule_render(output);
|
|
|
|
|
Some(())
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-24 15:11:16 -04:00
|
|
|
delegate_corner_radius!(State);
|