如何在Mac上用Python监听鼠标事件?

时间:2010-02-25 20:03:45

标签: python objective-c mouseevent pyobjc

我需要在用Mac编写的应用程序中监听Mac上的全局鼠标事件(未绑定到应用程序)。

我正在使用PyObjC,但我无法弄清楚如何做到这一点。简单的ObjC示例或其他Python技术也很受欢迎。

到目前为止我的代码:

from Quartz import *
def MyFunction(proxy, type, event):
    print event

CGEventTapCreate(kCGHIDEventTap, kCGTailAppendEventTap, kCGEventTapOptionListenOnly, kCGEventLeftMouseDown, MyFunction)

==分段错误

我知道我需要稍后将其添加到事件源中,但我需要先使用它。

[更新]

使用PyObjC表单Macports解决了段错误,所以现在我写了这个:

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 个答案:

答案 0 :(得分:2)

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)

答案 1 :(得分:1)

CGEventTapCreate http://developer.apple.com/mac/library/documentation/Carbon/Reference/QuartzEventServicesRef/Reference/reference.html#//apple_ref/c/func/CGEventTapCreate)的文档说您需要是root才能使用kCGHIDEventTap。您是否以root身份运行脚本? (sudo是这样做的一种方式)

如果你是,你还应该检查tap是否为None;这将有助于缩小问题范围。文档中列出的几个错误条件可能导致 CGEventTapCreate 返回NULL,这应该在Python中反映为None。

答案 2 :(得分:-1)

首先, CGEventTapCreate CGEventTapCreateForPSN 会泄漏一些内存 叫做。这是避免内存管理问题所必需的。因此 建议不要调用这些函数,至少称它们为少数 时间。

现在,鼠标事件的工作原理如下:

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