views:

56

answers:

0

I'm trying to write some code that discards all keyboard and mouse events when enabled on Mac OSX 10.6. My code runs as the root user. The approach I'm taking is to create an event tap that discards all events passed to it (while enabled). The event tap callback function looks like this:

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

And the code I'm using to enable and disable the event tap looks like this:

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

This approach works very well while the event tap is active - I can hammer on the keyboard and mouse as much as I want and no events make it through the system. However, when the tap is disabled all the keys I pushed while the tap was active appear in the current window. It's like the event tap is just delaying the events, rather than destroying them, which is odd, since the Mac documentation clearly states:

If the event tap is an active filter, your callback function should return one of the following:

The (possibly modified) event that is passed in. This event is passed back to the event system.

A newly-constructed event. After the new event has been passed back to the event system, the new event will be released along with the original event.

NULL if the event passed in is to be deleted.

I'm returning NULL, but the event doesn't seem to be deleted. Any ideas?