Fix synthesizing mouse events when touches change ordering

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 <samuel.rodal@nokia.com>
bb10
Laszlo Agocs 2012-01-23 10:28:58 +02:00 committed by Qt by Nokia
parent 141e5c3878
commit 7ed6a247bf
3 changed files with 46 additions and 7 deletions

View File

@ -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();
QList<QTouchEvent::TouchPoint> touchPoints = touchEvent.touchPoints();
if (eventType == QEvent::TouchBegin)
m_fakeMouseSourcePointId = touchPoints.first().id();
QWindowSystemInterfacePrivate::MouseEvent fake(w, e->timestamp, touchPoint.pos(), touchPoint.screenPos(), b, e->modifiers);
fake.synthetic = true;
processMouseEvent(&fake);
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;
}
}
}
}
}

View File

@ -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);

View File

@ -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<QWindowSystemInterface::TouchPoint> 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;