QSwipeGestureRecognizer: Allow for small direction changes.

When trying to do a straight right/left/up/down swipe, a minimal
change in the other direction caused to the gesture to be canceled.
Introduce a threshold for checking such to prevent this.

Task-number: QTBUG-46195
Change-Id: I3e199f2ec0c81d23a16073b1f5b8fff004958239
Reviewed-by: Shawn Rutledge <shawn.rutledge@theqtcompany.com>
bb10
Friedemann Kleint 2015-05-29 14:02:03 +02:00
parent 6468cf4e79
commit eb926dc31f
2 changed files with 26 additions and 13 deletions

View File

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

View File

@ -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<int>("swipeSubTest");
QTest::addColumn<bool>("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);