4

Is there any way to have a different background for each workspace without using CCSM? I've read a few horror stories and would rather avoid it if possible. I'm using Raring Ringtail (13.04)

3
  • @cipricus Do you have a fixed number of workspaces or should the solution handle a variable number of workspaces? Unity or Xubuntu? (both can be done). Dec 12, 2014 at 17:08
  • @JacobVlijm: personally I need 2, but 4 would be what many prefer I think. Unity is the assumed environment if not specified otherwise. Give an answer as large as possible and I will give you even a bigger bounty if the case. But mind that its without CCSM for the reason mentioned in the question: so, the alternative shouldn't be as risky as that.
    – user47206
    Dec 12, 2014 at 19:37
  • @JacobVlijm - see why without CCSM; I would prefer an answer that would not be too complicated. The question is 'simple'. :)
    – user47206
    Dec 12, 2014 at 20:10

1 Answer 1

5
+50

Having different wallpapers on different workspaces without using ccsm

The script below does not use compiz settings manager, but it assumes:

  • python3 is installed (if not let me know)
  • wmctrl is installed (to fetch the data on the workspaces). You might need to install it: sudo apt-get install wmctrl

It works no matter the number of workspaces; it calculates the number of columns of the workspaces and the row of the current workspace, and sets the user defined wallpaper for that (current) workspace.
After the script is started, just switch to the different workspaces and set the wallpaper in the "normal" (GUI) way. The script keeps track of the wallpaper(s) per workspace in a small file it creates. That should not cause any lag in performance, since the file is only read when the script initiates, or when the wallpapers per workspace are changed by the user.

enter image description here

The script

#!/usr/bin/env python3

import subprocess
import time
import os

key1 = "gsettings set org.gnome.desktop.background picture-uri "
key2 = "gsettings get org.gnome.desktop.background picture-uri"

def write_wspaces(file, current):
    with open(file, "wt") as wt:
        wt.write(current)

def read_wspaces(file):
    with open(file) as src:
        return src.read().strip()

def get_info(command):
    return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

def get_currwallpaper():
    return get_info(key2).replace("file://", "").strip()

# get resolution
output = get_info("xrandr").split(); idf = output.index("current")
res = (int(output[idf+1]), int(output[idf+3].replace(",", "")))

def calculate_geometry():
    # get viewport data
    vp = get_info("wmctrl -d").split(" ")
    span = vp[4].split("x"), vp[7].split(",")
    # calculate number of (horizontal) viewports
    n_vps_hor = int(int(span[0][0])/int(res[0]))
    n_vps_vert = int(int(span[0][2])/int(res[1]))
    n_wspaces = int(n_vps_hor)*int(n_vps_vert)
    # calculate current viewport
    curr_vp_hor = int((int(span[1][0])/int(res[0]))+1)
    curr_vp_vert = int((int(span[1][3])/int(res[1]))+1)
    return ((curr_vp_vert-1)*n_vps_hor)+curr_vp_hor, n_wspaces

home = os.environ["HOME"]
wspaces = home+"/"+".config/wall_wspaces"
if not os.path.exists(wspaces):
    os.makedirs(wspaces)
if not os.path.exists(wspaces+"/wspaces.txt"):
    current = get_currwallpaper().replace("'", "")
    writelist = []; [writelist.append(current) for i in range(calculate_geometry()[1])]
    write_wspaces(wspaces+"/wspaces.txt", str(writelist))
wall_list = eval(read_wspaces(wspaces+"/wspaces.txt"))

while True:
    curr_vp1 = calculate_geometry()[0]; currwallpaper1 = get_currwallpaper()
    time.sleep(2)
    curr_vp2 = calculate_geometry()[0]; currwallpaper2 = get_currwallpaper()
    if curr_vp1 != curr_vp2:
        command = key1+"file://"+str(wall_list[curr_vp2-1])
        subprocess.Popen(["/bin/bash", "-c", command])
    elif currwallpaper1 != currwallpaper2:
        wall_list = eval(read_wspaces(wspaces+"/wspaces.txt"))
        wall_list[int(curr_vp2)-1] = currwallpaper2
        write_wspaces(wspaces+"/wspaces.txt", str(wall_list))
    else:
        pass

How to use

Simply copy the script into an empty file, save it as workspace_walls.py and run it by the command:

python3 /path/to/workspace_walls.py

If it works as you like it to, add it to your startup applications: Dash > Startup Applications > Add


Edit:

Below a completely rewritten version of the script, to the model of this one.

The script (with a few minor differences) + GUI is also available as ppa:

enter image description here

sudo add-apt-repository ppa:vlijm/wswitcher
sudo apt-get update
sudo apt-get install wswitcher
#!/usr/bin/env python3
import subprocess    
import os
import time

workspace_data = os.environ["HOME"]+"/.wallpaper_data_"
key = [
    "gsettings get ",
    "gsettings set ",
    "org.gnome.desktop.background picture-uri",
    ]

def getwall():
    return subprocess.check_output(
        ["/bin/bash", "-c", key[0]+key[2]]
        ).decode("utf-8").strip()

def get_res():
    # get resolution
    xr = subprocess.check_output(["xrandr"]).decode("utf-8").split()
    pos = xr.index("current")
    return [int(xr[pos+1]), int(xr[pos+3].replace(",", "") )]

def current():
    # get the current viewport
    res = get_res()
    vp_data = subprocess.check_output(
        ["wmctrl", "-d"]
        ).decode("utf-8").split()
    dt = [int(n) for n in vp_data[3].split("x")]
    cols = int(dt[0]/res[0])
    curr_vpdata = [int(n) for n in vp_data[5].split(",")]
    curr_col = int(curr_vpdata[0]/res[0])+1
    curr_row = int(curr_vpdata[1]/res[1])
    return str(curr_col+curr_row*cols)

curr_ws1 = current()
currwall1 = getwall()

while True:
    time.sleep(1)
    currwall2 = getwall()
    # print(currwall2)
    curr_ws2 = current()
    datafile = workspace_data+curr_ws2
    if curr_ws2 == curr_ws1:
        if currwall2 != currwall1:
            open(datafile, "wt").write(currwall2)
    else:
        if not os.path.exists(datafile):
            open(datafile, "wt").write(currwall2)
        else:
            curr_set = open(datafile).read()
            command = key[1]+key[2]+' "'+str(curr_set)+'"'
            subprocess.Popen(["/bin/bash", "-c", command])
    curr_ws1 = curr_ws2
    currwall1 = getwall()

Budgie now supported

Added support for Budgie on July 21, 2017 for Zesty, when installed from the ppa (see above)

enter image description here

9
  • I have run it with 2 and 4 workspaces and I think it works as intended. only that what it does is that it changes the wallpaper each time when I click/select a workspace to the WP designated by the script to that WS, which leads to that typical lag normal when a wallpaper is set for the first time.. that is, all WS have the same WP, namely the one that is set by the script to the last selected WS, until a new WS is selected.when I use hotcorner to show WS they all have the same WP, which is changed (for all) when I select a new WS.
    – user47206
    Dec 12, 2014 at 22:38
  • 1
    @cipricus that is true, I am not sure if the ccsm version is different? (never used that) Dec 12, 2014 at 22:39
  • we'll see about that. maybe i will give ccsm a try although i have avoided touching that thing till now :) the bounty needs 16 hours to be granted. that lag is a problem especially with conky, the transition is not smooth
    – user47206
    Dec 12, 2014 at 22:43
  • ccsm is a nasty piece!! unity crashed and all that! conky, plank, logout, all wrong
    – user47206
    Dec 12, 2014 at 23:03
  • 1
    @cipricus simplified use of the script; simply run it and set wallpapers via GUI per workspace as usual (no more list editing in the script) Dec 13, 2014 at 13:23

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .