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)

Jacob Vlijm
  • 83,767
user165340
  • 41
  • 2
  • @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). – Jacob Vlijm Dec 12 '14 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. –  Dec 12 '14 at 19:37
  • @JacobVlijm - see why without CCSM; I would prefer an answer that would not be too complicated. The question is 'simple'. :) –  Dec 12 '14 at 20:10

1 Answers1

5

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

Jacob Vlijm
  • 83,767
  • 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. –  Dec 12 '14 at 22:38
  • 1
    @cipricus that is true, I am not sure if the ccsm version is different? (never used that) – Jacob Vlijm Dec 12 '14 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 –  Dec 12 '14 at 22:43
  • ccsm is a nasty piece!! unity crashed and all that! conky, plank, logout, all wrong –  Dec 12 '14 at 23:03
  • I have removed ccsm, too buggy, but from what I was able to see it can put different wallpapers for every workspace that do not have to be changed when the WS is selected. but it does not work ok with conky, also it messed up at the same time multiple programs, unity crashed, the upper panel etc. not usable –  Dec 12 '14 at 23:32
  • 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) – Jacob Vlijm Dec 13 '14 at 13:23
  • @Tim That's true!! I found it on your site if I remember well :) – Jacob Vlijm May 09 '15 at 11:47
  • @Tim not sure, I found it clicking around, but it's quite a while ago... – Jacob Vlijm May 09 '15 at 11:50
  • You never cease to amaze me Jacob. Nice job. – Parto May 10 '15 at 21:24