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

QTest::mouse* - pressing / releasing multiple buttons broken

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • P2: Important
    • None
    • 5.11
    • Testing: qtestlib
    • None

    Description

      QTest::mouse* API does not support pressing/releasing multiple buttons. And from git history it appears that it has been working like this since at least 2009 (looking at Qt4 repository), but possibly much longer. What it does:

      in Qt4:

      case MouseRelease:
                      me = QMouseEvent(QEvent::MouseButtonRelease, pos, widget->mapToGlobal(pos), button, 0, stateKey);
      

      in Qt5:

      case MouseRelease:
                  qt_handleMouseEvent(w, pos, global, Qt::NoButton, button, QEvent::MouseButtonRelease,
                                      stateKey, ++lastMouseTimestamp);
      

      So whenever we release a button, qtestlib "releases" them all, by setting "state" to 0/Qt::NoButton.

      Similar for mouse press events (code from Qt5):

      qt_handleMouseEvent(w, pos, global, button, button, QEvent::MouseButtonPress, stateKey, ++lastMouseTimestamp);
      

      whatever button is passed in, it is passed also as a state. Which would clear other buttons that were pressed (but not released) earlier.

      This qtestlib implementation (before https://codereview.qt-project.org/#/c/193415/) was relying on QGuiApplication to maintain and set correct QMouseEvents::buttons() state, which often resulted in unexpected state and even missing mouse events. For example for the following sequence of QTest commands:

      QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(50, 50));
      QTest::mousePress(&window, Qt::RightButton, 0, QPoint(50, 50));
      QTest::mouseRelease(&window, Qt::RightButton, 0, QPoint(50, 50));
      QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(50, 50));
      

      QGuiApplication::processMouseEvents would generate:

      QDEBUG : tst_qquickitem::ignoreButtonPressNotInAcceptedMouseButtons() ev:  QMouseEvent(MouseMove, localPos=50,50, screenPos=50,50)
      QDEBUG : tst_qquickitem::ignoreButtonPressNotInAcceptedMouseButtons() ev:  QMouseEvent(MouseButtonPress, LeftButton, localPos=50,50, screenPos=50,50)
      QDEBUG : tst_qquickitem::ignoreButtonPressNotInAcceptedMouseButtons() ev:  QMouseEvent(MouseButtonRelease, LeftButton, buttons=RightButton, localPos=50,50, screenPos=50,50)
      QDEBUG : tst_qquickitem::ignoreButtonPressNotInAcceptedMouseButtons() ev:  QMouseEvent(MouseButtonRelease, RightButton, localPos=50,50, screenPos=50,50)
      

      Which often would be enough for auto tests to pass, even when the generated events clearly are wrong. What made this even worse, is that QGuiApplication would reuse the state of whatever it was left as by the test function that run earlier.

      To support pressing/releasing multiple buttons qtestlib would need to remember button state between QTest::mouse* calls, but since we don't want button state set by one test function to affect subsequent test functions, the state would need to be reset before each test function call.

      Currently this can be worked around by using QWindowSystemInterface::handleMouseEvent API.
      See also: https://codereview.qt-project.org/#/c/208930/

      Attachments

        Issue Links

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

          Activity

            People

              paeglis Gatis Paeglis
              paeglis Gatis Paeglis
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Gerrit Reviews

                  There are no open Gerrit changes