Details
-
Bug
-
Resolution: Unresolved
-
P2: Important
-
None
-
5.15.0, 6.0.0
-
None
-
Xorg 1.20.8, xcb 1.1.0, ubuntu 20 x64, reproducible with Qt 5.15 and 6.0
Description
I'm using Qt to globally hook keyboard hotkeys for an accessibility application. If I press one key only I can correctly detect key press and key release events with X11, but if I do exactly this combination with two keys:
- Press D
- Press also W (D and W are now both pressed)
- Release D (W is still pressed)
- Release W
The event number 4 is not fired at all.
This is the code for a minimal reproducible sample
main.cpp
#include <QApplication> #include "hotkeyfilter.h" #include <X11/Xlib.h> int main(int argc, char *argv[]) { QApplication a(argc, argv); a.installNativeEventFilter(new HotkeyFilter()); // Registers the D and W keys on the keyboard for a global hotkey hook xcb_keycode_t keyValue = XKeysymToKeycode(QX11Info::display(), Qt::Key_D); xcb_connection_t* connection = QX11Info::connection(); auto cookie = xcb_grab_key_checked(connection, 1, static_cast<xcb_window_t>(QX11Info::appRootWindow()), 0, keyValue, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); auto cookieError = xcb_request_check(connection, cookie); if (cookieError != NULL) { qDebug() << "Could not register global hook"; return 1; } keyValue = XKeysymToKeycode(QX11Info::display(), Qt::Key_W); cookie = xcb_grab_key_checked(connection, 1, static_cast<xcb_window_t>(QX11Info::appRootWindow()), 0, keyValue, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); cookieError = xcb_request_check(connection, cookie); if (cookieError != NULL) { qDebug() << "Could not register global hook"; return 1; } return a.exec(); }
hotkeyfilter.h
#ifndef HOTKEYFILTER_H #define HOTKEYFILTER_H #include <QAbstractNativeEventFilter> #include <QKeySequence> #include <QtX11Extras/QX11Info> #include <QDebug> class HotkeyFilter : public QObject, public QAbstractNativeEventFilter { Q_OBJECT public: virtual bool nativeEventFilter(const QByteArray&, void* message, long*) Q_DECL_OVERRIDE { xcb_generic_event_t* e = static_cast<xcb_generic_event_t*>(message); if ((e->response_type & ~0x80) == XCB_KEY_PRESS) { xcb_key_press_event_t* ke = reinterpret_cast<xcb_key_press_event_t*>(e); qDebug().noquote() << "HOTKEY PRESS FOR KEY " << ke->detail; return true; } if ((e->response_type & ~0x80) == XCB_KEY_RELEASE) { xcb_key_press_event_t* ke = reinterpret_cast<xcb_key_press_event_t*>(e); qDebug().noquote() << "HOTKEY RELEASE FOR KEY " << ke->detail; return true; } return false; } }; #endif // HOTKEYFILTER_H
project.pro
QT += core widgets gui QT += x11extras CONFIG += c++14 LIBS += -L/usr/X11/lib -lX11 -lxcb SOURCES += \ main.cpp HEADERS += \ hotkeyfilter.h
This is the output I'm getting
HOTKEY PRESS FOR KEY 40 <- that's D HOTKEY PRESS FOR KEY 25 <- that's W HOTKEY RELEASE FOR KEY 40 <- that's D <- ??? no W release even though I physically released it on my keyboard!
Notice that this only seems to happen if I press the keys reasonably fast. Could this somehow be related to autorepeat?