OSX: ¿Detecta eventos keyDown en todo el sistema?

Estoy trabajando en una aplicación de tutoría de mecanografía para Mac OSX que necesita que se le envíen pulsaciones de teclas, incluso cuando la aplicación no está enfocada.

¿Hay alguna manera de que el sistema reenvíe las pulsaciones de teclas a la aplicación, posiblemente a través de NSDistributedNotificationCenter? Me busqué en Google tonto, y no he podido encontrar una respuesta ...

EDITAR: Código de muestra a continuación.

Gracias @NSGod por señalarme en la dirección correcta. Terminé agregando unmonitor de eventos globales usando el método addGlobalMonitorForEventsMatchingMask: handler :, que funciona de maravilla. Para completar, mi implementación se ve así:

// register for keys throughout the device...
[NSEvent addGlobalMonitorForEventsMatchingMask:NSKeyDownMask
                                       handler:^(NSEvent *event){

    NSString *chars = [[event characters] lowercaseString];
    unichar character = [chars characterAtIndex:0];

    NSLog(@"keydown globally! Which key? This key: %c", character);

}];

Para mí, la parte difícil era usar bloques, así que daré una pequeña descripción en caso de que ayude a alguien:

Lo que hay que notar sobre el código anterior es que todo esuna sola llamada al método en NSEvent. El bloque se suministra como argumento, directamentea la función. Se podría considerar como un método de delegado en línea. Solo porque me tomó un tiempo asimilarlo, voy a trabajar paso a paso aquí:

[NSEvent addGlobalMonitorForEventsMatchingMask:NSKeyDownMask

Este primer bit no es problema. Está llamando a un método de clase en NSEvent y diciéndole qué evento desea monitorear, en este caso NSKeyDownMask. UNAlista de máscaras para tipos de eventos compatibles puede ser encontradoaquí.

Ahora, llegamos a la parte difícil: controlador, que espera un bloqueo:

handler:^(NSEvent *event){

Me tomó algunos errores de compilación para hacerlo bien, pero (gracias Apple) fueron mensajes de error muy constructivos. Lo primero que debe notar es el quilate ^. Eso señala el inicio del bloqueo. Después de eso, entre paréntesis,

NSEvent *event

Que declara la variable que usará dentro del bloque para capturar el evento. Podrías llamarlo

NSEvent *someCustomNameForAnEvent

no importa, solo usarás ese nombre dentro del bloque. Entonces, eso es casi todo lo que hay que hacer. Asegúrate de cerrar tu llave y el soporte para finalizar la llamada al método:

}];

¡Y tu estas listo! Esto realmente es una especie de 'one-liner'. No importa dónde ejecute esta llamada dentro de su aplicación; lo hago en el método applicationDidFinishLaunching del AppDelegate. Luego, dentro del bloque, puede llamar a otros métodos desde su aplicación.

Respuestas a la pregunta(4)

Su respuesta a la pregunta