From 77b94a560dcbc0098dcd0d7b1f05a52594f58559 Mon Sep 17 00:00:00 2001 From: nevaforget Date: Sat, 28 Mar 2026 23:28:39 +0100 Subject: [PATCH] fix: prevent edge darkening on GPU-blurred wallpaper (v0.5.3) GskBlurNode samples pixels outside texture bounds as transparent, causing visible darkening at wallpaper edges. Fix renders the texture with 3x-sigma padding before blur, then clips back to original size. Symmetric fix with moonset v0.7.1. --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/greeter.rs | 25 +++++++++++++++++++------ 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 75dd62e..dda8764 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -569,7 +569,7 @@ dependencies = [ [[package]] name = "moongreet" -version = "0.5.2" +version = "0.5.3" dependencies = [ "gdk-pixbuf", "gdk4", diff --git a/Cargo.toml b/Cargo.toml index 0dc0f79..7e85611 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "moongreet" -version = "0.5.2" +version = "0.5.3" edition = "2024" description = "A greetd greeter for Wayland with GTK4 and Layer Shell" license = "MIT" diff --git a/src/greeter.rs b/src/greeter.rs index e4b35bf..08287ce 100644 --- a/src/greeter.rs +++ b/src/greeter.rs @@ -119,6 +119,10 @@ pub fn load_background_texture(bg_path: &Path) -> Option { // -- GPU blur via GskBlurNode ------------------------------------------------- /// Render a blurred texture using the GPU via GskBlurNode. +/// +/// To avoid edge darkening (blur samples transparent pixels outside bounds), +/// the texture is rendered with padding equal to 3x the blur sigma. The blur +/// is applied to the padded area, then cropped back to the original size. fn render_blurred_texture( widget: &impl IsA, texture: &gdk::Texture, @@ -126,15 +130,24 @@ fn render_blurred_texture( ) -> Option { let native = widget.native()?; let renderer = native.renderer()?; + + let w = texture.width() as f32; + let h = texture.height() as f32; + // Padding must cover the blur kernel radius (typically ~3x sigma) + let pad = (sigma * 3.0).ceil(); + let snapshot = gtk::Snapshot::new(); - let bounds = graphene_rs::Rect::new( - 0.0, 0.0, texture.width() as f32, texture.height() as f32, - ); + // Clip output to original texture size + snapshot.push_clip(&graphene_rs::Rect::new(pad, pad, w, h)); snapshot.push_blur(sigma as f64); - snapshot.append_texture(texture, &bounds); - snapshot.pop(); + // Render texture with padding on all sides (edges repeat via oversized bounds) + snapshot.append_texture(texture, &graphene_rs::Rect::new(0.0, 0.0, w + 2.0 * pad, h + 2.0 * pad)); + snapshot.pop(); // blur + snapshot.pop(); // clip + let node = snapshot.to_node()?; - Some(renderer.render_texture(&node, None)) + let viewport = graphene_rs::Rect::new(pad, pad, w, h); + Some(renderer.render_texture(&node, Some(&viewport))) } /// Create a wallpaper-only window for secondary monitors.