2015-04-02 25 views
14

Ich verwende CGEventTapCreateForPSN, um Schlüssel für meine Anwendung abzufangen und zu filtern. Ich bin nicht daran interessiert, Ereignisse für andere Anwendungen abzufangen. Ich bin mir ziemlich sicher, dass ein Event Tap zu schwer für meinen Zweck ist, aber ich konnte keinen besseren Weg finden, und die Verwendung des Event Tap funktioniert.CGEventTapCreateForPSN in Mavericks + (GetCurrentProcess nicht weiter unterstützt)

Speziell dieser Code macht was ich will.

GetCurrentProcess(&psn); 
CFMachPortRef eventTap = CGEventTapCreateForPSN(
    &psn, 
    kCGHeadInsertEventTap, 
    kCGEventTapOptionDefault, 
    CGEventMaskBit(kCGEventKeyDown) 
     | CGEventMaskBit(kCGEventKeyUp), 
    eventCallback, 
    userInfo); 

Und mein Rückruf ist schön behandelt, wobei die Ereignisse nur aus der aktuellen Anwendung abgefangen werden.

Leider sind alle Methoden, um die aktuelle ProcessSerialNumber zu erhalten, ab 10.9 veraltet. Es gibt einen alten Standard Weg, um die ProcessSerialNumber kennen zu anderen Routinen im gleichen Prozess passieren, mit dieser Initialisierung ...

ProcessSerialNumber psn = { 0, kCurrentProcess }; 

aber das funktioniert nicht, wenn CGEventTapCreateForPSN Aufruf. Die Headerdatei docs zeigt so viel an, und das folgende Code-Snippet gibt NULL als Bestätigung zurück.

ProcessSerialNumber psn = { 0, kCurrentProcess }; 
CFMachPortRef eventTap = CGEventTapCreateForPSN(
    &psn, 
    kCGHeadInsertEventTap, 
    kCGEventTapOptionDefault, 
    CGEventMaskBit(kCGEventKeyDown) 
     | CGEventMaskBit(kCGEventKeyUp), 
    eventCallback, 
    userInfo); 

kann ich CGEventTapCreate verwenden, aber es greift das gesamte Host, und ich würde dann filtern muß nichts auf meine Bewerbung gerichtet und die CGEventTapProxy undurchsichtig ist, und ich weiß nicht, wie es zu benutzen, um zu bestimmen, Wenn es meine App ist oder nicht.

Ich habe überprüft, dass der veraltete Code immer noch funktioniert, aber Apple kann entscheiden, ihn jederzeit zu entfernen. Also, hat jemand eine Idee, wie ich für den Aufruf CGEventTapCreateForPSN in Mavericks und darüber hinaus fortfahren sollte?

Danke!

+1

Dies ist nicht genau eine Antwort auf Ihre Frage, aber in Bezug auf einen möglichen besseren Weg haben Sie '+ [NSEvent addLocalMonitorForEventsMatchingMask: handler:]' '? – JWWalker

+0

Der Anstoß für die Installation des Ereignisabgriffs für schwerere Gewichte in diesem speziellen Fall besteht darin, dass ich Tastaturereignisse während einer Popup-Menü-Ereignisschleife abfangen (und möglicherweise ändern oder verhindern) muss. Leider überwacht '[NSEvent addLocalMonitorForEventsMatchingMask: handler:]' keine Ereignisse in einer verschachtelten Ereignisschleife. –

+2

Eine andere Methode, die ich zum Filtern von Mausereignissen verwendet habe, ist das Installieren eines Carbon-Event-Handlers auf dem Event-Dispatcher-Ziel ('GetEventDispatcherTarget()'). Soweit ich aus den 10.10 SDK-Headern erkennen kann, sind die erforderlichen APIs nicht veraltet und in 64 Bit verfügbar. – JWWalker

Antwort

0

Ich denke, Sie sollten NSApplication Unterklasse und überschreiben - (void)sendEvent:(NSEvent *)theEvent Methode für diesen Zweck. Von docs:

Sie sollten selten einen echten Bedarf finden Sie eine benutzerdefinierte NSApplication Unterklasse zu erstellen. Im Gegensatz zu einigen objektorientierten Bibliotheken müssen Sie in Cocoa nicht von NSApplication ableiten, um das Verhalten von Apps anzupassen. Stattdessen gibt es viele andere Möglichkeiten, eine App anzupassen.

auch:

WICHTIG

Viele AppKit Klassen verlassen sich auf die NSApplication Klasse und kann nicht richtig funktionieren, bis diese Klasse vollständig initialisiert ist. Daher sollten Sie beispielsweise nicht versuchen, Methoden anderer AppKit-Klassen über eine Initialisierungsmethode einer NSApplication-Unterklasse aufzurufen.

So können Sie alle Ereignisse abfangen, die durch Ihre Anwendung übergeben werden, und benutzerdefinierte NSApplicationDelegate-vererbte Protokollmethoden aufrufen.

Ich bin mir nicht sicher, ob dieser Ansatz das Problem löst, aber Sie versuchen es immer noch.

+0

Nein, das funktioniert nicht. Lesen Sie die Dokumentation genauer. Diese Methode wird nur für Ereignisse im Main Event aufgerufen Es behandelt keine verschachtelten Ereignisschleifen. Siehe die Kommentare, die dem ursprünglichen Beitrag für die gleiche Diskussion beigefügt sind. –