From 7ed6a247bfcf314b4a7bc8332b813b3e92997e41 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 23 Jan 2012 10:28:58 +0200 Subject: [PATCH] Fix synthesizing mouse events when touches change ordering MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit There is no guarantee the touches will be listed in the same order in an update: the platform/generic plug-in, the drivers, etc. are all free to shuffle the list of touch points in each report (even though the order is fairly stable with most systems). Therefore, to be safe, move and release events should be generated not from the first point in the list but from the one with the matching id. Change-Id: I6615224cbf2cfdc440143eb3191482a23d85c6a4 Reviewed-by: Samuel Rødal --- src/gui/kernel/qguiapplication.cpp | 22 +++++++++++++----- src/gui/kernel/qguiapplication_p.h | 1 + tests/auto/gui/kernel/qwindow/tst_qwindow.cpp | 32 ++++++++++++++++++++++++--- 3 files changed, 47 insertions(+), 8 deletions(-) diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 6e0d96a..6a8f858 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -114,6 +114,7 @@ static bool force_reverse = false; QGuiApplicationPrivate *QGuiApplicationPrivate::self = 0; QTouchDevice *QGuiApplicationPrivate::m_fakeTouchDevice = 0; +int QGuiApplicationPrivate::m_fakeMouseSourcePointId = 0; #ifndef QT_NO_CLIPBOARD QClipboard *QGuiApplicationPrivate::qt_clipboard = 0; @@ -1036,11 +1037,22 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To if (touchEvent.device()->type() != QTouchDevice::TouchPad) { Qt::MouseButtons b = eventType == QEvent::TouchEnd ? Qt::NoButton : Qt::LeftButton; - const QTouchEvent::TouchPoint &touchPoint = touchEvent.touchPoints().first(); - - QWindowSystemInterfacePrivate::MouseEvent fake(w, e->timestamp, touchPoint.pos(), touchPoint.screenPos(), b, e->modifiers); - fake.synthetic = true; - processMouseEvent(&fake); + QList touchPoints = touchEvent.touchPoints(); + if (eventType == QEvent::TouchBegin) + m_fakeMouseSourcePointId = touchPoints.first().id(); + + for (int i = 0; i < touchPoints.count(); ++i) { + const QTouchEvent::TouchPoint &touchPoint = touchPoints.at(i); + if (touchPoint.id() == m_fakeMouseSourcePointId) { + QWindowSystemInterfacePrivate::MouseEvent fake(w, e->timestamp, + touchPoint.pos(), + touchPoint.screenPos(), + b, e->modifiers); + fake.synthetic = true; + processMouseEvent(&fake); + break; + } + } } } } diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h index 1e2abb2..09db13e 100644 --- a/src/gui/kernel/qguiapplication_p.h +++ b/src/gui/kernel/qguiapplication_p.h @@ -206,6 +206,7 @@ private: static QGuiApplicationPrivate *self; static QTouchDevice *m_fakeTouchDevice; + static int m_fakeMouseSourcePointId; }; Q_GUI_EXPORT uint qHash(const QGuiApplicationPrivate::ActiveTouchPointsKey &k); diff --git a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp index 99777d9..ac8c8f9 100644 --- a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp +++ b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp @@ -246,10 +246,12 @@ public: keyReleaseCode = event->key(); } void mousePressEvent(QMouseEvent *event) { - if (ignoreMouse) + if (ignoreMouse) { event->ignore(); - else + } else { mousePressButton = event->button(); + mousePressScreenPos = event->screenPos(); + } } void mouseReleaseEvent(QMouseEvent *event) { if (ignoreMouse) @@ -257,6 +259,14 @@ public: else mouseReleaseButton = event->button(); } + void mouseMoveEvent(QMouseEvent *event) { + if (ignoreMouse) { + event->ignore(); + } else { + mouseMoveButton = event->button(); + mouseMoveScreenPos = event->screenPos(); + } + } void touchEvent(QTouchEvent *event) { if (ignoreTouch) { event->ignore(); @@ -285,7 +295,8 @@ public: } int keyPressCode, keyReleaseCode; - int mousePressButton, mouseReleaseButton; + int mousePressButton, mouseReleaseButton, mouseMoveButton; + QPointF mousePressScreenPos, mouseMoveScreenPos; int touchPressedCount, touchReleasedCount; bool ignoreMouse, ignoreTouch; @@ -339,12 +350,25 @@ void tst_QWindow::touchToMouseTranslation() QList points; QWindowSystemInterface::TouchPoint tp1, tp2; + const QRectF pressArea(101, 102, 4, 4); + const QRectF moveArea(105, 108, 4, 4); tp1.id = 1; tp1.state = Qt::TouchPointPressed; + tp1.area = pressArea; tp2.id = 2; tp2.state = Qt::TouchPointPressed; points << tp1 << tp2; QWindowSystemInterface::handleTouchEvent(&window, touchDevice, points); + // Now an update but with changed list order. The mouse event should still + // be generated from the point with id 1. + tp1.id = 2; + tp1.state = Qt::TouchPointStationary; + tp2.id = 1; + tp2.state = Qt::TouchPointMoved; + tp2.area = moveArea; + points.clear(); + points << tp1 << tp2; + QWindowSystemInterface::handleTouchEvent(&window, touchDevice, points); points[0].state = Qt::TouchPointReleased; points[1].state = Qt::TouchPointReleased; QWindowSystemInterface::handleTouchEvent(&window, touchDevice, points); @@ -352,6 +376,8 @@ void tst_QWindow::touchToMouseTranslation() QTRY_COMPARE(window.mousePressButton, int(Qt::LeftButton)); QTRY_COMPARE(window.mouseReleaseButton, int(Qt::LeftButton)); + QTRY_COMPARE(window.mousePressScreenPos, pressArea.center()); + QTRY_COMPARE(window.mouseMoveScreenPos, moveArea.center()); window.mousePressButton = 0; window.mouseReleaseButton = 0; -- 2.7.4