У меня есть приложение Qt, которое получает ключ с XGrabKey
, Я хочу, чтобы мое приложение показывало и скрывало, если я нажимаю горячую клавишу. Кроме того, он должен прятаться, если теряет фокус. Это хорошо работает с одним недостатком: XGrabKeyboard
который используется XGrabKey
, генерирует событие FocusIn и FocusOut. Это подразумевает, что, если я нажимаю горячую клавишу, когда приложение видно, приложение получает событие FocusOut, сразу же скрывается и получает событие горячей клавиши и снова отображается.
Можно ли как-то избежать X-сервера для генерации этих событий фокуса?
Я так не думаю, но вы можете проверить поле «mode» в XFocusChangeEvent. Это может быть NotifyNormal, NotifyWhileGrabbed, NotifyGrab или NotifyUngrab. Захват клавиш должен генерировать события в последних двух режимах, и поэтому вы можете игнорировать события в этих режимах, хотя я не уверен, как вы это сделаете с Qt.
Копайте глубже в течение нескольких часов. Я нашел решение, которое приятно. Использует Qt QWidget::nativeEvent
и libxcb. libxcb, похоже, является оболочкой libX11 следующего поколения. Но это ужасно без документов. Разверните, что Qt не предоставляет режим QFocusEvent
, Но я предполагаю, что это проклятие во всем, кто хочет быть независимым от платформы.
Примечание: это Qt5, в Qt4 были такие вещи, как QWidget::x11info()
.час
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;
}