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

Cannot change mouse cursor during mouse move on embedded QWindow widget

    XMLWordPrintable

Details

    • Windows

    Description

      As part of the user interface of a 3D view, I want to modify the mouse cursor to provide feedback about what action the user is currently performing. In this context, I have encountered the following issue on Windows with Qt 6.5.6 LTS.

      If QWidget::setCursor() is called during a MouseMove event on the container widget of an embedded window (created using QWidget::createWindowContainer()), the cursor does not change. Doing the same thing on an "ordinary" QWidget works as expected.

      I have attached a small reproducer application (main.cpp) which creates a window with two widgets: an embedded QWindow to the left and a standard QLabel to the right. For each widget, an event filter intercepts MousePress, MouseMove and MouseRelease events calls setCursor on the widget on the first MouseMove event after any mouse button has been pressed. The cursor is then unset when the mouse button has been released again.
      Testing these actions on the left widget fails: the cursor does not change. On the right widget, the cursor does change as intended.

      With the following environment variables set:

      QT_LOGGING_RULES=qt.qpa.window=true;qt.qpa.events=true;qt.qpa.windows=true
      QT_QPA_VERBOSE=2

      the logs give a hint about what is happening.

      For the left widget ( > indicates the mouse input)

      qt.qpa.events: Entering window  QWidgetWindow(0x21f47f02cd0, name="MyMainWindowWindow")
      > MOUSE PRESS
      qt.qpa.window: QWindowsWindow::setMouseGrabEnabled QWidgetWindow(0x21f47f02cd0, name="MyMainWindowWindow") true
      qt.qpa.events: Automatic mouse capture  QWidgetWindow(0x21f47f02cd0, name="MyMainWindowWindow")
      > MOUSE MOVE WITH BUTTON PRESSED
      qt.qpa.events: Leaving window  QWidgetWindow(0x21f47f02cd0, name="MyMainWindowWindow")
      qt.qpa.window: QWidgetWindow(0x21f47f02cd0, name="MyMainWindowWindow") QWindowsWindow::setCursor 0x10015  doApply= false
      qt.qpa.window: QWidgetWindow(0x21f47f02cd0, name="MyMainWindowWindow") QWindowsWindow::setCursor 0x10003  doApply= false
      > MOUSE RELEASE
      qt.qpa.window: QWindowsWindow::setMouseGrabEnabled QWidgetWindow(0x21f47f02cd0, name="MyMainWindowWindow") false
      qt.qpa.events: Releasing automatic mouse capture  QWidgetWindow(0x21f47f02cd0, name="MyMainWindowWindow")
      qt.qpa.events: Entering window  QWidgetWindow(0x21f47f02cd0, name="MyMainWindowWindow")
      qt.qpa.window: QWidgetWindow(0x21f47f02cd0, name="MyMainWindowWindow") QWindowsWindow::setCursor 0x10015  doApply= true
      qt.qpa.window: QWidgetWindow(0x21f47f02cd0, name="MyMainWindowWindow") QWindowsWindow::setCursor 0x10003  doApply= true
      qt.qpa.events: Leaving window  QWidgetWindow(0x21f47f02cd0, name="MyMainWindowWindow")

      For the right widget:

      qt.qpa.events: Entering window  QWidgetWindow(0x2159d22afe0, name="MyMainWindowWindow")
      > MOUSE PRESS
      qt.qpa.window: QWindowsWindow::setMouseGrabEnabled QWidgetWindow(0x2159d22afe0, name="MyMainWindowWindow") true
      qt.qpa.events: Automatic mouse capture  QWidgetWindow(0x2159d22afe0, name="MyMainWindowWindow")
      > MOUSE MOVE WITH BUTTON PRESSED
      qt.qpa.window: QWidgetWindow(0x2159d22afe0, name="MyMainWindowWindow") QWindowsWindow::setCursor 0x10015  doApply= true
      > MOUSE RELEASE
      qt.qpa.window: QWindowsWindow::setMouseGrabEnabled QWidgetWindow(0x2159d22afe0, name="MyMainWindowWindow") false
      qt.qpa.events: Releasing automatic mouse capture  QWidgetWindow(0x2159d22afe0, name="MyMainWindowWindow")
      qt.qpa.window: QWidgetWindow(0x2159d22afe0, name="MyMainWindowWindow") QWindowsWindow::setCursor 0x10003  doApply= true

      For the left widget, some kind of leave event is sent to the main window which the causes the QWindowsWindow::setCursor() function to not apply the cursor directly. The cursor is only applied after releasing the mouse button again, in which case it will directly be overwritten by the call to unsetCursor in my use case.

      It is possible to work around the issue using a native event filter which ignores the first WM_MOUSELEAVE event that follows the mouse press. This can be activated in the example program by defining the preprocessor symbol WORKAROUND_ACTIVE. Since I imagine that may break other behaviors in some cases, I am reporting this issue in the hope that a proper fix can be implemented in Qt.

      Attachments

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

        Activity

          People

            srutledg Shawn Rutledge
            staffanronnas Staffan Ronnas
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:

              Gerrit Reviews

                There are no open Gerrit changes