dotfiles/.config/awesome/autohidewibox.py

172 lines
5.1 KiB
Python
Executable File

#!/usr/bin/python3
import subprocess
import re
import configparser
import os.path as path
import sys
import threading
MODE_TRANSIENT = "transient"
MODE_TOGGLE = "toggle"
config = configparser.ConfigParser()
try:
userconf = path.join(path.expanduser("~"), ".config/autohidewibox.conf")
if len(sys.argv)>1 and path.isfile(sys.argv[1]):
config.read(sys.argv[1])
elif path.isfile(userconf):
config.read(userconf)
else:
config.read("/etc/autohidewibox.conf")
except configparser.MissingSectionHeaderError:
pass
awesomeVersion = config.get( "autohidewibox", "awesomeVersion", fallback=4)
superKeys = config.get( "autohidewibox", "superKeys", fallback="133,134").split(",")
wiboxes = config.get( "autohidewibox", "wiboxname", fallback="mywibox").split(",")
customhide = config.get( "autohidewibox", "customhide", fallback=None)
customshow = config.get( "autohidewibox", "customshow", fallback=None)
delayShow = config.getfloat( "autohidewibox", "delayShow", fallback=0)
delayHide = config.getfloat( "autohidewibox", "delayHide", fallback=0)
mode = config.get( "autohidewibox", "mode", fallback=MODE_TRANSIENT)
debug = config.getboolean("autohidewibox", "debug", fallback=False)
# (remove the following line if your wibox variables have strange characters)
wiboxes = [ w for w in wiboxes if re.match("^[a-zA-Z_][a-zA-Z0-9_]*$", w) ]
#python>=3.4: wiboxes = [ w for w in wiboxes if re.fullmatch("[a-zA-Z_][a-zA-Z0-9_]*", w) ]
delay = {True: delayShow, False: delayHide}
delayThread = None
wiboxIsCurrentlyVisible = False
waitingFor = False
nonSuperKeyWasPressed = False
cancel = threading.Event()
shPath = ""
shPotentialPaths = ["/usr/bin/sh", "/bin/sh"]
for p in shPotentialPaths:
if path.exists(p):
shPath = p
break
if shPath == "":
print("Can't find sh in any of: " + ",".join(shPotentialPaths), file=sys.stderr)
sys.exit(1)
hideCommand3 = "for k,v in pairs({wibox}) do v.visible = {state} end"
hideCommand4 = "for s in screen do s.{wibox}.visible = {state} end"
try:
hideCommand = hideCommand4 if int(awesomeVersion) >= 4 else hideCommand3
except ValueError:
hideCommand = hideCommand4
def _debug(*args):
if debug:
print(*args)
def setWiboxState(state=True, immediate=False):
global delayThread, waitingFor, cancel, wiboxIsCurrentlyShown
wiboxIsCurrentlyShown = state
dbgPstate = "show" if state else "hide"
if delay[not state] > 0:
_debug(dbgPstate, "delay other")
if type(delayThread) == threading.Thread and delayThread.is_alive():
# two consecutive opposing events cancel out. second event should not be called
_debug(dbgPstate, "delay other, thread alive -> cancel")
cancel.set()
return
if delay[state] > 0 and not immediate:
_debug(dbgPstate + " delay same")
if not (type(delayThread) == threading.Thread and delayThread.is_alive()):
_debug(dbgPstate, "delay same, thread dead -> start wait")
waitingFor = state
cancel.clear()
delayThread = threading.Thread(group=None, target=waitDelay, kwargs={"state": state})
delayThread.daemon = True
delayThread.start()
# a second event setting the same state is silently discarded
return
_debug("state:", dbgPstate)
customcmd = customshow if state else customhide
if customcmd:
subprocess.call(
shPath + " " +
"-c \"echo '" +
customcmd +
"' | awesome-client\"",
shell=True)
for wibox in wiboxes:
subprocess.call(
shPath + " " +
"-c \"echo '" +
hideCommand.format(wibox=wibox, state="true" if state else "false") +
"' | awesome-client\"",
shell=True)
def waitDelay(state=True):
if not cancel.wait(delay[state]/1000):
setWiboxState(state=state, immediate=True)
try:
setWiboxState(False)
proc = subprocess.Popen(['xinput', '--test-xi2', '--root', '3'], stdout=subprocess.PIPE)
field = None
keystate = None
for line in proc.stdout:
l = line.decode("utf-8").strip()
eventmatch = re.match("EVENT type (\\d+) \\(.+\\)", l)
detailmatch = re.match("detail: (\\d+)", l)
if eventmatch:
_debug(eventmatch)
try:
field = "event"
keystate = eventmatch.group(1)
_debug("found event, waiting for detail...")
except IndexError:
field = None
keystate = None
if (field is "event") and detailmatch:
_debug(detailmatch)
try:
if detailmatch.group(1) in superKeys:
_debug("is a super key")
if keystate == "13": # press
nonSuperKeyWasPressed = False
if mode == MODE_TRANSIENT:
_debug("showing wibox")
setWiboxState(True)
if keystate == "14": # release
if mode == MODE_TRANSIENT:
_debug("hiding wibox")
setWiboxState(False)
# Avoid toggling the wibox when a super key is used in conjunction
# with another key.
elif mode == MODE_TOGGLE and not nonSuperKeyWasPressed:
_debug("toggling wibox")
setWiboxState(not wiboxIsCurrentlyShown)
nonSuperKeyWasPressed = False
else:
nonSuperKeyWasPressed = True
except IndexError:
_debug("Couldn't parse keystate number.")
pass
finally:
field = None
keystate = None
except KeyboardInterrupt:
pass
finally:
setWiboxState(True, True)
# print("Shutting down")