2010-12-23 18 views
5

Estoy tratando de agregar un evento trampa para habilitar/deshabilitar evento desde mi panel táctil mágico. Pensé que esto sería sencillo, es decir, registrar un evento trampa y, cuando sea necesario, descartar el evento al devolver NULL. La idea es usar el parche para una entrada de datos específica que consume mucho tiempo, las aplicaciones para ingresar los datos son de terceros, así que no puedo simplemente agregar el código para quererlo allí. Así que pensé en monitorear los eventos del sistema y luego enviar la entrada deseada a través de un grupo de CGEventCreateKeyboardEvent s.Consumir eventos de mouse/trackpad OSX con un evento toque

El problema es que devolver nulo no parece descartar los eventos, un poco más de investigación sugiere que esto no está restringido a los que provienen del trackpad sino también a mi mouse usb predeterminado.

Mi código está por debajo. Con lo que está debajo espero no poder mover el mouse, si cambio (A) para usar kCGEventScrollWheel o kCGEventLeftMouseDragged, entonces el evento se consume, es decir, desplazamiento o arrastre hacia la izquierda no ocurren. ¿Esto significa que no todos los eventos pueden descartarse? Con suerte sólo estoy perdiendo algo obvio aquí

#define case_print(a) case a: printf("%s - %d\n",#a,a); break; 


    CGEventRef eventOccurred(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void* refcon) { 
    int subType = CGEventGetIntegerValueField(event, kCGMouseEventSubtype); 
    if (type == NSEventTypeGesture || subType == NX_SUBTYPE_MOUSE_TOUCH) { 
     printf("touchpad\n"); 

     switch(type) { 
       case_print(kCGEventNull) 
       case_print(kCGEventLeftMouseDown) 
       case_print(kCGEventLeftMouseUp) 
       case_print(kCGEventRightMouseDown) 
       case_print(kCGEventRightMouseUp) 
       case_print(kCGEventMouseMoved) 
       case_print(kCGEventLeftMouseDragged) 
       case_print(kCGEventRightMouseDragged) 
       case_print(kCGEventScrollWheel) 
       case_print(kCGEventOtherMouseDown) 
       case_print(kCGEventOtherMouseUp) 
       case_print(kCGEventOtherMouseDragged) 
       case_print(kCGEventTapDisabledByTimeout) 
       case_print(kCGEventTapDisabledByUserInput) 
       case_print(NSEventTypeGesture) 
       case_print(NSEventTypeMagnify) 
       case_print(NSEventTypeSwipe) 
       case_print(NSEventTypeRotate) 
       case_print(NSEventTypeBeginGesture) 
       case_print(NSEventTypeEndGesture) 
      default: 
       printf("default: %d\n",type); 
       break;  
     } 

     event = NULL; 
    } else { 
     if (type == kCGEventMouseMoved) { // (A) 
      printf("discarding mouse event"); 
      event = NULL; 
     } 
    } 

    return event; 
} 


CFMachPortRef createEventTap() { 
    CGEventMask eventMask = NSAnyEventMask; 

    if (!AXAPIEnabled() && !AXIsProcessTrusted()) { 
     printf("axapi not enabled"); 
    } 

    return CGEventTapCreate(kCGHIDEventTap, 
          kCGHeadInsertEventTap, 
          kCGEventTapOptionDefault, 
          eventMask, 
          eventOccurred, 
          NULL); 
} 

int main (int argc, const char * argv[]) { 
    CFMachPortRef tap = createEventTap(); 

    if (tap) { 
     CFRunLoopSourceRef rl = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, tap, 0); 
     CFRunLoopAddSource(CFRunLoopGetMain(), rl, kCFRunLoopCommonModes); 
     CGEventTapEnable(tap, true); 
     CFRunLoopRun(); 

     printf("Tap created.\n"); 
     sleep(-1); 
    } else { 
     printf("failed!\n"); 
    } 

    return 0; 
} 

Nota: "axapi no está activado" no se emitirá aunque yo no creo que la opción de accesibilidad afecta a todo menos los eventos de teclado.

Por cierto, he visto algunas publicaciones similares sobre cómo obtener los eventos del panel táctil, simplemente no hay nada aplicable a descartarlos (aparte de devolver el nulo debería funcionar).

Respuesta

1

Si su toque es pasivo, al devolver NULL no se verá afectado el flujo de eventos. De la documentación CGEventTapCallBack referencia:.

"Si el grifo evento es una oyente pasivo, la función de devolución de llamada puede devolver el caso de que se pasa en, o NULL En cualquier caso, el flujo de eventos no es afectado."

Sin embargo, parece que el grifo está activo. Por lo tanto, su NULL de retorno debería eliminar el evento. ¿Has considerado modificar el evento para anular la acción?

También tenga en cuenta que la llamada CGEventTapCreate requiere permisos de usuario raíz para interceptar todos los eventos. ¿Tu proceso se ejecuta como root?

+0

¿Por qué se marcó como la respuesta? ¿Pudiste detener el procesamiento de un evento de mouse? Puedo detener los eventos clave, pero no los movimientos del mouse ... – cksubs

4

Creo que no es posible descartar simplemente estos eventos. Desde el archivo de cabecera CGEventTypes.h:

"El caso pasó a la devolución de llamada es retenido por el código de llamada, y es en libertad después de la devolución de llamada devuelve y los datos se pasan de nuevo al sistema evento. Si un evento diferente se devuelto por la función de devolución de llamada, entonces ese evento se dará a conocer por el código de llamada junto con el evento original , después de que los datos de eventos se ha transmitido de vuelta al sistema de eventos ".

He jugado un poco con esto y parece que después de que devuelve la devolución de llamada, el servidor de la ventana comprueba activamente nuevamente lo que has hecho con el evento.Solo permite la eliminación de eventos clave y eventos de mouse arriba/abajo, pero al igual que ignora la eliminación de eventos movidos por el mouse (bueno, el renderizado del mouse se procesa en cualquier otro lugar, creo) parece ignorar la eliminación (es decir, su devolución de llamada devuelve NULL) para los gestos del mouse

Las figuras, considerando tocar para gestos no se explican específicamente en la documentación (ningún tipo definido en este nivel).

He intentado devolver un evento diferente (presionando una tecla) y este se maneja adicionalmente al gesto original. Liberar el evento en su devolución de llamada no lo hace, ya sea (por supuesto), solo resulta en una excepción.

Lo único que no probé es manipular directamente los datos internos pasados ​​de CGEvent para al menos hacer que el gesto no haga nada (eliminar todos los movimientos, etc.), pero eso es difícil porque no hay métodos específicos definidos para hacer ese. Sin embargo, estoy bastante seguro de que la información necesaria se encuentra en algún lugar de los diversos campos accesibles a través de los métodos CGEventSet *.

Miré tan lejos como IOLLEvent.h para descubrir su estructura de datos, pero esto era demasiado feo para que mi gusto profundizara aún más. Esperemos que Lion ofrezca un poco más sobre el tipo de gesto de eventos en el nivel CF.

+1

que serían CGEventSetIntegerValueField (event, kCGMouseEventDeltaX, 0); y CGEventSetIntegerValueField (event, kCGMouseEventDeltaY, 0); pero también es ignorado. – valexa

3

Puedo corroborar que en 10.6 ninguno de los siguientes métodos tiene éxito para este propósito.

1-devuelva NULL

2-devolviendo un nuevo evento de ratón con la posición anterior del cursor

3-devolver el evento pasado con él es kCGMouseEventDelta de cambió a 0

No puedo hablar de 10.7 pero digamos que no levantaré mis esperanzas.

Sin embargo, hay una cosa que podría hacer en lugar de soltar el movimiento, moverlo de nuevo a la ubicación anterior con CGWarpMouseCursorPosition, en efecto, el cursor dejará de moverse con solo un ligero cambio en el primero.

+0

Mi experiencia es la misma ... no puedo devolver nulo ni modificar los deltas para evitar el movimiento del mouse. Muevo el cursor hacia atrás pero el cursor todavía parpadea en la ubicación original. Esperando evitar eso aquí: http://stackoverflow.com/questions/9899534/prevent-mousemovedevent-callback-from-processing-the-movement-or-globally-hid – cksubs

Cuestiones relacionadas