2011-11-21 3 views
6

У меня есть код здесь, который ограничивает мышь для региона на экране, он работает относительно хорошо, только с одной большой проблемой. Мышь не перемещается чисто/плавно при движении по краям области, вместо этого прыгает очень прерывно, я полагаю, что это может быть связано с CGWarpMouseCursorPosition, вызывающим задержку на каждом «деформации».Почему CGWarpMouseCursorPosition вызывает задержку? Если это не так, то что?

Может ли кто-нибудь сказать, что это что-то в моем коде, вызывающее эту задержку, или если это фактически функция деформации мыши. Если это функция деформации мыши, есть ли способ получить плавное перемещение мыши? Я сделал то же самое во флеше, и он работает безупречно, я знаю, что цикл не просто занимает столько времени, чтобы выполнить, что он замедляет работу, потому что он работает только 4 или 5 раз.

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

Я не думаю, что это медленно; время, самое длинное, что я получил, было 0,006 секунды. Это может быть лучше всего несколькими способами: вы должны определить область с разделителями в NS- или CGRect, и я думаю, вы можете вырезать цикл. –

+0

Прямоугольник - это всего лишь временный демонстрационный инструмент. Я на самом деле собираюсь тестировать это на черно-белом растровом изображении, где черные пиксельные зоны удобны для мыши, а белые зоны, на которые мышь не может двигаться. Форма черной области будет довольно странной, и поэтому я думаю, что петля может понадобиться. Разве у вас нет лучшего решения? – BumbleShrimp

+0

Возможно, на самом деле это облегчит поиск мыши, выходящей за пределы приемлемой области. Трюк будет найти ближайший приемлемый момент, чтобы переместить его обратно, но да, я думаю, вам понадобится цикл для этого. Во всяком случае, я удивлен, просто изменив местоположение и дельта события (или даже изменив и вернув копию), не работает. –

ответ

4

Как вы обнаружили, CGSetLocalEventsSuppressionInterval фиксирует вашу проблему.

Однако он не рекомендуется на 10.6. Apple docs:

Эта функция не рекомендуется для общего использования из-за недокументированных особых случаев и нежелательных побочных эффектов. Рекомендуемая замена для этой функции - CGEventSourceSetLocalEventsSuppressionInterval, которая позволяет отрегулировать интервал подавления для конкретного источника события, влияя только на события, отправленные с использованием этого источника событий.

К сожалению, замена CGEventSourceSetLocalEventsSuppressionInterval не работает с CGWarpMouseCursorPosition движениями.

Вместо этого используйте CGAssociateMouseAndMouseCursorPosition(true) сразу после перекоса:

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

документация не имеет никакого упоминания об этом поведении, но, кажется, чтобы отменить интервал подавления после деформации.

1

Вы, вероятно, ищет CGSetLocalEventsSuppressionInterval(), метод нежелателен 10,6 ... он все еще работает, хотя в 10,7.

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

+0

Да, я обнаружил, что на днях, но он работает отлично, поэтому я дам вам ответ. Спасибо за ваше время/усилия. – BumbleShrimp

Смежные вопросы