diff --git a/src/widgets/kernel/qstandardgestures.cpp b/src/widgets/kernel/qstandardgestures.cpp index d19e473d18..3d6ae3f322 100644 --- a/src/widgets/kernel/qstandardgestures.cpp +++ b/src/widgets/kernel/qstandardgestures.cpp @@ -334,23 +334,27 @@ QGestureRecognizer::Result QSwipeGestureRecognizer::recognize(QGesture *state, d->swipeAngle = QLineF(p1.startScreenPos(), p1.screenPos()).angle(); static const int MoveThreshold = 50; + static const int directionChangeThreshold = MoveThreshold / 8; if (qAbs(xDistance) > MoveThreshold || qAbs(yDistance) > MoveThreshold) { // measure the distance to check if the direction changed d->lastPositions[0] = p1.screenPos().toPoint(); d->lastPositions[1] = p2.screenPos().toPoint(); d->lastPositions[2] = p3.screenPos().toPoint(); - QSwipeGesture::SwipeDirection horizontal = - xDistance > 0 ? QSwipeGesture::Right : QSwipeGesture::Left; - QSwipeGesture::SwipeDirection vertical = - yDistance > 0 ? QSwipeGesture::Down : QSwipeGesture::Up; - if (d->verticalDirection == QSwipeGesture::NoDirection) + result = QGestureRecognizer::TriggerGesture; + // QTBUG-46195, small changes in direction should not cause the gesture to be canceled. + if (d->verticalDirection == QSwipeGesture::NoDirection || qAbs(yDistance) > directionChangeThreshold) { + const QSwipeGesture::SwipeDirection vertical = yDistance > 0 + ? QSwipeGesture::Down : QSwipeGesture::Up; + if (d->verticalDirection != QSwipeGesture::NoDirection && d->verticalDirection != vertical) + result = QGestureRecognizer::CancelGesture; d->verticalDirection = vertical; - if (d->horizontalDirection == QSwipeGesture::NoDirection) + } + if (d->horizontalDirection == QSwipeGesture::NoDirection || qAbs(xDistance) > directionChangeThreshold) { + const QSwipeGesture::SwipeDirection horizontal = xDistance > 0 + ? QSwipeGesture::Right : QSwipeGesture::Left; + if (d->horizontalDirection != QSwipeGesture::NoDirection && d->horizontalDirection != horizontal) + result = QGestureRecognizer::CancelGesture; d->horizontalDirection = horizontal; - if (d->verticalDirection != vertical || d->horizontalDirection != horizontal) { - result = QGestureRecognizer::CancelGesture; - } else { - result = QGestureRecognizer::TriggerGesture; } } else { if (q->state() != Qt::NoGesture) diff --git a/tests/auto/widgets/gestures/qgesturerecognizer/tst_qgesturerecognizer.cpp b/tests/auto/widgets/gestures/qgesturerecognizer/tst_qgesturerecognizer.cpp index 67c431d16e..dc2adad5da 100644 --- a/tests/auto/widgets/gestures/qgesturerecognizer/tst_qgesturerecognizer.cpp +++ b/tests/auto/widgets/gestures/qgesturerecognizer/tst_qgesturerecognizer.cpp @@ -269,7 +269,8 @@ void tst_QGestureRecognizer::pinchGesture() enum SwipeSubTest { SwipeLineSubTest, - SwipeChangeDirectionSubTest, + SwipeDirectionChangeSubTest, + SwipeSmallDirectionChangeSubTest }; void tst_QGestureRecognizer::swipeGesture_data() @@ -277,7 +278,8 @@ void tst_QGestureRecognizer::swipeGesture_data() QTest::addColumn("swipeSubTest"); QTest::addColumn("gestureExpected"); QTest::newRow("Line") << int(SwipeLineSubTest) << true; - QTest::newRow("ChangeDirection") << int(SwipeChangeDirectionSubTest) << false; + QTest::newRow("DirectionChange") << int(SwipeDirectionChangeSubTest) << false; + QTest::newRow("SmallDirectionChange") << int(SwipeSmallDirectionChangeSubTest) << true; } void tst_QGestureRecognizer::swipeGesture() @@ -314,10 +316,17 @@ void tst_QGestureRecognizer::swipeGesture() case SwipeLineSubTest: linearSequence(5, moveDelta, swipeSequence, points, &widget); break; - case SwipeChangeDirectionSubTest: + case SwipeDirectionChangeSubTest: linearSequence(5, moveDelta, swipeSequence, points, &widget); linearSequence(3, QPoint(-moveDelta.x(), moveDelta.y()), swipeSequence, points, &widget); break; + case SwipeSmallDirectionChangeSubTest: { // QTBUG-46195, small changes in direction should not cause the gesture to be canceled. + const QPoint smallChangeMoveDelta(50, 1); + linearSequence(5, smallChangeMoveDelta, swipeSequence, points, &widget); + linearSequence(1, QPoint(smallChangeMoveDelta.x(), -3), swipeSequence, points, &widget); + linearSequence(5, smallChangeMoveDelta, swipeSequence, points, &widget); + } + break; } releaseSequence(swipeSequence, points, &widget);