2013-02-08 71 views
0

使用CGEventTap停止观看键盘事件点击的正确方法是什么?在应用程序运行时停止拦截键盘输入 - CGEventTap

我正在构建一个简单的后台应用程序,用于转换特定键的输出。感谢this excellent post on CGEventTap,我已经能够启用密钥转换。不幸的是,我似乎无法阻止它杀死应用程序。

当用户切换复选框以打开或关闭功能时,会调用以下方法。切换ON立即发生。切换OFF可能需要一分钟或更长时间才会生效。我通过日志看到“禁用,停止转​​换水龙头”。被检测到。但关键转换只是继续下去。我不明白为什么。

- (void)watchEventTap 
{  
     @autoreleasepool 
     { 
      CFRunLoopSourceRef runLoopSource = NULL; 
      CFMachPortRef eventTap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap, kCGEventTapOptionDefault, CGEventMaskBit(kCGEventKeyUp) | CGEventMaskBit(kCGEventKeyDown) | CGEventMaskBit(NX_SYSDEFINED), myCGEventCallback, NULL); 
      runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0); 

      if (!eventTap) 
      { 
       NSLog(@"Couldn't create event tap!"); 
       exit(1); 
      } 

      if (self.shortcutEnabled) // User default toggled ON 
      { 
       NSLog(@"Enabled. Convert taps."); 
       CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes); 
       CGEventTapEnable(eventTap, true); 
       // CFRunLoopRun(); // This blocks rest of app from executing 
      } 
      else // User default toggled OFF 
      { 
       NSLog(@"Disabled. Stop converting taps."); 
       CFRunLoopRemoveSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes); 
       CGEventTapEnable(eventTap, false); 
       // Clean up the event tap and source after ourselves. 
       CFMachPortInvalidate(eventTap); 
       CFRunLoopSourceInvalidate(runLoopSource); 
       CFRelease(eventTap); 
       CFRelease(runLoopSource); 
       eventTap = NULL; 
       runLoopSource = NULL; 
      } 
     } 
//  exit(0); // This blocks rest of app from executing 
} 

感谢您的任何建议。我是新建的Mac OS X应用程序,所以请原谅我,如果我做了一些无知的事情。

回答

2

感谢有经验的Mac开发人员,我解决了我的问题。每次调用方法时,我都会创建一个新的runLoopsSource。

现在我已经为tapEvent和runLoop创建了实例变量。只需要一行来停止eventTap。修改方法如下:

- (void)watchEventTap 
{ 

    @autoreleasepool 
    { 

     if ([[NSUserDefaults standardUserDefaults] isEnabledNumLockDV] == YES) // User default toggled ON 
     { 
      _runLoopSource = NULL; 
      _eventTap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap, kCGEventTapOptionDefault, CGEventMaskBit(kCGEventKeyUp) | CGEventMaskBit(kCGEventKeyDown) | CGEventMaskBit(NX_SYSDEFINED), myCGEventCallback, NULL); 
      _runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, _eventTap, 0); 

      if (!_eventTap) 
      { 
       NSLog(@"Couldn't create event tap!"); 
       exit(1); 
      } 

      NSLog(@"Enabled. Convert taps."); 
      CFRunLoopAddSource(CFRunLoopGetCurrent(), _runLoopSource, kCFRunLoopCommonModes); 
      CGEventTapEnable(_eventTap, true); 
     } 
     else if ([[NSUserDefaults standardUserDefaults] isEnabledNumLockDV] == NO) // User default toggled OFF 
     { 
      NSLog(@"Disabled. Stop converting taps."); 
      CGEventTapEnable(_eventTap, false); 
     } 

    } 
} 
相关问题