Skip to content

Instantly share code, notes, and snippets.

@kgaughan
Last active January 5, 2020 00:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kgaughan/d1180cf7bf4adebeaf6498ff499400d0 to your computer and use it in GitHub Desktop.
Save kgaughan/d1180cf7bf4adebeaf6498ff499400d0 to your computer and use it in GitHub Desktop.
talideon-wallpaper
#!/usr/bin/env python3
#
# talideon-wallpaper
# by Keith Gaughan <http://talideon.com/>
#
# A pipemenu script for Openbox for selecting and setting the current
# wallpaper.
#
# Copyright (c) Keith Gaughan, 2008.
# All Rights Reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS "AS IS" AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# This license is subject to the laws and courts of the Republic of Ireland.
#
import os, sys
from os import path
from sys import argv
try:
from xml.etree import cElementTree as et
except:
from xml.etree import ElementTree as et
FALLBACK_SETTERS = ["hsetroot -center"]
SETTINGS = path.expanduser("~/.config/talideon.com/wallpaper")
WP_LINK = path.join(SETTINGS, "current")
def which(name):
"""
Finds the path of some named executable available on PATH.
"""
env_path = os.environ.get("PATH")
if env_path:
for dirname in env_path.split(os.pathsep):
executable = path.join(dirname, name)
if path.isfile(executable):
return executable
return None
def get_setters():
"""
Loads the list of all wallpaper setting commands.
"""
setters = []
setters_path = path.join(SETTINGS, "setters")
if path.isfile(setters_path):
try:
handle = open(setters_path, "r")
for line in handle:
line = line.strip()
if line != "" and line[0] != "#":
setters.append(line)
finally:
handle.close()
setters.extend(FALLBACK_SETTERS)
return setters
def show_wallpaper():
"""
Gets a wallpaper setter to set the backdrop on the root window.
"""
for setter in get_setters():
parts = setter.split(" ", 2)
location = which(parts[0])
if location is not None:
parts[0] = location
parts.append(path.realpath(WP_LINK))
os.spawnvpe(os.P_NOWAIT, location, parts, os.environ)
return
def set_wallpaper(wallpaper):
"""
Records the user's wallpaper selection.
"""
if path.isfile(wallpaper) and wallpaper != WP_LINK:
os.unlink(WP_LINK)
os.symlink(wallpaper, WP_LINK)
def generate_directory_menu(dirname, tree):
"""
Generates the Openbox menuitems for a given directory.
"""
for name in sorted(os.listdir(dirname)):
full_path = path.join(dirname, name)
if path.isfile(full_path):
tree.start("item", {"label": name[: name.rfind(".")]})
tree.start("action", {"name": "Execute"})
tree.start("execute")
tree.data("%s '%s'" % (argv[0], full_path))
tree.end("execute")
tree.end("action")
tree.end("item")
# Unfortunately, submenus, either as pipemenus or directly embedded
# in a pipemenu, aren't allowed, but we'll leave this in anyway as
# if/when it does, it'll be a nice hidden bonus feature.
elif path.isdir(full_path):
tree.start("menu", {"label": name})
generate_directory_menu(full_path, tree)
tree.end("menu")
def generate_pipemenu(dirname):
"""
Generates a pipemenu for a given directory.
"""
tree = et.TreeBuilder()
tree.start("openbox_pipe_menu")
generate_directory_menu(dirname, tree)
return et.tostring(tree.close(), "UTF-8")
def bad_path():
"""
Generates a pipemenu indicating that the path given was not a valid one.
"""
tree = et.TreeBuilder()
tree.start("openbox_pipe_menu")
tree.start("item", {"label": "Bad path"})
return et.tostring(tree.close(), "UTF-8")
if __name__ == "__main__":
if not path.exists(SETTINGS):
os.makedirs(SETTINGS)
if len(argv) == 1:
# With no args, the currently selected wallpaper is rendered.
show_wallpaper()
elif len(argv) >= 2:
if path.isdir(argv[1]):
# With one arg that' a directory, a pipemenu of that directory's
# contents is generated.
print(generate_pipemenu(argv[1]))
elif path.isfile(argv[1]):
# With one arg that's a file, that file is make the current
# wallpaper.
set_wallpaper(path.realpath(argv[1]))
show_wallpaper()
else:
print(bad_path())
print("Bad path.", file=sys.stderr)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment