Skip to content

Instantly share code, notes, and snippets.

@glubsy
Last active February 25, 2022 18:56
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save glubsy/706317543bf793d74f79c079a440552d to your computer and use it in GitHub Desktop.
Save glubsy/706317543bf793d74f79c079a440552d to your computer and use it in GitHub Desktop.
Improvements on u/caagr98's i3bg.py script for workspace-specific wallpapers
#!/usr/bin/env python3
#i3 per-workspace background for Caagr98 https://gist.github.com/Caagr98/f74e149403e5c1f92006158f09108a78
#deps: pip3 install python3-xlib i3ipc Pillow
# usage: i3bg2.py /path/to/directory
# where directory holds wallpapers to randomly pick from (optional)
import Xlib.threaded
import Xlib
import Xlib.display
from Xlib import Xatom
from PIL import Image
import sys
import os.path
import random
from collections import defaultdict
try:
import i3ipc.i3ipc as i3ipc
except ImportError:
import i3ipc
Image.Image.tostring = Image.Image.tobytes
if len(sys.argv) > 1:
picture_path = sys.argv[1]
else:
picture_path = ""
wallpaper_files = {}
#TODO: get workspaces with loaded_config_file_name() parsing the config?
workspace = {
"1": "1: ",
"2": "2: ",
"3": "3: ",
"4": "4: ",
"5": "5: ",
"6": "6: ",
"7": "7: ",
"8": "8: ",
"9": "9: ♪",
"10": "10: "
}
if os.path.isdir(picture_path):
for x in range(1,11):
wallpaper_files[workspace[str(x)]] = picture_path + os.sep + random.choice([x for x in os.listdir(os.path.expanduser(picture_path)) \
if os.path.isfile(os.path.join(picture_path, x))])
else:
# specify manually because no valid path submited
wallpaper_files = {
workspace['1']: "#0E0E0E",
workspace['2']: "~/Pictures/wallpapers/f01e4257412885.59d4e4cd5e722.jpg",
workspace['3']: "#0E0E0E",
workspace['4']: "#0E0E0E",
workspace['5']: "#0E0E0E",
workspace['6']: "~/Pictures/wallpapers/MnmI88n.jpg",
workspace['7']: "~/Pictures/wallpapers/37088990882_a324d208d4_o.png",
workspace['8']: "~/Pictures/wallpapers/s2lj7bI.jpg",
workspace['9']: "~/Pictures/wallpapers/MnmI88n.jpg",
workspace['10']: "~/Pictures/test.jpg"
}
backgrounds = defaultdict(lambda: "#0E0E0E", {
workspace['1']: wallpaper_files[workspace['1']],
workspace['2']: wallpaper_files[workspace['2']],
workspace['3']: wallpaper_files[workspace['3']],
workspace['4']: wallpaper_files[workspace['4']],
workspace['5']: wallpaper_files[workspace['5']],
workspace['6']: wallpaper_files[workspace['6']],
workspace['7']: wallpaper_files[workspace['7']],
workspace['8']: wallpaper_files[workspace['8']],
workspace['9']: wallpaper_files[workspace['9']],
workspace['10']: wallpaper_files[workspace['10']]
})
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)
root.clear_area()
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))
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)
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()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment