2013-02-08 31 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); 
     } 

    } 
} 
相關問題