是否可以(或如何)创建一种机制(在Linux X11,C++中),就像Windows中的全局挂钩(SetWindowsHookEx())一样工作?

我希望能够捕获关键事件,但是可能会进一步传播。我正在尝试使用XGrabKey解决方案(例如xbindkeys中的解决方案),但是当我设置捕获关键事件时,此事件为“已消耗”。

该机制的要求如下:

  • 全局/系统范围内-捕获事件,而不管焦点在哪个窗口
  • “捕获保持”和“捕获通过”的可能性
  • 它必须相当快

  • 示例代码如下所示:
    bool myFlagIsSet = false;
    XEvent event;
    while (true) {
        while (XPending(display) > 0) {
            usleep(SLEEP_TIME);
        }
    
        XNextEvent(display, &event);
        switch (e.type) {
            case KeyPress:
                if (myFlagIsSet) {
                    //do not propagate
                }
                // propagate
                break;
            case KeyRelease:
                if (myFlagIsSet) {
                    //do not propagate
                }
                // propagate
                break;
        }
    }
    

    在Windows上,我只是写道:
    if(event.isConsumed()) {
        return LRESULT(1);
    }
    //...
    return CallNextHookEx(hookHandle, nCode, wParam, lParam);
    

    我也尝试使用XUngrabKey和XSendEvent:
    switch (event.type) {
        case KeyPress:
            if (myFlagIsSet) {
                //do not propagate
            }
            // propagate
            XUngrabKey(...);
            XSendEvent(..., &event);
            XGrabKey(...);
            break;
        case KeyRelease:
            ...
        }
    

    不幸的是XSendEvent出于我未知的原因-即使已注释XGrabKey行,也不要发送此事件。

    是否可以成功完成此方法?

    如果我被判失败,请提出其他建议

    编辑

    我想使用Compiz Window Manager在Ubuntu Gnome上实现此功能

    最佳答案

    XSendEvent()可能确实发送了它;但由于它被广泛认为是安全漏洞,因此大多数程序会忽略设置了send_event标志的UI事件。

    标准的X11协议(protocol)不允许这样做。 XInput 2.0扩展可能会,但我对此表示怀疑。尽管Windows假定每个程序都监听一个事件队列,以便程序可以拦截事件并阻止将事件发送到其他监听器,但每个X11客户端都有自己的独立队列,并且所有在X11客户端上注册感兴趣的客户端事件在其队列中接收到它的独立副本。这意味着在正常情况下,错误的程序不可能阻止其他程序运行;但这也意味着,在某个客户端必须阻止其他客户端的情况下,它必须进行服务器抢夺,以防止该服务器处理任何其他客户端的事件。

    关于c++ - Linux X11-全局键盘 Hook ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6560553/

    10-13 08:41