objective-c macos keyboard-hook nsevent

objective c - Modificar NSEvent para enviar una clave diferente a la que se presionĂ³



objective-c macos (2)

Me encontré con esta respuesta, necesitando hacer lo mismo pero solo para eventos dentro de mi propia aplicación no global. Hay una solución mucho más simple para este problema mucho más simple, que menciono aquí en caso de que sea útil para cualquier otra persona:

  • Intercepté el evento en la ventana, creando una anulación para sendEvent :. Luego reviso los eventos clave (KeyUp o KeyDown) y luego simplemente creo un evento nuevo utilizando casi todos los datos del evento anterior, luego llamo a la superclase NSWindow con este evento.

Esto parece funcionar perfectamente para mí y no tuve que modificar la parte de KeyCode, pero quizás esto podría ser un problema ...

Ejemplo en Swift:

class KeyInterceptorWindow : NSWindow { override func sendEvent(theEvent: NSEvent) { if theEvent.type == .KeyDown || theEvent.type == .KeyUp { println(theEvent.description) let newEvent = NSEvent.keyEventWithType(theEvent.type, location: theEvent.locationInWindow, modifierFlags: theEvent.modifierFlags, timestamp: theEvent.timestamp, windowNumber: theEvent.windowNumber, context: theEvent.context, characters: "H", charactersIgnoringModifiers: theEvent.charactersIgnoringModifiers!, isARepeat: theEvent.ARepeat, keyCode: theEvent.keyCode) super.sendEvent(newEvent!) } else { super.sendEvent(theEvent) } }

}

Estoy tratando de crear un gancho de teclado OS X para fines de tecnología de asistencia (es decir, no se preocupe, no es un registrador de teclas).

Cuando un usuario presiona una tecla, quiero evitar la pulsación de tecla real y enviar una pulsación de tecla falsa (carácter de mi elección) en su lugar.

Tengo el siguiente código:

- (void) hookTheKeyboard { CGEventMask keyboardMask = CGEventMaskBit(kCGEventKeyDown); id eventHandler = [NSEvent addGlobalMonitorForEventsMatchingMask:keyboardMask handler:^(NSEvent *keyboardEvent) { NSLog(@"keyDown: %c", [[keyboardEvent characters] characterAtIndex:0]); //Want to: Stop the keyboard input //Want to: Send another key input instead }]; }

¿Alguna ayuda para lograr alguno de esos objetivos? Básicamente modificando el NSEvent "keyboardEvent" para enviar un carácter diferente. Gracias.


No puede hacer esto con la API de NSEvent , pero puede hacerlo con un CGEventTap . Puede crear un toque de evento activo y registrar una devolución de llamada que recibe un CGEventRef y puede modificarlo (si es necesario) y devolverlo para modificar el flujo de eventos real.

EDITAR

Aquí hay un programa simple que, mientras se ejecuta, reemplaza cada tecla "b" con una "v":

#import <Cocoa/Cocoa.h> CGEventRef myCGEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) { //0x0b is the virtual keycode for "b" //0x09 is the virtual keycode for "v" if (CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode) == 0x0B) { CGEventSetIntegerValueField(event, kCGKeyboardEventKeycode, 0x09); } return event; } int main(int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; CFRunLoopSourceRef runLoopSource; CFMachPortRef eventTap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap, kCGEventTapOptionDefault, kCGEventMaskForAllEvents, myCGEventCallback, NULL); if (!eventTap) { NSLog(@"Couldn''t create event tap!"); exit(1); } runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0); CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes); CGEventTapEnable(eventTap, true); CFRunLoopRun(); CFRelease(eventTap); CFRelease(runLoopSource); [pool release]; exit(0); }

(Historia divertida: cuando estaba editando este post, seguí intentando escribir "reemplaza cada vez que se pulsa", pero seguía saliendo como "reemplaza cada pulsación de" v ". Estaba confundido. Entonces recordé que No había detenido la aplicación todavía.