Last active
January 5, 2020 00:47
-
-
Save kgaughan/d1180cf7bf4adebeaf6498ff499400d0 to your computer and use it in GitHub Desktop.
talideon-wallpaper
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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