Jak monitorować stan klucza modyfikatora globalnego (w dowolnej aplikacji)?
Używam kodu węglowego w moim projekcie Cocoa do obsługi globalnych zdarzeń kluczowych (skrótów) z innych aplikacji. Obecnie mam konfigurację akEventHotKeyReleased
obsługa zdarzeń i mogę z powodzeniem uzyskać skróty klawiszowe, gdy moja aplikacja nie jest aktywna. To powoduje pewne działanie w mojej aplikacji.
Mam problem z zachowaniemkEventHotKeyReleased
jest:
Powiedz na przykład, że naciskam kombinację klawiszy Cmd-Shift-P. Jak tylko zwolnię klawisz „P”, wyzwalane jest zdarzenie „hot key”.Muszę być w stanie wyzwolić zdarzenie (lub uruchomić je ręcznie), gdywszystko klawiszy nie jest wciśnięty (tj. zwolnione są także klawisze Cmd i Shift).
Łatwo jest monitorować klawisze dostępu, ale nie widziałem nic do monitorowania poszczególnych naciśnięć klawiszy. Gdybym mógł monitorować stan klawiszy modyfikujących, byłbym w biznesie.
Jakieś wskazówki, jak to zrobić?
Z góry dziękuję!
AKTUALIZACJA:
Próbowałem użyćkEventRawKeyUp
ikEventRawKeyModifiersChanged
ale kiedykEventHotKeyReleased
działa te dwa nie, chociaż ustawiam je dokładnie tak samo jakkEventHotKeyReleased
.
EventTypeSpec eventTypes[] = {{kEventClassKeyboard, kEventHotKeyReleased}, {kEventClassKeyboard, kEventRawKeyUp}};
// Changing the order in the list does not help, nor does removing kEventHotKeyReleased
OSStatus err = InstallApplicationEventHandler(&globalHotkeyHandler, GetEventTypeCount(eventTypes), eventTypes, NULL, NULL);
// err == noErr after this line
TheglobalHotKeyHandler
metoda jest wymaganakEventHotKeyReleased
, ale nie dlakEventRawKeyUp
z jakiegoś powodu nie mogę pojąć. Oto co mojeglobalHotKeyHandler
metoda wygląda następująco:
OSStatus globalHotkeyHandler(EventHandlerCallRef nextHandler, EventRef anEvent, void *userData) {
NSLog(@"Something happened!");
}
Czy istnieje dodatkowe połączenie, które trzeba wykonać lub coś, o czym zapomniałem?
N.B: Na pierwszy rzut oka wygląda na to, że dostęp do urządzeń wspomagających jest wyłączony, alenie jest. Więc jestem całkiem nieświadomy.
AKTUALIZACJA 2:
Zbadałem trochę na tematCGEventTap
Leibowitzn zasugerował i wymyśliłem tę konfigurację:
CFMachPortRef keyUpEventTap = CGEventTapCreate(kCGHIDEventTap,kCGHeadInsertEventTap,kCGEventTapOptionListenOnly,kCGEventKeyUp,&keyUpCallback,NULL);
CFRunLoopSourceRef keyUpRunLoopSourceRef = CFMachPortCreateRunLoopSource(NULL, keyUpEventTap, 0);
CFRelease(keyUpEventTap);
CFRunLoopAddSource(CFRunLoopGetCurrent(), keyUpRunLoopSourceRef, kCFRunLoopDefaultMode);
CFRelease(keyUpRunLoopSourceRef);
... i wywołanie zwrotne:
CGEventRef keyUpCallback (CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {
NSLog(@"KeyUp event tapped!");
return event;
}
Jak widać, używamkCGEventKeyUp
jak maska zdarzenia, ale jakoś to odbieramzdarzenia myszy w dół ??
AKTUALIZACJA 3:
Ok, zapomnij o tym, przeoczyłem wiersz w dokumencie, który powiedział, że używa tego CGEventMaskBit (kCGEventKeyUp), więc prawidłowe połączenie to:
CGEventTapCreate(kCGHIDEventTap,kCGHeadInsertEventTap,kCGEventTapOptionListenOnly,CGEventMaskBit(kCGEventKeyUp),&keyUpCallback,NULL);
Nadal mam problem: klawisze modyfikujące nie wyzwalają kCGEventKeyUp ...
AKTUALIZACJA 4:
Ok, zapomnij o tym jeszcze raz ... Odpowiem na moje pytania będę musiał odpowiedzieć 5 minut po zapytaniu ich dzisiaj, huh!
Aby przechwytywać klawisze modyfikujące, użyjkCGEventFlagsChanged
:
CGEventTapCreate(kCGHIDEventTap,kCGHeadInsertEventTap,kCGEventTapOptionListenOnly,CGEventMaskBit(kCGEventFlagsChanged),&callbackFunction,NULL);
Tak więc w istocie udało mi się wykryć stan klucza klucza modyfikującego i modyfikatora, aleNadal jestem zainteresowany poznaniemczemu kEventRawKeyUp
nie działa...
N.B: Zauważ również, że pracuję nad Tiger, aby w jak największym stopniu obsługiwać nowe i starsze wersje systemu operacyjnego. CGEventTap ma tylko 10.4+, więc na razie będę go używać, ale rozwiązanie kompatybilne wstecz będzie mile widziane.