Pergunta

Eu estou usando algum código de Carbono no meu projeto de cacau para lidar com os principais eventos globais (atalhos) de outras aplicações. Atualmente tenho configurar um manipulador de eventos kEventHotKeyReleased e eu com êxito pode obter chaves quentes quando meu aplicativo não está ativo. Que desencadeia uma operação em meu aplicativo.

O problema que tenho com o comportamento de kEventHotKeyReleased é:

dizer por exemplo que pressione a combinação de teclas Command-Shift-P. Assim que eu solte a tecla "P", o evento tecla de atalho é acionado. Eu preciso ser capaz de disparar o evento (ou acioná-lo manualmente) quando todas das chaves são unpressed . (Ou seja: o Cmd e Shift são liberados também)

É fácil para monitorar as teclas de atalho, mas eu não vi nada para monitorar as teclas digitadas individuais. Se eu pudesse monitorar os estados-chave modificadoras eu estaria no negócio.

Todas as dicas sobre como fazer isso?

Agradecemos antecipadamente!


UPDATE:

Eu tentei usar kEventRawKeyUp e kEventRawKeyModifiersChanged mas enquanto kEventHotKeyReleased funciona aqueles dois não, embora eu configurá-los na exata mesma maneira que kEventHotKeyReleased.

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

O método globalHotKeyHandler é chamado para kEventHotKeyReleased, mas não para kEventRawKeyUp por algum motivo eu não consigo entender. Aqui está o que o meu método globalHotKeyHandler parece com:

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

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

NB: À primeira vista, parece que ele poderia ser que o acesso de dispositivos de assistência está desativada, mas não é . Então eu sou muito ignorante.


UPDATE 2:

Eu investiguei um pouco sobre o CGEventTap Leibowitzn sugeriu e eu vim com essa 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);

... eo callback:

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

Como você pode ver eu estou usando kCGEventKeyUp como a máscara para a torneira evento, mas de alguma forma eu estou recebendo do mouse eventos ??! ??


Update 3:

Ok esquecer que, eu tinha vista para a linha no doc que disse para usar CGEventMaskBit (kCGEventKeyUp) para este parâmetro, para que a chamada correta é:

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

Ainda estou tendo um problema, porém: as teclas modificadoras não acionar o kCGEventKeyUp ...


Update 4:

Ok esquecer que de novo ... Eu sou obrigado a resposta às minhas próprias perguntas 5 minutos após pedindo-lhes huh hoje!

Para chaves interceptar modificadoras, uso kCGEventFlagsChanged:

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

Então, em essência eu tenho a chave e modificador de chave de trabalho de detecção de estado, mas eu ainda estou interessado em saber por kEventRawKeyUp não trabalho ...


NB: Observe também que estou desenvolvendo em Tiger com o objetivo de ter suporte para novos e mais velhos versões do sistema operacional, tanto quanto possível. CGEventTap é 10.4+ somente assim eu vou estar usando isso para agora, mas uma solução compatível com versões anteriores seria bem-vinda.

Foi útil?

Solução

Uma opção é EventTaps uso. Isso permite monitorar todos os eventos de teclado. Vejo: http://developer.apple.com/mac/library/documentation/Carbon/Reference/QuartzEventServicesRef/Reference/reference.html#//apple_ref/c/func/CGEventTapCreate

Infelizmente torneiras evento irá parar de funcionar se um aplicativo está solicitando entrada segura. Por exemplo Quicken.

Outras dicas

OSStatus err = InstallApplicationEventHandler(&globalHotkeyHandler, GetEventTypeCount(eventTypes), eventTypes, NULL, NULL);

Este não é global. Isso instala o manipulador somente quando o seu próprio aplicativo está ativo, e (creio eu) após próprios filtros de eventos do gerenciador de eventos do Carbon.

Você precisa usar InstallEventHandler, que leva um alvo evento como seu primeiro parâmetro (InstallApplicationEventHandler é uma macro que passa o destino do evento de aplicação).

Para os eventos que ocorrem durante a sua aplicação não está ativo, o alvo que você quer é GetEventMonitorTarget(). Para eventos que ocorrem enquanto o aplicativo é ativo, o alvo que você quer é GetEventDispatcherTarget(). Para eventos de captura não importa qual aplicativo está ativo, instalar o manipulador em ambos os alvos.

Hoje em dia, porém, eu tinha acabado de usar CGEventTaps, como Leibowitzn sugeriu.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top