Details
-
Bug
-
Resolution: Fixed
-
P2: Important
-
5.4.1, 5.5.1
-
None
-
Linux (Ubuntu), with mouse and touchscreen connected.
Description
To reproduce:
Set the attribute, Qt::AA_SynthesizeTouchForUnhandledMouseEvents on the QApplication in main.cpp.
Create an instance of a QWidget derived class with e.g. the following definition of event:
bool Widget::event(QEvent *e) { switch (e->type()) { case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::MouseButtonDblClick: case QEvent::MouseMove: qDebug() << "Squeak squeak..."; e->ignore(); return false; case QEvent::TouchBegin: case QEvent::TouchUpdate: case QEvent::TouchEnd: case QEvent::TouchCancel: qDebug() << "Stop touching me!"; e->accept(); return true; default: break; } return QWidget::event(e); }
Run the application.
Click on the widget with a mouse.
Expected results:
"Squeak squeak...", followed by, "Stop touching me", as the unused mouse event should be synthesized into a touch event.
Actual results:
Only the "Squeak squeak..." output appears.
I have verified that touch events are accepted by the widget (by using the touch screen).
I have tested with both QWidgets and QQuickItems within QQuickWidgets. Neither worked.
Debugging a minimal example, I noticed a possible problem in QWidgetWindow::handleMouseEvent(QEvent *event).
At line 1771 of qguiapplication.cpp, QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent *e) calls QGuiApplication::sendSpontaneousEvent(window, &ev). This QMouseEvent pointer, ev eventually get passed down to QWidgetWindow::handleMouseEvent(QEvent *event).
At qwidgetwindow.cpp line 538, it creates a QMouseEvent, translated, which copies most of the original event's data, but takes the windowPos as its localPos. translated then gets sent down the widget hierarchy by a call to QApplication::sendMouseEvent(..). In the situation we're interested in (Nothing accepts the event), translated eventually gets its member, m_accept set to 0.
However, the accepted value of translated is never taken into account once control returns to QWidgetWindow::handleMouseEvent(QEvent *event), thus the original event that was passed into the function still has m_accept set to 1. This means that when control gets back to QGuiApplicationPrivate::processMouseEvent(..), the expression !ev.isAccepted on line 1772 evaluates to false, meaning the code to synthesise touch events is not executed.