Pi66

Home | Repos | About | Blog | Gaza

walrs
pywal but if its Fast-Minimal-Simple
git clone https://git.pi66.xyz/walrs

About | Files | Commits | Refs | License


refactor: improve wallpaper setter logic

Author: pi66
Date: 2026-09-27 18:55
commit: aa760e84

Stat

M src/wallpaper.rs 429 +71 -358

Diff

diff --git a/src/wallpaper.rs b/src/wallpaper.rs
index 8ee2083..2a757b6 100644
--- a/src/wallpaper.rs
+++ b/src/wallpaper.rs
@@ -1,391 +1,104 @@
 use crate::utils::run;
 use crate::utils::{get_absolute_path, info, warning};
+use std::collections::HashMap;
 use std::env;
 use std::path::Path;
 use std::process::{exit, Command, Stdio};

-fn run_with_output(command: &str) -> Option<String> { - let output = Command::new("sh") - .arg("-c") - .arg(command) - .stderr(Stdio::null()) - .output() // ✅ Remove stdout(Stdio::null()) to capture output - .ok()?; - ...

Show all

diff --git a/src/wallpaper.rs b/src/wallpaper.rs
index 8ee2083..2a757b6 100644
--- a/src/wallpaper.rs
+++ b/src/wallpaper.rs
@@ -1,391 +1,104 @@
 use crate::utils::run;
 use crate::utils::{get_absolute_path, info, warning};
+use std::collections::HashMap;
 use std::env;
 use std::path::Path;
 use std::process::{exit, Command, Stdio};

-fn run_with_output(command: &str) -> Option<String> { - let output = Command::new("sh") - .arg("-c") - .arg(command) - .stderr(Stdio::null()) - .output() // ✅ Remove stdout(Stdio::null()) to capture output - .ok()?; - - if output.status.success() { - String::from_utf8(output.stdout) - .ok() - .map(|s| s.trim().to_string()) - } else { - None - } -} - -fn spawn(command: &str) { +fn spawn(cmd: &str) { let _ = Command::new("sh") .arg("-c") - .arg(command) - .stderr(Stdio::null()) + .arg(cmd) .stdout(Stdio::null()) + .stderr(Stdio::null()) .spawn(); }

-fn get_desktop_env() -> Option<String> { - // Check specifically for Sway first - if env::var("SWAYSOCK").is_ok() || run("pgrep -x sway") { - return Some("SWAY".to_string()); - } - - // Check if Hyprland is running - if run("pgrep -x Hyprland") || env::var("HYPRLAND_INSTANCE_SIGNATURE").is_ok() { - return Some("HYPRLAND".to_string()); - } - - // Check if i3 is running - if run("pgrep -x i3") || env::var("I3SOCK").is_ok() { - return Some("I3".to_string()); - } - - // Check if bspwm is running - if run("pgrep -x bspwm") { - return Some("BSPWM".to_string()); - } - - // Check if qtile is running - if run("pgrep -x qtile") { - return Some("QTILE".to_string()); - } - - // Check environment variables - let keys = [ - "XDG_CURRENT_DESKTOP", - "DESKTOP_SESSION", - "GNOME_DESKTOP_SESSION_ID", - "MATE_DESKTOP_SESSION_ID", - "DESKTOP_STARTUP_ID", - "WAYLAND_DISPLAY", - ]; - - for key in keys.iter() { - if let Ok(val) = env::var(key) { - if !val.is_empty() { - if *key == "DESKTOP_STARTUP_ID" && val.contains("awesome") { - return Some("AWESOME".to_string()); - } - - if *key == "WAYLAND_DISPLAY" { - // Try to identify specific Wayland compositor - if let Ok(desktop) = env::var("XDG_CURRENT_DESKTOP") { - return Some(desktop); - } else { - return Some("WAYLAND".to_string()); - } - } - - return Some(val); +fn detect_de() -> String { + for key in ["XDG_CURRENT_DESKTOP", "DESKTOP_SESSION"] { + if let Ok(v) = env::var(key) { + if !v.is_empty() { + return v.to_lowercase(); } } } - None + String::new() }

-fn set_wm_wallpaper(img: &str, send: bool) { - if run("which xwallpaper") { - spawn(&format!("xwallpaper --zoom '{img}'")); - info("Wallpaper", "wallpaper set with xwallpaper", send); - } else if run("which feh") { - spawn(&format!("feh --no-fehbg --bg-fill '{img}'")); - info("Wallpaper", "wallpaper set with feh", send); - } else if run("which hsetroot") { - spawn(&format!("hsetroot -fill '{img}'")); - info("Wallpaper", "wallpaper set with hsetroot", send); - } else if run("which nitrogen") { - spawn(&format!("nitrogen --set-zoom-fill --save '{img}'")); - info("Wallpaper", "wallpaper set with nitrogen", send); - } else if run("which xsetroot") { - warning( - "Wallpaper", - "using xsetroot, but it does not support images properly", - send, - ); - spawn("xsetroot -solid '#000000'"); - info("Wallpaper", "set solid background with xsetroot", send); - } else { - warning("Wallpaper", "can't find any app to set wallpaper", send); - exit(1) - } +fn is_wayland() -> bool { + env::var("WAYLAND_DISPLAY").is_ok() }

-fn set_desktop_wallpaper(d: &str, img: &str, send: bool) { - let abs_path = get_absolute_path(img).unwrap_or_else(|| { - warning("Wallpaper", "failed to get absolute path", send); - img.to_string() - }); - if d.contains("hyprland") { - // Hyprland-specific wallpaper handling - if run("which swww") { - if !run("pgrep -x swww-daemon") { - spawn("swww-daemon &"); - // Give daemon time to start - std::thread::sleep(std::time::Duration::from_millis(500)); - } - spawn(&format!( - "swww img '{abs_path}' --transition-type fade --transition-fps 60" - )); - info("Wallpaper", "wallpaper set with swww for Hyprland", send); - } else if run("which hyprpaper") { - spawn(&format!("hyprpaper '{abs_path}'")); - info("Wallpaper", "wallpaper set with hyprpaper", send); - } else if run("which swaybg") { - spawn(&format!("pkill swaybg; swaybg -i '{abs_path}' -m fill &")); - info("Wallpaper", "wallpaper set with swaybg for Hyprland", send); - } else if run("which wbg") { - spawn(&format!("pkill wbg; wbg '{abs_path}' &")); - info("Wallpaper", "wallpaper set with wbg for Hyprland", send); - } else { - warning( - "Wallpaper", - "no suitable wallpaper tool found for Hyprland (try installing swww, hyprpaper, swaybg, or wbg)", - send, - ); - exit(1); - } - } else if d.contains("xfce") || d.contains("xubuntu") { - // Try to find the active monitor - let monitors = run_with_output("xfconf-query -c xfce4-desktop -l | grep last-image") - .unwrap_or_default(); - if !monitors.is_empty() { - for line in monitors.lines() { - spawn(&format!( - "xfconf-query --channel xfce4-desktop --property {} --set '{}'", - line.trim(), - abs_path - )); - } - } else { - // Fallback to default monitor - spawn(&format!( - "xfconf-query --channel xfce4-desktop --property /backdrop/screen0/monitor0/workspace0/last-image --set '{abs_path}'" - )); - } - info("Wallpaper", "wallpaper set with XFCE settings", send); - } else if d.contains("gnome") || d.contains("unity") || d.contains("ubuntu") { - // Check for GNOME version for compatibility - if run("gsettings get org.gnome.desktop.background picture-uri-dark") { - // GNOME 42+ with light/dark mode support - spawn(&format!( - "gsettings set org.gnome.desktop.background picture-uri 'file://{abs_path}'" - )); - spawn(&format!( - "gsettings set org.gnome.desktop.background picture-uri-dark 'file://{abs_path}'" - )); - } else { - // Older GNOME versions - spawn(&format!( - "gsettings set org.gnome.desktop.background picture-uri 'file://{abs_path}'" - )); - } - info("Wallpaper", "wallpaper set with GNOME settings", send); - } else if d.contains("mate") { - spawn(&format!( - "gsettings set org.mate.background picture-filename '{abs_path}'" - )); - info("Wallpaper", "wallpaper set with MATE settings", send); - } else if d.contains("cinnamon") { - spawn(&format!( - "gsettings set org.cinnamon.desktop.background picture-uri 'file://{abs_path}'" - )); - info("Wallpaper", "wallpaper set with Cinnamon settings", send); - } else if d.contains("sway") { - if run("which swww") { - if !run("pgrep -x swww-daemon") { - spawn("swww-daemon &"); - std::thread::sleep(std::time::Duration::from_millis(500)); - } - spawn(&format!( - "swww img '{abs_path}' --transition-type fade --transition-fps 60" - )); - info("Wallpaper", "wallpaper set with swww for Sway", send); - } else if run("which swaybg") { - spawn(&format!("pkill swaybg; swaybg -i '{abs_path}' -m fill &")); - info("Wallpaper", "wallpaper set with swaybg for Sway", send); - } else { - warning( - "Wallpaper", - "no suitable wallpaper tool found for Sway (try installing swww or swaybg)", - send, - ); - exit(1) - } - } else if d.contains("awesome") { - spawn(&format!( - "awesome-client &#34;require('gears').wallpaper.maximized('{abs_path}')&#34;" - )); - info("Wallpaper", "wallpaper set with Awesome WM", send); - } else if d.contains("kde") || d.contains("plasma") { - let script = format!( - r#"var allDesktops = desktops();for (i=0;i<allDesktops.length;i++){{d = allDesktops[i];d.wallpaperPlugin = "org.kde.image";d.currentConfigGroup = Array("Wallpaper", "org.kde.image", "General");d.writeConfig("Image", "{abs_path}");}}"# - ); - spawn(&format!( - "qdbus org.kde.plasmashell /PlasmaShell org.kde.PlasmaShell.evaluateScript &#34;{script}&#34;" - )); - info("Wallpaper", "wallpaper set with KDE Plasma settings", send); - } else if d.contains("i3") || d.contains("bspwm") || d.contains("qtile") { - set_wm_wallpaper(&abs_path, send); - } else if d.contains("wayland") { - // Generic Wayland - try multiple approaches - if run("which swww") { - if !run("pgrep -x swww-daemon") { - spawn("swww-daemon &"); - std::thread::sleep(std::time::Duration::from_millis(500)); - } - spawn(&format!("swww img '{abs_path}'")); - info("Wallpaper", "wallpaper set with swww", send); - } else if run("which swaybg") { - spawn(&format!("pkill swaybg; swaybg -i '{abs_path}' -m fill &")); - info("Wallpaper", "wallpaper set with swaybg", send); - } else if run("which wbg") { - spawn(&format!("pkill wbg; wbg '{abs_path}' &")); - info("Wallpaper", "wallpaper set with wbg", send); - } else { - warning( - "Wallpaper", - "no suitable Wayland wallpaper tool found (try installing swww, swaybg, or wbg)", - send, - ); - exit(1); - } - } else if d.contains("wayfire") { - if run("which wbg") { - spawn(&format!("pkill wbg; wbg '{abs_path}' &")); - info("Wallpaper", "wallpaper set with wbg for Wayfire", send); - } else if run("which swaybg") { - spawn(&format!("pkill swaybg; swaybg -i '{abs_path}' -m fill &")); - info("Wallpaper", "wallpaper set with swaybg for Wayfire", send); - } else { - warning( - "Wallpaper", - "no suitable wallpaper tool found for Wayfire (try installing wbg or swaybg)", - send, - ); - exit(1); - } - } else if d.contains("river") { - if run("which wbg") { - spawn(&format!("pkill wbg; wbg '{abs_path}' &")); - info("Wallpaper", "wallpaper set with wbg for River", send); - } else if run("which swaybg") { - spawn(&format!("pkill swaybg; swaybg -i '{abs_path}' -m fill &")); - info("Wallpaper", "wallpaper set with swaybg for River", send); - } else { - warning( - "Wallpaper", - "no suitable wallpaper tool found for River (try installing wbg or swaybg)", - send, - ); - exit(1); - } - } else if d.contains("fht") || d.contains("fht-compositor") { - // fht-compositor support - it's a Wayland compositor - if run("which swaybg") { - spawn(&format!("pkill swaybg; swaybg -i '{abs_path}' -m fill &")); - info( - "Wallpaper", - "wallpaper set with swaybg for fht-compositor", - send, - ); - } else if run("which wbg") { - spawn(&format!("pkill wbg; wbg '{abs_path}' &")); - info( - "Wallpaper", - "wallpaper set with wbg for fht-compositor", - send, - ); - } else if run("which swww") { - if !run("pgrep -x swww-daemon") { - spawn("swww-daemon &"); - std::thread::sleep(std::time::Duration::from_millis(500)); - } - spawn(&format!("swww img '{abs_path}'")); - info( - "Wallpaper", - "wallpaper set with swww for fht-compositor", - send, - ); - } else { - warning( - "Wallpaper", - "no suitable wallpaper tool found for fht-compositor (try installing swaybg, wbg, or swww)", - send, - ); - exit(1); - } - } else if d.contains("deepin") { - spawn(&format!( - "gsettings set com.deepin.wrap.gnome.desktop.background picture-uri 'file://{abs_path}'" - )); - info("Wallpaper", "wallpaper set with Deepin settings", send); - } else if d.contains("lxqt") { - spawn(&format!("pcmanfm-qt --set-wallpaper='{abs_path}'")); - info("Wallpaper", "wallpaper set with LXQt settings", send); - } else if d.contains("lxde") { - spawn(&format!("pcmanfm --set-wallpaper='{abs_path}'")); - info("Wallpaper", "wallpaper set with LXDE settings", send); - } else if d.contains("budgie") { - spawn(&format!( - "gsettings set org.gnome.desktop.background picture-uri 'file://{abs_path}'" - )); - info( - "Wallpaper", - "wallpaper set with Budgie (GNOME) settings", - send, - ); - } else if d.contains("enlightenment") || d.contains("e17") || d.contains("e16") { - if run("which enlightenment_remote") { - spawn(&format!( - "enlightenment_remote -desktop-bg-add 0 0 0 0 '{abs_path}'" - )); - info("Wallpaper", "wallpaper set with Enlightenment", send); - } else { - set_wm_wallpaper(&abs_path, send); +fn de_commands(de: &str, path: &str) -> Option<Vec<String>> { + let map: HashMap<&str, Vec<String>> = HashMap::from([ + ("gnome", vec![ + format!("gsettings set org.gnome.desktop.background picture-uri 'file://{path}'"), + format!("gsettings set org.gnome.desktop.background picture-uri-dark 'file://{path}'"), + ]), + ("unity", vec![format!("gsettings set org.gnome.desktop.background picture-uri 'file://{path}'")]), + ("budgie", vec![format!("gsettings set org.gnome.desktop.background picture-uri 'file://{path}'")]), + ("mate", vec![format!("gsettings set org.mate.background picture-filename '{path}'")]), + ("cinnamon", vec![format!("gsettings set org.cinnamon.desktop.background picture-uri 'file://{path}'")]), + ("deepin", vec![format!("gsettings set com.deepin.wrap.gnome.desktop.background picture-uri 'file://{path}'")]), + ("xfce", vec![format!("xfconf-query --channel xfce4-desktop --property /backdrop/screen0/monitor0/workspace0/last-image --set '{path}'")]), + ("lxqt", vec![format!("pcmanfm-qt --set-wallpaper='{path}'")]), + ("lxde", vec![format!("pcmanfm --set-wallpaper='{path}'")]), + ("kde", vec![format!( + r#"qdbus org.kde.plasmashell /PlasmaShell org.kde.PlasmaShell.evaluateScript "var d=desktops();for(i=0;i<d.length;i++){{d[i].wallpaperPlugin='org.kde.image';d[i].currentConfigGroup=Array('Wallpaper','org.kde.image','General');d[i].writeConfig('Image','{path}');}}""# + )]), + ]); + + for (key, cmds) in &map { + if de.contains(key) { + return Some(cmds.clone()); } + } + None +} + +fn generic_tools(wayland: bool, path: &str) -> Vec<(&'static str, String)> { + if wayland { + vec![ + ("swww", format!("swww-daemon >/dev/null 2>&1 & sleep 0.3; swww img '{path}'")), + ("swaybg", format!("pkill swaybg; swaybg -i '{path}' -m fill &")), + ("hyprpaper", format!("hyprpaper '{path}'")), + ("wbg", format!("pkill wbg; wbg '{path}' &")), + ] } else { - // Default to the generic wallpaper setters - info( - "Wallpaper", - &format!("Unknown desktop environment: {}, trying generic tools", d), - send, - ); - set_wm_wallpaper(&abs_path, send); + vec![ + ("xwallpaper", format!("xwallpaper --zoom '{path}'")), + ("feh", format!("feh --no-fehbg --bg-fill '{path}'")), + ("hsetroot", format!("hsetroot -fill '{path}'")), + ("nitrogen", format!("nitrogen --set-zoom-fill --save '{path}'")), + ] } }

pub fn change_wallpaper(img: &str, send: bool) { if !Path::new(img).is_file() { warning("Wallpaper", "invalid image path", send); - exit(1) + exit(1); }

- match get_desktop_env() { - Some(d) => { - if send { - info( - "Desktop", - &format!("Detected desktop environment: {}", d), - send, - ); - } - set_desktop_wallpaper(&d.to_lowercase(), img, send); + let path = get_absolute_path(img).unwrap_or_else(|| img.to_string()); + let de = detect_de(); + + if let Some(cmds) = de_commands(&de, &path) { + for c in cmds { + spawn(&c); } - None => { - if send { - warning( - "Desktop", - "Could not detect desktop environment, using generic tools", - send, - ); - } - set_wm_wallpaper(img, send); + info("Wallpaper", &format!("wallpaper set for {de}"), send); + return; + } + + for (bin, cmd) in generic_tools(is_wayland(), &path) { + if run(&format!("which {bin}")) { + spawn(&cmd); + info("Wallpaper", &format!("wallpaper set with {bin}"), send); + return; } } + + warning("Wallpaper", "no suitable wallpaper tool found", send); + exit(1); }

// Created by Pi66

// Copyright ©Pi66 2026