2010-02-25 4 views
9

Мне нужно прослушивать глобальные события мыши (не привязанные к приложению) на моем Mac в приложении, написанном на Python.Как я могу прослушивать событие мыши в Python на Mac?

Я использую PyObjC, но я не могу понять, как это сделать. Также были оценены простые примеры ObjC или другие методы Python.

Мой код до сих пор:

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

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

== вина Сегментация

Я знаю, что мне нужно, чтобы добавить его к источнику события позже, но мне нужно, чтобы получить эту работу первым.

[обновление]

Использование PyObjC форма MacPorts решена Segfault, так что теперь я писал:

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(); 

Но это только работает вечно, и не реагирует на события мыши, что не так?

ответ

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) 
+0

Это должен быть правильный ответ –

-1

Во-первых, CGEventTapCreate и CGEventTapCreateForPSN просачиваться некоторую память, когда они называются. Это необходимо для предотвращения проблем с управлением памятью. Поэтому рекомендуется не называть эти функции, по крайней мере, называть их небольшим числом раз.

Теперь событие мыши что-то вроде это работает:

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

Я не хочу, чтобы отправить событий, я хочу их слушать. CGEventCreateMouseEvent предназначен для создания событий, а не для событий. – Pepijn

+0

Извините. Я испортил вам пример неправильного кода. –

+1

Существует еще один метод для события Tap, который, как я думал, я вам даю. –

1

Документация CGEventTapCreate (http://developer.apple.com/mac/library/documentation/Carbon/Reference/QuartzEventServicesRef/Reference/reference.html#//apple_ref/c/func/CGEventTapCreate) говорит, что вы должны быть корень использовать kCGHIDEventTap. Вы используете свой скрипт как root? (sudo - один из способов сделать это)

Если вы находитесь, вы также должны проверить, нет ли крана None; что поможет сузить проблему. В документации есть несколько условий ошибки, которые могут вызвать CGEventTapCreate, чтобы вернуть NULL, который должен быть отражен как None в Python.

+0

Судо или нет, не имеет значения, и нажмите и запустите LoopSource. Есть ли альтернатива kCGHIDEventTap? Я заметил, что CFRunLoopRunInMode (kCFRunLoopDefaultMode, 20, False) работает в течение 20 секунд, но передача True заканчивается немедленно, но все же не выводится из MyFunction. – Pepijn

+0

Может ли это быть связано с созданием CGEventRef, которое вы пытаетесь напечатать? Возможно, вы можете попробовать напечатать постоянную строку в MyFunction, чтобы убедиться. Кроме этого, я действительно не знаю. –

+0

Я попытался просто напечатать «привет», но это тоже не помогло. Может быть, функция называется где-то, где stdout устанавливается по-другому? – Pepijn