Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-89800

X11: cannot detect key release when pressing two keys at the same time

    XMLWordPrintable

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
    • Linux/X11

    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:

      1. Press D
      2. Press also W (D and W are now both pressed)
      3. Release D (W is still pressed)
      4. 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?

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            liaqi Liang Qi
            madg8 Marco Alesiani
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:

              Gerrit Reviews

                There are no open Gerrit changes