diff --git a/src/widgets/kernel/qgesture_p.h b/src/widgets/kernel/qgesture_p.h
index 183a2eba0fa939063dd350b88e40e53556bd1b9f..26d9ede59ddc19f3fb4ad86f62dfe30a61d02ace 100644
--- a/src/widgets/kernel/qgesture_p.h
+++ b/src/widgets/kernel/qgesture_p.h
@@ -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
diff --git a/src/widgets/kernel/qgesturemanager.cpp b/src/widgets/kernel/qgesturemanager.cpp
index 739e6b1870c197286fdf588eda2079e02b40475b..c9af3062d33234a11ced3589fac7471d48cc6b02 100644
--- a/src/widgets/kernel/qgesturemanager.cpp
+++ b/src/widgets/kernel/qgesturemanager.cpp
@@ -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);
diff --git a/src/widgets/kernel/qstandardgestures.cpp b/src/widgets/kernel/qstandardgestures.cpp
index 9e3cb473e5509b164a23f8b6454f162e818e0463..6656903e70dc8c0b760f6551530c72598b0aafdc 100644
--- a/src/widgets/kernel/qstandardgestures.cpp
+++ b/src/widgets/kernel/qstandardgestures.cpp
@@ -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;
diff --git a/src/widgets/kernel/qstandardgestures_p.h b/src/widgets/kernel/qstandardgestures_p.h
index aeabd9cc7ee1eec0247fc375b5357b62d0069d93..15ba31f26a32fa2cbc198d0e5e1047ce9724c204 100644
--- a/src/widgets/kernel/qstandardgestures_p.h
+++ b/src/widgets/kernel/qstandardgestures_p.h
@@ -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
diff --git a/tests/auto/widgets/gestures/qgesturerecognizer/tst_qgesturerecognizer.cpp b/tests/auto/widgets/gestures/qgesturerecognizer/tst_qgesturerecognizer.cpp
index 833494f25ef4cef9a0b8a90f48074a3aabf399ad..bdf610e4264fc9a6ef34a4be6416209f4a3f23be 100644
--- a/tests/auto/widgets/gestures/qgesturerecognizer/tst_qgesturerecognizer.cpp
+++ b/tests/auto/widgets/gestures/qgesturerecognizer/tst_qgesturerecognizer.cpp
@@ -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()