More important that any of the previous tips if you want to avoid wasting lots of time killing locked processes or chasing wierd behaviour:
- Don't do anything much in an event handler set with pyatspy.Registry.registerEventListener(). Rather do the work in your main thread.
I hadn't realized that AT-SPI listeners are synchonous so you're want to do as little as quickly as possible. You can pass references to Accessibles out from the listeners.
I was getting lockups even with my test script that simply prints events. Changing to using gobject.on_idle() solved this. This is a huge relief and a real time saver but I really should have twigged it sooner. After all I once coded many complex interrupt routines in my assembler and embedded C days.
While these removes problems with lockups it introduces a new set as some accessibles are temporary and have gone by the time you process them. At least this is the case with popups where I wanted to process the the tree contained in the window. I guess I'm learning why menus are in the main tree as well, but still haven't found a good way to link them from a popup/pulldown. I think the only way is to make assumptions about where you are and which menu has appeared.
Anyway her's an example that prints accessibles, assuming they stay around. It also assumes that the idels are processed in the order they are added. A much safer approach would be a inter 'process' queue (I think it safe to assume it's non prememtive).
def eventCallback(event):
def printEvent():
ts = int(os.times()[-1] % 10000)
print ts, event.type, event.detail1, event.detail2,
(str(event.any_data) if event.any_data else ''),
'nt', event.host_application, event.source, repr(event.source_role)
return False # remove this func from idle processing
gobject.idle_add(printEvent)
EVENTS = ('document', 'focus', 'object', 'window', 'terminal')
pyatspi.Registry.registerEventListener(eventCallback, *EVENTS)
There's no particular reason that printEvent() is a closure, you can pass arguments like event through idle_add(). Complete code.