2010-02-25 9 views
9

Ich muss in einer in Python geschriebenen App auf globale Mausereignisse (nicht an eine App gebunden) auf meinem Mac warten.Wie kann ich ein Mausereignis in Python auf dem Mac hören?

Ich benutze PyObjC, aber ich kann nicht herausfinden, wie es geht. Einfache ObjC-Beispiele oder andere Python-Techniken werden ebenfalls geschätzt.

Mein Code so weit:

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

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

== Segmentation fault

Ich weiß, dass ich es zu einer Ereignisquelle später hinzufügen müssen, aber ich brauche diese erste Arbeit zu bekommen.

[update]

Mit PyObjC Form Macports die segfault gelöst, so jetzt habe ich dies:

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

Aber das läuft nur für immer und reagiert nicht auf Mausereignisse, was ist falsch?

Antwort

2

Der vierte Parameter von CGEventTapCreate ist CGEventMask eventsOfInterest, und Sie gaben es kCGEventLeftMouseDown, die eine Enum des Typs _CGEventType ist. Anstelle der Ganzzahlkonstante müssen Sie das entsprechende Bit in der Bitmaske spiegeln. Sie können diese CGEventMaskBit

Also anstatt dies mit tun:

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

Wir können dies tun:

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

oder äquivalent:

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

Dies sollte die richtige Antwort sein –

-1

Zuerst CGEventTapCreate und CGEventTapCreateForPSN einige Speicherverlust, wenn sie genannt werden. Dies wird benötigt, um Speicherverwaltungsprobleme zu vermeiden. Es ist daher ratsam, diese Funktionen nicht aufzurufen, zumindest nennen sie sie eine kleine Nummer von Zeiten.

Jetzt, ein Maus-Ereignis so etwas wie dies funktioniert:

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

Ich will nicht senden Ereignisse, ich möchte auf sie hören. CGEventCreateMouseEvent dient zum Erstellen von Ereignissen und nicht zum Abhören von Ereignissen. – Pepijn

+0

Entschuldigung. Ich habe es versäumt, Ihnen das falsche Codebeispiel zu geben. –

+1

Es gibt eine andere Methode für das Tap Event, von der ich dachte, dass ich sie dir geben würde. –

1

Die Dokumentation für CGEventTapCreate (http://developer.apple.com/mac/library/documentation/Carbon/Reference/QuartzEventServicesRef/Reference/reference.html#//apple_ref/c/func/CGEventTapCreate) sagt, dass Sie benötigen root sein kCGHIDEventTap zu verwenden. Führen Sie Ihr Skript als root aus? (sudo ist eine Möglichkeit, dies zu tun)

Wenn Sie sind, sollten Sie auch überprüfen, ob Tap ist keine; das wird helfen, das Problem einzugrenzen. In der Dokumentation sind mehrere Fehlerzustände aufgeführt, die dazu führen können, dass CGEventTapCreate NULL zurückgibt, was in Python als None angezeigt werden sollte.

+0

Sudo oder nicht macht keinen Unterschied, sowohl tap und runLoopSource enthalten etwas. Gibt es eine Alternative zu kCGHIDEventTap? Ich habe festgestellt, dass CFRunLoopRunInMode (kCFRunLoopDefaultMode, 20, False) 20 Sekunden lang ausgeführt wird, aber die Ausgabe von True wird sofort beendet, aber nicht von MyFunction ausgegeben. – Pepijn

+0

Könnte es etwas damit zu tun haben, die CGEventRef, die Sie drucken möchten, zu stringieren? Vielleicht könnten Sie versuchen, eine konstante Zeichenfolge in MyFunction zu drucken, nur um sicherzugehen. Ansonsten weiß ich es nicht genau. –

+0

Ich habe versucht, nur 'Hallo' zu drucken, aber das hat auch nicht geholfen. Könnte es sein, dass die Funktion irgendwo aufgerufen wird, wo stdout anders eingestellt ist? – Pepijn