QPanGestureRecognizer: Make the number of touch points a parameter.

Prepare for determining the suitable number of touch points
from the device type. For now, 2 points are used as
before, which can be overridden by setting the environment
variable QT_PAN_TOUCHPOINTS. Add member variable
to QPanGesturePrivate which is set on gesture creation and later
used for comparison.

Task-number: QTBUG-40461
Change-Id: I6d9e35ca752375bc6a54435482ca0925195b8142
Reviewed-by: Shawn Rutledge <shawn.rutledge@digia.com>
bb10
Friedemann Kleint 2014-10-30 14:43:51 +01:00
parent 954552ceac
commit 2fb3941198
5 changed files with 41 additions and 20 deletions

View File

@ -80,7 +80,7 @@ class QPanGesturePrivate : public QGesturePrivate
public:
QPanGesturePrivate()
: acceleration(0), xVelocity(0), yVelocity(0)
: acceleration(0), xVelocity(0), yVelocity(0), pointCount(2)
{
}
@ -95,6 +95,7 @@ public:
qreal acceleration;
qreal xVelocity;
qreal yVelocity;
int pointCount; // ### fixme Qt 5.5: Add accessor to QPanGesture.
};
class QPinchGesturePrivate : public QGesturePrivate

View File

@ -63,6 +63,24 @@
QT_BEGIN_NAMESPACE
static inline int panTouchPoints()
{
// Override by environment variable for testing.
static const char panTouchPointVariable[] = "QT_PAN_TOUCHPOINTS";
if (qEnvironmentVariableIsSet(panTouchPointVariable)) {
bool ok;
const int result = qgetenv(panTouchPointVariable).toInt(&ok);
if (ok && result >= 1)
return result;
qWarning() << "Ignoring invalid value of " << panTouchPointVariable;
}
// Pan should use 1 finger on a touch screen and 2 fingers on touch pads etc.
// where 1 finger movements are used for mouse event synthetization. For now,
// default to 2 until all classes inheriting QScrollArea are fixed to handle it
// correctly.
return 2;
}
QGestureManager::QGestureManager(QObject *parent)
: QObject(parent), state(NotGesture), m_lastCustomGestureId(Qt::CustomGesture)
{
@ -73,7 +91,7 @@ QGestureManager::QGestureManager(QObject *parent)
registerGestureRecognizer(new QMacPinchGestureRecognizer);
registerGestureRecognizer(new QMacPanGestureRecognizer);
#else
registerGestureRecognizer(new QPanGestureRecognizer);
registerGestureRecognizer(new QPanGestureRecognizer(panTouchPoints()));
registerGestureRecognizer(new QPinchGestureRecognizer);
registerGestureRecognizer(new QSwipeGestureRecognizer);
registerGestureRecognizer(new QTapGestureRecognizer);

View File

@ -44,10 +44,6 @@
QT_BEGIN_NAMESPACE
QPanGestureRecognizer::QPanGestureRecognizer()
{
}
QGesture *QPanGestureRecognizer::create(QObject *target)
{
if (target && target->isWidgetType()) {
@ -62,6 +58,15 @@ QGesture *QPanGestureRecognizer::create(QObject *target)
return new QPanGesture;
}
static QPointF panOffset(const QList<QTouchEvent::TouchPoint> &touchPoints, int maxCount)
{
QPointF result;
const int count = qMin(touchPoints.size(), maxCount);
for (int p = 0; p < count; ++p)
result += touchPoints.at(p).pos() - touchPoints.at(p).startPos();
return result / qreal(count);
}
QGestureRecognizer::Result QPanGestureRecognizer::recognize(QGesture *state,
QObject *,
QEvent *event)
@ -76,18 +81,15 @@ QGestureRecognizer::Result QPanGestureRecognizer::recognize(QGesture *state,
result = QGestureRecognizer::MayBeGesture;
QTouchEvent::TouchPoint p = ev->touchPoints().at(0);
d->lastOffset = d->offset = QPointF();
d->pointCount = m_pointCount;
break;
}
case QEvent::TouchEnd: {
if (q->state() != Qt::NoGesture) {
const QTouchEvent *ev = static_cast<const QTouchEvent *>(event);
if (ev->touchPoints().size() == 2) {
QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0);
QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1);
if (ev->touchPoints().size() == d->pointCount) {
d->lastOffset = d->offset;
d->offset =
QPointF(p1.pos().x() - p1.startPos().x() + p2.pos().x() - p2.startPos().x(),
p1.pos().y() - p1.startPos().y() + p2.pos().y() - p2.startPos().y()) / 2;
d->offset = panOffset(ev->touchPoints(), d->pointCount);
}
result = QGestureRecognizer::FinishGesture;
} else {
@ -97,16 +99,12 @@ QGestureRecognizer::Result QPanGestureRecognizer::recognize(QGesture *state,
}
case QEvent::TouchUpdate: {
const QTouchEvent *ev = static_cast<const QTouchEvent *>(event);
if (ev->touchPoints().size() >= 2) {
QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0);
QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1);
if (ev->touchPoints().size() >= d->pointCount) {
d->lastOffset = d->offset;
d->offset =
QPointF(p1.pos().x() - p1.startPos().x() + p2.pos().x() - p2.startPos().x(),
p1.pos().y() - p1.startPos().y() + p2.pos().y() - p2.startPos().y()) / 2;
d->offset = panOffset(ev->touchPoints(), d->pointCount);
if (d->offset.x() > 10 || d->offset.y() > 10 ||
d->offset.x() < -10 || d->offset.y() < -10) {
q->setHotSpot(p1.startScreenPos());
q->setHotSpot(ev->touchPoints().first().startScreenPos());
result = QGestureRecognizer::TriggerGesture;
} else {
result = QGestureRecognizer::MayBeGesture;

View File

@ -55,11 +55,14 @@ QT_BEGIN_NAMESPACE
class QPanGestureRecognizer : public QGestureRecognizer
{
public:
QPanGestureRecognizer();
explicit QPanGestureRecognizer(int pointCount = 2) : m_pointCount(pointCount) {}
QGesture *create(QObject *target);
QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event);
void reset(QGesture *state);
private:
const int m_pointCount;
};
class QPinchGestureRecognizer : public QGestureRecognizer

View File

@ -71,6 +71,7 @@ tst_QGestureRecognizer::tst_QGestureRecognizer()
: m_fingerDistance(qRound(QGuiApplication::primaryScreen()->physicalDotsPerInch() / 2.0))
, m_touchDevice(new QTouchDevice)
{
qputenv("QT_PAN_TOUCHPOINTS", "2"); // Prevent device detection of pan touch point count.
}
void tst_QGestureRecognizer::initTestCase()