2010-02-25 22 views
9

Necesito escuchar eventos de mouse globales (no vinculados a una aplicación) en mi Mac en una aplicación escrita en Python.¿Cómo puedo escuchar un evento de mouse en Python en Mac?

Estoy usando PyObjC, pero no puedo encontrar la manera de hacerlo. También se aprecian ejemplos de ObjC sencillos u otras técnicas de Python.

Mi código hasta ahora:

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

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

Fallo de segmentación ==

Sé que necesito para añadirlo a una fuente de eventos más adelante, pero tengo que conseguir este trabajo en primer lugar.

[Actualización]

Usando PyObjC forma MacPorts solucionó el error de segmentación, por lo que ahora me escribió esto:

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

Pero esto sólo funciona para siempre y no responde a los eventos del ratón, lo que está mal?

Respuesta

2

El cuarto parámetro de CGEventTapCreate es CGEventMask eventsOfInterest, y le dio kCGEventLeftMouseDown que es una enumeración del tipo _CGEventType. En lugar de que el número entero sea constante, debe voltear el bit apropiado en la máscara de bits. Esto se puede hacer usando CGEventMaskBit

Así que en lugar de esto:

tap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap, 
    kCGEventTapOptionListenOnly, kCGEventLeftMouseDown, MyFunction, None) 

podemos hacer esto:

tap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap, 
    kCGEventTapOptionListenOnly, CGEventMaskBit(kCGEventLeftMouseDown), 
    MyFunction, None) 

o equivalentemente:

tap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap, 
    kCGEventTapOptionListenOnly, (1 << kCGEventLeftMouseDown), 
    MyFunction, None) 
+0

esta debería ser la respuesta correcta –

-1

En primer lugar, CGEventTapCreate y CGEventTapCreateForPSN escape algo de memoria cuando se llaman. Esto es necesario para evitar problemas de administración de memoria. Es por lo tanto aconsejable no llamar a estas funciones, al menos se les llama un pequeño número de veces.

Ahora, un evento de ratón funciona algo como esto:

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

no quiero enviar eventos, quiero escucharlos. CGEventCreateMouseEvent es para crear eventos, no eventos. – Pepijn

+0

Lo siento. Me equivoqué al darte el ejemplo de código incorrecto. –

+1

Hay otro método para el Evento Tap que pensé que te estaba dando. –

1

La documentación para CGEventTapCreate (http://developer.apple.com/mac/library/documentation/Carbon/Reference/QuartzEventServicesRef/Reference/reference.html#//apple_ref/c/func/CGEventTapCreate) dice que tiene que ser root para usar kCGHIDEventTap. ¿Estás ejecutando tu script como root? (sudo es una forma de hacerlo)

Si lo es, también debe comprobar si el toque es Ninguno; eso ayudará a reducir el problema. Hay varias condiciones de error enumeradas en la documentación que pueden causar CGEventTapCreate para devolver NULL, que debe reflejarse como None en Python.

+0

Sudo o no no hace la diferencia, tanto tap como runLoopSource contienen algo. ¿Hay una alternativa a kCGHIDEventTap? Noté que CFRunLoopRunInMode (kCFRunLoopDefaultMode, 20, False) se ejecuta durante 20 segundos, pero el suministro de True termina inmediatamente, pero aún no sale de MyFunction. – Pepijn

+0

¿Podría ser algo relacionado con la codificación del CGEventRef que está intentando imprimir? Quizás puedas intentar imprimir una cadena constante en MyFunction solo para asegurarte. Aparte de eso, realmente no lo sé. –

+0

Intenté simplemente imprimir 'hola', pero eso tampoco ayudó. ¿Podría ser que la función se llame en algún lugar donde stdout se establece de manera diferente? – Pepijn

Cuestiones relacionadas