2011-11-21 9 views
6

Tengo un código aquí que restringe el mouse a una región en la pantalla, funciona relativamente bien, con un solo gran problema. El mouse no se mueve limpiamente/sin problemas cuando se ejecuta a lo largo de los bordes del área, sino que salta de una manera muy entrecortada, creo que esto podría deberse a CGWarpMouseCursorPosition que causa un retraso en cada "deformación".¿Por qué CGWarpMouseCursorPosition causa un retraso? Si no es así, ¿qué es?

¿Alguien puede decir si es algo en mi código que está causando este retraso, o si de hecho es la función de deformación del mouse. Si se trata de la función de deformación del mouse, ¿hay alguna manera de que pueda obtener una reubicación sin problemas del mouse? He hecho lo mismo en flash y funciona sin problemas, sé que el ciclo no solo toma mucho tiempo en ejecutarse que está ralentizando las cosas porque solo funciona 4 o 5 veces.

CGEventRef 
mouse_filter(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) { 


    CGPoint point = CGEventGetLocation(event); 

    float tX = point.x; 
    float tY = point.y; 

    if(tX <= 700 && tX >= 500 && tY <= 800 && tY >= 200){ 
     // target is inside O.K. area, do nothing 
    }else{ 

    CGPoint target; 

    //point inside restricted region: 
    float iX = 600; // inside x 
    float iY = 500; // inside y 

    // delta to midpoint between iX,iY and tX,tY 
    float dX; 
    float dY; 

    float accuracy = .5; //accuracy to loop until reached 

    do { 
     dX = (tX-iX)/2; 
     dY = (tY-iY)/2; 

     if((tX-dX) <= 700 && (tX-dX) >= 500 && (tY-dY) <= 800 && (tY-dY) >= 200){ 
      iX += dX; 
      iY += dY; 
     } else { 
      tX -= dX; 
      tY -= dY; 
     } 

    } while (abs(dX)>accuracy || abs(dY)>accuracy); 

     target = CGPointMake(roundf(tX), roundf(tY)); 
     CGWarpMouseCursorPosition(target); 

    } 



    return event; 
} 

int 
main(int argc, char *argv[]) { 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 
    CFRunLoopSourceRef runLoopSource; 
    CGEventMask event_mask; 
    event_mask = CGEventMaskBit(kCGEventMouseMoved) | CGEventMaskBit(kCGEventLeftMouseDragged) | CGEventMaskBit(kCGEventRightMouseDragged) | CGEventMaskBit(kCGEventOtherMouseDragged); 

    CFMachPortRef eventTap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap, 0, event_mask, mouse_filter, 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); 
} 
+0

No creo que sea lento; cronometrando, el tiempo más largo que tardé fue de 0.006 segundos. Sin embargo, podría ser mejor en un par de formas: debe definir la región delimitada en un NS- o CGRect, y creo que puede cortar el bucle. –

+0

El rectángulo es solo una herramienta de demostración temporal. De hecho, voy a probar esto con un mapa de bits en blanco y negro, donde las zonas de píxeles negros son aptas para ratón y zonas blancas en las que el mouse no se puede mover. La forma del área negra será bastante extraña y, por lo tanto, creo que el ciclo puede ser necesario. A menos que tengas una mejor solución? – BumbleShrimp

+0

Eso en realidad podría hacer que sea más fácil encontrar si el mouse se ha salido del área aceptable. El truco sería encontrar el punto aceptable más cercano para moverlo de nuevo a, pero sí, creo que necesitarás un bucle para eso. De todos modos, me sorprende que simplemente modificar la ubicación y el delta del evento (o incluso modificar y devolver una copia) no funcione. –

Respuesta

4

Como has descubierto, CGSetLocalEventsSuppressionInterval solucione el problema.

Sin embargo, está obsoleto a partir de 10.6. Apple docs Estado:

Esta función no está recomendado para uso general debido a los casos especiales sin papeles y efectos secundarios indeseables. El reemplazo recomendado para esta función es CGEventSourceSetLocalEventsSuppressionInterval, que permite ajustar el intervalo de supresión para un origen de evento específico, afectando solo los eventos publicados utilizando ese origen de evento.

Desafortunadamente, el reemplazo CGEventSourceSetLocalEventsSuppressionInterval no funciona con CGWarpMouseCursorPosition movimientos.

su lugar, utilice CGAssociateMouseAndMouseCursorPosition(true) inmediatamente después de la urdimbre:

CGPoint warpPoint = CGPointMake(42, 42); 
CGWarpMouseCursorPosition(warpPoint); 
CGAssociateMouseAndMouseCursorPosition(true); 

La documentación no hace mención de este comportamiento, pero parece que cancelar el intervalo de supresión después de la urdimbre.

1

probablemente usted está buscando CGSetLocalEventsSuppressionInterval(), un método de utilizarse a partir de 10.6 ... todavía funciona aunque en 10.7.

http://developer.apple.com/library/mac/#documentation/Carbon/Reference/QuartzEventServicesRef/DeprecationAppendix/AppendixADeprecatedAPI.html#//apple_ref/c/func/CGSetLocalEventsSuppressionInterval

+0

Sí, el otro día lo encontré, pero funciona perfectamente, así que le daré la respuesta. Gracias por su tiempo/esfuerzo. – BumbleShrimp

Cuestiones relacionadas