diff options
author | Frederik Gladhorn <frederik.gladhorn@theqtcompany.com> | 2016-09-30 14:47:31 +0200 |
---|---|---|
committer | Frederik Gladhorn <frederik.gladhorn@qt.io> | 2016-10-04 09:01:05 +0000 |
commit | c6d66f2e88b42079df9c21c10cf8922871932a32 (patch) | |
tree | 573581023530ea3c76c4d0575dc36d8c8ba3f36d /src | |
parent | 33407ae00d7500255cd38b3c02a33a3f7359e9e2 (diff) |
Fix mouse and touch grabbing issues
We keep track of the touch device and point ID, but didn't use them when
queried for the mouse grabber. When setting the grabber, also take touch
into account.
Qt Location's touch/mouse handling, when it called the grab
functions was not working correctly, because in QQuickWindow, we'd check
for the old grabber and due to not checking the device/id, we'd get the
wrong item, which would then result in the ungrab function not being
called.
When some item steals the grab for a touch point that was previously
accepted as a synthetic mouse point, there was a high chance we would
fail to deliver a mouse ungrab event.
Make sure to ungrab the mouse as soon as we find any point with the
corresponding ID. In addition, the multi point touch area tried to grab
ids which were invalid (-1), avoid that.
Task-number: QTBUG-55229
Task-number: QTBUG-56213
Change-Id: I73e4587bf4f94a65d88c5b60d93bc07743512e56
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
Reviewed-by: Frederik Gladhorn <frederik.gladhorn@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/quick/items/qquickmultipointtoucharea.cpp | 6 | ||||
-rw-r--r-- | src/quick/items/qquickwindow.cpp | 44 |
2 files changed, 36 insertions, 14 deletions
diff --git a/src/quick/items/qquickmultipointtoucharea.cpp b/src/quick/items/qquickmultipointtoucharea.cpp index 504e63174a..706980cd13 100644 --- a/src/quick/items/qquickmultipointtoucharea.cpp +++ b/src/quick/items/qquickmultipointtoucharea.cpp @@ -470,8 +470,10 @@ void QQuickMultiPointTouchArea::grabGesture() QVector<int> ids; ids.reserve(_touchPoints.size()); - for (auto it = _touchPoints.keyBegin(), end = _touchPoints.keyEnd(); it != end; ++it) - ids.append(*it); + for (auto it = _touchPoints.keyBegin(), end = _touchPoints.keyEnd(); it != end; ++it) { + if (*it != -1) // -1 might be the mouse-point, but we already grabbed the mouse above. + ids.append(*it); + } grabTouchPoints(ids); setKeepTouchGrab(true); } diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index ada56fbc25..0151a4e3ca 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -741,16 +741,16 @@ void QQuickWindowPrivate::setMouseGrabber(QQuickItem *grabber) qCDebug(DBG_MOUSE_TARGET) << "grabber" << q->mouseGrabberItem() << "->" << grabber; QQuickItem *oldGrabber = q->mouseGrabberItem(); - QQuickPointerEvent *event = QQuickPointerDevice::genericMouseDevice()->pointerEvent(); - Q_ASSERT(event->pointCount() == 1); - event->point(0)->setGrabber(grabber); - if (grabber && touchMouseId != -1 && touchMouseDevice) { // update the touch item for mouse touch id to the new grabber qCDebug(DBG_TOUCH_TARGET) << "TP (mouse)" << touchMouseId << "->" << q->mouseGrabberItem(); auto point = touchMouseDevice->pointerEvent()->pointById(touchMouseId); if (point) point->setGrabber(grabber); + } else { + QQuickPointerEvent *event = QQuickPointerDevice::genericMouseDevice()->pointerEvent(); + Q_ASSERT(event->pointCount() == 1); + event->point(0)->setGrabber(grabber); } if (oldGrabber) { @@ -763,13 +763,30 @@ void QQuickWindowPrivate::setMouseGrabber(QQuickItem *grabber) void QQuickWindowPrivate::grabTouchPoints(QQuickItem *grabber, const QVector<int> &ids) { - Q_Q(QQuickWindow); QSet<QQuickItem*> ungrab; for (int i = 0; i < ids.count(); ++i) { // FIXME: deprecate this function, we need a device + int id = ids.at(i); + if (Q_UNLIKELY(id < 0)) { + qWarning("ignoring grab of touchpoint %d", id); + continue; + } + if (id == touchMouseId) { + auto point = touchMouseDevice->pointerEvent()->pointById(id); + auto touchMouseGrabber = point->grabber(); + if (touchMouseGrabber) { + point->setGrabber(nullptr); + touchMouseGrabber->mouseUngrabEvent(); + ungrab.insert(touchMouseGrabber); + touchMouseDevice = nullptr; + touchMouseId = -1; + } + qCDebug(DBG_MOUSE_TARGET) << "grabTouchPoints: mouse grabber changed due to grabTouchPoints:" << touchMouseGrabber << "-> null"; + } + const auto touchDevices = QQuickPointerDevice::touchDevices(); for (auto device : touchDevices) { - auto point = device->pointerEvent()->pointById(ids.at(i)); + auto point = device->pointerEvent()->pointById(id); if (!point) continue; QQuickItem *oldGrabber = point->grabber(); @@ -780,12 +797,6 @@ void QQuickWindowPrivate::grabTouchPoints(QQuickItem *grabber, const QVector<int if (oldGrabber) ungrab.insert(oldGrabber); } - - QQuickItem *mouseGrabberItem = q->mouseGrabberItem(); - if (touchMouseId == ids.at(i) && mouseGrabberItem && mouseGrabberItem != grabber) { - qCDebug(DBG_MOUSE_TARGET) << "grabTouchPoints: grabber" << mouseGrabberItem << "-> null"; - setMouseGrabber(nullptr); - } } for (QQuickItem *oldGrabber : qAsConst(ungrab)) oldGrabber->touchUngrabEvent(); @@ -1467,6 +1478,15 @@ QObject *QQuickWindow::focusObject() const */ QQuickItem *QQuickWindow::mouseGrabberItem() const { + Q_D(const QQuickWindow); + + if (d->touchMouseId != -1 && d->touchMouseDevice) { + QQuickPointerEvent *event = d->touchMouseDevice->pointerEvent(); + auto point = event->pointById(d->touchMouseId); + Q_ASSERT(point); + return point->grabber(); + } + QQuickPointerEvent *event = QQuickPointerDevice::genericMouseDevice()->pointerEvent(); Q_ASSERT(event->pointCount()); return event->point(0)->grabber(); |