improve gesture recognition

In order to not make misdetections with sub-pixel movements the gesture
recognizer completely ignored those. This fails however when you move
your fingers very slowly, so instead accumulate the delta and only use
it for direction detection if it's high enough.
This commit is contained in:
Xaver Hugl 2021-06-26 01:00:56 +02:00
parent eb62dbb9c5
commit fe11219a0c
2 changed files with 21 additions and 7 deletions

View file

@ -142,24 +142,30 @@ int GestureRecognizer::startSwipeGesture(uint fingerCount, const QPointF &startP
void GestureRecognizer::updateSwipeGesture(const QSizeF &delta)
{
m_swipeUpdates << delta;
if (std::abs(delta.width()) < 1 && std::abs(delta.height()) < 1) {
// some (touch) devices report sub-pixel movement on screen edges
// this often cancels gestures -> ignore these movements
m_currentDelta += delta;
// with high resolution touch(pad) gestures can be cancelled without intention
// -> don't cancel movements if their accumulated values are too small but also still update the gesture for animations
if (std::abs(m_currentDelta.width()) > 1 || std::abs(m_currentDelta.height()) > 1) {
m_lastDelta = m_currentDelta;
m_currentDelta = QSizeF(0, 0);
} else if (std::abs(m_lastDelta.width()) < 1 && std::abs(m_lastDelta.height()) < 1) {
// no direction yet
return;
}
// determine the direction of the swipe
if (delta.width() == delta.height()) {
if (m_lastDelta.width() == m_lastDelta.height()) {
// special case of diagonal, this is not yet supported, thus cancel all gestures
cancelActiveSwipeGestures();
return;
}
SwipeGesture::Direction direction;
if (std::abs(delta.width()) > std::abs(delta.height())) {
if (std::abs(m_lastDelta.width()) > std::abs(m_lastDelta.height())) {
// horizontal
direction = delta.width() < 0 ? SwipeGesture::Direction::Left : SwipeGesture::Direction::Right;
direction = m_lastDelta.width() < 0 ? SwipeGesture::Direction::Left : SwipeGesture::Direction::Right;
} else {
// vertical
direction = delta.height() < 0 ? SwipeGesture::Direction::Up : SwipeGesture::Direction::Down;
direction = m_lastDelta.height() < 0 ? SwipeGesture::Direction::Up : SwipeGesture::Direction::Down;
}
const QSizeF combinedDelta = std::accumulate(m_swipeUpdates.constBegin(), m_swipeUpdates.constEnd(), QSizeF(0, 0));
for (auto it = m_activeSwipeGestures.begin(); it != m_activeSwipeGestures.end();) {
@ -182,12 +188,16 @@ void GestureRecognizer::cancelActiveSwipeGestures()
Q_EMIT g->cancelled();
}
m_activeSwipeGestures.clear();
m_currentDelta = QSizeF(0, 0);
m_lastDelta = QSizeF(0, 0);
}
void GestureRecognizer::cancelSwipeGesture()
{
cancelActiveSwipeGestures();
m_swipeUpdates.clear();
m_currentDelta = QSizeF(0, 0);
m_lastDelta = QSizeF(0, 0);
}
void GestureRecognizer::endSwipeGesture()
@ -202,6 +212,8 @@ void GestureRecognizer::endSwipeGesture()
}
m_activeSwipeGestures.clear();
m_swipeUpdates.clear();
m_currentDelta = QSizeF(0, 0);
m_lastDelta = QSizeF(0, 0);
}
}

View file

@ -201,6 +201,8 @@ private:
QVector<Gesture*> m_activeSwipeGestures;
QMap<Gesture*, QMetaObject::Connection> m_destroyConnections;
QVector<QSizeF> m_swipeUpdates;
QSizeF m_lastDelta = QSizeF(0, 0);
QSizeF m_currentDelta = QSizeF(0, 0);
};
}