Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/146.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ X11:如何实现无焦点丢失的全局热键_C++_Qt_Events_Hotkeys_Xorg - Fatal编程技术网

C++ X11:如何实现无焦点丢失的全局热键

C++ X11:如何实现无焦点丢失的全局热键,c++,qt,events,hotkeys,xorg,C++,Qt,Events,Hotkeys,Xorg,我有一个Qt应用程序,它可以用XGrabKey抓取钥匙。如果我按下热键,我希望我的应用程序显示和隐藏。此外,如果它失去焦点,它必须隐藏。这很好地解决了一个缺点:由XGrabKey使用的XGrabKeyboard会在ans FocusOut事件中生成FocusIn。这意味着,如果我在应用程序可见时按下热键,应用程序将接收FocusOut事件,隐藏并立即在该事件之后接收热键事件并再次显示 我可以避免X服务器生成这些焦点事件吗?我不这么认为,但是您可以检查XFocusChangeEvent中的“mod

我有一个Qt应用程序,它可以用
XGrabKey
抓取钥匙。如果我按下热键,我希望我的应用程序显示和隐藏。此外,如果它失去焦点,它必须隐藏。这很好地解决了一个缺点:由
XGrabKey
使用的
XGrabKeyboard
会在ans FocusOut事件中生成FocusIn。这意味着,如果我在应用程序可见时按下热键,应用程序将接收FocusOut事件,隐藏并立即在该事件之后接收热键事件并再次显示


我可以避免X服务器生成这些焦点事件吗?

我不这么认为,但是您可以检查XFocusChangeEvent中的“mode”字段。它可以是NotifyNormal、NotifyWhileGrabbed、NotifyGrab或NotifyUngrab。抓取键应该生成最后两种模式的事件,因此您可以选择忽略这些模式下的事件,尽管我不确定如何使用Qt做到这一点。

深入挖掘了大约几个小时,我修补了一个感觉不错的解决方案。它使用Qt
QWidget::nativeEvent
和libxcb。libxcb似乎是下一代libX11包装器。但它是可怕的无证文件。解开Qt不提供
QFocusEvent
模式的锁定。但我想这是一切想要成为平台不可知论者的祸根

注意:这是Qt5,Qt4有类似于
QWidget::x11info()

h

.cpp

/**************************************************************************//**
*@brief Class::nativeEvent
*此特殊事件处理程序可以在子类中重新实现以接收
*由在中传递的eventType标识的本机平台事件
*消息参数。在重新实现此函数时,如果您想
*停止Qt正在处理的事件,返回true并设置结果。如果你
*返回false,此本机事件被传递回Qt,Qt转换
*事件转换为Qt事件并将其发送到小部件。
*
*每个本机事件都会调用此方法。在X11上,eventType设置为
*“xcb_generic_event_t”,可以将消息转换为
*xcb\u通用\u事件\u t指针。
*
*@param-eventType
*@param消息
*@如果此事件应停止,返回指示器将被进一步处理。
*/
bool类::nativeEvent(常量QByteArray和事件类型,void*消息,long*)
{
if(eventType==“xcb\u generic\u event\t”)
{
xcb_generic_event_t*event=静态_cast(消息);
开关(事件->响应类型&~0x80)
{
案例XCB_FOCUS_IN:{
xcb_focus_in_event_t*fe=(xcb_focus_in_event_t*)事件;
如果(fe->mode&(XCB_NOTIFY_mode_GRAB | XCB_NOTIFY_mode_UNGRAB)){
返回true;//忽略此事件
}
打破
}
案例XCB\U焦点\U OUT:{
xcb_focus_out_event_t*fe=(xcb_focus_out_event_t*)事件;
如果(fe->mode&(XCB_NOTIFY_mode_GRAB | XCB_NOTIFY_mode_UNGRAB)){
返回true;//忽略此事件
}
打破
}
}
}
返回false;
}

非常感谢您分享此信息!这与我正在做的一些工作非常相关。
class Class : public QWidget
{
    Q_OBJECT
public:
    Class(QWidget *parent = 0);
    ~Class();

protected:
    virtual bool nativeEvent(const QByteArray &eventType, void *message, long *) override;
};
/**************************************************************************//**
 * @brief Class::nativeEvent
 * This special event handler can be reimplemented in a subclass to receive
 * native platform events identified by eventType which are passed in the
 * message parameter. In your reimplementation of this function, if you want to
 * stop the event being handled by Qt, return true and set result. If you
 * return false, this native event is passed back to Qt, which translates the
 * event into a Qt event and sends it to the widget.
 *
 * This method is called for every native event. On X11, eventType is set to
 * "xcb_generic_event_t", and the message can be casted to a
 * xcb_generic_event_t pointer.
 *
 * @param eventType
 * @param message
 * @return Indicator if this event shall be stoped being handled further.
 */
bool Class::nativeEvent(const QByteArray &eventType, void *message, long *)
{
    if (eventType == "xcb_generic_event_t")
    {
        xcb_generic_event_t* event = static_cast<xcb_generic_event_t *>(message);
        switch (event->response_type & ~0x80)
        {
        case XCB_FOCUS_IN: {
            xcb_focus_in_event_t *fe = (xcb_focus_in_event_t *)event;
            if (fe->mode & (XCB_NOTIFY_MODE_GRAB|XCB_NOTIFY_MODE_UNGRAB)){
                return true; // Ignore this events
            }
            break;
        }
        case XCB_FOCUS_OUT: {
            xcb_focus_out_event_t *fe = (xcb_focus_out_event_t *)event;
            if (fe->mode & (XCB_NOTIFY_MODE_GRAB|XCB_NOTIFY_MODE_UNGRAB)){
                return true; // Ignore this events
            }
            break;
        }
        }
    }
    return false;
}