2011-01-18 8 views
2

Итак, я потратил кучу времени на создание этого действительно классного приложения для макросов клавиатуры. Он отлично работает, единственная проблема заключается в том, что через пару минут он просто перестает работать. Он перестает называться, когда я нажимаю клавишу.Приложение случайно перестает получать нажатия клавиш (CGEventTaps)

Я не смог заблокировать его, но это всегда занимает не менее 30 секунд. Обычно это не произойдет в течение нескольких минут. К тому времени я перехвачу и отправил много событий. Приложение все еще работает, когда это происходит.

Вот пример того, что я делаю, чтобы слушать

-(void)listen { 

     CFMachPortRef downEventTap = CGEventTapCreate(kCGHIDEventTap,kCGHeadInsertEventTap,kCGEventTapOptionDefault,CGEventMaskBit(kCGEventKeyDown),&onKeyDown,self); 
     downSourceRef = CFMachPortCreateRunLoopSource(NULL, downEventTap, 0); 
     CFRelease(downEventTap); 
     CFRunLoopAddSource(CFRunLoopGetCurrent(), downSourceRef, kCFRunLoopDefaultMode); 
     CFRelease(downSourceRef) 
} 

и обработчик -

CGEventRef onKeyDown(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) { 
    NSLog(@"DOWN (%i)", CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode)); 
    // When it matches, I return CGEventCreate(NULL) to stop the event 
    return event; 
} 

Также обратите внимание, что, когда я перехватывать событие (и вернуть, что CGEventCreate(NULL)), я обычно выдайте один или несколько ключевых нажатий, используя следующий код. Обратите внимание, что KeyCmd и т. Д. Являются просто ярлыками для нормальных констант.

- (void)sendKey:(KeyCode)code cmd:(BOOL)cmd alt:(BOOL)alt ctl:(BOOL)ctl shift:(BOOL)shift { 

    CGEventFlags flags = 0; 

    if (cmd) flags = flags | KeyCmd; 
    if (alt) flags = flags | KeyAlt; 
    if (ctl) flags = flags | KeyCtl; 
    if (shift) flags = flags | KeyShift;  

    CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateCombinedSessionState); 
    CGEventRef keyDownPress = CGEventCreateKeyboardEvent(source, (CGKeyCode)code, YES); 

    CGEventSetFlags(keyDownPress, flags); 

    CGEventPost(kCGAnnotatedSessionEventTap, keyDownPress); 

    CFRelease(keyDownPress); 
    CFRelease(source); 
} 

Спасибо!

ответ

6

Есть ошибка в Snow Leopard, я думаю, что останавливает вашего слушателя, если что-то истекает.

В обработчике keyDown проверьте следующий тип и просто включите прослушиватель.

if (type == kCGEventTapDisabledByTimeout) { 
    NSLog(@"Event Taps Disabled! Re-enabling"); 
      CGEventTapEnable(eventTap, true); 
    return event; 
}