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