# $Id: actions.py,v 1.37 2003/11/04 21:23:03 mackstann Exp $
import sys, os
import kahakai
from events import *
class RedirectingLog(object):
def __init__(self, filename, replace, name):
self.filename = filename
self.name = name
self.prefix = "Python %s: " % name
self._oldfp = replace
self._log = file(filename, "a")
print >> self._log, "Python: %s log opened" % self.name
self._oldfp.flush()
def __getattr__(self, attr):
return getattr(self._oldfp, attr)
def write(self, text):
lines = [ line.rstrip() + "\n" for line in
filter(str.strip, text.split("\n")) ]
for line in lines:
for f in (self._log, self._oldfp):
f.write("%s%s" % (self.prefix, line))
logfn = os.path.expanduser("~/.kahakai/log")
kahakaiInst = kahakai.Kahakai.Instance()
def screen():
return kahakaiInst.script_current_screen
_objects = []
_beendone = []
def execute(screen, command):
if not os.fork():
os.setsid()
os.putenv(*screen.displaystring.split('='));
os.execl("/bin/sh", "/bin/sh", "-c", command);
sys.exit(0);
def _bindAction(bindto, actionList, event, function, param):
assert bindto in ("window","menu")
action = kahakai.Action()
_objects.append(action)
if not event.set(action): return
if bindto == "window":
if not isinstance(function, kahakai.WindowFunction):
function = kahakai.createWindowFunction(function)
_objects.append(function)
action.winfunc = function
else:
action.menufunc = function
action.param = param
actionList.append(action)
bindWindowAction = lambda *args: _bindAction("window", *args)
bindMenuAction = lambda *args: _bindAction("menu", *args)
def _processFunction(function, functionType):
"""
Function argument parsing code common to all three *Action() functions.
functionType is either 'window', 'screen' or 'menu'.
Returns function and the parameter
"""
assert functionType in ('screen', 'menu', 'window')
param = ""
if isinstance(function, tuple):
function, param = function
if isinstance(param, int):
param = str(param)
if isinstance(function, str):
if function.startswith('{') and function.endswith('}'):
command = function[1:-1]
function = lambda screen, *args: execute(screen, command)
return kahakai.createScreenFunction(function), param
else:
if functionType in ("window", "menu", "screen"):
fullname = "%sEv%s" % (functionType.capitalize(), function)
scrfullname = "ScreenEv%s" % function
if hasattr(kahakai, fullname):
return getattr(kahakai, fullname)(), param
elif hasattr(kahakai, scrfullname):
return getattr(kahakai, scrfullname)(), param
else:
raise ValueError("notice: '%s' is not a valid %s function"
% (function, functionType))
else:
raise ValueError("`%s' is not a valid action target"
% functionType)
classes = {'menu' : kahakai.MenuFunction,
'window': kahakai.WindowFunction,
'screen': kahakai.ScreenFunction}
wrappers = {'menu' : kahakai.createMenuFunction,
'window': kahakai.createWindowFunction,
'screen': kahakai.createScreenFunction}
if not isinstance(function, classes[functionType]):
if callable(function):
function = wrappers[functionType](function)
else:
raise ValueError("Wrong type for a function: %s" % type(function))
return function, param
def getWindowActionList(screen, name):
assert name.startswith('window.')
if name.startswith('window.button_'):
id = name[len('window.button_'):]
actionList = screen.config.bacts[id]
#print "ACTIONLIST: ", actionList
else:
actionLists = {
'frame': screen.config.frameacts,
'title': screen.config.titleacts,
'label': screen.config.labelacts,
'handle': screen.config.handleacts,
'activeclient': screen.config.awinacts,
'focused': screen.config.awinacts,
'passiveclient': screen.config.pwinacts,
'unfocused': screen.config.pwinacts,
'leftgrip': screen.config.lgacts,
'rightgrip': screen.config.rgacts,
}
suffix = name[len('window.'):]
if not suffix.lower() in actionLists:
warn("Unknown window target %s" % suffix)
return None
else:
actionList = actionLists[suffix.lower()]
return actionList
def windowAction(screen, name, event, function):
try:
function, param = _processFunction(function, 'window')
except (), err:
print "warning: actions.windowAction() caught exception:"
print err
return
_objects.append(function)
if name.startswith('window.'):
bindWindowAction(getWindowActionList(screen, name),
event, function, param)
else:
warn("Unsupported window action target %s" % name)
def getMenuActionList(screen, name):
assert name.startswith('menu.'), name
actionLists = {
'title': screen.config.mtacts,
'item': screen.config.miacts,
'sub': screen.config.msacts,
'checkbox': screen.config.mcbacts}
suffix = name[len('menu.'):]
if not suffix.lower() in actionLists:
warn("Unknown menu target %s" % suffix)
return None
else:
return actionLists[suffix.lower()]
def menuAction(screen, name, event, function):
action = kahakai.Action()
_objects.append(action)
if not event.set(action): return
try:
function, param = _processFunction(function, 'menu')
except (), err:
print "warning: actions.menuAction() caught exception:"
print err
return
_objects.append(function)
if name.startswith('menu.'):
actionList = getMenuActionList(screen, name)
bindMenuAction(actionList, event, function, param)
else:
warn("Unsupported menu action target %s" % name)
def screenAction(screen, event, function, edge=None):
action = kahakai.Action()
_objects.append(action)
if not event.set(action): return
param = ""
try:
function, param = _processFunction(function, 'screen')
except (), err:
print "warning: actions.screenAction() caught exception:"
print err
return
_objects.append(function)
action.rootfunc = function
action.param = param
screen.config.rootacts.append(action)
def edgeAction(screen, event, function, edge):
action = kahakai.Action()
_objects.append(action)
if not event.set(action): return
param = ""
try:
function, param = _processFunction(function, 'screen')
except (), err:
print "warning: actions.edgeAction() caught exception:"
print err
return
_objects.append(function)
action.rootfunc = function
action.param = param
edge = edge.lower()
if edge == 'n': screen.config.neacts.append(action)
elif edge == 's': screen.config.seacts.append(action)
elif edge == 'e': screen.config.eeacts.append(action)
elif edge == 'w': screen.config.weacts.append(action)
else:
warn("Wrong edge: %s (should be n, s, e, w)" % edge)
# screen
_delayedScreenActs = []
def doDelayedScreenActs():
global _delayedScreenActs
_screenActions(_delayedScreenActs)
_delayedScreenActs = []
def screenActions(actions):
_delayedScreenActs.extend(actions)
def _screenActions(actions):
for event, function in actions:
screenAction(screen(), event, function)
# edges
_delayedEdgeActs = {}
def doDelayedEdgeActs():
global _delayedEdgeActs
for edge, actions in _delayedEdgeActs.items():
_edgeActions(actions, edge)
_delayedEdgeActs = {}
def edgeActions(actions, edge):
if not _delayedEdgeActs.has_key(edge):
_delayedEdgeActs[edge] = []
_delayedEdgeActs[edge].extend(actions)
def _edgeActions(actions, edge):
for event, function in actions:
edgeAction(screen(), event, function, edge)
# windows
_delayedWinActs = {}
def doDelayedWinActs():
global _delayedWinActs
for name, actions in _delayedWinActs.items():
_windowActions(name, actions)
_delayedWinActs = {}
def windowActions(name, actions):
"""Not the real thing; appends the actions to the hash containing delayed
actions, for later execution by doDelayedWinActs"""
if not _delayedWinActs.has_key(name):
_delayedWinActs[name] = []
_delayedWinActs[name].extend(actions)
def _windowActions(name, actions):
"""Formerly known as windowActions, now hidden due to caching"""
actionList = getWindowActionList(screen(), name)
for event, function in actions:
function, param = _processFunction(function, 'window')
_objects.append(function)
bindWindowAction(actionList, event, function, param)
# menus
_delayedMenuActs = {}
def doDelayedMenuActs():
global _delayedMenuActs
for name, actions in _delayedMenuActs.items():
_menuActions(name, actions)
_delayedMenuActs = {}
def menuActions(name, actions):
if not _delayedMenuActs.has_key(name):
_delayedMenuActs[name] = []
_delayedMenuActs[name].extend(actions)
def _menuActions(name, actions):
actionList = getMenuActionList(screen(), name)
for event, function in actions:
function, param = _processFunction(function, 'menu')
_objects.append(function)
bindMenuAction(actionList, event, function, param)
def _handleMapRequest(config, window, event, action):
winClass = window.classhint.res_class
winName = window.classhint.res_name
config.newWindow(window, winClass, winName, event, action)
def init():
"""This should always be run. Any code that absolutely needs to be in
effect for everyone should go here."""
try:
stdout = RedirectingLog(logfn, sys.stdout, "stdout")
except (), err:
print "error in opening RedirectingLog for stdout:"
print err
else:
sys.stdout = stdout
try:
stderr = RedirectingLog(logfn, sys.stderr, "stderr")
except (), err:
print "error in opening RedirectingLog for stderr:"
print err
else:
sys.stderr = stderr
# close task switcher on release of alt
allMenuActions([ (KeyRelease('Alt_L'), "UnmapTree"),
(KeyRelease('Alt_L'), "Func") ],
["item"])
_beendone.append("init")
def finish():
if not "init" in _beendone:
print "You didn't call init()! This is required!"
doDelayedWinActs()
doDelayedMenuActs()
doDelayedEdgeActs()
doDelayedScreenActs()
_beendone.append("finish")
def install(config):
_callable = lambda method: callable(getattr(config, method))
for method in filter(_callable, dir(config)):
# window parts (inc. buttons)
if method.startswith("window_"):
windowpart = method.replace("window_","window.")
# doh
windowpart = windowpart.replace("unfocused", "passiveclient")
windowpart = windowpart.replace("focused", "activeclient")
windowActions(windowpart, getattr(config, method)())
# menus
elif method.startswith("menu_"):
menuActions(method.replace("menu_","menu."),
getattr(config, method)())
# edges
elif method.endswith("Edge"):
edgeActions(getattr(config, method)(), method[0])
# misc
elif method == "globals":
config.globals()
elif method == "globalKeyBindings":
globalActions(config.globalKeyBindings())
elif method == "root":
screenActions(config.root())
elif method == "defaultAllWindows":
allWindowActions(config.defaultAllWindows())
elif method == "defaultAllMenus":
allMenuActions(config.defaultAllMenus())
elif method == "defaultAllTitle":
allWindowActions(config.defaultAllTitle(),
["title","label"])
elif method == "defaultAllDecor":
allWindowActions(config.defaultAllWindows(),
["title","label","handle","leftgrip","rightgrip"])
elif method == "newWindow":
allWindowActions([(MapRequest(),
lambda *args: _handleMapRequest(config, *args))])
finish()
allWindowTargets = """frame activeclient passiveclient
title label leftgrip rightgrip handle""".split()
allMenuTargets = "title item sub checkbox".split()
def _allActions(prefix, actionsfunc, actions, targets):
for target in targets:
actionsfunc("%s%s"%(prefix,target), actions)
def allWindowActions(actions, selective=allWindowTargets):
_allActions("window.",windowActions, actions, selective)
def allMenuActions(actions, selective=allMenuTargets):
_allActions("menu.", menuActions, actions, selective)
def globalActions(actions):
allWindowActions(actions)
screenActions(actions)
allMenuActions(actions)
|