|
Server : Apache/2.2.17 (Unix) mod_ssl/2.2.17 OpenSSL/0.9.8e-fips-rhel5 DAV/2 PHP/5.2.17 System : Linux localhost 2.6.18-419.el5 #1 SMP Fri Feb 24 22:47:42 UTC 2017 x86_64 User : nobody ( 99) PHP Version : 5.2.17 Disable Function : NONE Directory : /proc/22697/root/usr/bin/ |
Upload File : |
#!/usr/bin/python
__author__ = 'David Malcolm <dmalcolm@redhat.com>, Zack Cerza <zcerza@redhat.com>'
appName = 'Script Recorder'
import os
os.environ['GTK_MODULES']=''
from dogtail.utils import checkForA11yInteractively
checkForA11yInteractively()
import atspi
import dogtail.tree
import gtk.gdk
import dogtail.rawinput
import re
# Begin GUI code
import threading
class PlaybackThread(threading.Thread):
def __init__(self, script):
threading.Thread.__init__(self)
self.script = script
def run(self):
exec self.script
import gobject
import gnome
import gtk.glade
try:
import gtksourceview
useGtkSourceView = True
except:
useGtkSourceView = False
def createSourceView():
langManager = gtksourceview.SourceLanguagesManager()
lang = langManager.get_language_from_mime_type("text/x-python")
buffer = gtksourceview.SourceBuffer()
sourceView = gtksourceview.SourceView(buffer)
buffer.set_language(lang)
buffer.set_highlight(True)
return sourceView
class RecorderGUI(gnome.Program):
def __init__(self):
gnome.Program.__init__(self)
appAuthors = ['Zack Cerza <zcerza@redhat.com>']
program = gnome.program_init(appName, '0.1')
if os.path.exists('recorder.glade'):
x = gtk.glade.XML('recorder.glade')
else:
import sys
exec_root = sys.argv[0].split("/bin/")[0]
if exec_root[0] is not '/':
exec_root = "/usr"
x = gtk.glade.XML(exec_root + '/share/dogtail/glade/recorder.glade')
self.window = x.get_widget('window')
try:
self.window.set_icon_from_file('../icons/dogtail-head.svg')
except:
self.window.set_icon_from_file('/usr/share/icons/hicolor/scalable/apps/dogtail-head.svg')
self.recordButton = x.get_widget('recordButton')
self.playButton = x.get_widget('playButton')
self.playButton.set_sensitive(False)
self.clearButton = x.get_widget('clearButton')
self.clearButton.set_sensitive(False)
self.saveButton = x.get_widget('saveButton')
self.saveButton.set_sensitive(False)
if useGtkSourceView:
oldTextView = x.get_widget('scriptTextView')
parent = oldTextView.get_parent()
parent.remove(oldTextView)
sourceView = createSourceView()
parent.add(sourceView)
sourceView.show()
self.scriptTextView = sourceView
else:
self.scriptTextView = x.get_widget('scriptTextView')
self.scriptTextView.set_editable(False)
#self.writerComboBox = x.get_widget('writerComboBox')
#self.writerComboBox.set_active(0)
#self.writerComboBox.set_sensitive(True)
# The following line added because self.writerComboBox is gone:
recorder.writerClass = ProceduralScriptWriter
self.connectSignals()
self.window.show_all()
gtk.main()
def connectSignals(self):
#self.writerComboBox.connect('changed', self.setWriterClass)
self.recordButton.connect('clicked', self.toggleRecording, self.scriptTextView)
self.playButton.connect('clicked', self.playScript, self.scriptTextView)
self.clearButton.connect('clicked', self.clearScript, self.scriptTextView)
self.saveButton.connect('clicked', self.saveScript)
self.window.connect('delete_event', self.quit)
def setWriterClass (self, comboBox):
selected = comboBox.get_active_text()
if selected == "Procedural":
recorder.writerClass = ProceduralScriptWriter
elif selected == "Object-Oriented":
recorder.writerClass = OOScriptWriter
else:
print selected, "isn't a ScriptWriter, but it is selected. How?"
def toggleRecording(self, recordButton = None, scriptTextView = None):
label = self.recordButton.get_label()
recordID = 'gtk-media-record'
stopID = 'gtk-media-stop'
if label == recordID:
#self.writerComboBox.set_sensitive(False)
self.playButton.set_sensitive(False)
self.clearButton.set_sensitive(False)
self.saveButton.set_sensitive(False)
self.scriptTextView.set_editable(False)
self.recordButton.set_label(stopID)
recorder.startRecording(self.recordButton, self.scriptTextView)
elif label == stopID:
#self.writerComboBox.set_sensitive(True)
self.playButton.set_sensitive(True)
self.clearButton.set_sensitive(True)
self.saveButton.set_sensitive(True)
self.scriptTextView.set_editable(True)
self.recordButton.set_label(recordID)
recorder.stopRecording(self.recordButton, self.scriptTextView)
def stopRecording(self):
self.recordButton.set_label('gtk-media-stop')
self.toggleRecording()
def playScript(self, button = None, scriptTextView = None):
self.recordButton.set_sensitive(False)
self.playButton.set_sensitive(False)
self.scriptTextView.set_editable(False)
buffer = self.scriptTextView.get_buffer()
startIter = buffer.get_start_iter()
endIter = buffer.get_end_iter()
scriptText = buffer.get_text(startIter, endIter)
self.playbackThread = PlaybackThread(scriptText)
self.playbackThread.start()
self.playbackThread.join()
self.playButton.set_sensitive(True)
self.recordButton.set_sensitive(True)
self.scriptTextView.set_editable(True)
def clearScript(self, button = None, scriptTextView = None):
self.scriptTextView.get_buffer().set_text('')
self.clearButton.set_sensitive(False)
self.saveButton.set_sensitive(False)
def saveScript(self, button):
"""
Brings up a file chooser dialog asking where to save the script.
"""
self.saveFileChooser = gtk.FileChooserDialog("Save Script...", None, \
gtk.FILE_CHOOSER_ACTION_SAVE, (gtk.STOCK_CANCEL, \
gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK))
self.saveFileChooser.set_default_response(gtk.RESPONSE_OK)
# Why this isn't default, I do not understand.
self.saveFileChooser.set_do_overwrite_confirmation(True)
filter = gtk.FileFilter()
filter.set_name('Python files')
filter.add_pattern('*.py')
self.saveFileChooser.add_filter(filter)
filter = gtk.FileFilter()
filter.set_name('All Files')
filter.add_pattern('*')
self.saveFileChooser.add_filter(filter)
response = self.saveFileChooser.run()
if response == gtk.RESPONSE_OK:
fileName = self.saveFileChooser.get_filename()
# Append a .py to the file name if necessary
if fileName[-3:] != '.py':
fileName += '.py'
file = open(fileName, 'w')
buffer = self.scriptTextView.get_buffer()
startIter = buffer.get_start_iter()
endIter = buffer.get_end_iter()
scriptText = buffer.get_text(startIter, endIter)
file.write(scriptText)
file.close()
self.saveFileChooser.destroy()
def quit(self, *args):
self.stopRecording()
gtk.main_quit()
# End GUI code
def logEvent(event):
source = event.source
if isinstance(source, atspi.Accessible):
sourceStr = " source:%s"%(str(dogtail.tree.Node(source)))
else:
sourceStr = ""
print "Got event: %s%s"%(event.type, sourceStr)
class ScriptWriter:
"""
Abstract Writer subclass which writes out Python scripts
"""
def __init__(self, scriptTextView = None):
self.scriptBuffer = ""
self.scriptTextView = scriptTextView
self.debug = False
def recordLine(self, string):
print string
if self.scriptTextView:
buffer = self.scriptTextView.get_buffer()
iter = buffer.get_end_iter()
if buffer.get_line_count() > 1:
string = '\n' + string
buffer.insert(iter, string)
# Scroll to the end
iter = buffer.get_end_iter()
mark = buffer.create_mark('end', iter, True)
self.scriptTextView.scroll_mark_onscreen(mark)
buffer.delete_mark(mark)
else:
self.scriptBuffer += '\n' + string
def recordClick(self, node):
raise NotImplementedError
def recordTyping(self, string, type, node):
raise NotImplementedError
def recordKeyCombo(self, string, type, node):
raise NotImplementedError
class OOScriptWriter(ScriptWriter):
"""
Concrete Writer subclass which writes out Python scripts in an object-oriented
style
"""
def __init__(self, scriptTextView = None):
ScriptWriter.__init__(self, scriptTextView)
self.debugVariables = False
self.recordLine("#!/usr/bin/python\nfrom dogtail.tree import *\n")
# maintain a dict from variable names to search paths
self.variables = {}
def generateVariableName(self, predicate):
# Ensure uniqueness
result = predicate.makeScriptVariableName()
if result in self.variables:
# This variable name is already in use; need to append a number:
index = 1
while result+str(index) in self.variables:
index+=1
return result+str(index)
else:
return result
def printVariables(self):
# debug hook
print "variables:"
for (varName, varAbsPath) in self.variables.iteritems():
print "varName:%s -> absPath:%s"%(varName, varAbsPath)
def generateAbsSearchPathMethodCall(self, absSearchPath):
"""
Generates a method call that identifies the absolute search path,
optimizing away prefixes where possible with variable names.
"""
# We optimize away the longest common absolute path prefix, i.e. the
# shortest relative path suffix:
if self.debug:
print "*******************"
print "generateAbsSearchPathMethodCall for %s"%absSearchPath
self.printVariables()
shortestRelativePath = None
for (varName, varAbsPath) in self.variables.iteritems():
relPath = varAbsPath.getRelativePath(absSearchPath)
if relPath:
if shortestRelativePath:
if relPath.length() < shortestRelativePath[2].length():
shortestRelativePath = (varName, varAbsPath, relPath)
else:
shortestRelativePath = (varName, varAbsPath, relPath)
if self.debug:
if shortestRelativePath:
(varName, varAbsPath, relPath) = shortestRelativePath
print "shortestRelativePath: (%s, %s, %s)"%(varName, varAbsPath, relPath)
else:
print "shortestRelativePath: None"
print "*******************"
if shortestRelativePath:
(varName, varAbsPath, relPath) = shortestRelativePath
return varName+relPath.makeScriptMethodCall()
else:
# Have to specify it as an absolute path:
return "root"+absSearchPath.makeScriptMethodCall()
def recordClick(self, node):
"""
Record a mouse click
"""
if node == None: return
searchPath = node.getAbsoluteSearchPath()
if self.debug:
print "----------------------------------"
print "click on %s"%searchPath
print "Full script would be: root%s"%searchPath.makeScriptMethodCall()
# Generate variables for nodes likely to be referred to often (application, window)
# FIXME: make this smarter?
for i in [1,2,3]:
if i<searchPath.length():
prefixPath = searchPath.getPrefix(i)
if self.debugVariables:
print "Considering: %s"%prefixPath
if not prefixPath in self.variables.values():
if self.debugVariables:
print "It is not yet a variable"
self.printVariables()
predicate = prefixPath.getPredicate(i-1)
varName = predicate.makeScriptVariableName()
self.recordLine(varName+" = "+self.generateAbsSearchPathMethodCall(prefixPath))
self.variables[varName]=prefixPath
else:
if self.debugVariables:
print "It is already a variable"
result = self.generateAbsSearchPathMethodCall(searchPath)
result +=".click()"
if self.debug:
print "----------------------------------"
self.recordLine(result)
class ProceduralScriptWriter(ScriptWriter):
"""
Concrete Writer subclass which writes out Python scripts in a procedural
style
"""
currentWidget = None
currentDialog = None
currentFrame = None
currentApplication = None
def __init__(self, scriptTextView = None):
ScriptWriter.__init__(self, scriptTextView)
self.recordLine("#!/usr/bin/python\nfrom dogtail.procedural import *\n")
def setUpFocus(self, node):
"""
Writes out the necessary focus.application() and focus.dialog() lines
to the script.
"""
application = FakeNode.findAncestor(node, roleName = 'application')
if application:
needApp = True
if self.currentApplication:
if application == self.currentApplication: needApp = False
if needApp:
self.recordLine("focus.application('%s')" % application.name)
self.currentApplication = application
elif application == None:
print "Warning: could not determine which application you are clicking or typing on."
print " It is most likely not reporting its toplevel Accessible as having a"
print " role name of 'application'. Please file a bug against it!"
dialog = FakeNode.findAncestor(node, roleName = 'dialog')
if dialog:
needDialog = True
if dialog == self.currentDialog: needDialog = False
if needDialog:
self.recordLine("focus.dialog('%s')" % dialog.name)
self.currentDialog = dialog
else:
frame = FakeNode.findAncestor(node, roleName='frame')
if frame:
needFrame = True
if frame == self.currentFrame: needFrame = False
if needFrame:
self.recordLine("focus.frame('%s')" % frame.name)
self.currentFrame = frame
def recordClick(self, node, button):
if node == None: return False
self.setUpFocus(node)
widget = node
#possibleActions = ['click', 'activate', 'open', 'menu']
possibleActions = ['click', 'activate', 'menu']
foundAnAction = False
for action in possibleActions:
if action in widget.actions.keys():
if button == 1 and action == 'menu': break
foundAnAction = True
self.recordLine("%s('%s', roleName='%s')" % \
(action, widget.name.replace('\n','\\n'), widget.roleName))
break
if not foundAnAction:
if hasattr(widget, 'select') and button != 1:
self.recordLine("select('%s', roleName='%s')" % \
(widget.name.replace('\n','\\n'), widget.roleName))
else:
if button != 1: btn = ', button = ' + str(button)
else: btn = ''
s = "click('%s', roleName='%s', raw=True%s)" % \
(widget.name.replace('\n','\\n'), widget.roleName, btn)
self.recordLine(s)
self.currentWidget = widget
def recordTyping(self, string, type, node):
if not string: return
self.setUpFocus(node)
self.recordLine("type(\"" + string.replace('"','\\"') + "\")")
def recordKeyCombo(self, string, type, node):
if not string: return
self.setUpFocus(node)
self.recordLine("keyCombo(\"" + string + "\")")
class FakeNode(dogtail.tree.Node):
"""A "cached pseudo-copy" of a Node
This class exists for cases where we know we're going to need information
about a Node instance at a point in time where it's no longer safe to
assume that the Accessible it wraps is still valid. It is designed to
cache enough information to allow all of the necessary Node methods to
execute properly and return something meaningful.
As it is often necessary to know the Node instance's parent, it creates
FakeNode instances of each and every one of its ancestors.
"""
def __init__(self, node):
if node == None: raise TypeError, node
self.__node = node
self.name = self.__node.name
self.roleName = self.__node.roleName
self.description = self.__node.description
self.actions = self.__node.actions
self.debugName = self.__node.debugName
self.text = self.__node.text
self.position = self.__node.position
self.size = self.__node.size
if node.parent: self.parent = FakeNode(self.__node.parent)
else: self.parent = None
if node.labellee: self.labellee = FakeNode(self.__node.labellee)
else: self.labellee = None
def __getattr__(self, name):
raise AttributeError, name
def __setattr__(self, name, value):
self.__dict__[name] = value
def __cmp__(self, otherNode):
if not otherNode: return True
nameMatch = False
roleNameMatch = False
descMatch = False
nameMatch = otherNode.name == self.name
roleNameMatch = otherNode.roleName == self.roleName
descMatch = otherNode.description == self.description
match = nameMatch and roleNameMatch and descMatch
return not match
def findAncestor(node, name = None, roleName = None, description = None):
while node.parent:
nameMatch = False
roleNameMatch = False
descMatch = False
if name != None: nameMatch = node.parent.name == name
else: nameMatch = True
if roleName != None: roleNameMatch = node.parent.roleName == roleName
else: roleNameMatch = True
if description != None:
descMatch = node.parent.description == description
else: descMatch = True
match = nameMatch and roleNameMatch and descMatch
if match: return node.parent
node = node.parent
return None
findAncestor = staticmethod(findAncestor)
# Singleton EventRecorder
global recorder
class EventRecorder:
"""
Event Recorder
"""
modifiers = {
atspi.Accessibility_MODIFIER_NUMLOCK: 'NumLock',
atspi.Accessibility_MODIFIER_META3: 'Meta3',
atspi.Accessibility_MODIFIER_META2: 'Meta2',
atspi.Accessibility_MODIFIER_META: 'Meta',
atspi.Accessibility_MODIFIER_ALT: 'Alt',
atspi.Accessibility_MODIFIER_CONTROL: 'Control',
atspi.Accessibility_MODIFIER_SHIFTLOCK: 'ShiftLock',
atspi.Accessibility_MODIFIER_SHIFT: 'Shift' }
def __init__(self, writerClass = ProceduralScriptWriter):
self.writer = None
self.writerClass = writerClass
self.lastFocusedNode = None
self.lastSelectedNode = None
self.lastPressedNode = None
self.lastReleasedNode = None
self.typedTextBuffer = ""
self.lastTypedNode = None
self.absoluteNodePaths = True
self.listeners = []
import gtk.keysyms
def __registerEvents(self):
# Only specific events are recorded:
listeners = []
# Focus events:
listeners.append(atspi.EventListener(marshalOnFocus, ["focus:"]))
# State Changed events:
listeners.append(atspi.EventListener(marshalOnSelect, ["object:state-changed:selected"]))
# Mouse button events:
listeners.append(atspi.EventListener(marshalOnMouseButton, ["mouse:button"]))
# Keystroke events:
listeners.append(atspi.DeviceListener(marshalOnKeyPress))
# Window creation:
#listeners.append(atspi.EventListener(marshalOnWindowCreate, ["window:create"]))
return listeners
def startRecording(self, unused = None, scriptTextView = None):
self.writer = self.writerClass(scriptTextView)
self.listeners = self.__registerEvents()
# set lastKeyPressTimeStamp to 1, which is an invalid value.
self.lastKeyPressTimeStamp = 1
atspi.event_main()
def stopRecording(self, unused = None, scriptTextView = None):
for listener in self.listeners:
listener.deregister()
atspi.event_quit()
self.writer = None
def onFocus(self, event):
sourceNode = dogtail.tree.Node(event.source)
sourceNode = FakeNode(sourceNode)
#if sourceNode == self.lastPressedNode or \
# sourceNode == self.lastReleasedNode:
# sourceNode._FakeNode__node.blink()
self.lastFocusedNode = sourceNode
def onSelect(self, event):
sourceNode = dogtail.tree.Node(event.source)
sourceNode = FakeNode(sourceNode)
self.lastSelectedNode = sourceNode
def onMouseButton(self, event):
#logEvent(event)
self.writer.recordTyping(self.typedTextBuffer, "pressed", self.lastFocusedNode)
self.typedTextBuffer = ""
isPress = isRelease = False
g=re.match('mouse:button:(\d)(p|r)', event.type).groups()
button = int(g[0])
if g[1] == 'p': isPress = True
elif g[1] == 'r': isRelease = True
# The source node is always "main" - which sucks. We have to detect
# the real source ourselves.
def detectByCoordinates(nodes, x, y):
# From a list of nodes, find the smallest one that (x, y) is in
def isCandidate(node, x, y):
# If (x, y) is inside the node, return True
if node and node.position:
#print "x,y: %s, %s" % (x, y)
#print "position: %s, size: %s" % (node.position, node.size)
if node.position[0] <= x <= (node.position[0] + node.size[0]) and \
node.position[1] <= y <= (node.position[1] + node.size[1]):
return True
def getAllDescendants(node):
result = []
for child in node.children:
result.append(child)
result.extend(getAllDescendants(child))
#for grandChild in child.children:
# result.append(grandChild)
return result
def smallestNode(nodes):
# Return the node with the smallest area
areas = {}
for node in nodes:
area = node.size[0] * node.size[1]
if areas.get(area, None):
print "Two nodes are the same size?!"
print str(areas[area]) + "|" + str(node)
areas[area] = node
if areas:
return areas[min(areas.keys())]
detectedNode = None
for node in nodes:
if isCandidate(node, x, y):
detectedNode = node
# table children don't send focus signals, so we have to
# find the child itself.
if node.roleName == 'table':
detectedNode = None
if not hasattr(node, 'children'):
node = node._FakeNode__node
# getAllDescendants() is very expensive :(
possibleNodes = getAllDescendants(node)
probableNodes = [n for n in possibleNodes if \
isCandidate(n, x, y)]
detectedNode = smallestNode(probableNodes)
return detectedNode
x = event.detail1
y = event.detail2
if self.lastSelectedNode != self.lastFocusedNode:
possibleNodes = (self.lastSelectedNode, self.lastFocusedNode)
else:
# If self.lastSelectedNode isn't meaningful, don't waste time on
# it with detectByCoordinates().
possibleNodes = [self.lastFocusedNode]
detectedNode = detectByCoordinates(possibleNodes, x, y)
if detectedNode and ((detectedNode.name == appName and \
detectedNode.roleName == 'frame') or \
FakeNode.findAncestor(detectedNode, \
roleName = 'frame', name = appName)):
self.lastPressedNode = None
self.lastReleasedNode = None
return
if detectedNode and not isinstance(detectedNode, FakeNode):
detectedNode = FakeNode(detectedNode)
if isPress:
self.lastPressedNode = detectedNode
elif isRelease:
self.lastReleasedNode = detectedNode
if isRelease and detectedNode:
self.writer.recordClick(detectedNode, button)
def __checkModMask(fullMask, partMask, toCheck):
result = False
if fullMask == 0 or partMask == 0:
return (partMask, result)
if partMask - toCheck >= 0:
partMask = partMask - toCheck
result = True
return (partMask, result)
__checkModMask = staticmethod(__checkModMask)
def __getModifiers(self, modMask, keyChar):
partMask = modMask
modsDict = {}
keys = self.modifiers.keys()
keys.sort()
for i in keys[::-1]:
(partMask, pressed) = self.__checkModMask(modMask, partMask, i)
if pressed: modsDict[self.modifiers[i]] = i
# Screw capslock.
if modsDict.has_key('ShiftLock'):
del modsDict['ShiftLock']
# Shift+foo is not considered a key combo if foo is printable
if modsDict.has_key('Shift') and not keyChar == '':
del modsDict['Shift']
return modsDict
def onKeyPress(self, event):
# The Fn key on my Thinkpad has a keyID of 0. Ignore it.
if not event.keyID: return
if event.type == atspi.SPI_KEY_PRESSED:
type = "pressed"
elif event.type == atspi.SPI_KEY_RELEASED:
type = "released"
return
self.lastKeyPressTimeStamp = event.timeStamp
if self.lastKeyPressTimeStamp < 0:
elapsedTime = event.timeStamp - self.lastKeyPressTimeStamp
else:
elapsedTime = 0
if self.lastFocusedNode:
self.lastFocusedNode.text = self.lastFocusedNode._FakeNode__node.text
keyString = dogtail.rawinput.keyStrings[event.keyID]
keyChar = dogtail.rawinput.keySymToUniChar(event.keyID)
# If the only key being pressed is a modifier, don't do anything.
if keyString.startswith("Alt_") or keyString.startswith("Control_") \
or keyString.startswith("Meta_") or \
keyString.startswith("Shift") or keyString == 'Caps_Lock':
isJustAMod = True
return
else:
isJustAMod = False
modsDict = self.__getModifiers(event.modifiers, keyChar)
def buildModifierString(modsDict):
s = ''
if modsDict:
for mod in modsDict.keys():
s = s + '<' + mod + '>'
return s
modString = buildModifierString(modsDict)
# If modifiers are present, we're dealing with a key combo
if modString: combo = True
# Otherwise, we assume for a second that we're not.
else: combo = False
# If the key represents a printable character, use that.
if keyChar != '': key = keyChar
else:
# Otherwise, use the keyString, e.g. 'Return'.
key = keyString
# We treat nonprintable characters like key combos.
combo = True
if not combo and self.lastTypedNode is not None and \
(self.lastTypedNode != self.lastFocusedNode):
#print "changed node, flushing"
flush = True
else: flush = False
#print "%s ! %s ! %s" % (str(self.lastTypedNode), str(self.lastFocusedNode), self.typedTextBuffer)
if combo:
self.writer.recordTyping(self.typedTextBuffer, "pressed", self.lastFocusedNode)
self.typedTextBuffer = ""
self.writer.recordKeyCombo(modString + key, type, self.lastFocusedNode)
self.lastTypedNode = self.lastFocusedNode
elif flush:
self.writer.recordTyping(self.typedTextBuffer, "pressed", self.lastTypedNode)
self.typedTextBuffer = key
self.lastTypedNode = self.lastFocusedNode
else:
if self.typedTextBuffer == "":
self.lastTypedNode = self.lastFocusedNode
self.typedTextBuffer = self.typedTextBuffer + key
return
# If we're using the keyString or have modifiers, flush
# self.typedTextBuffer by recording a line and also record the key
# combo.
if modString or flush:
if self.typedTextBuffer:
self.writer.recordTyping(self.typedTextBuffer, "pressed", self.lastFocusedNode)
if not combo:
self.typedTextBuffer = key
else:
self.typedTextBuffer = ""
self.lastTypedNode = self.lastFocusedNode
if modString or combo:
self.writer.recordKeyCombo(modString + key, type, self.lastFocusedNode)
# Otherwise add to the buffer, and wait to flush it.
else:
if self.typedTextBuffer == "":
self.lastTypedNode = self.lastFocusedNode
self.typedTextBuffer = self.typedTextBuffer + key
def onWindowCreate(self, event):
# logEvent(event)
sourceNode = dogtail.tree.Node(event.source)
# print "Window creation: %s"%str(sourceNode)
def getLogStringForNode(self, node):
if self.absoluteNodePaths:
return node.getAbsoluteSearchPath()
else:
return node
# Under construction. These ought to be methods, but am having Python assertion
# failures in refcounting when trying to hook them up using lambda expressions; grrr...
import traceback
def marshalOnFocus(event):
try: recorder.onFocus(event)
except: traceback.print_exc()
def marshalOnSelect(event):
try: recorder.onSelect(event)
except: traceback.print_exc()
def marshalOnMouseButton(event):
try: recorder.onMouseButton(event)
except: traceback.print_exc()
def marshalOnKeyPress(event):
try: recorder.onKeyPress(event)
except: traceback.print_exc()
def marshalOnWindowCreate(event):
try: recorder.onWindowCreate(event)
except: traceback.print_exc()
recorder = EventRecorder()
recorderGUI = RecorderGUI()
#recorder.writer.debug = True
#recorder.writer.debugVariables = True
# vim: sw=4 ts=4 sts=4 et ai