Search code examples
javalinuxgnomewallpaperkde-plasma

Is there a universal way to set a wallpaper on Linux?


I am building a program that periodically changes your wallpaper with one taken from reddit. It currently supports windows, but I would like it to work also on Linux. The program is developed in Java.

The problem is that each DE has its unique way of changing a wallpaper: XFCE, Cinnamon, GNOME etc.

I wanted to find a simple universal way to do this. This is my code so far (it uses the XFCE solution because my machine runs on XFCE):

public static void setWallpaper(String wallpaperPath) { 
    String s = "xfconf-query -c xfce4-desktop -p /backdrop/screen0/monitorVGA-1/workspace0/last-image -s \"" + wallpaperPath + "\"";
    ProcessBuilder processBuilder = new ProcessBuilder().command("bash", "-c", s);
    Process process = processBuilder.start();
}

I already tried with xwallpaper but it just doesn't work, no change, no output, no error.


Solution

  • This is the best solution i found, but I bet it could be improved. I scan $XDG_CURRENT_DESKTOP first and then $GDM_SESSION (apparently the xdg doesn't always existas an environment variable). Then I act based on what environment I found and set the wallpaper.

    public static void main(String[] args) {
            String wpPath = "/path/to/file";
            String os = System.getProperty("os.name");
            switch (os) {
                case "Windows 10":
                    System.out.println("WINODWS DETECTED");
                    break;
                case "Linux":
                    String de = identifyDE();
                    if (de == null) {
                        System.out.println("Couldn't identify your Desktop Environment"); // log Severe
                        break;
                    }
    
                    switch (de) {
                        case "xfce":
                            executeProcess("xfconf-query -c xfce4-desktop -p /backdrop/screen0/monitorVGA-1/workspace0/last-image -s \"" + wpPath + "\"");
                            break;
                        case "gnome":
                            executeProcess("gsettings set org.gnome.desktop.background draw-background false && gsettings set org.gnome.desktop.background picture-uri \"file://" + wpPath + "\" && gsettings set org.gnome.desktop.background draw-background true");
                            break;
                        case "kde":
                            executeProcess("qdbus org.kde.plasmashell /PlasmaShell org.kde.PlasmaShell.evaluateScript 'var allDesktops = desktops();print (allDesktops);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\", \"" + wpPath + "\")}'");
                            break;
                        case "unity":
                            executeProcess("gsettings set org.gnome.desktop.background picture-uri \"file://" + wpPath + "\"");
                            break;
                        case "cinnamon":
                            executeProcess("gsettings set org.cinnamon.desktop.background picture-uri  \"file://" + wpPath + "\"");
                            break;
                        default:
                            System.out.println("Can't recognize DE: " + de);
                    }
    
    
                    break;
                default:
                    System.out.println("Can't recognize OS: " + os);
            }
        }
    
    public static String identifyDE() {
            String de;
            de = System.getenv("XDG_CURRENT_DESKTOP").toLowerCase();
    
            if (de.contains("xfce")) {
                return "xfce";
            } else if (de.contains("kde")) {
                return "kde";
            } else if (de.contains("unity")) {
                return "unity";
            } else if (de.contains("gnome")) {
                return "gnome";
            } else if (de.contains("cinnamon")) {
                return "cinnamon";
            } else if (de.contains("mate")) {
                return "mate";
            } else if (de.contains("deepin")) {
                return "deepin";
            } else if (de.contains("budgie")) {
                return "budgie";
            } else if (de.contains("lxqt")) {
                return "lxqt";
            } else {
                System.out.println("Not identifiable with: echo $XDG_CURRENT_DESKTOP: " + de);
            }
    
            de = System.getenv("GDM_SESSION").toLowerCase();
    
            if (de.contains("xfce")) {
                return "xfce";
            } else if (de.contains("kde")) {
                return "kde";
            } else if (de.contains("unity")) {
                return "unity";
            } else if (de.contains("gnome")) {
                return "gnome";
            } else if (de.contains("cinnamon")) {
                return "cinnamon";
            }  else if (de.contains("mate")) {
                return "mate";
            } else if (de.contains("deepin")) {
                return "deepin";
            } else if (de.contains("budgie")) {
                return "budgie";
            } else if (de.contains("lxqt")) {
                return "lxqt";
            } else {
                System.out.println("Not identifiable with: echo $GDM_SESSION: " + de);
            }
    
            return null;
        }
    
    public static String executeProcess(String s) {
            ProcessBuilder pb = new ProcessBuilder("bash", "-c", s);
            pb.redirectErrorStream(true);
            Process p = null;
            try {
                p = pb.start();
            } catch (IOException e) {
                e.printStackTrace();
            }
            BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
    
            StringBuilder res = new StringBuilder();
            String line;
    
            try {
                while ((line = reader.readLine()) != null) {
                    res.append(line);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
    
    
            return res.toString();
        }
    

    This piece of code does need further testing as for now it has been tested only on manjaro XFCE and manjaro KDE, I'm not even sure about some of the names (deepin's XDG_CURRENT_DESKTOP contains "deepin" or "dde"?). However I think it's a good solution (or a backbone for one) so I'm posting this anyway.

    Sources: