开发者

How can I listen for a mouse event in Python on Mac?

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 c开发者_开发百科ode 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)


The documentation for CGEventTapCreate (http://developer.apple.com/mac/library/documentation/Carbon/Reference/QuartzEventServicesRef/Reference/reference.html#//apple_ref/c/func/CGEventTapCreate) says that you need to be root to use kCGHIDEventTap. Are you running your script as root? (sudo is one way to do this)

If you are, you should also check whether tap is None; that will help narrow down the problem. There are several error conditions listed in the documentation that can cause CGEventTapCreate to return NULL, which should be reflected as None in Python.


First, CGEventTapCreate and CGEventTapCreateForPSN leak some memory when they are called. This is needed to avoid memory management problems. It is therefore advisable not to call these functions, are at least call them a small number of times.

Now, a mouse event works something like this:

evt = CGEventCreateMouseEvent(None, kCGEventLeftMouseDown, (80, 90), kCGMouseButtonLeft)
self.failUnlessIsInstance(evt, CGEventRef)
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜