fix: prevent edge darkening on GPU-blurred wallpaper (v0.6.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.
This commit is contained in:
parent
fff18bfb9d
commit
77d6994b8f
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -575,7 +575,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "moonlock"
|
||||
version = "0.6.2"
|
||||
version = "0.6.3"
|
||||
dependencies = [
|
||||
"gdk-pixbuf",
|
||||
"gdk4",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "moonlock"
|
||||
version = "0.6.2"
|
||||
version = "0.6.3"
|
||||
edition = "2024"
|
||||
description = "A secure Wayland lockscreen with GTK4, PAM and fingerprint support"
|
||||
license = "MIT"
|
||||
|
||||
@ -483,6 +483,10 @@ fn create_background_picture(
|
||||
|
||||
/// Render a blurred texture using the widget's GPU renderer.
|
||||
/// Returns None if the renderer is not available.
|
||||
///
|
||||
/// 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<gtk::Widget>,
|
||||
texture: &gdk::Texture,
|
||||
@ -490,18 +494,24 @@ fn render_blurred_texture(
|
||||
) -> Option<gdk::Texture> {
|
||||
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::Rect::new(
|
||||
0.0,
|
||||
0.0,
|
||||
texture.width() as f32,
|
||||
texture.height() as f32,
|
||||
);
|
||||
// Clip output to original texture size
|
||||
snapshot.push_clip(&graphene::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::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::Rect::new(pad, pad, w, h);
|
||||
Some(renderer.render_texture(&node, Some(&viewport)))
|
||||
}
|
||||
|
||||
/// Load an image file and set it as the avatar. Stores the texture in the cache.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user