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 modifiers parameter is as for the keyboard events, see Working with the keyboard. When the user begins a drag operation (i.e., pressing and holding a mouse button and then moving the mouse), the window in which they began the drag will continue to receive the on_mouse_drag event as long as the button is held down.
import pymouse width, height = m. screen_size() midWidth = (width + 1) / 2 midHeight = (height + 1) / 2 m = PyMouse() k = PyKeyboard() def onClick(): m. move(midWidth, midHeight) try: while True: # if button is held down: # continue # onClick() except KeyboardInterrupt: print('\nDone.
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With