Skip to content

Instantly share code, notes, and snippets.

@Kyuuhachi
Created December 11, 2016 00:28
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Kyuuhachi/f74e149403e5c1f92006158f09108a78 to your computer and use it in GitHub Desktop.
Save Kyuuhachi/f74e149403e5c1f92006158f09108a78 to your computer and use it in GitHub Desktop.
i3 per-workspace background for /u/Ghostotw
#!/usr/bin/env python3
import Xlib.threaded
import Xlib
import Xlib.display
from Xlib import Xatom
from PIL import Image
import os.path
from collections import defaultdict
try:
import i3ipc.i3ipc as i3ipc
except ImportError:
import i3ipc
backgrounds = defaultdict(lambda: "#FFFFFF", {
"6": "#FF00FF",
"7": "~/Desktop/img.jpg",
})
i3ipc.WorkspaceEvent = lambda data, conn: data
i3ipc.GenericEvent = lambda data: data
i3ipc.WindowEvent = lambda data, conn: data
i3ipc.BarconfigUpdateEvent = lambda data: data
i3ipc.BindingEvent = lambda data: data
i3ipc.Con = lambda data, parent, conn: data
i3 = i3ipc.Connection()
background_cache = {}
def change_workspace(name):
display = Xlib.display.Display()
screen = display.screen()
root = screen.root
w, h = screen.width_in_pixels, screen.height_in_pixels
if (name, w, h) not in background_cache:
background_cache[name, w, h] = gen_bg(root.create_pixmap(w, h, screen.root_depth), name)
id = background_cache[name, w, h].id
root.change_property(display.get_atom("_XROOTPMAP_ID"), Xatom.PIXMAP, 32, [id])
root.change_property(display.get_atom("ESETROOT_PMAP_ID"), Xatom.PIXMAP, 32, [id])
root.change_attributes(background_pixmap=id)
display.sync()
def gen_bg(pixmap, name):
geom = pixmap.get_geometry()
w, h = geom.width, geom.height
paint = pixmap.create_gc()
bg = backgrounds[name]
if bg[:1] == '#':
paint.change(foreground=int(bg[1:], 16))
pixmap.fill_rectangle(paint, 0, 0, w, h)
else:
im = Image.open(os.path.expanduser(bg))
im.thumbnail((w, h), Image.ANTIALIAS)
pixmap.put_pil_image(paint, 0, 0, im)
return pixmap
for output in i3.get_outputs():
if output["current_workspace"]:
change_workspace(output["current_workspace"])
def workspace_event(i3, evt):
if evt["change"] != "focus":
return
change_workspace(evt["current"]["name"])
i3.on("workspace", workspace_event)
i3.subscriptions = 0xFF
i3.main()
@glubsy
Copy link

glubsy commented Mar 12, 2018

In order to fix the tostring() method being deprecated in Pillow:

Image.Image.tostring = Image.Image.tobytes

In order to have the pixmap drawn correctly on root window, we need to refresh it:

root.clear_area()

In order to have wallpaper which dimensions are smaller than our scree, we need to resize it:

		im = Image.open(os.path.expanduser(bg))
		size = im.size
		if size[0] != w or size[1] != h:
			im = im.resize((w, h), Image.LANCZOS)
		try:
			pixmap.put_pil_image(paint, 0, 0, im)
		except Exception as e:
			print("Xlib error in drawable.put_pil_image():", e)

Here's a revision of this script, which works currently: https://gist.github.com/glubsy/706317543bf793d74f79c079a440552d

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment