diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp
index 0c015f39c7946b632287bac04d2069d625734f93..b809f0a0ab0d526601601535d53fa7cddd038484 100644
--- a/src/core/render_widget_host_view_qt.cpp
+++ b/src/core/render_widget_host_view_qt.cpp
@@ -115,17 +115,28 @@ static inline Qt::InputMethodHints toQtInputMethodHints(ui::TextInputType inputT
     }
 }
 
+static inline int firstAvailableId(const QMap<int, int> &map)
+{
+    ui::BitSet32 usedIds;
+    QMap<int, int>::const_iterator end = map.end();
+    for (QMap<int, int>::const_iterator it = map.begin(); it != end; ++it)
+        usedIds.mark_bit(it.value());
+    return usedIds.first_unmarked_bit();
+}
+
 static inline ui::GestureProvider::Config QtGestureProviderConfig() {
     ui::GestureProvider::Config config = ui::DefaultGestureProviderConfig();
     // Causes an assert in CreateWebGestureEventFromGestureEventData and we don't need them in Qt.
     config.gesture_begin_end_types_enabled = false;
+    // Swipe gestures aren't forwarded, we don't use them and they abort the gesture detection.
+    config.scale_gesture_detector_config.gesture_detector_config.swipe_enabled = config.gesture_detector_config.swipe_enabled = false;
     return config;
 }
 
 class MotionEventQt : public ui::MotionEvent {
 public:
-    MotionEventQt(QTouchEvent *ev, const base::TimeTicks &eventTime, Action action, int index = -1)
-        : touchPoints(ev->touchPoints())
+    MotionEventQt(const QList<QTouchEvent::TouchPoint> &touchPoints, const base::TimeTicks &eventTime, Action action, int index = -1)
+        : touchPoints(touchPoints)
         , eventTime(eventTime)
         , action(action)
         , index(index)
@@ -770,6 +781,25 @@ void RenderWidgetHostViewQt::processMotionEvent(const ui::MotionEvent &motionEve
     m_host->ForwardTouchEvent(content::CreateWebTouchEventFromMotionEvent(motionEvent));
 }
 
+QList<QTouchEvent::TouchPoint> RenderWidgetHostViewQt::mapTouchPointIds(const QList<QTouchEvent::TouchPoint> &inputPoints)
+{
+    QList<QTouchEvent::TouchPoint> outputPoints = inputPoints;
+    for (int i = 0; i < outputPoints.size(); ++i) {
+        QTouchEvent::TouchPoint &point = outputPoints[i];
+
+        int qtId = point.id();
+        QMap<int, int>::const_iterator it = m_touchIdMapping.find(qtId);
+        if (it == m_touchIdMapping.end())
+            it = m_touchIdMapping.insert(qtId, firstAvailableId(m_touchIdMapping));
+        point.setId(it.value());
+
+        if (point.state() == Qt::TouchPointReleased)
+            m_touchIdMapping.remove(qtId);
+    }
+
+    return outputPoints;
+}
+
 float RenderWidgetHostViewQt::dpiScale() const
 {
     return m_adapterClient ? m_adapterClient->dpiScale() : 1.0;
@@ -940,8 +970,10 @@ void RenderWidgetHostViewQt::handleTouchEvent(QTouchEvent *ev)
         m_eventsToNowDelta = base::TimeTicks::Now() - eventTimestamp;
     eventTimestamp += m_eventsToNowDelta;
 
+    QList<QTouchEvent::TouchPoint> touchPoints = mapTouchPointIds(ev->touchPoints());
+
     if (ev->type() == QEvent::TouchCancel) {
-        MotionEventQt cancelEvent(ev, eventTimestamp, ui::MotionEvent::ACTION_CANCEL);
+        MotionEventQt cancelEvent(touchPoints, eventTimestamp, ui::MotionEvent::ACTION_CANCEL);
         processMotionEvent(cancelEvent);
         return;
     }
@@ -949,9 +981,9 @@ void RenderWidgetHostViewQt::handleTouchEvent(QTouchEvent *ev)
     if (ev->type() == QEvent::TouchBegin)
         m_sendMotionActionDown = true;
 
-    for (int i = 0; i < ev->touchPoints().size(); ++i) {
+    for (int i = 0; i < touchPoints.size(); ++i) {
         ui::MotionEvent::Action action;
-        switch (ev->touchPoints()[i].state()) {
+        switch (touchPoints[i].state()) {
         case Qt::TouchPointPressed:
             if (m_sendMotionActionDown) {
                 action = ui::MotionEvent::ACTION_DOWN;
@@ -963,14 +995,14 @@ void RenderWidgetHostViewQt::handleTouchEvent(QTouchEvent *ev)
             action = ui::MotionEvent::ACTION_MOVE;
             break;
         case Qt::TouchPointReleased:
-            action = ev->touchPoints().size() > 1 ? ui::MotionEvent::ACTION_POINTER_UP : ui::MotionEvent::ACTION_UP;
+            action = touchPoints.size() > 1 ? ui::MotionEvent::ACTION_POINTER_UP : ui::MotionEvent::ACTION_UP;
             break;
         default:
             // Ignore Qt::TouchPointStationary
             continue;
         }
 
-        MotionEventQt motionEvent(ev, eventTimestamp, action, i);
+        MotionEventQt motionEvent(touchPoints, eventTimestamp, action, i);
         processMotionEvent(motionEvent);
     }
 }
diff --git a/src/core/render_widget_host_view_qt.h b/src/core/render_widget_host_view_qt.h
index 301ff2df90ccd0d02b6e583681cab58def7e86fc..d4a3ff2481700fdb251754646d88e65cfd214733 100644
--- a/src/core/render_widget_host_view_qt.h
+++ b/src/core/render_widget_host_view_qt.h
@@ -45,6 +45,7 @@
 #include "content/browser/accessibility/browser_accessibility_manager.h"
 #include "content/browser/renderer_host/render_widget_host_view_base.h"
 #include "ui/events/gesture_detection/filtered_gesture_provider.h"
+#include <QMap>
 #include <QPoint>
 #include <QRect>
 #include <QtGlobal>
@@ -221,6 +222,7 @@ public:
 private:
     void sendDelegatedFrameAck();
     void processMotionEvent(const ui::MotionEvent &motionEvent);
+    QList<QTouchEvent::TouchPoint> mapTouchPointIds(const QList<QTouchEvent::TouchPoint> &inputPoints);
     float dpiScale() const;
 
     bool IsPopup() const;
@@ -230,6 +232,7 @@ private:
     ui::FilteredGestureProvider m_gestureProvider;
     base::TimeDelta m_eventsToNowDelta;
     bool m_sendMotionActionDown;
+    QMap<int, int> m_touchIdMapping;
     scoped_ptr<RenderWidgetHostViewQtDelegate> m_delegate;
 
     QExplicitlySharedDataPointer<DelegatedFrameNodeData> m_frameNodeData;