2010-05-12 14 views
18

मैं कुछ कोड है कि सभी कीबोर्ड और माउस घटनाओं जब पर मैक OSX 10.6 सक्षम को छोड़ देता है लिखने की कोशिश कर रहा हूँ। मेरा कोड रूट उपयोगकर्ता के रूप में चलता है। जिस दृष्टिकोण को मैं ले रहा हूं वह एक ईवेंट टैप बनाना है जो इसे पारित सभी घटनाओं को छोड़ देता है (सक्षम होने पर)। घटना नल कॉलबैक फ़ंक्शन इस तरह दिखता है:मैक घटना नल सिर्फ खारिज कर दिया देरी घटनाओं

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"; 
    } 
} 

यह दृष्टिकोण काम करता है बहुत अच्छी तरह से है, जबकि घटना नल सक्रिय है - मैं जितना चाहूं कीबोर्ड और माउस पर हथौड़ा लगा सकता हूं और कोई भी घटना सिस्टम के माध्यम से नहीं बनाती है। हालांकि, जब टैप को अक्षम किया गया था तब टैप अक्षम हो गई थी, जबकि वर्तमान विंडो में टैप सक्रिय था। यह घटना नल सिर्फ घटनाओं में देरी कर रहा है, बजाय नष्ट करने के लिए उन्हें, जो अजीब है की तरह है के बाद से मैक प्रलेखन स्पष्ट रूप से कहा गया है: घटना नल एक सक्रिय फिल्टर है

हैं, तो आपके कॉलबैक फ़ंक्शन में से एक वापस आ जाएगी निम्नलिखित:।

(संभवतः संशोधित) घटना है कि में पारित हो जाता है इस घटना को वापस घटना प्रणाली को पारित कर दिया है।

एक नव निर्मित कार्यक्रम। नई घटना को घटना प्रणाली में वापस भेज दिए जाने के बाद, नई घटना मूल घटना के साथ जारी की जाएगी।

शून्य अगर घटना में पारित हटाया जाने वाला है।

मैं वापस लौट रहा हूं, लेकिन घटना को हटाया नहीं जा रहा है। कोई विचार?

+0

आप इस समस्या को हल किया? मैंने अभी भी वही व्यवहार किया है। – Dan

+0

नहीं, दुर्भाग्य से नहीं। – Thomi

+0

यह भी देखें http://stackoverflow.com/questions/4518559/consuming-osx-mouse-trackpad-events-with-an-event-tap – James

उत्तर

0

मैं यह सत्यापित कर सकता हूं कि वापस लौटने से एनयूएलएल कुछ घटनाओं को प्रभावी ढंग से हटा देता है, लेकिन मैंने यह भी देखा है कि यह कब होता है, वास्तव में यह तय करता है कि अनुमति देने के लिए कौन से विलोपन अस्पष्ट हैं लेकिन ऐसा लगता है कि बड़े पैमाने पर हटाने को रोकने की प्रतीत होती है जैसे: जब आप एक पंक्ति में 100 से अधिक घटनाओं या तो हटा देते हैं।

1

जुड़ा हुआ टिप्पणी मैं क्या देख से एक जवाब नहीं है, इसलिए मैं मैं क्या देखा है जब इस सामग्री के साथ चारों ओर poking से कुछ जानकारी डंप करेंगे।

पहले, मैं CGEventTapCreateForPSN साथ ज्यादा बेहतर किस्मत है। ऐसा लगता है कि सिस्टम आपको अपने टैप को प्रतिबंधित करने के लिए कुछ छूट देता है। हालांकि, इस उदाहरण से ऐसा लगता है कि यह पर्याप्त नहीं है।

आगे - और इस// आप सभी की जरूरत है ... अपने कॉल में वापस हो सकता है, तो आप शायद चाहते हैं (और आवश्यकता हो सकती है) के बाद की घटनाओं के लिए जाँच करने के लिए: क्या की परवाह किए बिना

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

विभिन्न दस्तावेज करता है या नहीं कहता है, यह मेरा अवलोकन है कि ओएस को लगता है कि यह खराब कॉलबैक के लिए 'जांच' है; मूल रूप से इवेंट टैप कॉलबैक अक्षम करना जो सार्वभौमिक घटनाओं को खा रहे हैं। यदि आप इन मामलों में फिर से पंजीकरण करते हैं तो ओएस इसके साथ ठीक लगता है, जैसा कि कह रहा है: ठीक है, आपको पता है कि आप क्या कर रहे हैं, लेकिन मैं निश्चित रूप से सुनिश्चित करने के लिए आपको थोड़ी देर में दबा दूंगा।

1

यह वास्तव में अजीब बात है, हम एक ही उद्देश्य के लिए घटना नल (इनपुट किसी दिए गए परिदृश्य में अवरुद्ध) का उपयोग करें और पूरी तरह से काम करता है 10.4 - 10.8.2।हम kCGTailAppendEventTap बजाय का उपयोग

  • : excpet एक बात है, यह ब्लॉक या कोई पासवर्ड संवाद से घटनाओं प्राप्त (जो एक बड़ा आश्चर्य नहीं है) नहीं करना चाहिए

    क्या मैं अब देख सकते हैं आप नमूना की तुलना में अलग है kCGHeadInsertEventTap की (यह कोई फर्क नहीं होना चाहिए)

  • हम कुछ स्थापित कॉलबैक
  • हम कुछ स्वयं इंजेक्शन की घटनाओं में कुछ उपयोगकर्ता घटना डेटा है, कि फिल्टर करके निकाल में प्रवेश करने की घटना है, लेकिन इस के अलावा हम बस शून्य वापसी एक ड्रॉप करने अवांछित घटना (जैसे आप करते हैं), मैं पुष्टि कर सकता हूं, सभी घटनाएं अनजान नहीं हैं!
  • हम घटना इस तरह से नल चालू/बंद:
 
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; 
} 
संबंधित मुद्दे