Skip to content

Commit 2e3bb2d

Browse files
wash2Drakulix
authored andcommitted
refactor(corner-radius): cleanup & add pre commit hooks
1 parent 819887e commit 2e3bb2d

File tree

2 files changed

+109
-74
lines changed

2 files changed

+109
-74
lines changed

src/wayland/handlers/corner_radius.rs

Lines changed: 1 addition & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
use cosmic_protocols::corner_radius::v1::server::cosmic_corner_radius_toplevel_v1;
2-
use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel;
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};
62

73
use crate::wayland::protocols::corner_radius::{
8-
delegate_corner_radius, CacheableCorners, CornerRadiusData, CornerRadiusHandler,
4+
delegate_corner_radius, CornerRadiusData, CornerRadiusHandler,
95
CornerRadiusState,
106
};
117

@@ -16,13 +12,6 @@ impl CornerRadiusHandler for State {
1612
&mut self.common.corner_radius_state
1713
}
1814

19-
fn toplevel_from_resource(
20-
&mut self,
21-
toplevel: &xdg_toplevel::XdgToplevel,
22-
) -> Option<ToplevelSurface> {
23-
self.common.xdg_shell_state.get_toplevel(toplevel)
24-
}
25-
2615
fn set_corner_radius(
2716
&mut self,
2817
_: &cosmic_corner_radius_toplevel_v1::CosmicCornerRadiusToplevelV1,
@@ -42,45 +31,6 @@ impl CornerRadiusHandler for State {
4231
tracing::warn!("Failed to force redraw for corner radius reset.");
4332
}
4433
}
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-
}
8434
}
8535

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

src/wayland/protocols/corner_radius.rs

Lines changed: 108 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
1+
use cosmic_protocols::corner_radius::v1::server::cosmic_corner_radius_toplevel_v1::CosmicCornerRadiusToplevelV1;
12
use cosmic_protocols::corner_radius::v1::server::{
23
cosmic_corner_radius_manager_v1, cosmic_corner_radius_toplevel_v1,
34
};
4-
use smithay::reexports::{
5-
wayland_protocols::xdg::shell::server::xdg_toplevel::XdgToplevel,
6-
wayland_server::{Client, Dispatch, DisplayHandle, GlobalDispatch, Resource, Weak},
7-
};
5+
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
6+
use smithay::utils::HookId;
7+
use smithay::wayland::compositor::add_pre_commit_hook;
88
use smithay::wayland::compositor::with_states;
99
use smithay::wayland::compositor::Cacheable;
10-
use smithay::wayland::shell::xdg::ToplevelSurface;
10+
use smithay::wayland::shell::xdg::SurfaceCachedState;
11+
use smithay::{
12+
reexports::{
13+
wayland_protocols::xdg::shell::server::xdg_toplevel::XdgToplevel,
14+
wayland_server::{Client, Dispatch, DisplayHandle, GlobalDispatch, Resource, Weak},
15+
},
16+
wayland::shell::xdg::XdgShellHandler,
17+
};
18+
use std::collections::HashMap;
1119
use std::sync::Mutex;
1220
use wayland_backend::server::GlobalId;
1321

@@ -44,14 +52,8 @@ impl CornerRadiusState {
4452
}
4553
}
4654

47-
pub trait CornerRadiusHandler {
48-
fn add_corners(
49-
&mut self,
50-
toplevel: &XdgToplevel,
51-
toplevel_obj: cosmic_corner_radius_toplevel_v1::CosmicCornerRadiusToplevelV1,
52-
);
55+
pub trait CornerRadiusHandler: XdgShellHandler {
5356
fn corner_radius_state(&mut self) -> &mut CornerRadiusState;
54-
fn toplevel_from_resource(&mut self, toplevel: &XdgToplevel) -> Option<ToplevelSurface>;
5557
fn set_corner_radius(
5658
&mut self,
5759
toplevel: &cosmic_corner_radius_toplevel_v1::CosmicCornerRadiusToplevelV1,
@@ -100,7 +102,7 @@ where
100102
fn request(
101103
state: &mut D,
102104
_client: &Client,
103-
_resource: &cosmic_corner_radius_manager_v1::CosmicCornerRadiusManagerV1,
105+
resource: &cosmic_corner_radius_manager_v1::CosmicCornerRadiusManagerV1,
104106
request: <cosmic_corner_radius_manager_v1::CosmicCornerRadiusManagerV1 as smithay::reexports::wayland_server::Resource>::Request,
105107
_data: &(),
106108
_dhandle: &DisplayHandle,
@@ -109,15 +111,85 @@ where
109111
match request {
110112
cosmic_corner_radius_manager_v1::Request::Destroy => {
111113
let corner_radius_state = state.corner_radius_state();
112-
corner_radius_state.instances.retain(|i| i != _resource);
114+
corner_radius_state.instances.retain(|i| i != resource);
113115
}
114116
cosmic_corner_radius_manager_v1::Request::GetCornerRadius { id, toplevel } => {
115-
let data = Mutex::new(CornerRadiusInternal {
116-
toplevel: toplevel.downgrade(),
117-
corners: None,
118-
});
119-
let obj = data_init.init(id, data);
120-
state.add_corners(&toplevel, obj);
117+
if let Some(surface) = state.xdg_shell_state().get_toplevel(&toplevel) {
118+
let radius_exists = with_states(surface.wl_surface(), |surface_data| {
119+
let hook_ids = surface_data.data_map.get_or_insert_threadsafe(|| {
120+
Mutex::new(HashMap::<
121+
WlSurface,
122+
(HookId, Weak<CosmicCornerRadiusToplevelV1>),
123+
>::new())
124+
});
125+
let guard = hook_ids.lock().unwrap();
126+
guard
127+
.get(surface.wl_surface())
128+
.map(|(_, t)| t.upgrade().is_ok())
129+
});
130+
if radius_exists.unwrap_or_default() {
131+
resource.post_error(
132+
cosmic_corner_radius_manager_v1::Error::CornerRadiusExists as u32,
133+
format!("{resource:?} CosmicCornerRadiusToplevelV1 object already exists for the surface"),
134+
);
135+
}
136+
let data = Mutex::new(CornerRadiusInternal {
137+
toplevel: toplevel.downgrade(),
138+
corners: None,
139+
});
140+
let obj = data_init.init(id, data);
141+
let obj_downgrade = obj.downgrade();
142+
143+
let needs_hook = radius_exists.is_none();
144+
if needs_hook {
145+
let hook_id = add_pre_commit_hook::<D, _>(
146+
surface.wl_surface(),
147+
move |_, _dh, surface| {
148+
let corner_radii_too_big = with_states(surface, |surface_data| {
149+
let corners = surface_data
150+
.cached_state
151+
.get::<CacheableCorners>()
152+
.pending()
153+
.clone();
154+
surface_data
155+
.cached_state
156+
.get::<SurfaceCachedState>()
157+
.pending()
158+
.geometry
159+
.zip(corners.0.as_ref())
160+
.is_some_and(|(geo, corners)| {
161+
let half_min_dim =
162+
u8::try_from(geo.size.w.min(geo.size.h) / 2)
163+
.unwrap_or(u8::MAX);
164+
corners.top_right > half_min_dim
165+
|| corners.top_left > half_min_dim
166+
|| corners.bottom_right > half_min_dim
167+
|| corners.bottom_left > half_min_dim
168+
})
169+
});
170+
171+
if corner_radii_too_big {
172+
obj.post_error(
173+
cosmic_corner_radius_toplevel_v1::Error::RadiusTooLarge
174+
as u32,
175+
format!("{obj:?} corner radius too large"),
176+
);
177+
}
178+
},
179+
);
180+
181+
with_states(surface.wl_surface(), |surface_data| {
182+
let hook_ids = surface_data.data_map.get_or_insert_threadsafe(|| {
183+
Mutex::new(HashMap::<
184+
WlSurface,
185+
(HookId, Weak<CosmicCornerRadiusToplevelV1>),
186+
>::new())
187+
});
188+
let mut guard = hook_ids.lock().unwrap();
189+
guard.insert(surface.wl_surface().clone(), (hook_id, obj_downgrade));
190+
});
191+
}
192+
}
121193
}
122194
_ => unimplemented!(),
123195
}
@@ -166,7 +238,20 @@ where
166238
return;
167239
};
168240

169-
if let Some(surface) = state.toplevel_from_resource(&toplevel) {
241+
if let Some(surface) = state.xdg_shell_state().get_toplevel(&toplevel) {
242+
with_states(surface.wl_surface(), |surface_data| {
243+
if let Some(hook_ids_mutex) =
244+
surface_data.data_map.get::<Mutex<
245+
HashMap<WlSurface, (HookId, Weak<CosmicCornerRadiusToplevelV1>)>,
246+
>>()
247+
{
248+
let mut hook_ids = hook_ids_mutex.lock().unwrap();
249+
hook_ids.remove(surface.wl_surface());
250+
}
251+
});
252+
}
253+
254+
if let Some(surface) = state.xdg_shell_state().get_toplevel(&toplevel) {
170255
with_states(surface.wl_surface(), |s| {
171256
let mut cached = s.cached_state.get::<CacheableCorners>();
172257
let pending = cached.pending();
@@ -193,7 +278,7 @@ where
193278
return;
194279
};
195280

196-
if let Some(surface) = state.toplevel_from_resource(&toplevel) {
281+
if let Some(surface) = state.xdg_shell_state().get_toplevel(&toplevel) {
197282
with_states(surface.wl_surface(), |s| {
198283
let mut cached = s.cached_state.get::<CacheableCorners>();
199284
let pending = cached.pending();
@@ -215,7 +300,7 @@ where
215300
return;
216301
};
217302

218-
if let Some(surface) = state.toplevel_from_resource(&toplevel) {
303+
if let Some(surface) = state.xdg_shell_state().get_toplevel(&toplevel) {
219304
with_states(surface.wl_surface(), |s| {
220305
let mut cached = s.cached_state.get::<CacheableCorners>();
221306
let pending = cached.pending();

0 commit comments

Comments
 (0)