aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/quick/items/qquickwindow.cpp42
-rw-r--r--src/quick/items/qquickwindow_p.h3
-rw-r--r--tests/auto/quick/qquickwindow/tst_qquickwindow.cpp56
3 files changed, 85 insertions, 16 deletions
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index f705f132fc..c55db04566 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -64,6 +64,7 @@
#include <QtGui/qpainter.h>
#include <QtGui/qevent.h>
#include <QtGui/qmatrix4x4.h>
+#include <QtGui/qpa/qplatformtheme.h>
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qabstractanimation.h>
#include <QtCore/QLibraryInfo>
@@ -632,25 +633,28 @@ static QMouseEvent *touchToMouseEvent(QEvent::Type type, const QTouchEvent::Touc
return me;
}
-bool QQuickWindowPrivate::checkIfDoubleClicked(ulong newPressEventTimestamp)
+bool QQuickWindowPrivate::checkIfDoubleTapped(ulong newPressEventTimestamp, QPoint newPressPos)
{
- bool doubleClicked;
+ bool doubleClicked = false;
+
+ if (touchMousePressTimestamp > 0) {
+ QPoint distanceBetweenPresses = newPressPos - touchMousePressPos;
+ const int doubleTapDistance = QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::TouchDoubleTapDistance).toInt();
+ doubleClicked = (qAbs(distanceBetweenPresses.x()) <= doubleTapDistance) && (qAbs(distanceBetweenPresses.y()) <= doubleTapDistance);
- if (touchMousePressTimestamp == 0) {
- // just initialize the variable
- touchMousePressTimestamp = newPressEventTimestamp;
- doubleClicked = false;
- } else {
- ulong timeBetweenPresses = newPressEventTimestamp - touchMousePressTimestamp;
- ulong doubleClickInterval = static_cast<ulong>(QGuiApplication::styleHints()->
- mouseDoubleClickInterval());
- doubleClicked = timeBetweenPresses < doubleClickInterval;
if (doubleClicked) {
- touchMousePressTimestamp = 0;
- } else {
- touchMousePressTimestamp = newPressEventTimestamp;
+ ulong timeBetweenPresses = newPressEventTimestamp - touchMousePressTimestamp;
+ ulong doubleClickInterval = static_cast<ulong>(QGuiApplication::styleHints()->
+ mouseDoubleClickInterval());
+ doubleClicked = timeBetweenPresses < doubleClickInterval;
}
}
+ if (doubleClicked) {
+ touchMousePressTimestamp = 0;
+ } else {
+ touchMousePressTimestamp = newPressEventTimestamp;
+ touchMousePressPos = newPressPos;
+ }
return doubleClicked;
}
@@ -707,7 +711,9 @@ bool QQuickWindowPrivate::deliverTouchAsMouse(QQuickItem *item, QQuickPointerEve
if (auto pointerEventPoint = pointerEvent->pointById(p.id()))
pointerEventPoint->setGrabberItem(item);
- if (checkIfDoubleClicked(event->timestamp())) {
+ if (checkIfDoubleTapped(event->timestamp(), p.screenPos().toPoint())) {
+ // since we synth the mouse event from from touch, we respect the
+ // QPlatformTheme::TouchDoubleTapDistance instead of QPlatformTheme::MouseDoubleClickDistance
QScopedPointer<QMouseEvent> mouseDoubleClick(touchToMouseEvent(QEvent::MouseButtonDblClick, p, event.data(), item, false));
QCoreApplication::sendEvent(item, mouseDoubleClick.data());
event->setAccepted(mouseDoubleClick->isAccepted());
@@ -722,6 +728,12 @@ bool QQuickWindowPrivate::deliverTouchAsMouse(QQuickItem *item, QQuickPointerEve
// Touch point was there before and moved
} else if (touchMouseDevice == device && p.id() == touchMouseId) {
if (p.state() & Qt::TouchPointMoved) {
+ if (touchMousePressTimestamp != 0) {
+ const int doubleTapDistance = QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::TouchDoubleTapDistance).toInt();
+ const QPoint moveDelta = p.screenPos().toPoint() - touchMousePressPos;
+ if (moveDelta.x() >= doubleTapDistance || moveDelta.y() >= doubleTapDistance)
+ touchMousePressTimestamp = 0; // Got dragged too far, dismiss the double tap
+ }
if (QQuickItem *mouseGrabberItem = q->mouseGrabberItem()) {
QScopedPointer<QMouseEvent> me(touchToMouseEvent(QEvent::MouseMove, p, event.data(), mouseGrabberItem, false));
QCoreApplication::sendEvent(item, me.data());
diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h
index 5a3807b24f..63760a3b68 100644
--- a/src/quick/items/qquickwindow_p.h
+++ b/src/quick/items/qquickwindow_p.h
@@ -135,8 +135,9 @@ public:
#endif
int touchMouseId;
QQuickPointerDevice *touchMouseDevice;
- bool checkIfDoubleClicked(ulong newPressEventTimestamp);
+ bool checkIfDoubleTapped(ulong newPressEventTimestamp, QPoint newPressPos);
ulong touchMousePressTimestamp;
+ QPoint touchMousePressPos; // in screen coordiantes
void cancelTouchMouseSynthesis();
// Mouse positions are saved in widget coordinates
diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
index 4cf7fa7119..f08b9207d1 100644
--- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
+++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
@@ -353,6 +353,11 @@ protected:
m_mouseEvents << *event;
}
+ void mouseDoubleClickEvent(QMouseEvent *event) override {
+ qCDebug(lcTests) << event;
+ m_mouseEvents << *event;
+ }
+
public:
QList<QMouseEvent> m_mouseEvents;
QList<QTouchEvent> m_touchEvents;
@@ -401,6 +406,8 @@ private slots:
void mouseFromTouch_basic();
void synthMouseFromTouch_data();
void synthMouseFromTouch();
+ void synthMouseDoubleClickFromTouch_data();
+ void synthMouseDoubleClickFromTouch();
void clearWindow();
@@ -1241,6 +1248,55 @@ void tst_qquickwindow::synthMouseFromTouch()
QCOMPARE(ev.source(), Qt::MouseEventSynthesizedByQt);
}
+void tst_qquickwindow::synthMouseDoubleClickFromTouch_data()
+{
+ QTest::addColumn<QPoint>("movement");
+ QTest::addColumn<QPoint>("distanceBetweenPresses");
+ QTest::addColumn<bool>("expectedSynthesizedDoubleClickEvent");
+
+ QTest::newRow("normal") << QPoint(0, 0) << QPoint(0, 0) << true;
+ QTest::newRow("with 1 pixel wiggle") << QPoint(1, 1) << QPoint(1, 1) << true;
+ QTest::newRow("too much distance to second tap") << QPoint(0, 0) << QPoint(50, 0) << false;
+ QTest::newRow("too much drag") << QPoint(50, 0) << QPoint(0, 0) << false;
+ QTest::newRow("too much drag and too much distance to second tap") << QPoint(50, 0) << QPoint(50, 0) << false;
+}
+
+void tst_qquickwindow::synthMouseDoubleClickFromTouch()
+{
+ QFETCH(QPoint, movement);
+ QFETCH(QPoint, distanceBetweenPresses);
+ QFETCH(bool, expectedSynthesizedDoubleClickEvent);
+
+ QCoreApplication::setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, true);
+ QScopedPointer<MouseRecordingWindow> window(new MouseRecordingWindow);
+ QScopedPointer<MouseRecordingItem> item(new MouseRecordingItem(false, nullptr));
+ item->setParentItem(window->contentItem());
+ window->resize(250, 250);
+ window->setPosition(100, 100);
+ window->setTitle(QTest::currentTestFunction());
+ window->show();
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
+ QTest::qWait(100);
+
+ QPoint p1 = item->mapToScene(item->clipRect().center()).toPoint();
+ QTest::touchEvent(window.data(), touchDevice).press(0, p1, window.data());
+ QTest::touchEvent(window.data(), touchDevice).move(0, p1 + movement, window.data());
+ QTest::touchEvent(window.data(), touchDevice).release(0, p1 + movement, window.data());
+
+ QPoint p2 = p1 + distanceBetweenPresses;
+ QTest::touchEvent(window.data(), touchDevice).press(1, p2, window.data());
+ QTest::touchEvent(window.data(), touchDevice).move(1, p2 + movement, window.data());
+ QTest::touchEvent(window.data(), touchDevice).release(1, p2 + movement, window.data());
+
+ const int eventCount = item->m_mouseEvents.count();
+ QVERIFY(eventCount >= 2);
+
+ const int nDoubleClicks = std::count_if(item->m_mouseEvents.constBegin(), item->m_mouseEvents.constEnd(), [](const QMouseEvent &ev) { return (ev.type() == QEvent::MouseButtonDblClick); } );
+ const bool foundDoubleClick = (nDoubleClicks == 1);
+ QCOMPARE(foundDoubleClick, expectedSynthesizedDoubleClickEvent);
+
+}
+
void tst_qquickwindow::clearWindow()
{
QQuickWindow *window = new QQuickWindow;