Como monitorar o estado da tecla modificadora global (em qualquer aplicativo)?

Estou usando algum código Carbono no meu projeto Cocoa para manipular eventos de chaves globais (atalhos) de outros aplicativos. Atualmente eu configurei umkEventHotKeyReleased manipulador de eventos e posso obter com sucesso teclas de atalho quando meu aplicativo não está ativo. Isso aciona alguma operação no meu aplicativo.

O problema que tenho com o comportamento dekEventHotKeyReleased é:

Digamos, por exemplo, pressione a combinação de teclas Cmd-Shift-P. Assim que eu solto a tecla "P", o evento da tecla de atalho é acionado.Eu preciso ser capaz de acionar o evento (ou acioná-lo manualmente) quandotodos das chaves são desfeitas (isto é, as teclas Cmd e Shift são liberadas também).

É fácil monitorar as teclas de atalho, mas não vi nada para monitorar as teclas digitadas individualmente. Se eu pudesse monitorar os estados da tecla modificadora, eu estaria no negócio.

Alguma dica de como fazer isso?

Desde já, obrigado!

ATUALIZAR:

Eu tentei usarkEventRawKeyUp ekEventRawKeyModifiersChanged mas enquantokEventHotKeyReleased funciona esses dois não, mesmo que eu configurá-los da mesma maneira comokEventHotKeyReleased.

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

oglobalHotKeyHandler método é chamado parakEventHotKeyReleasedmas não parakEventRawKeyUp Por alguma razão eu não consigo entender. Aqui está o meuglobalHotKeyHandler método se parece com:

OSStatus globalHotkeyHandler(EventHandlerCallRef nextHandler, EventRef anEvent, void *userData) {
    NSLog(@"Something happened!");
}

Existe uma chamada adicional que precisa ser feita ou outra coisa que eu esqueci?

N.B: À primeira vista, parece que o Access for Assistive Devices está desativado, masnão é. Então eu sou bem sem noção.

ATUALIZAÇÃO 2:

Eu investiguei um pouco sobre oCGEventTap Leibowitzn sugeriu e eu criei esta configuração:

CFMachPortRef keyUpEventTap = CGEventTapCreate(kCGHIDEventTap,kCGHeadInsertEventTap,kCGEventTapOptionListenOnly,kCGEventKeyUp,&keyUpCallback,NULL);
CFRunLoopSourceRef keyUpRunLoopSourceRef = CFMachPortCreateRunLoopSource(NULL, keyUpEventTap, 0);
CFRelease(keyUpEventTap);
CFRunLoopAddSource(CFRunLoopGetCurrent(), keyUpRunLoopSourceRef, kCFRunLoopDefaultMode);
CFRelease(keyUpRunLoopSourceRef);

... e o retorno de chamada:

CGEventRef keyUpCallback (CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {
    NSLog(@"KeyUp event tapped!");
    return event;
}

Como você pode ver, estou usandokCGEventKeyUp como a máscara para o evento toque, mas de alguma forma eu estou recebendoeventos de mouse para baixo ??!

ATUALIZAÇÃO 3:

Ok esqueça que, eu esqueci a linha no documento que dizia usar CGEventMaskBit (kCGEventKeyUp) para este parâmetro, então a chamada correta é:

CGEventTapCreate(kCGHIDEventTap,kCGHeadInsertEventTap,kCGEventTapOptionListenOnly,CGEventMaskBit(kCGEventKeyUp),&keyUpCallback,NULL);

Eu ainda estou tendo um problema: as teclas modificadoras não ativam o kCGEventKeyUp ...

ATUALIZAÇÃO 4:

Ok esqueça isso de novo ... Estou obrigado a responder às minhas próprias perguntas 5 minutos depois de pedir-lhes hoje hein!

Para interceptar teclas modificadoras, usekCGEventFlagsChanged:

CGEventTapCreate(kCGHIDEventTap,kCGHeadInsertEventTap,kCGEventTapOptionListenOnly,CGEventMaskBit(kCGEventFlagsChanged),&callbackFunction,NULL);

Então, em essência, eu tenho a chave e modificador de detecção de estado chave trabalhando, masEu ainda estou interessado em saberporque kEventRawKeyUp não funciona...

N.B: Observe também que estou desenvolvendo no Tiger com o objetivo de ter suporte para versões novas e antigas do sistema operacional o máximo possível. O CGEventTap é apenas 10.4 +, por isso vou usar isso por enquanto, mas uma solução compatível com versões anteriores seria bem-vinda.

questionAnswers(2)

yourAnswerToTheQuestion