应用程序随机停止接收按键(CGEventTaps)

时间:2011-01-18 17:35:46

标签: objective-c cocoa macos macos-carbon cgeventtap

所以,我浪费了很多时间来创建这个非常酷的键盘宏应用程序。它工作得很好,唯一的问题是,几分钟后,它就会停止工作。当我按下一个键时,它就不再被调用了。

我无法将其锁定,但始终需要至少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);
}

谢谢!

1 个答案:

答案 0 :(得分:7)

我认为Snow Leopard中存在一个错误,如果出现问题,会阻止您的听众。

在keyDown处理程序中,检查以下类型,然后重新启用侦听器。

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