如何在Mac上用Python监听鼠标事件?
我需要在我的Mac上监听全局的鼠标事件(不是绑定到某个应用程序的),这个应用是用Python写的。
我在用PyObjC,但我不知道该怎么做。如果有简单的ObjC例子或者其他Python的方法也可以。
到目前为止我的代码是:
from Quartz import *
def MyFunction(proxy, type, event):
print event
CGEventTapCreate(kCGHIDEventTap, kCGTailAppendEventTap, kCGEventTapOptionListenOnly, kCGEventLeftMouseDown, MyFunction)
== 出现了段错误
我知道我需要把它添加到事件源中,但我得先让这个工作起来。
[更新]
使用Macports中的PyObjC解决了段错误,所以我现在写了这个:
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();
但是这个代码一直在运行,没法响应鼠标事件,问题出在哪里呢?
3 个回答
首先,CGEventTapCreate 和 CGEventTapCreateForPSN 这两个函数在被调用时会泄露一些内存。这是为了避免内存管理上的问题。因此,建议不要频繁调用这些函数,或者至少尽量少调用它们。
接下来,鼠标事件的工作原理大致是这样的:
evt = CGEventCreateMouseEvent(None, kCGEventLeftMouseDown, (80, 90), kCGMouseButtonLeft)
self.failUnlessIsInstance(evt, CGEventRef)
关于CGEventTapCreate的说明(你可以在这里找到详细信息:http://developer.apple.com/mac/library/documentation/Carbon/Reference/QuartzEventServicesRef/Reference/reference.html#//apple_ref/c/func/CGEventTapCreate),它提到要使用kCGHIDEventTap这个功能,你需要有管理员权限。你运行你的脚本时是以管理员身份吗?(可以用sudo命令来实现)
如果是的话,你还应该检查一下tap是否为None;这能帮助你更好地找出问题所在。文档中列出了几种错误情况,这些情况可能导致CGEventTapCreate返回NULL,在Python中这会显示为None。
CGEventTapCreate的第四个参数是 CGEventMask eventsOfInterest
,你给它传入了 kCGEventLeftMouseDown
,这是一个类型为 _CGEventType
的枚举值。其实,你需要在位掩码中翻转相应的位,而不是直接使用这个整数常量。你可以使用 CGEventMaskBit
来做到这一点。
所以,不应该这样写:
tap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap,
kCGEventTapOptionListenOnly, kCGEventLeftMouseDown, MyFunction, None)
我们可以这样写:
tap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap,
kCGEventTapOptionListenOnly, CGEventMaskBit(kCGEventLeftMouseDown),
MyFunction, None)
或者等价于:
tap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap,
kCGEventTapOptionListenOnly, (1 << kCGEventLeftMouseDown),
MyFunction, None)