2011-11-21 3 views
6

Ho un codice qui che limita il mouse a una regione sullo schermo, sta funzionando relativamente bene, con solo un grosso problema. Il mouse non viene spostato in modo pulito/scorrevole quando si corre lungo i bordi dell'area, ma salta in modo molto irregolare, credo che ciò potrebbe essere dovuto a CGWarpMouseCursorPosition che causa un ritardo su ogni "curvatura".Perché CGWarpMouseCursorPosition causa un ritardo? Se non lo è, che cos'è?

Qualcuno può dire se è qualcosa nel mio codice che sta causando questo ritardo, o se è in realtà la funzione di curvatura del mouse. Se è la funzione warp del mouse, c'è un modo per ottenere una traslazione regolare del mouse? Ho fatto la stessa cosa in flash e funziona in modo impeccabile, so che il ciclo non richiede solo tanto tempo per essere eseguito, ma rallenta le cose perché funziona solo 4 o 5 volte.

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

Non penso sia lento; calcolandolo, il tempo più lungo che ho avuto è stato di 0.006 secondi. Potrebbe essere migliore in un paio di modi, però: dovresti definire la regione delimitata in un NS- o CGRect, e penso che tu possa tagliare il ciclo. –

+0

Il rettangolo è solo uno strumento demo temporaneo. Veramente sto testando questo con una bitmap in bianco e nero, in cui le zone dei pixel neri sono ottimizzate per il mouse e le zone bianche in cui il mouse non può spostarsi. La forma dell'area nera sarà piuttosto bizzarra, e quindi penso che il ciclo potrebbe essere necessario. A meno che tu non abbia una soluzione migliore? – BumbleShrimp

+0

Ciò potrebbe rendere più semplice scoprire se il mouse è andato oltre l'area accettabile. Il trucco sarebbe trovare il punto più vicino accettabile per spostarlo di nuovo in, ma sì, penso che avrete bisogno di un ciclo per quello. Ad ogni modo, sono sorpreso semplicemente modificando la posizione e il delta dell'evento (o anche modificando e restituendo una copia) non funziona. –

risposta

4

Come hai scoperto, CGSetLocalEventsSuppressionInterval correzioni vostro problema.

Tuttavia, è deprecato dal 10.6. lo stato dei documenti Apple:

Questa funzione non è consigliata per l'uso generale a causa di casi speciali non documentati e di effetti collaterali indesiderati. La sostituzione consigliata per questa funzione è CGEventSourceSetLocalEventsSuppressionInterval, che consente di regolare l'intervallo di soppressione per un'origine evento specifica, interessando solo gli eventi pubblicati utilizzando tale origine evento.

Sfortunatamente, la sostituzione CGEventSourceSetLocalEventsSuppressionInterval non funziona con i movimenti CGWarpMouseCursorPosition.

Invece, utilizzare CGAssociateMouseAndMouseCursorPosition(true) subito dopo l'ordito:

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

La documentazione non fa menzione di questo comportamento, ma sembra annullare l'intervallo di soppressione dopo l'ordito.

1

Probabilmente siete alla ricerca di CGSetLocalEventsSuppressionInterval(), un metodo deprecato come di 10,6 ... funziona ancora anche se in 10.7.

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

+0

Sì, l'ho trovato l'altro giorno, ma funziona perfettamente, quindi ho intenzione di darti la risposta. Grazie per il tuo tempo/impegno. – BumbleShrimp

Problemi correlati