I need to listen for global mouse events(not bound to an app) on my Mac in an app written in Python.
I'm using PyObjC, but I can't figure out how to do it. Plain ObjC examples or other Python techniques also appreciated.
My code so far:
from Quartz import *
def MyFunction(proxy, type, event):
print event
CGEventTapCreate(kCGHIDEventTap, kCGTailAppendEventTap, kCGEventTapOptionListenOnly, kCGEventLeftMouseDown, MyFunction)
== Segmentation fault
I know I need to add it to an event source later on, but I need to get this working first.
[update]
Using PyObjC form Macports solved the segfault, so now I wrote this:
from Quartz import *
def MyFunction(p, t, e, c):
print e
tap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap, kCGEventTapOptionListenOnly, kCGEventLeftMouseDown, MyFunction, None)
runLoopSource = CFMachPortCreateRunLoopSource(None, tap, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode);
CGEventTapEnable(tap, True);
CFRunLoopRun();
But this just runs forever and does not respond to mouse events, what is wrong?
The fourth parameter of CGEventTapCreate is CGEventMask eventsOfInterest
, and you gave it kCGEventLeftMouseDown
which is an enum of type _CGEventType
. Instead of the integer constant, you need to flip the appropriate bit in the bitmask. You can do this using CGEventMaskBit
So instead of this:
tap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap,
kCGEventTapOptionListenOnly, kCGEventLeftMouseDown, MyFunction, None)
We can do this:
tap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap,
kCGEventTapOptionListenOnly, CGEventMaskBit(kCGEventLeftMouseDown),
MyFunction, None)
or equivalently:
tap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap,
kCGEventTapOptionListenOnly, (1 << kCGEventLeftMouseDown),
MyFunction, None)