Success: compiz wallpapers changed via python script (Ubuntu 14.10 XFCE4)

I started using Linux because it had cool desktop features that made it fun and interesting. The compiz window manager was a highlight, but I stopped using it for a while because I could not make the dbus commands work to change the background after version 0.9 or so. I don't enjoy Unity, but do like XFCE4, and have been using the Openbox window manager.

Openbox is OK, but it lacks flavor. No wobbly windows, not garish animations that we love so much.

Recently, on Ubuntu 14.10, using XFCE4 as the main desktop environment, I had some time and decided to re-investigate ways to run Compiz. Most things are working well now, especially since I have this swell new script
to change wallpapers. There are some verbose comments at the beginning.

A key benefit of this approach is it handles a lot of book keeping, so the script can eliminate the entire wallpaper vector and replace with one image, or it can replace a single image within the wallpaper vector, or it can grow the vector. I'll paste in an example session after the code.

If you want to know how to get Compiz going without the Unity Desktop,
this is not a bad set of advice
http://www.webupd8.org/2012/11/how-to-set-up-compiz-in-xubuntu-1210-or.html

Caution: Do follow the advice to run ccsm before starting Compiz, and DO
enable the plugins. TURN ON wallpapers.

Caution: In the separate ccsm preferences dialogue (bottom left, above "advanced search"), make sure you choose the Gsettings backend and do allow the interaction with the desktop environment.

Caution: If you have Unity installed, it is necessary to remove it, or else
launching compiz with the Gsettings back end gets Ubuntu all confused and
Unity keeps starting at same time. If you have trouble with that, I can help

#!/usr/bin/env python3

## Paul E. Johnson 
## 20150102

## A script to randomly reassign compiz background images for viewports.
## Recall compiz after 0.9.2 uses "viewports" to simulate workspaces.

## Will choose an image file randomly from within dir hierarchy. 

## Can replace one viewport's wallpaper.  The w argument will be
## interpreted in one of 3 ways 
## 
## 1. If w < 1, (either 0 or a negative number), this means remove all
## existing wallpapers and replace with one randomly chosen image.
##
## 2. If 1 <= w <= N (where there are N wallpaper images already
## defined), then the image on viewport w will be replaced. All of the
## other images will remain the same.
##
## 3. If N < w, we interpret this as a request to expand the
## wallpaper array by one.


## I thought it was a little interesting to make types 1 and 3
## work together with compiz. To change the number of wallpapers,
## it is required to correctly change these variables in the
## wallpaper plugin as well:
## "bg-fill-type"
## "bg-image-pos"
## "bg-color1", 
## "bg-color2", s

## I had previously been doing this by dbus-send, but compiz's
## interaction with dbus has become less and less stable, so this version
## uses "gsettings".

## About the schema argument:
## Because I do not use Unity as my desktop environment, I have to point
## SCHEMA at the location where compiz stores wallpapers. If you get
## compiz working with XFCE4, for example, make sure you use the Gsettings
## backend and DO allow Compiz to interact with the desktop environment in
## advanced settings. 

## If you are using Unity, you probably need to change the path, removing
## "Default" with "unity".  You can do from command line or by editing script.



import argparse
import subprocess
import sys
import os
import random

parser = argparse.ArgumentParser()
parser.add_argument("-d", "--dir",  help = "directory path", 
                    default = "/usr/local/share/Backgrounds")
parser.add_argument("-w", "--workspace", 
                    help = "workspace number, 0, 1-n, or > n", default = "-1", 
                    type = int)
parser.add_argument("-schema", help = "gsettings shema", 
                    metavar = "SCHEMA", default = "org.compiz.wallpaper:/org/compiz/profiles/Default/plugins/wallpaper/")
parser.add_argument("-key", help = "gsettings key", metavar = "KEY", default = "bg-image")
args = parser.parse_args()

array = eval(subprocess.check_output(["gsettings", "get", args.schema, args.key]))

## print(array)
arraylen = len(array)

filename = random.choice([os.path.join(dp, f) for dp, dn, fn in os.walk(os.path.expanduser(args.dir)) for f in fn])
print("The newly found filename is:")
print(filename)

## print("Array length was")
## print(arraylen)

## python arrays index 0, ... , N-1, so downshift workspace number
ws = args.workspace - 1

## If ws 0 or smaller, we are going to reset whole collection back to
## just one image. if ws > N of images, then add a new image.
if ws < 0:
    array=[str(filename)]
    subprocess.call(["gsettings", "set", args.schema, args.key, str(array)])
    subprocess.call(["gsettings", "set", args.schema, "bg-fill-type", str("[0]")])
    subprocess.call(["gsettings", "set", args.schema, "bg-image-pos", str("[0]")])
    subprocess.call(["gsettings", "set", args.schema, "bg-color1", str("['#000000ff']")])
    subprocess.call(["gsettings", "set", args.schema, "bg-color2", str("['#000000ff']")])
elif ws < arraylen:
    array[ws]=str(filename)
    subprocess.call(["gsettings", "set", args.schema, args.key, str(array)])
else:
    array.append(str(filename))
    subprocess.call(["gsettings", "set", args.schema, args.key, str(array)])
    arraylen = len(array)
    subprocess.call(["gsettings", "set", args.schema, "bg-fill-type", str([0]*arraylen)])
    subprocess.call(["gsettings", "set", args.schema, "bg-image-pos", str([0]*arraylen)])
    subprocess.call(["gsettings", "set", args.schema, "bg-color1", str(['#000000ff']*arraylen)])
    subprocess.call(["gsettings", "set", args.schema, "bg-color2", str(['#000000ff']*arraylen)])



subprocess.call(["gsettings", "set", args.schema, args.key, str(array)])

print("HELLO, corrected image array is:")               
print('\n '.join(array))

I've got a massive background image collection, I think you'll get the idea

First, I'll give a negative value for w, so all existing wallpapers will be replaced by one:

$ ./pjbg.py -w -1 -d /usr/local/share/Backgrounds
The newly found filename is:
/usr/local/share/Backgrounds/Water/DOT_Arizona_VII_Grand_Canyon_Clear_Creek_6.jpg
HELLO, corrected image array is:
/usr/local/share/Backgrounds/Water/DOT_Arizona_VII_Grand_Canyon_Clear_Creek_6.jpg

Second, lets grow some more wallpapers

$ ./pjbg.py -w 5 -d /usr/local/share/Backgrounds
The newly found filename is:
/usr/local/share/Backgrounds/Scenery/Village_in_Alta_Roca_Region_Corsica_France.jpg
HELLO, corrected image array is:
/usr/local/share/Backgrounds/Water/DOT_Arizona_VII_Grand_Canyon_Clear_Creek_6.jpg
 /usr/local/share/Backgrounds/Scenery/Village_in_Alta_Roca_Region_Corsica_France.jpg

$ ./pjbg.py -w 5 -d /usr/local/share/Backgrounds
The newly found filename is:
/usr/local/share/Backgrounds/Scenery/dot_peru_machu_picchu_7.jpg
HELLO, corrected image array is:
/usr/local/share/Backgrounds/Water/DOT_Arizona_VII_Grand_Canyon_Clear_Creek_6.jpg
 /usr/local/share/Backgrounds/Scenery/Village_in_Alta_Roca_Region_Corsica_France.jpg
 /usr/local/share/Backgrounds/Scenery/dot_peru_machu_picchu_7.jpg

$ ./pjbg.py -w 5 -d /usr/local/share/Backgrounds
The newly found filename is:
/usr/local/share/Backgrounds/Italy/DOT_Italy_XIII_Venice_086.jpg
HELLO, corrected image array is:
/usr/local/share/Backgrounds/Water/DOT_Arizona_VII_Grand_Canyon_Clear_Creek_6.jpg
 /usr/local/share/Backgrounds/Scenery/Village_in_Alta_Roca_Region_Corsica_France.jpg
 /usr/local/share/Backgrounds/Scenery/dot_peru_machu_picchu_7.jpg
 /usr/local/share/Backgrounds/Italy/DOT_Italy_XIII_Venice_086.jpg

$ ./pjbg.py -w 5 -d /usr/local/share/Backgrounds
The newly found filename is:
/usr/local/share/Backgrounds/Scenery/DOT_Colorado_IV_009_Mesa_Verde_National_Park.jpg
HELLO, corrected image array is:
/usr/local/share/Backgrounds/Water/DOT_Arizona_VII_Grand_Canyon_Clear_Creek_6.jpg
 /usr/local/share/Backgrounds/Scenery/Village_in_Alta_Roca_Region_Corsica_France.jpg
 /usr/local/share/Backgrounds/Scenery/dot_peru_machu_picchu_7.jpg
 /usr/local/share/Backgrounds/Italy/DOT_Italy_XIII_Venice_086.jpg
 /usr/local/share/Backgrounds/Scenery/DOT_Colorado_IV_009_Mesa_Verde_National_Park.jpg

After that, I have 5 wallpaper images stored. So when I run the same command again, the
program no longer adds a new element, but it instead replaces workspace 5.

$ ./pjbg.py -w 5 -d /usr/local/share/Backgrounds
The newly found filename is:
/usr/local/share/Backgrounds/Scenery/Sozaijiten_085-Mountains-091_dbg.jpg
HELLO, corrected image array is:
/usr/local/share/Backgrounds/Water/DOT_Arizona_VII_Grand_Canyon_Clear_Creek_6.jpg
 /usr/local/share/Backgrounds/Scenery/Village_in_Alta_Roca_Region_Corsica_France.jpg
 /usr/local/share/Backgrounds/Scenery/dot_peru_machu_picchu_7.jpg
 /usr/local/share/Backgrounds/Italy/DOT_Italy_XIII_Venice_086.jpg
 /usr/local/share/Backgrounds/Scenery/Sozaijiten_085-Mountains-091_dbg.jpg

$ ./pjbg.py -w 5 -d /usr/local/share/Backgrounds
The newly found filename is:
/usr/local/share/Backgrounds/dot_greece_ix_cape_sounion_poseidon_temple_3.jpg
HELLO, corrected image array is:
/usr/local/share/Backgrounds/Water/DOT_Arizona_VII_Grand_Canyon_Clear_Creek_6.jpg
 /usr/local/share/Backgrounds/Scenery/Village_in_Alta_Roca_Region_Corsica_France.jpg
 /usr/local/share/Backgrounds/Scenery/dot_peru_machu_picchu_7.jpg
 /usr/local/share/Backgrounds/Italy/DOT_Italy_XIII_Venice_086.jpg
 /usr/local/share/Backgrounds/dot_greece_ix_cape_sounion_poseidon_temple_3.jpg

You can monitor the effect of this in 2 ways.

1. Run "ccsm", look in the Wallpapers plugin
2. Run "dconf-editor", look under org.... to see the settings change.

After all of that, you end up with a vector of viewports

About pauljohn

Paul E. Johnson is a Professor of Political Science at the University of Kansas. He is an avid Linux User, an adequate system administrator and C programmer, and humility is one of his greatest strengths.
This entry was posted in Linux and tagged , , . Bookmark the permalink.

Leave a Reply