Ubuntu – How to get a different Unity Launcher with different icons on each workspace

iconslauncherunityviewportsworkspaces

I read through the various answers to having separate desktop folders in each Workspace using Screenlets, devilspie, or CCSM … but that's not the answer to my question. I installed 14.04 LTS a few days ago and have had good success getting most of my apps and some new ones to run. What I would like is to have 4 separate workspaces, each with some different icons for the environments I run.
For example,

  • Workspace 1 – dedicated to science and math apps
  • Workspace 2 – dedicated to music tools
  • Workspace 3 – for electronic circuits and simulations
  • Workspace 4 – for web browsing and general computing

Think of an Android tablet where each screen can contain separate icons.

It must be obvious how to do this, but I can't find an answer. I am 4 days old on Ubuntu, so please don't assume I know what I'm doing!

Best Answer

Setting a different Unity Launcher per workspace:


1. enter image description here 2. enter image description here 3. enter image description here 4. enter image description here

The solution below makes it easily possible to have a different set of launcher icons per workspace, no matter how many workspaces you have.

The setup includes two parts:

  1. A (one) shortcut key combination to "remember" the set of launcher icons for the current workspace.

  2. A script to run in the background, keeping track of what is the current workspace and setting the corresponding Unity Launcher. It acts whenever the user switches workspace.

How it works

Two small scripts are involved:

The first script does one simple thing: it writes the contents of the current launcher into a (hidden) file in your home directory, named (numbered) after your current workspace.

The second script keeps an eye on what is the current workspace. If there is a workspace change, the script sees if a corresponding (launcher-) datafile exists (created by the first script). If so, it reads the file and alters the Unity Launcher, as remembered in the file.

That's it.

How to set up

  1. The script needs wmctrl to be installed:

    sudo apt-get install wmctrl
    
  2. Create a directory in which both scripts will be stored. It is importants that both scripts are kept together in one directory, since they share functionality and one imports from the other. For the same reason, it is important that you name them exactly as indicated below.

  3. Copy each of the scripts below into a (different) empty file, save them into the directory (created in 2.), exactly named as:

    set_workspace.py

    #!/usr/bin/env python3
    import subprocess    
    import os
    
    workspace_data = os.environ["HOME"]+"/.launcher_data_"
    key = ["gsettings get ", "gsettings set ", "com.canonical.Unity.Launcher favorites"]
    
    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)
    
    def remember_current():  
        currlauncher = subprocess.check_output(["/bin/bash", "-c", key[0]+key[2]]).decode("utf-8").strip()
        f = workspace_data+current()
        open(f, "w").write(currlauncher)
    
    if __name__ == "__main__":
        remember_current()
    

    launcher_perworkspace.py

    #!/usr/bin/env python3
    import subprocess
    import set_workspace
    import time
    
    workspace_data = set_workspace.workspace_data
    key = set_workspace.key
    
    def check_datafile(desktop):
        f = workspace_data+str(desktop)
        try:
            new_launcher = open(f).read()
            command = key[1]+key[2]+' "'+str(new_launcher)+'"'
            subprocess.Popen(["/bin/bash", "-c", command])
        except FileNotFoundError:
            pass
    
    curr_dt1 = set_workspace.current()
    check_datafile(curr_dt1)
    
    while True:
        time.sleep(1)
        curr_dt2 = set_workspace.current()
        if curr_dt2 != curr_dt1:
            check_datafile(curr_dt2)
        curr_dt1 = curr_dt2
    
  4. Add the first script (set_workspace.py) to a shortcut key combination of your choice: System Settings > "Keyboard" > "Shortcuts" > "Custom Shortcuts". Click the "+" and add the command:

    python3 /path/to/set_workspace.py
    
  5. Run the key combination and see if a file, like: .launcher_data_3 is created in your home directory. You will probably need to press Ctrl+H to make the file visible (files, starting with a . are invisible by default).

    Navigate through your workspaces and repeat the procedure: set a combination of launcher icons, and press your key combination to "remember" the set for that specific workspace.

  6. You're practically done now. Test-run the background script with the command (from a terminal window, keep it running):

    python3 /path/to/launcher_perworkspace.py
    

    If all works fine, and your launcher switches per workspace, add the following command to your Startup applications: Dash > Startup Applications > Add:

    /bin/bash -c "sleep 15&&python3 /path/to/launcher_perworkspace.py"
    

Notes

  1. If you want to alter the set of launcher icons for a specific workspace, simply navigate to the workspace, add/remove icons as you like and press your key combinbation (no need to restart the background script).
  2. From the comment(s) I get the feeling there is some misunderstanding on the shortcut to remember the current Launcher for the current workspace. You only need one keyboard shortcut to "save" the current launcher for the current workspace. It will work exactly the same, no matter what workspace you are on. The script itself will determine what is the current workspace.

Edit

From your comment, I understand that you are unsure to run the script(s) and you are afraid you will mess up your current launcher.

I am pretty sure that is too much (or too little :)) respect for what the script is doing. However, you can simply backup yor current Unity Launcher with the command:

printf 'gsettings set com.canonical.Unity.Launcher favorites "' > ~/launcher_output&&printf "$(gsettings get com.canonical.Unity.Launcher favorites)">>~/launcher_output&&printf '"'>>~/launcher_output

This will create a file ~/launcher_output, containing the complete command to restore your Unity Launcher to the initial situation. In case of emergency, simply copy the file's content and paste it in the terminal.

But again, it is really unlikely you will mess up your launcher, unless you change the script manually.


IMPORTANT EDIT (2)

As requested in a comment, hereby a version that runs without having to use any shortcut combination; just run the script and start setting up your launchers on the specific workspaces. The script will create (invisible) files in your home directory, to remember your set of (Unity-) launchers on the different workspaces.

I tried this in "version 1" of the script, but always "embedding" the two launcher-checks between two workspace-checks turned out to be the trick to prevent unwanted behaviour (saving incorrect data) when moving quickly through the workspaces.

How to use

  1. Like the first version, this script uses wmctrl:

    sudo apt-get install wmctrl

  2. Copy the script into an empty file, save it as launcher_toworkspace.py

  3. Run it with the command:

    python3 /path/to/launcher_toworkspace.py
    
  4. If it works as expected, add the following command to your Startup Applications:

    /bin/bash -c "sleep 15&&python3 /path/to/launcher_toworkspace.py"
    

The script

#!/usr/bin/env python3
import subprocess    
import os
import time

datadir = os.environ["HOME"]+"/.config/lswitcher"
if not os.path.exists(datadir):
    os.makedirs(datadir)
workspace_data = datadir+"/launcher_data_"

key = [
    "gsettings get ",
    "gsettings set ",
    "com.canonical.Unity.Launcher favorites",
    ]

def get_launcher():
    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()
currlauncher1 = get_launcher()

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

Note

If you set up your workspaces with the previous version of the script, they should also work for this version.

PPA

As per 2015-04-23, the nice question of Dennis J, and the encouragement of Parto, have lead to creating a ppa for the script, covered on webupd8, including a GUI to manage it.

ppa:vlijm/lswitcher

To install it, run:

sudo add-apt-repository ppa:vlijm/lswitcher
sudo apt-get update
sudo apt-get install lswitcher

enter image description here

Since now, it is packaged for Trusty & Utopic. I will add others after testing. I will also add a .deb installer, but I'd suggest using the ppa, since usually this kind of things is updated every now and then.

Since the location of the viewport data has changed from ~/ to ~/.config/lswitcher, you'll have to set up your Unity Launcher again if you used the previous script.

Related Question