11
votes

Comment puis-je écouter un événement de souris à Python sur Mac?

J'ai besoin d'écouter les événements mondiaux de la souris (non liés à une application) sur mon Mac dans une application écrite dans Python.

J'utilise Pyobjc, mais je ne peux pas comprendre comment le faire. Les exemples unis objc ou d'autres techniques de python ont également apprécié. P>

Mon code jusqu'à présent: p>

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


0 commentaires

3 Réponses :


-1
votes

Premier, cgeventtapcreate strong> et cgeventtapcreateforpsn strong> fuite de la mémoire quand ils sont appelés. Ceci est nécessaire pour éviter les problèmes de gestion de la mémoire. Il est donc conseillé de ne pas appeler ces fonctions, les appelent au moins un petit nombre de fois.

Maintenant, un événement de souris fonctionne comme ceci: P>

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


2 commentaires

Je ne veux pas envoyer d'événements, je veux écouter pour eux. CGEventCreatemouseevent est destiné à créer des événements, pas de robinets d'événement.


Il existe une autre méthode pour l'événement TAP que je pensais que je vous donnais.



1
votes

La documentation pour cgeventtapcreate ( http://developer.apple.com/mac/library/documentation/carbon/reference/quartzeventservicesref/reference/reference.html#//apple_ref/c/func / Cgeventtaprcreate ) dit que vous devez être root à utiliser kcghideventTap. Exécutez votre script en tant que root? (sudo est une façon de le faire)

Si vous êtes, vous devez également vérifier si le robinet n'est pas; cela aidera à réduire le problème. Il existe plusieurs conditions d'erreur énumérées dans la documentation pouvant causer cgeventtapcreate pour renvoyer NULL, qui doit être reflétée comme aucun dans Python.


3 commentaires

Sudo ou non ne fait pas une différence, le robinet et le runloopsource contiennent quelque chose. Y a-t-il une alternative à KCGHIdeventTap? J'ai remarqué que cfrunloopruninmode (kcfrunloopdefauldmode, 20, false) fonctionne pendant 20 secondes, mais la fourniture de véritables extrémités immédiatement, mais elle n'est toujours pas sortie de la mycée.


Pourrait-il être quelque chose à voir avec le stringifiant le cgeventtref que vous essayez d'imprimer? Peut-être que vous pourriez essayer d'imprimer une chaîne constante dans la mycée juste pour vous assurer. Autre que cela, je ne sais pas vraiment.


J'ai essayé de simplement imprimer 'salut', mais cela n'a pas aidé non plus. Pourrait-il être que la fonction est appelée quelque part où stdout est défini différemment?



3
votes

Le quatrième paramètre de CGENTTTAPCreate est CGENTMASK EFRESOFIEREST CODE>, et vous l'avez donné KCGENventLeftMouseDown code> qui est un énorme de type _cgeventtype code>. Au lieu de la constante entière, vous devez retourner le bit approprié dans le masque de bit. Vous pouvez le faire en utilisant cgeventmaskbit code>

donc au lieu de cela: p> xxx pré>

Nous pouvons faire ceci: p>

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


0 commentaires