Add window blur, organize Settings, and reduce launcher memory

This commit is contained in:
Samuel Onoja committed 2026-10-14 01:01:21 +01:00
1 parent bbc2f226d8
commit 07a8e50f47
17 files changed
+260 -88

No files matched your search

+6
View File
@@ -195,6 +195,12 @@ pub(super) fn grouped_elements(
{
elements.push(material);
}
if window.material.is_none()
&& let Some(blur) =
super::window_blur::window_blur_element(state, renderer, output, window.presentation, corners)
{
elements.push(blur);
}
let theme = &state.theme_settings;
let (offset_factor, blur_factor, opacity_factor) = window.presentation.shadow_factors();
if let Some(shadow) = window_shadow_element(
+1
View File
@@ -1,6 +1,7 @@
mod backdrop;
mod capture;
mod closing;
mod window_blur;
mod window_content;
pub(crate) use closing::ClosedWindow;
#[cfg(test)]
+4
View File
@@ -20,6 +20,7 @@ pub(super) struct WindowBuffers {
pub borders: WindowBorderBuffers,
pub dim: WindowBorderBuffers,
pub resize_fill: WindowBorderBuffers,
pub blur: HashMap<(ErasedContextId, OutputId), super::window_blur::WindowBlur>,
pub shadow: WindowShadowBuffers,
corner_shape: Option<CornerShape>,
thumbnail_shapes: HashMap<OutputId, CornerShape>,
@@ -48,6 +49,7 @@ impl RenderResources {
buffers.dim.contexts.clear();
buffers.resize_fill.contexts.clear();
buffers.shadow.contexts.clear();
buffers.blur.clear();
if let Some(snapshot) = &mut buffers.snapshot {
snapshot.commit.increment();
@@ -101,6 +103,7 @@ impl RenderResources {
for window in self.windows.values_mut() {
window.thumbnail_shapes.remove(&id);
window.blur.retain(|(_, output), _| *output != id);
}
for surface in self.surfaces.values_mut() {
@@ -167,6 +170,7 @@ impl RenderResources {
window.dim.contexts.remove(context);
window.resize_fill.contexts.remove(context);
window.shadow.contexts.remove(context);
window.blur.retain(|(key, _), _| key != context);
if window
.snapshot
+6
View File
@@ -340,6 +340,12 @@ fn scene_elements(
{
elements.push(background);
}
if material_surface.is_none()
&& let Some(blur) =
super::window_blur::window_blur_element(state, renderer, output, sample.presentation, corners)
{
elements.push(blur);
}
if let Some(shadow) = shadow {
elements.push(shadow.into());
}
+101
View File
@@ -0,0 +1,101 @@
use super::*;
#[derive(Debug)]
pub(super) struct WindowBlur {
parameters: MaterialParameters,
element: BlurRenderElement,
}
pub(super) fn window_blur_element(
state: &mut Ferese,
renderer: &mut GlesRenderer,
output: &Output,
presentation: crate::presentation::WindowPresentation,
corners: RoundedRect,
) -> Option<AnimatedWindowRenderElement> {
let radius = state.theme_settings.backdrop_blur;
if !state.focus_effect.enabled
|| !state.focus_effect.blur
|| state.theme_settings.reduce_transparency
|| radius <= 0.0
|| presentation.focus_alpha <= 0.0
|| presentation.focus_alpha >= 1.0
|| presentation.alpha() <= 0.0
{
if let Some(window) = state.render.windows.get_mut(&presentation.id) {
window.blur.clear();
}
return None;
}
let mode = output.current_mode()?;
let scale = output.current_scale().fractional_scale();
let transform = output.current_transform().invert();
let output_size = output
.current_transform()
.transform_size(mode.size)
.to_f64()
.to_logical(scale)
.to_i32_ceil();
let geometry = corners.rect.to_f64().to_logical(scale).to_i32_up();
let Some(visible) = geometry.intersection(Rectangle::from_size(output_size)) else {
if let Some(window) = state.render.windows.get_mut(&presentation.id) {
window.blur.clear();
}
return None;
};
let sample_geometry = expanded_blur_region(visible, radius.ceil() as i32, output_size);
let sample_physical = sample_geometry.to_physical_precise_round(scale);
let parameters = MaterialParameters {
panel: None,
corner_radii: [corners.radius; 4],
// Replace the sharp backdrop completely. Window content supplies the
// transparency; only the lifecycle animation fades this background.
presentation_alpha: presentation.opacity.current.clamp(0.0, 1.0) as f32,
background_opacity: 0.0,
blur: (radius * scale) as f32,
sample_geometry,
sample_physical,
sample_framebuffer: framebuffer_clip_rect(sample_physical, mode.size, transform),
shadow_rect: [0.0; 4],
shadow_values: [0.0; 2],
shadow_bounds: geometry,
geometry,
tint: [0.0; 4],
generation: 0,
opaque: false,
visible_framebuffer: framebuffer_clip_rect(corners.rect, mode.size, transform),
};
let key = (renderer.context_id().erased(), state.output_id(output)?);
let program = blur_program(&mut state.render, renderer)?;
let buffers = &mut state.render.windows.entry(presentation.id).or_default().blur;
let capture_rect = framebuffer_capture_rect(parameters.sample_framebuffer);
let capture_size = Size::from((capture_rect[2], capture_rect[3]));
if buffers
.get(&key)
.is_none_or(|cached| cached.element.texture.size() != capture_size)
{
let texture = match Offscreen::<GlesTexture>::create_buffer(renderer, Fourcc::Abgr8888, capture_size) {
Ok(texture) => texture,
Err(error) => {
tracing::warn!(%error, "window blur allocation failed");
buffers.remove(&key);
return None;
}
};
let element = BlurRenderElement::new(texture, program.0, &parameters, Arc::new(AtomicBool::new(true)));
buffers.insert(
key.clone(),
WindowBlur {
parameters: parameters.clone(),
element,
},
);
}
let cached = buffers.get_mut(&key)?;
if cached.parameters != parameters {
cached.element.update(&parameters);
cached.parameters = parameters;
}
Some(cached.element.clone().into())
}