【问题标题】:Mac event tap just delays discarded eventsMac事件点击只是延迟丢弃的事件
【发布时间】:2010-05-12 09:57:40
【问题描述】:

我正在尝试编写一些在 Mac OSX 10.6 上启用时丢弃所有键盘和鼠标事件的代码。我的代码以 root 用户身份运行。我正在采取的方法是创建一个事件点击,丢弃所有传递给它的事件(启用时)。事件点击回调函数如下所示:

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

当事件点击处于活动状态时,这种方法非常有效 - 我可以随意敲击键盘和鼠标,并且没有任何事件通过系统。但是,当点击被禁用时,我在点击处于活动状态时按下的所有键都会出现在当前窗口中。就像事件点击只是延迟事件,而不是破坏它们,这很奇怪,因为 Mac 文档明确指出:

如果事件点击是一个活动过滤器,你的回调函数应该返回以下之一:

传入的(可能已修改的)事件。此事件被传回事件系统。

一个新建的事件。新事件传回事件系统后,新事件将与原事件一起释放。

如果要删除传入的事件,则为NULL。

我返回 NULL,但该事件似乎没有被删除。有什么想法吗?

【问题讨论】:

标签: c++ macos events quartz-graphics macos-carbon


【解决方案1】:

链接的评论没有我所看到的答案,所以我将转储一些我在浏览这些东西时看到的信息。

首先,我对CGEventTapCreateForPSN 的运气要好得多。就好像系统给了你一些限制你的水龙头的余地。然而,从这个例子看来,这还不够。

接下来 - 这个/可能/是您所需要的...在您的回电中,您可能希望(并且可能需要)检查以下事件:

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

不管各种文档做了什么或没说什么,我观察到操作系统感觉像是在“探测”错误的回调;基本上禁用普遍吃事件的事件点击回调。如果你在这些情况下重新注册,操作系统似乎没问题,就好像在说:好吧,你似乎知道你在做什么,但我可能会再戳你一下以确保。

【讨论】:

    【解决方案2】:

    这真的很奇怪,我们将事件点击用于相同目的(在给定场景中的输入阻塞)并且在 10.4 - 10.8.2 中完美运行。除了一件事,它不应该阻止或接收来自密码对话框的事件(这不足为奇)

    我现在看到的与您的示例不同的是:

    • 我们使用 kCGTailAppendEventTap 而不是 kCGHeadInsertEventTap(这应该无关紧要)
    • 我们在已安装的回调中记录一些事件
    • 我们在一些自注入事件中有一些用户事件数据,这些数据被过滤掉了,但除此之外,我们只是返回 NULL 以删除不需要的事件(就像您一样),我可以确认,并非所有事件都是可忽略的!李>
    • 我们以这种方式打开/关闭事件点击:
    bool SetInputFilter(bool bOn) { 布尔结果=假; CFRunLoopRef runLoopRef = CFRunLoopGetMain(); 如果 (bOn) { // 创建一个事件点击。 CGEventMask eventMask = kCGEventMaskForAllEvents; 如果 ((m_eventTapInput = CGEventTapCreate(kCGHIDEventTap, kCGTailAppendEventTap, kCGEventTapOptionDefault, eventMask, CGInputEventCallback, this)) == NULL) { Log(L"创建事件点击失败"); 返回结果; } // 创建一个运行循环源。 m_runLoopEventTapSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, m_eventTapInput, 0); CFRelease(m_eventTapInput); // CFMachPortCreateRunLoopSource 保留 m_eventTapInput 如果(m_runLoopEventTapSource == NULL){ Log(L"未能为事件点击创建运行循环源"); 返回结果; } // 添加到当前运行循环。 CFRunLoopAddSource(runLoopRef, m_runLoopEventTapSource, kCFRunLoopCommonModes);//kCFRunLoopDefaultMode); CFRelease(m_runLoopEventTapSource); // CFRunLoopAddSource 保留 m_runLoopEventTapSource 结果=真; } 别的 { // 禁用事件点击。 如果(m_eventTapInput) CGEventTapEnable(m_eventTapInput, false); // 从当前运行循环中移除我们的运行循环源。 if (runLoopRef && m_runLoopEventTapSource) { CFRunLoopRemoveSource(runLoopRef, m_runLoopEventTapSource, kCFRunLoopCommonModes);//kCFRunLoopDefaultMode); m_runLoopEventTapSource = NULL; // 删除 m_runLoopEventTapSource 也会释放 m_runLoopEventTapSource 的最后引用 m_eventTapInput = NULL; // 删除 m_runLoopEventTapSource 也会释放 m_eventTapInput 的最后引用 } } 返回结果; }

    【讨论】:

      【解决方案3】:

      我可以验证返回 NULL 确实有效地删除了一些事件,但我也见过它没有的时候,它究竟如何决定允许哪些删除尚不清楚,但看起来似乎阻止了大规模删除,例如:当你连续删除100多个事件。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-12-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-02
        相关资源
        最近更新 更多