From 518b0834725f308bcf7e2c4f493b32258ebd2def Mon Sep 17 00:00:00 2001 From: Samuel Onoja Date: Wed, 30 Sep 2026 05:51:43 +0100 Subject: [PATCH] Align modal blur regions and preserve materials during resize --- compositor/src/winit.rs | 5 ++- shell/ferese-shell/src/motion.rs | 55 +++++++++++++++++++++----------- 2 files changed, 41 insertions(+), 19 deletions(-) diff --git a/compositor/src/winit.rs b/compositor/src/winit.rs index 78958ed..a84d4bf 100644 --- a/compositor/src/winit.rs +++ b/compositor/src/winit.rs @@ -1416,7 +1416,10 @@ fn output_elements( behavior, )); let source = window.geometry().size; - if !scale_content && (source.w < constrain.size.w || source.h < constrain.size.h) { + if material_surface.is_none() + && !scale_content + && (source.w < constrain.size.w || source.h < constrain.size.h) + { let mut color = state.theme_settings.surface_base_color.0; color[3] = close_alpha; if let Some(fill) = window_tint_element( diff --git a/shell/ferese-shell/src/motion.rs b/shell/ferese-shell/src/motion.rs index 551cd7a..1393862 100644 --- a/shell/ferese-shell/src/motion.rs +++ b/shell/ferese-shell/src/motion.rs @@ -443,24 +443,7 @@ impl Widget for Motion<'_, M> { collector.0.push(content.bounds()); } } - let origin = layout.bounds().position(); - let translation = self.translation(); - let regions = collector - .0 - .into_iter() - .take(32) - .filter(|r| r.width > 0.0 && r.height > 0.0) - .map(|r| { - [ - (r.x - origin.x + translation.x).round() as i32, - (r.y - origin.y + translation.y).round() as i32, - r.width.round() as i32, - r.height.round() as i32, - self.radius.round().max(0.0) as i32, - ] - }) - .collect(); - *self.regions.lock().unwrap() = regions; + *self.regions.lock().unwrap() = collector.into_regions(self.translation(), self.radius); let cursor = self.cursor(cursor); self.content.as_widget_mut().update( tree, event, layout, cursor, renderer, clipboard, shell, viewport, @@ -523,6 +506,26 @@ impl Widget for Motion<'_, M> { } struct CollectRegions(Vec); + +impl CollectRegions { + fn into_regions(self, translation: Vector, radius: f32) -> Vec<[i32; 5]> { + self.0 + .into_iter() + .take(32) + .filter(|r| r.width > 0.0 && r.height > 0.0) + .map(|r| { + [ + (r.x + translation.x).round() as i32, + (r.y + translation.y).round() as i32, + r.width.round() as i32, + r.height.round() as i32, + radius.round().max(0.0) as i32, + ] + }) + .collect() + } +} + impl widget::Operation for CollectRegions { fn traverse(&mut self, children: &mut dyn FnMut(&mut dyn widget::Operation)) { children(self); @@ -549,6 +552,22 @@ impl widget::Operation for CollectRegions { #[cfg(test)] mod tests { use super::*; + + #[test] + fn centered_modal_material_tracks_surface_position_and_animation() { + let mut collector = CollectRegions(Vec::new()); + let card = Rectangle::new((380.0, 420.0).into(), (440.0, 220.0).into()); + widget::Operation::container( + &mut collector, + Some(&widget::Id::new("ferese-blur-card")), + card, + ); + assert_eq!( + collector.into_regions(Vector::new(0.0, -2.0), 14.0), + vec![[380, 418, 440, 220, 14]] + ); + } + #[test] fn popup_waits_for_configuration_then_opens_and_closes_faster() { let now = std::time::Instant::now();