Skip to content

Commit

Permalink
libgestures/gestures/swipe: add diagonal directions
Browse files Browse the repository at this point in the history
  • Loading branch information
taj-ny committed Jan 30, 2025
1 parent 9ff84da commit 01f4f4e
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 44 deletions.
87 changes: 57 additions & 30 deletions src/libgestures/libgestures/gestures/gesturerecognizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ void GestureRecognizer::unregisterGestures()
m_gestures.clear();
}

void GestureRecognizer::setWidthToHeightRatio(const qreal &ratio)
{
m_widthToHeightRatio = ratio;
}

void GestureRecognizer::setInputEventsToSample(const uint8_t &events)
{
m_inputEventsToSample = events;
Expand Down Expand Up @@ -107,7 +112,8 @@ bool GestureRecognizer::swipeGestureUpdate(const QPointF &delta, bool &endedPrem
{
if (m_sampledInputEvents++ != m_inputEventsToSample)
{
m_accumulatedAbsoluteSampledDelta += std::abs(delta.x()) + std::abs(delta.y());
m_accumulatedAbsoluteSampledDelta += std::sqrt(std::pow(delta.x(), 2) + std::pow(delta.y(), 2));
m_currentSwipeDelta = {};
return true;
}

Expand All @@ -119,38 +125,47 @@ bool GestureRecognizer::swipeGestureUpdate(const QPointF &delta, bool &endedPrem
m_isDeterminingSpeed = false;
}

SwipeDirection direction; // Overall direction
Axis swipeAxis;

// Pick an axis for gestures so horizontal ones don't change to vertical ones without lifting fingers
if (m_currentSwipeAxis == Axis::None)
{
if (std::abs(m_currentSwipeDelta.x()) >= std::abs(m_currentSwipeDelta.y()))
swipeAxis = Axis::Horizontal;
else
swipeAxis = Axis::Vertical;
SwipeDirection validDirection = SwipeDirection::None;
SwipeDirection direction = SwipeDirection::None;

if (m_validSwipeDirection == SwipeDirection::None) {
qWarning() << m_currentSwipeDelta;
if (isSwipeDiagonal(m_currentSwipeDelta)) {
if ((m_currentSwipeDelta.x() > 0 && m_currentSwipeDelta.y() < 0)
|| (m_currentSwipeDelta.x() < 0 && m_currentSwipeDelta.y() > 0)) {
validDirection = SwipeDirection::LeftDownRightUp;
} else if ((m_currentSwipeDelta.x() > 0 && m_currentSwipeDelta.y() > 0)
|| (m_currentSwipeDelta.x() < 0 && m_currentSwipeDelta.y() < 0)) {
validDirection = SwipeDirection::LeftUpRightDown;
}
} else if (std::abs(m_currentSwipeDelta.x()) > std::abs(m_currentSwipeDelta.y())) {
validDirection = SwipeDirection::LeftRight;
} else {
validDirection = SwipeDirection::UpDown;
}

if (std::abs(m_currentSwipeDelta.x()) >= 5 || std::abs(m_currentSwipeDelta.y()) >= 5)
{
if (std::abs(m_currentSwipeDelta.x()) >= 5 || std::abs(m_currentSwipeDelta.y()) >= 5) {
// only lock in a direction if the delta is big enough
// to prevent accidentally choosing the wrong direction
m_currentSwipeAxis = swipeAxis;
m_validSwipeDirection = validDirection;
}
} else {
validDirection = m_validSwipeDirection;
}
else
swipeAxis = m_currentSwipeAxis;

// Find the current swipe direction
switch (swipeAxis)
{
case Axis::Vertical:
direction = m_currentSwipeDelta.y() < 0 ? SwipeDirection::Up : SwipeDirection::Down;
break;
case Axis::Horizontal:
direction = m_currentSwipeDelta.x() < 0 ? SwipeDirection::Left : SwipeDirection::Right;
break;
default:
Q_UNREACHABLE();
qreal deltaSingle = 0;
if (validDirection == SwipeDirection::LeftRight) {
direction = delta.x() < 0 ? SwipeDirection::Left : SwipeDirection::Right;
deltaSingle = delta.x();
} else if (validDirection == SwipeDirection::UpDown) {
direction = delta.y() < 0 ? SwipeDirection::Up : SwipeDirection::Down;
deltaSingle = delta.y();
} else if (validDirection == SwipeDirection::LeftDownRightUp) {
direction = delta.x() > 0 && delta.y() < 0 ? SwipeDirection::RightUp : SwipeDirection::LeftDown;
deltaSingle = std::sqrt(std::pow(delta.x(), 2) + std::pow(delta.y(), 2));
} else if (validDirection == SwipeDirection::LeftUpRightDown) {
direction = delta.x() < 0 && delta.y() < 0 ? SwipeDirection::LeftUp : SwipeDirection::RightDown;
deltaSingle = std::sqrt(std::pow(delta.x(), 2) + std::pow(delta.y(), 2));
}

for (auto it = m_activeSwipeGestures.begin(); it != m_activeSwipeGestures.end();)
Expand All @@ -160,7 +175,11 @@ bool GestureRecognizer::swipeGestureUpdate(const QPointF &delta, bool &endedPrem
if ((!((gesture->direction() == SwipeDirection::LeftRight
&& (direction == SwipeDirection::Left || direction == SwipeDirection::Right))
|| (gesture->direction() == SwipeDirection::UpDown
&& (direction == SwipeDirection::Up || direction == SwipeDirection::Down)))
&& (direction == SwipeDirection::Up || direction == SwipeDirection::Down))
|| (gesture->direction() == SwipeDirection::LeftDownRightUp
&& (direction == SwipeDirection::LeftDown || direction == SwipeDirection::RightUp))
|| (gesture->direction() == SwipeDirection::LeftUpRightDown
&& (direction == SwipeDirection::LeftUp || direction == SwipeDirection::RightDown)))
&& gesture->direction() != direction)
|| (gesture->speed() != GestureSpeed::Any && gesture->speed() != m_speed))
{
Expand All @@ -169,7 +188,7 @@ bool GestureRecognizer::swipeGestureUpdate(const QPointF &delta, bool &endedPrem
continue;
}

Q_EMIT gesture->updated(swipeAxis == Axis::Vertical ? delta.y() : delta.x(), endedPrematurely);
Q_EMIT gesture->updated(deltaSingle, endedPrematurely);
if (endedPrematurely)
return true;

Expand Down Expand Up @@ -266,13 +285,21 @@ void GestureRecognizer::gestureCancel(std::vector<std::shared_ptr<TGesture>> &ac
resetMembers();
}

bool GestureRecognizer::isSwipeDiagonal(const QPointF &delta) const
{
constexpr auto min = 35 * (M_PI / 180);
constexpr auto max = 70 * (M_PI / 180);
const auto angle = atan2(std::abs(delta.y() * m_widthToHeightRatio), std::abs(delta.x()));
return angle >= min && angle <= max;
}

void GestureRecognizer::resetMembers()
{
m_accumulatedAbsoluteSampledDelta = 0;
m_sampledInputEvents = 0;
m_isDeterminingSpeed = false;
m_previousPinchScale = 1;
m_currentSwipeAxis = Axis::None;
m_validSwipeDirection = SwipeDirection::None;
m_currentSwipeDelta = QPointF();
m_speed = GestureSpeed::Any;
}
Expand Down
9 changes: 8 additions & 1 deletion src/libgestures/libgestures/gestures/gesturerecognizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class GestureRecognizer : public QObject
*/
void unregisterGestures();

void setWidthToHeightRatio(const qreal &ratio);
void setInputEventsToSample(const uint8_t &events);
void setSwipeFastThreshold(const qreal &threshold);
void setPinchInFastThreshold(const qreal &threshold);
Expand Down Expand Up @@ -104,19 +105,25 @@ class GestureRecognizer : public QObject
template <class TGesture>
void gestureCancel(std::vector<std::shared_ptr<TGesture>> &activeGestures);

/**
* Checks whether the swipe gesture the specified delta belongs to has been performed diagonally.
*/
bool isSwipeDiagonal(const QPointF &delta) const;

void resetMembers();

std::vector<std::shared_ptr<Gesture>> m_gestures;

std::vector<std::shared_ptr<SwipeGesture>> m_activeSwipeGestures;
Axis m_currentSwipeAxis = Axis::None;
SwipeDirection m_validSwipeDirection = SwipeDirection::None;
QPointF m_currentSwipeDelta;

std::vector<std::shared_ptr<PinchGesture>> m_activePinchGestures;
qreal m_previousPinchScale = 1;

std::vector<std::shared_ptr<HoldGesture>> m_activeHoldGestures;

qreal m_widthToHeightRatio = 1;
uint8_t m_inputEventsToSample = 3;
qreal m_swipeGestureFastThreshold = 20;
qreal m_pinchInFastThreshold = 0.04;
Expand Down
14 changes: 13 additions & 1 deletion src/libgestures/libgestures/gestures/swipegesture.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,20 @@ enum class SwipeDirection
Right,
Down,
Up,

LeftUp,
LeftDown,
RightUp,
RightDown,

// Bi-directional
LeftRight,
UpDown
UpDown,

LeftUpRightDown,
LeftDownRightUp,

None
};

class SwipeGesture : public Gesture
Expand Down
30 changes: 18 additions & 12 deletions src/libgestures/libgestures/yaml_convert.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ struct convert<std::shared_ptr<libgestures::GestureRecognizer>>
gestureRecognizer->registerGesture(gestureNode.as<std::shared_ptr<libgestures::Gesture>>());
}

gestureRecognizer->setWidthToHeightRatio(node["width_to_height_ratio"].as<qreal>(gestureRecognizer->m_widthToHeightRatio));
const auto speedNode = node["speed"];
if (speedNode.IsDefined()) {
gestureRecognizer->setInputEventsToSample(
Expand Down Expand Up @@ -252,24 +253,29 @@ struct convert<libgestures::PinchDirection>
}
};

const std::map<QString, libgestures::SwipeDirection> directions =
{
{ "left", libgestures::SwipeDirection::Left },
{ "right", libgestures::SwipeDirection::Right },
{ "up", libgestures::SwipeDirection::Up },
{ "down", libgestures::SwipeDirection::Down },
{ "left_up", libgestures::SwipeDirection::LeftUp },
{ "left_down", libgestures::SwipeDirection::LeftDown },
{ "right_up", libgestures::SwipeDirection::RightUp },
{ "right_down", libgestures::SwipeDirection::RightDown },
{ "left_right", libgestures::SwipeDirection::LeftRight },
{ "up_down", libgestures::SwipeDirection::UpDown },
{ "left_up_right_down", libgestures::SwipeDirection::LeftUpRightDown },
{ "left_down_right_up", libgestures::SwipeDirection::LeftDownRightUp }
};
template <>
struct convert<libgestures::SwipeDirection>
{
static bool decode(const Node &node, libgestures::SwipeDirection &direction)
{
const auto directionRaw = node.as<QString>();
if (directionRaw == "left") {
direction = libgestures::SwipeDirection::Left;
} else if (directionRaw == "right") {
direction = libgestures::SwipeDirection::Right;
} else if (directionRaw == "left_right") {
direction = libgestures::SwipeDirection::LeftRight;
} else if (directionRaw == "up") {
direction = libgestures::SwipeDirection::Up;
} else if (directionRaw == "down") {
direction = libgestures::SwipeDirection::Down;
} else if (directionRaw == "up_down") {
direction = libgestures::SwipeDirection::UpDown;
if (directions.contains(directionRaw)) {
direction = directions.at(directionRaw);
} else {
throw Exception(node.Mark(), "Invalid swipe direction");
}
Expand Down

0 comments on commit 01f4f4e

Please sign in to comment.