我有一个Qt应用程序,用XGrabKey
抓取一个密钥。如果我按下热键,我希望我的应用程序显示和隐藏。此外,如果它失去焦点,它必须隐藏。这很好地解决了一个缺点:XGrabKeyboard
使用的XGrabKey
会生成FocusIn和FocusOut事件。这意味着,如果我在应用程序可见时按热键,应用程序将收到FocusOut事件,在收到hotkeyevent并再次显示之后隐藏并且非常好。
我可以以某种方式避免X服务器生成这些焦点事件吗?
答案 0 :(得分:1)
我不这么认为,但你可以查看"模式" XFocusChangeEvent中的字段。它可以是NotifyNormal,NotifyWhileGrabbed,NotifyGrab或NotifyUngrab。抓取键应该使用最后两种模式生成事件,因此您可以选择忽略具有这些模式的事件,但我不确定如何使用Qt执行此操作。
答案 1 :(得分:1)
Diggin深入大约几个小时我修改了一个感觉很好的解决方案。它使用Qt QWidget::nativeEvent
和libxcb。 libxcb似乎是下一代libX11包装器。但它非常无人问津。不冷却Qt不提供QFocusEvent
的模式。但我想这就是想要与平台无关的一切的祸根。
注意:这是Qt5,Qt4有像QWidget::x11info()
·H
class Class : public QWidget
{
Q_OBJECT
public:
Class(QWidget *parent = 0);
~Class();
protected:
virtual bool nativeEvent(const QByteArray &eventType, void *message, long *) override;
};
的.cpp
/**************************************************************************//**
* @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;
}