2010-05-12 2 views
18

Mac OSX 10.6에서 모든 키보드 및 마우스 이벤트를 삭제하는 코드를 작성하려고합니다. 내 코드는 루트 사용자로 실행됩니다. 내가 취하고있는 접근법은 전달 된 모든 이벤트를 삭제하는 이벤트 탭을 만드는 것입니다 (활성화 된 상태에서). 이벤트 탭 콜백 함수는 다음과 같습니다Mac 이벤트 탭에서 버려진 이벤트가 지연됩니다.

CGEventRef MyTapCallback(CGEventTapProxy proxy, 
         CGEventType type, 
         CGEventRef event, 
         void *refcon) 
{ 
    return CKeyLocker::isEnabled() ? NULL : event; 
} 

내가 사용하고 이벤트 탭을 사용하지 않도록 사용하고 코드는 다음과 같습니다

void CKeyLocker::enable(bool bEnable) 
{ 
    if (bEnable == m_bEnabled) 
     return; 

    if (bEnable) 
    { 
     // which events are we interested in? 
     CGEventMask evMask = kCGEventMaskForAllEvents; 
     CFMachPortRef mp = CGEventTapCreate(kCGHIDEventTap, 
              kCGHeadInsertEventTap, 
              kCGEventTapOptionDefault, 
              evMask, 
              MyTapCallback, 
              NULL); 

     if (mp) 
     { 
      qDebug() << "Tap created and active. mp =" << mp; 
      m_enabledTap = mp; 
      m_bEnabled = true; 
     } 
    } 
    else 
    { 
     CGEventTapEnable(m_enabledTap, false); 
     CFRelease(m_enabledTap); 
     m_enabledTap =0; 
     m_bEnabled = false; 
     qDebug() << "Tap destroyed and inactive"; 
    } 
} 

이 방법을 작동 아주 잘 동안 이벤트 탭 활성화되어 있습니다 - 나는 원하는대로 키보드와 마우스를 망가 트릴 수 있으며 시스템을 통해 이벤트가 발생하지 않습니다. 그러나 탭이 비활성화되어있을 때 탭이 활성 상태 인 동안 푸시 한 모든 키가 현재 창에 나타납니다. 이벤트 탭에서 이벤트를 지연시키는 것보다는 맥 오에스 문서에서 명확히 말합니다 :

이벤트 탭이 활성 필터 인 경우 콜백 함수는 다음 중 하나를 반환해야합니다. 다음과 같습니다.

전달 된 (수정 된) 이벤트.이 이벤트는 이벤트 시스템으로 다시 전달됩니다.

새로 생성 된 이벤트입니다. 새 이벤트가 이벤트 시스템으로 다시 전달되면 새 이벤트가 원래 이벤트와 함께 해제됩니다.

전달 된 이벤트가 삭제되면 NULL입니다.

NULL을 반환하지만 이벤트가 삭제 된 것 같습니다. 어떤 아이디어?

+0

당신은이 문제를 해결 했습니까? 방금 똑같은 행동을했습니다. – Dan

+0

아니요, 불행히도 아닙니다. – Thomi

+0

또한보십시오 http://stackoverflow.com/questions/4518559/consuming-osx-mouse-trackpad-events-with-an-event-tap – James

답변

0

NULL을 반환하면 효과적으로 일부 이벤트가 삭제된다는 것을 확인할 수 있지만 삭제할 때 삭제할 항목을 명확하게 결정하는 방법을 알았지 만 대용량 삭제가 방지 된 것처럼 보입니다. 100 개 이상의 이벤트를 연속으로 삭제합니다.

1

링크 된 댓글에는 내가 본 것에 대한 답변이 없으므로이 정보로 주변을 파고 들었을 때의 정보를 덤프합니다.

먼저 나는 CGEventTapCreateForPSN으로 운이 훨씬 좋습니다. 마치 시스템에서 탭을 제한하기위한 여유를 주듯이 말입니다. 그러나이 예제에서는 충분하지 않은 것처럼 보입니다.

다음은 - 이것은// 당신이 필요로하는 사용자의 통화에서 다시 모든 것을 할 수있다, 당신은 아마 원하는 (그리고해야 할 수도 있습니다) 다음 이벤트를 확인하기 위해 :

switch (type) 
{ 
    case kCGEventTapDisabledByTimeout: 
    case kCGEventTapDisabledByUserInput: 
    { 
     CFMachPortRef *pTap = (CFMachPortRef*)refcon; 
     CGEventTapEnable(*pTap, true); 
     return NULL; 
    } 
    default: 
     break; 
} 

을 상관없이 무엇을의 다양한 문서가 말하거나 말하지 않는다. OS가 나쁜 콜백에 대해 '프로빙'하는 것처럼 느낀다는 것이 내 관찰이다. 보편적으로 이벤트를 먹는 이벤트 탭 콜백을 기본적으로 비활성화합니다. 이러한 경우에 다시 등록하면 운영 체제는 확인한 것처럼 보입니다. 좋아, 당신이하는 일을 알고있는 것 같지만, 확인을 위해 다시 한 번 당신을 찌를 것입니다.

1

정말 이상합니다. 동일한 시나리오 (주어진 시나리오에서 입력 차단)에 대해 이벤트 탭을 사용하고 완벽하게 10.4 - 10.8.2로 작동합니다.excpet 한 가지, 그것은 차단 안 나 (큰 놀람하지 않은) 암호 대화 상자에서 이벤트를 수신

내가 지금 볼 수있는 것은 당신이 샘플에 비해 차이가 있습니다 :

  • 우리가 대신 kCGTailAppendEventTap를 사용 kCGHeadInsertEventTap의 우리가 필터링
  • 우리가 어떤 자기 주입 이벤트에서 일부 사용자 이벤트 데이터가 설치된 콜백, 로그인 어떤 이벤트를 할 수 있지만,이 외에도에서 우리는 단순히을 드롭 NULL을 반환
  • (이 문제가되지해야한다) 원하지 않는 이벤트 (당신처럼), 나는 확인할 수 있습니다. 모든 이벤트가 무시할 수있는 것은 아닙니다!
  • 우리는 이벤트가이 방법을 눌러 ON/OFF 설정 :
 
bool SetInputFilter(bool bOn) 
{ 
    bool result = false; 
    CFRunLoopRef runLoopRef = CFRunLoopGetMain(); 

    if (bOn) { 
     // Create an event tap. 
     CGEventMask eventMask = kCGEventMaskForAllEvents; 
     if ((m_eventTapInput = CGEventTapCreate(kCGHIDEventTap, 
               kCGTailAppendEventTap, 
               kCGEventTapOptionDefault, 
               eventMask, CGInputEventCallback, this)) == NULL) { 
      Log(L"Failed to create event tap"); 
      return result; 
     } 

     // Create a run loop source. 
     m_runLoopEventTapSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, m_eventTapInput, 0); 
     CFRelease(m_eventTapInput); // CFMachPortCreateRunLoopSource retains m_eventTapInput 
     if (m_runLoopEventTapSource == NULL) { 
      Log(L"Failed to create run loop source for event tap"); 
      return result; 
     } 

     // Add to the current run loop. 
     CFRunLoopAddSource(runLoopRef, m_runLoopEventTapSource, kCFRunLoopCommonModes);//kCFRunLoopDefaultMode); 
     CFRelease(m_runLoopEventTapSource); // CFRunLoopAddSource retains m_runLoopEventTapSource 
     result = true; 
    } 
    else { 
     // Disable the event tap. 
     if (m_eventTapInput) 
      CGEventTapEnable(m_eventTapInput, false); 

     // Remove our run loop source from the current run loop. 
     if (runLoopRef && m_runLoopEventTapSource) { 
      CFRunLoopRemoveSource(runLoopRef, m_runLoopEventTapSource, kCFRunLoopCommonModes);//kCFRunLoopDefaultMode); 
      m_runLoopEventTapSource = NULL; // removing m_runLoopEventTapSource releases last reference of m_runLoopEventTapSource too 
      m_eventTapInput = NULL;   // removing m_runLoopEventTapSource releases last reference of m_eventTapInput too 
     } 
    } 
    return result; 
} 
관련 문제