refactor(corner-radius): cleanup & add pre commit hooks
This commit is contained in:
parent
819887e298
commit
2e3bb2d80e
2 changed files with 109 additions and 74 deletions
|
|
@ -1,11 +1,7 @@
|
||||||
use cosmic_protocols::corner_radius::v1::server::cosmic_corner_radius_toplevel_v1;
|
use cosmic_protocols::corner_radius::v1::server::cosmic_corner_radius_toplevel_v1;
|
||||||
use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel;
|
|
||||||
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::{
|
use crate::wayland::protocols::corner_radius::{
|
||||||
delegate_corner_radius, CacheableCorners, CornerRadiusData, CornerRadiusHandler,
|
delegate_corner_radius, CornerRadiusData, CornerRadiusHandler,
|
||||||
CornerRadiusState,
|
CornerRadiusState,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -16,13 +12,6 @@ impl CornerRadiusHandler for State {
|
||||||
&mut self.common.corner_radius_state
|
&mut self.common.corner_radius_state
|
||||||
}
|
}
|
||||||
|
|
||||||
fn toplevel_from_resource(
|
|
||||||
&mut self,
|
|
||||||
toplevel: &xdg_toplevel::XdgToplevel,
|
|
||||||
) -> Option<ToplevelSurface> {
|
|
||||||
self.common.xdg_shell_state.get_toplevel(toplevel)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_corner_radius(
|
fn set_corner_radius(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: &cosmic_corner_radius_toplevel_v1::CosmicCornerRadiusToplevelV1,
|
_: &cosmic_corner_radius_toplevel_v1::CosmicCornerRadiusToplevelV1,
|
||||||
|
|
@ -42,45 +31,6 @@ impl CornerRadiusHandler for State {
|
||||||
tracing::warn!("Failed to force redraw for corner radius reset.");
|
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<()> {
|
fn force_redraw(state: &mut State, data: &CornerRadiusData) -> Option<()> {
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,21 @@
|
||||||
|
use cosmic_protocols::corner_radius::v1::server::cosmic_corner_radius_toplevel_v1::CosmicCornerRadiusToplevelV1;
|
||||||
use cosmic_protocols::corner_radius::v1::server::{
|
use cosmic_protocols::corner_radius::v1::server::{
|
||||||
cosmic_corner_radius_manager_v1, cosmic_corner_radius_toplevel_v1,
|
cosmic_corner_radius_manager_v1, cosmic_corner_radius_toplevel_v1,
|
||||||
};
|
};
|
||||||
use smithay::reexports::{
|
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
|
||||||
wayland_protocols::xdg::shell::server::xdg_toplevel::XdgToplevel,
|
use smithay::utils::HookId;
|
||||||
wayland_server::{Client, Dispatch, DisplayHandle, GlobalDispatch, Resource, Weak},
|
use smithay::wayland::compositor::add_pre_commit_hook;
|
||||||
};
|
|
||||||
use smithay::wayland::compositor::with_states;
|
use smithay::wayland::compositor::with_states;
|
||||||
use smithay::wayland::compositor::Cacheable;
|
use smithay::wayland::compositor::Cacheable;
|
||||||
use smithay::wayland::shell::xdg::ToplevelSurface;
|
use smithay::wayland::shell::xdg::SurfaceCachedState;
|
||||||
|
use smithay::{
|
||||||
|
reexports::{
|
||||||
|
wayland_protocols::xdg::shell::server::xdg_toplevel::XdgToplevel,
|
||||||
|
wayland_server::{Client, Dispatch, DisplayHandle, GlobalDispatch, Resource, Weak},
|
||||||
|
},
|
||||||
|
wayland::shell::xdg::XdgShellHandler,
|
||||||
|
};
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use wayland_backend::server::GlobalId;
|
use wayland_backend::server::GlobalId;
|
||||||
|
|
||||||
|
|
@ -44,14 +52,8 @@ impl CornerRadiusState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait CornerRadiusHandler {
|
pub trait CornerRadiusHandler: XdgShellHandler {
|
||||||
fn add_corners(
|
|
||||||
&mut self,
|
|
||||||
toplevel: &XdgToplevel,
|
|
||||||
toplevel_obj: cosmic_corner_radius_toplevel_v1::CosmicCornerRadiusToplevelV1,
|
|
||||||
);
|
|
||||||
fn corner_radius_state(&mut self) -> &mut CornerRadiusState;
|
fn corner_radius_state(&mut self) -> &mut CornerRadiusState;
|
||||||
fn toplevel_from_resource(&mut self, toplevel: &XdgToplevel) -> Option<ToplevelSurface>;
|
|
||||||
fn set_corner_radius(
|
fn set_corner_radius(
|
||||||
&mut self,
|
&mut self,
|
||||||
toplevel: &cosmic_corner_radius_toplevel_v1::CosmicCornerRadiusToplevelV1,
|
toplevel: &cosmic_corner_radius_toplevel_v1::CosmicCornerRadiusToplevelV1,
|
||||||
|
|
@ -100,7 +102,7 @@ where
|
||||||
fn request(
|
fn request(
|
||||||
state: &mut D,
|
state: &mut D,
|
||||||
_client: &Client,
|
_client: &Client,
|
||||||
_resource: &cosmic_corner_radius_manager_v1::CosmicCornerRadiusManagerV1,
|
resource: &cosmic_corner_radius_manager_v1::CosmicCornerRadiusManagerV1,
|
||||||
request: <cosmic_corner_radius_manager_v1::CosmicCornerRadiusManagerV1 as smithay::reexports::wayland_server::Resource>::Request,
|
request: <cosmic_corner_radius_manager_v1::CosmicCornerRadiusManagerV1 as smithay::reexports::wayland_server::Resource>::Request,
|
||||||
_data: &(),
|
_data: &(),
|
||||||
_dhandle: &DisplayHandle,
|
_dhandle: &DisplayHandle,
|
||||||
|
|
@ -109,15 +111,85 @@ where
|
||||||
match request {
|
match request {
|
||||||
cosmic_corner_radius_manager_v1::Request::Destroy => {
|
cosmic_corner_radius_manager_v1::Request::Destroy => {
|
||||||
let corner_radius_state = state.corner_radius_state();
|
let corner_radius_state = state.corner_radius_state();
|
||||||
corner_radius_state.instances.retain(|i| i != _resource);
|
corner_radius_state.instances.retain(|i| i != resource);
|
||||||
}
|
}
|
||||||
cosmic_corner_radius_manager_v1::Request::GetCornerRadius { id, toplevel } => {
|
cosmic_corner_radius_manager_v1::Request::GetCornerRadius { id, toplevel } => {
|
||||||
let data = Mutex::new(CornerRadiusInternal {
|
if let Some(surface) = state.xdg_shell_state().get_toplevel(&toplevel) {
|
||||||
toplevel: toplevel.downgrade(),
|
let radius_exists = with_states(surface.wl_surface(), |surface_data| {
|
||||||
corners: None,
|
let hook_ids = surface_data.data_map.get_or_insert_threadsafe(|| {
|
||||||
});
|
Mutex::new(HashMap::<
|
||||||
let obj = data_init.init(id, data);
|
WlSurface,
|
||||||
state.add_corners(&toplevel, obj);
|
(HookId, Weak<CosmicCornerRadiusToplevelV1>),
|
||||||
|
>::new())
|
||||||
|
});
|
||||||
|
let guard = hook_ids.lock().unwrap();
|
||||||
|
guard
|
||||||
|
.get(surface.wl_surface())
|
||||||
|
.map(|(_, t)| t.upgrade().is_ok())
|
||||||
|
});
|
||||||
|
if radius_exists.unwrap_or_default() {
|
||||||
|
resource.post_error(
|
||||||
|
cosmic_corner_radius_manager_v1::Error::CornerRadiusExists as u32,
|
||||||
|
format!("{resource:?} CosmicCornerRadiusToplevelV1 object already exists for the surface"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
let data = Mutex::new(CornerRadiusInternal {
|
||||||
|
toplevel: toplevel.downgrade(),
|
||||||
|
corners: None,
|
||||||
|
});
|
||||||
|
let obj = data_init.init(id, data);
|
||||||
|
let obj_downgrade = obj.downgrade();
|
||||||
|
|
||||||
|
let needs_hook = radius_exists.is_none();
|
||||||
|
if needs_hook {
|
||||||
|
let hook_id = add_pre_commit_hook::<D, _>(
|
||||||
|
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 {
|
||||||
|
obj.post_error(
|
||||||
|
cosmic_corner_radius_toplevel_v1::Error::RadiusTooLarge
|
||||||
|
as u32,
|
||||||
|
format!("{obj:?} corner radius too large"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
with_states(surface.wl_surface(), |surface_data| {
|
||||||
|
let hook_ids = surface_data.data_map.get_or_insert_threadsafe(|| {
|
||||||
|
Mutex::new(HashMap::<
|
||||||
|
WlSurface,
|
||||||
|
(HookId, Weak<CosmicCornerRadiusToplevelV1>),
|
||||||
|
>::new())
|
||||||
|
});
|
||||||
|
let mut guard = hook_ids.lock().unwrap();
|
||||||
|
guard.insert(surface.wl_surface().clone(), (hook_id, obj_downgrade));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
|
|
@ -166,7 +238,20 @@ where
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(surface) = state.toplevel_from_resource(&toplevel) {
|
if let Some(surface) = state.xdg_shell_state().get_toplevel(&toplevel) {
|
||||||
|
with_states(surface.wl_surface(), |surface_data| {
|
||||||
|
if let Some(hook_ids_mutex) =
|
||||||
|
surface_data.data_map.get::<Mutex<
|
||||||
|
HashMap<WlSurface, (HookId, Weak<CosmicCornerRadiusToplevelV1>)>,
|
||||||
|
>>()
|
||||||
|
{
|
||||||
|
let mut hook_ids = hook_ids_mutex.lock().unwrap();
|
||||||
|
hook_ids.remove(surface.wl_surface());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(surface) = state.xdg_shell_state().get_toplevel(&toplevel) {
|
||||||
with_states(surface.wl_surface(), |s| {
|
with_states(surface.wl_surface(), |s| {
|
||||||
let mut cached = s.cached_state.get::<CacheableCorners>();
|
let mut cached = s.cached_state.get::<CacheableCorners>();
|
||||||
let pending = cached.pending();
|
let pending = cached.pending();
|
||||||
|
|
@ -193,7 +278,7 @@ where
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(surface) = state.toplevel_from_resource(&toplevel) {
|
if let Some(surface) = state.xdg_shell_state().get_toplevel(&toplevel) {
|
||||||
with_states(surface.wl_surface(), |s| {
|
with_states(surface.wl_surface(), |s| {
|
||||||
let mut cached = s.cached_state.get::<CacheableCorners>();
|
let mut cached = s.cached_state.get::<CacheableCorners>();
|
||||||
let pending = cached.pending();
|
let pending = cached.pending();
|
||||||
|
|
@ -215,7 +300,7 @@ where
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(surface) = state.toplevel_from_resource(&toplevel) {
|
if let Some(surface) = state.xdg_shell_state().get_toplevel(&toplevel) {
|
||||||
with_states(surface.wl_surface(), |s| {
|
with_states(surface.wl_surface(), |s| {
|
||||||
let mut cached = s.cached_state.get::<CacheableCorners>();
|
let mut cached = s.cached_state.get::<CacheableCorners>();
|
||||||
let pending = cached.pending();
|
let pending = cached.pending();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue