Description: Add the experimentalDevicePixelRatio API again
 This is basically a revert of 69e9b8 + c2c5952, which removes the
 experimental API.
 . 
 QtWebKit now queries the platform plugin for the devicePixelRatio property, 
 and it's up to the plugin to return the correct value (there's no way to 
 programatically set it anymore, see 
 http://qt-project.org/doc/qt-5.0/qtgui/qwindow.html#devicePixelRatio).
 . 
 The correct and upstreamable way to fix this will be to ensure that our 
 platform plugin re-implements this method (which defaults to returning 
 1.0).

Origin: vendor
Forwarded: not-needed

diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebpage.cpp b/Source/WebKit2/UIProcess/API/qt/qquickwebpage.cpp
index a7d74b2..0f12a4e 100644
--- a/Source/WebKit2/UIProcess/API/qt/qquickwebpage.cpp
+++ b/Source/WebKit2/UIProcess/API/qt/qquickwebpage.cpp
@@ -86,23 +86,12 @@ QSGNode* QQuickWebPage::updatePaintNode(QSGNode* oldNode, UpdatePaintNodeData*)
 
     QtWebPageSGNode* node = static_cast<QtWebPageSGNode*>(oldNode);
 
-    const QWindow* window = this->window();
-    ASSERT(window);
-
-    if (window && d->webPageProxy->deviceScaleFactor() != window->devicePixelRatio()) {
-        d->webPageProxy->setIntrinsicDeviceScaleFactor(window->devicePixelRatio());
-        // This signal is queued since if we are running a threaded renderer. This might cause failures
-        // if tests are reading the new value between the property change and the signal emission.
-        emit d->viewportItem->experimental()->test()->devicePixelRatioChanged();
-    }
-
     if (!node)
-        node = new QtWebPageSGNode;
+        node = new QtWebPageSGNode();
 
     node->setRenderer(renderer);
 
     node->setScale(d->contentsScale);
-    node->setDevicePixelRatio(window->devicePixelRatio());
     QColor backgroundColor = d->webPageProxy->drawsTransparentBackground() ? Qt::transparent : Qt::white;
     QRectF backgroundRect(QPointF(0, 0), d->contentsSize);
     node->setBackground(backgroundRect, backgroundColor);
diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp b/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp
index c3e372b..c5827b2 100644
--- a/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp
+++ b/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp
@@ -280,6 +280,7 @@ QQuickWebViewPrivate::QQuickWebViewPrivate(QQuickWebView* viewport)
     viewport->setPixelAligned(true);
     QObject::connect(viewport, SIGNAL(visibleChanged()), viewport, SLOT(_q_onVisibleChanged()));
     QObject::connect(viewport, SIGNAL(urlChanged()), viewport, SLOT(_q_onUrlChanged()));
+    QObject::connect(experimental, SIGNAL(devicePixelRatioChanged()), experimental->test(), SIGNAL(devicePixelRatioChanged()));
     pageView.reset(new QQuickWebPage(viewport));
 }
 
@@ -827,15 +828,16 @@ void QQuickWebViewLegacyPrivate::updateViewportSize()
     if (viewportSize.isEmpty())
         return;
 
+    float devicePixelRatio = webPageProxy->deviceScaleFactor();
     pageView->setContentsSize(viewportSize);
+    // Make sure that our scale matches the one passed to setVisibleContentsRect.
+    pageView->setContentsScale(devicePixelRatio);
 
     // The fixed layout is handled by the FrameView and the drawing area doesn't behave differently
     // whether its fixed or not. We still need to tell the drawing area which part of it
     // has to be rendered on tiles, and in desktop mode it's all of it.
-    webPageProxy->drawingArea()->setSize(viewportSize.toSize(), IntSize());
-    // The backing store scale factor should already be set to the device pixel ratio
-    // of the underlying window, thus we set the effective scale to 1 here.
-    webPageProxy->drawingArea()->setVisibleContentsRect(FloatRect(FloatPoint(), FloatSize(viewportSize)), 1, FloatPoint());
+    webPageProxy->drawingArea()->setSize((viewportSize / devicePixelRatio).toSize(), IntSize());
+    webPageProxy->drawingArea()->setVisibleContentsRect(FloatRect(FloatPoint(), FloatSize(viewportSize / devicePixelRatio)), devicePixelRatio, FloatPoint());
 }
 
 qreal QQuickWebViewLegacyPrivate::zoomFactor() const
@@ -867,6 +869,11 @@ void QQuickWebViewFlickablePrivate::onComponentComplete()
     m_pageViewportController.reset(new PageViewportController(webPageProxy.get(), m_pageViewportControllerClient.data()));
     pageView->eventHandler()->setViewportController(m_pageViewportControllerClient.data());
 
+    // Notify about device pixel ratio here because due to the delayed instantiation
+    // of the viewport controller the correct value might not have reached QWebKitTest
+    // in time it was used from QML.
+    emit experimental->test()->devicePixelRatioChanged();
+
     // Trigger setting of correct visibility flags after everything was allocated and initialized.
     _q_onVisibleChanged();
 }
@@ -1194,6 +1201,59 @@ void QQuickWebViewExperimental::setUserAgent(const QString& userAgent)
 /*!
     \internal
 
+    \qmlproperty real WebViewExperimental::devicePixelRatio
+    \brief The ratio between the CSS units and device pixels when the content is unscaled.
+
+    When designing touch-friendly contents, knowing the approximated target size on a device
+    is important for contents providers in order to get the intented layout and element
+    sizes.
+
+    As most first generation touch devices had a PPI of approximately 160, this became a
+    de-facto value, when used in conjunction with the viewport meta tag.
+
+    Devices with a higher PPI learning towards 240 or 320, applies a pre-scaling on all
+    content, of either 1.5 or 2.0, not affecting the CSS scale or pinch zooming.
+
+    This value can be set using this property and it is exposed to CSS media queries using
+    the -webkit-device-pixel-ratio query.
+
+    For instance, if you want to load an image without having it upscaled on a web view
+    using a device pixel ratio of 2.0 it can be done by loading an image of say 100x100
+    pixels but showing it at half the size.
+
+    FIXME: Move documentation example out in separate files
+
+    @media (-webkit-min-device-pixel-ratio: 1.5) {
+        .icon {
+            width: 50px;
+            height: 50px;
+            url: "/images/icon@2x.png"; // This is actually a 100x100 image
+        }
+    }
+
+    If the above is used on a device with device pixel ratio of 1.5, it will be scaled
+    down but still provide a better looking image.
+*/
+
+qreal QQuickWebViewExperimental::devicePixelRatio() const
+{
+    Q_D(const QQuickWebView);
+    return d->webPageProxy->deviceScaleFactor();
+}
+
+void QQuickWebViewExperimental::setDevicePixelRatio(qreal devicePixelRatio)
+{
+    Q_D(QQuickWebView);
+    if (0 >= devicePixelRatio || devicePixelRatio == this->devicePixelRatio())
+        return;
+
+    d->webPageProxy->setIntrinsicDeviceScaleFactor(devicePixelRatio);
+    emit devicePixelRatioChanged();
+}
+
+/*!
+    \internal
+
     \qmlproperty int WebViewExperimental::deviceWidth
     \brief The device width used by the viewport calculations.
 
diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h b/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h
index 1b372fa..8de0bc1 100644
--- a/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h
+++ b/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h
@@ -256,6 +256,7 @@ class QWEBKIT_EXPORT QQuickWebViewExperimental : public QObject {
     Q_PROPERTY(int preferredMinimumContentsWidth WRITE setPreferredMinimumContentsWidth READ preferredMinimumContentsWidth NOTIFY preferredMinimumContentsWidthChanged)
     Q_PROPERTY(int deviceWidth WRITE setDeviceWidth READ deviceWidth NOTIFY deviceWidthChanged)
     Q_PROPERTY(int deviceHeight WRITE setDeviceHeight READ deviceHeight NOTIFY deviceHeightChanged)
+    Q_PROPERTY(qreal devicePixelRatio READ devicePixelRatio WRITE setDevicePixelRatio NOTIFY devicePixelRatioChanged)
 
     Q_PROPERTY(QWebNavigationHistory* navigationHistory READ navigationHistory CONSTANT FINAL)
 
@@ -311,6 +312,8 @@ public:
     void setDeviceWidth(int);
     int deviceHeight() const;
     void setDeviceHeight(int);
+    qreal devicePixelRatio() const;
+    void setDevicePixelRatio(qreal);
     QList<QUrl> userScripts() const;
     void setUserScripts(const QList<QUrl>& userScripts);
     QUrl remoteInspectorUrl() const;
@@ -367,6 +370,7 @@ Q_SIGNALS:
     void proxyAuthenticationDialogChanged();
     void userAgentChanged();
     void deviceWidthChanged();
+    void devicePixelRatioChanged();
     void deviceHeightChanged();
     void enterFullScreenRequested();
     void exitFullScreenRequested();
diff --git a/Source/WebKit2/UIProcess/CoordinatedGraphics/LayerTreeCoordinatorProxy.cpp b/Source/WebKit2/UIProcess/CoordinatedGraphics/LayerTreeCoordinatorProxy.cpp
index 9cb2c1b..ce5a96f 100644
--- a/Source/WebKit2/UIProcess/CoordinatedGraphics/LayerTreeCoordinatorProxy.cpp
+++ b/Source/WebKit2/UIProcess/CoordinatedGraphics/LayerTreeCoordinatorProxy.cpp
@@ -56,11 +56,6 @@ void LayerTreeCoordinatorProxy::updateViewport()
     m_drawingAreaProxy->updateViewport();
 }
 
-float LayerTreeCoordinatorProxy::deviceScaleFactor() const
-{
-    return m_drawingAreaProxy->page()->deviceScaleFactor();
-}
-
 void LayerTreeCoordinatorProxy::dispatchUpdate(const Function<void()>& function)
 {
     m_renderer->appendUpdate(function);
@@ -183,20 +178,19 @@ void LayerTreeCoordinatorProxy::setAnimationsLocked(bool locked)
     dispatchUpdate(bind(&LayerTreeRenderer::setAnimationsLocked, m_renderer.get(), locked));
 }
 
-void LayerTreeCoordinatorProxy::setVisibleContentsRect(const FloatRect& rect, float pageScaleFactor, const FloatPoint& trajectoryVector)
+void LayerTreeCoordinatorProxy::setVisibleContentsRect(const FloatRect& rect, float scale, const FloatPoint& trajectoryVector)
 {
     // Inform the renderer to adjust viewport-fixed layers.
     dispatchUpdate(bind(&LayerTreeRenderer::setVisibleContentsRect, m_renderer.get(), rect));
 
     // Round the rect instead of enclosing it to make sure that its size stays the same while panning. This can have nasty effects on layout.
     IntRect roundedRect = roundedIntRect(rect);
-    const float effectiveScale = deviceScaleFactor() * pageScaleFactor;
-    if (roundedRect == m_lastSentVisibleRect && effectiveScale == m_lastSentScale && trajectoryVector == m_lastSentTrajectoryVector)
+    if (rect == m_lastSentVisibleRect && scale == m_lastSentScale && trajectoryVector == m_lastSentTrajectoryVector)
         return;
 
-    m_drawingAreaProxy->page()->process()->send(Messages::LayerTreeCoordinator::SetVisibleContentsRect(roundedRect, effectiveScale, trajectoryVector), m_drawingAreaProxy->page()->pageID());
+    m_drawingAreaProxy->page()->process()->send(Messages::LayerTreeCoordinator::SetVisibleContentsRect(roundedRect, scale, trajectoryVector), m_drawingAreaProxy->page()->pageID());
     m_lastSentVisibleRect = roundedRect;
-    m_lastSentScale = effectiveScale;
+    m_lastSentScale = scale;
     m_lastSentTrajectoryVector = trajectoryVector;
 }
 
diff --git a/Source/WebKit2/UIProcess/CoordinatedGraphics/LayerTreeCoordinatorProxy.h b/Source/WebKit2/UIProcess/CoordinatedGraphics/LayerTreeCoordinatorProxy.h
index a3961ff..fb58b1a 100644
--- a/Source/WebKit2/UIProcess/CoordinatedGraphics/LayerTreeCoordinatorProxy.h
+++ b/Source/WebKit2/UIProcess/CoordinatedGraphics/LayerTreeCoordinatorProxy.h
@@ -64,7 +64,7 @@ public:
     void deleteCompositingLayer(WebLayerID);
     void setRootCompositingLayer(WebLayerID);
     void setContentsSize(const WebCore::FloatSize&);
-    void setVisibleContentsRect(const WebCore::FloatRect&, float pageScaleFactor, const WebCore::FloatPoint& trajectoryVector);
+    void setVisibleContentsRect(const WebCore::FloatRect&, float scale, const WebCore::FloatPoint& trajectoryVector);
     void didRenderFrame(const WebCore::IntSize& contentsSize, const WebCore::IntRect& coveredRect);
     void createTileForLayer(int layerID, int tileID, const WebCore::IntRect&, const SurfaceUpdateInfo&);
     void updateTileForLayer(int layerID, int tileID, const WebCore::IntRect&, const SurfaceUpdateInfo&);
@@ -94,8 +94,6 @@ public:
 #endif
     void setBackgroundColor(const WebCore::Color&);
 
-    float deviceScaleFactor() const;
-
 protected:
     void dispatchUpdate(const Function<void()>&);
 
diff --git a/Source/WebKit2/UIProcess/PageViewportController.cpp b/Source/WebKit2/UIProcess/PageViewportController.cpp
index a34782c..bbee994 100644
--- a/Source/WebKit2/UIProcess/PageViewportController.cpp
+++ b/Source/WebKit2/UIProcess/PageViewportController.cpp
@@ -46,9 +46,9 @@ PageViewportController::PageViewportController(WebKit::WebPageProxy* proxy, Page
     , m_minimumScaleToFit(1)
     , m_initiallyFitToViewport(true)
     , m_hadUserInteraction(false)
-    , m_pageScaleFactor(1)
+    , m_effectiveScale(1)
     , m_viewportPosIsLocked(false)
-    , m_pageScaleFactorIsLocked(false)
+    , m_effectiveScaleIsLocked(false)
 {
     // Initializing Viewport Raw Attributes to avoid random negative or infinity scale factors
     // if there is a race condition between the first layout and setting the viewport attributes for the first time.
@@ -67,15 +67,15 @@ PageViewportController::PageViewportController(WebKit::WebPageProxy* proxy, Page
 
 float PageViewportController::innerBoundedViewportScale(float viewportScale) const
 {
-    return clampTo(viewportScale, m_minimumScaleToFit, m_rawAttributes.maximumScale);
+    return clampTo(viewportScale, toViewportScale(m_minimumScaleToFit), toViewportScale(m_rawAttributes.maximumScale));
 }
 
 float PageViewportController::outerBoundedViewportScale(float viewportScale) const
 {
     if (m_allowsUserScaling) {
         // Bounded by [0.1, 10.0] like the viewport meta code in WebCore.
-        float hardMin = std::max<float>(0.1, 0.5 * m_minimumScaleToFit);
-        float hardMax = std::min<float>(10, 2 * m_rawAttributes.maximumScale);
+        float hardMin = toViewportScale(std::max<float>(0.1, 0.5 * m_minimumScaleToFit));
+        float hardMax = toViewportScale(std::min<float>(10, 2 * m_rawAttributes.maximumScale));
         return clampTo(viewportScale, hardMin, hardMax);
     }
     return innerBoundedViewportScale(viewportScale);
@@ -144,12 +144,12 @@ void PageViewportController::didRenderFrame(const IntSize& contentsSize, const I
     // All position and scale changes resulting from a web process event should
     // go through here to be applied on the viewport to avoid showing incomplete
     // tiles to the user during a few milliseconds.
-    if (m_pageScaleFactorIsLocked) {
-        m_client->setContentsScale(m_pageScaleFactor, false);
-        m_pageScaleFactorIsLocked = false;
+    if (m_effectiveScaleIsLocked) {
+        m_client->setContentsScale(m_effectiveScale, false);
+        m_effectiveScaleIsLocked = false;
     }
     if (m_viewportPosIsLocked) {
-        FloatPoint clampedPos = clampViewportToContents(m_viewportPos, m_pageScaleFactor);
+        FloatPoint clampedPos = clampViewportToContents(m_viewportPos, m_effectiveScale);
         // There might be rendered frames not covering our requested position yet, wait for it.
         if (FloatRect(clampedPos, viewportSizeInContentsCoordinates()).intersects(coveredRect)) {
             m_client->setViewportPosition(clampedPos);
@@ -163,7 +163,7 @@ void PageViewportController::pageTransitionViewportReady()
     if (!m_rawAttributes.layoutSize.isEmpty()) {
         m_hadUserInteraction = false;
         float initialScale = m_initiallyFitToViewport ? m_minimumScaleToFit : m_rawAttributes.initialScale;
-        applyScaleAfterRenderingContents(innerBoundedViewportScale(initialScale));
+        applyScaleAfterRenderingContents(innerBoundedViewportScale(toViewportScale(initialScale)));
     }
 
     // At this point we should already have received the first viewport arguments and the requested scroll
@@ -179,7 +179,7 @@ void PageViewportController::pageDidRequestScroll(const IntPoint& cssPosition)
     if (m_webPageProxy->areActiveDOMObjectsAndAnimationsSuspended())
         return;
 
-    FloatRect endVisibleContentRect(clampViewportToContents(cssPosition, m_pageScaleFactor), viewportSizeInContentsCoordinates());
+    FloatRect endVisibleContentRect(clampViewportToContents(cssPosition, m_effectiveScale), viewportSizeInContentsCoordinates());
     if (m_lastFrameCoveredRect.intersects(endVisibleContentRect))
         m_client->setViewportPosition(endVisibleContentRect.location());
     else
@@ -203,8 +203,8 @@ void PageViewportController::didChangeContentsVisibility(const FloatPoint& viewp
 {
     if (!m_viewportPosIsLocked)
         m_viewportPos = viewportPos;
-    if (!m_pageScaleFactorIsLocked)
-        m_pageScaleFactor = viewportScale;
+    if (!m_effectiveScaleIsLocked)
+        m_effectiveScale = viewportScale;
 
     syncVisibleContents(trajectoryVector);
 }
@@ -215,9 +215,9 @@ void PageViewportController::syncVisibleContents(const FloatPoint& trajectoryVec
     if (!drawingArea || m_viewportSize.isEmpty() || m_contentsSize.isEmpty())
         return;
 
-    FloatRect visibleContentsRect(clampViewportToContents(m_viewportPos, m_pageScaleFactor), viewportSizeInContentsCoordinates());
+    FloatRect visibleContentsRect(clampViewportToContents(m_viewportPos, m_effectiveScale), viewportSizeInContentsCoordinates());
     visibleContentsRect.intersect(FloatRect(FloatPoint::zero(), m_contentsSize));
-    drawingArea->setVisibleContentsRect(visibleContentsRect, m_pageScaleFactor, trajectoryVector);
+    drawingArea->setVisibleContentsRect(visibleContentsRect, m_effectiveScale, trajectoryVector);
 
     m_client->didChangeVisibleContents();
 }
@@ -242,13 +242,13 @@ void PageViewportController::didChangeViewportAttributes(const WebCore::Viewport
 
 WebCore::FloatSize PageViewportController::viewportSizeInContentsCoordinates() const
 {
-    return WebCore::FloatSize(m_viewportSize.width() / m_pageScaleFactor, m_viewportSize.height() / m_pageScaleFactor);
+    return WebCore::FloatSize(m_viewportSize.width() / m_effectiveScale, m_viewportSize.height() / m_effectiveScale);
 }
 
 void PageViewportController::applyScaleAfterRenderingContents(float scale)
 {
-    m_pageScaleFactor = scale;
-    m_pageScaleFactorIsLocked = true;
+    m_effectiveScale = scale;
+    m_effectiveScaleIsLocked = true;
     syncVisibleContents();
 }
 
@@ -264,9 +264,9 @@ bool PageViewportController::updateMinimumScaleToFit(bool userInitiatedUpdate)
     if (m_viewportSize.isEmpty() || m_contentsSize.isEmpty())
         return false;
 
-    bool currentlyScaledToFit = fuzzyCompare(m_pageScaleFactor, m_minimumScaleToFit, 0.001);
+    bool currentlyScaledToFit = fuzzyCompare(m_effectiveScale, toViewportScale(m_minimumScaleToFit), 0.001);
 
-    float minimumScale = WebCore::computeMinimumScaleFactorForContentContained(m_rawAttributes, WebCore::roundedIntSize(m_viewportSize), WebCore::roundedIntSize(m_contentsSize), 1);
+    float minimumScale = WebCore::computeMinimumScaleFactorForContentContained(m_rawAttributes, WebCore::roundedIntSize(m_viewportSize), WebCore::roundedIntSize(m_contentsSize), devicePixelRatio());
 
     if (minimumScale <= 0)
         return false;
@@ -276,11 +276,11 @@ bool PageViewportController::updateMinimumScaleToFit(bool userInitiatedUpdate)
 
         if (!m_webPageProxy->areActiveDOMObjectsAndAnimationsSuspended()) {
             if (!m_hadUserInteraction || (userInitiatedUpdate && currentlyScaledToFit))
-                applyScaleAfterRenderingContents(m_minimumScaleToFit);
+                applyScaleAfterRenderingContents(toViewportScale(m_minimumScaleToFit));
             else {
                 // Ensure the effective scale stays within bounds.
-                float boundedScale = innerBoundedViewportScale(m_pageScaleFactor);
-                if (!fuzzyCompare(boundedScale, m_pageScaleFactor, 0.001))
+                float boundedScale = innerBoundedViewportScale(m_effectiveScale);
+                if (!fuzzyCompare(boundedScale, m_effectiveScale, 0.001))
                     applyScaleAfterRenderingContents(boundedScale);
             }
         }
diff --git a/Source/WebKit2/UIProcess/PageViewportController.h b/Source/WebKit2/UIProcess/PageViewportController.h
index fcc4e17..231b1c1 100644
--- a/Source/WebKit2/UIProcess/PageViewportController.h
+++ b/Source/WebKit2/UIProcess/PageViewportController.h
@@ -56,7 +56,7 @@ public:
     float devicePixelRatio() const;
     float minimumContentsScale() const { return m_minimumScaleToFit; }
     float maximumContentsScale() const { return m_rawAttributes.maximumScale; }
-    float currentContentsScale() const { return m_pageScaleFactor; }
+    float currentContentsScale() const { return fromViewportScale(m_effectiveScale); }
 
     void setHadUserInteraction(bool didUserInteract) { m_hadUserInteraction = didUserInteract; }
 
@@ -73,6 +73,8 @@ public:
     void pageDidRequestScroll(const WebCore::IntPoint& cssPosition);
 
 private:
+    float fromViewportScale(float scale) const { return scale / devicePixelRatio(); }
+    float toViewportScale(float scale) const { return scale * devicePixelRatio(); }
     void syncVisibleContents(const WebCore::FloatPoint &trajectoryVector = WebCore::FloatPoint::zero());
     void applyScaleAfterRenderingContents(float scale);
     void applyPositionAfterRenderingContents(const WebCore::FloatPoint& pos);
@@ -94,10 +96,10 @@ private:
     WebCore::FloatSize m_viewportSize;
     WebCore::FloatSize m_contentsSize;
     WebCore::IntSize m_clientContentsSize;
-    float m_pageScaleFactor;
+    float m_effectiveScale; // Should always be cssScale * devicePixelRatio.
 
     bool m_viewportPosIsLocked;
-    bool m_pageScaleFactorIsLocked;
+    bool m_effectiveScaleIsLocked;
     WebCore::FloatRect m_lastFrameCoveredRect;
 };
 
diff --git a/Source/WebKit2/UIProcess/qt/PageViewportControllerClientQt.cpp b/Source/WebKit2/UIProcess/qt/PageViewportControllerClientQt.cpp
index 6351555..95dee3e 100644
--- a/Source/WebKit2/UIProcess/qt/PageViewportControllerClientQt.cpp
+++ b/Source/WebKit2/UIProcess/qt/PageViewportControllerClientQt.cpp
@@ -209,12 +209,12 @@ void PageViewportControllerClientQt::focusEditableArea(const QRectF& caretArea,
     // This can only happen as a result of a user interaction.
     ASSERT(m_controller->hadUserInteraction());
 
-    const float editingFixedScale = 2;
+    const float editingFixedScale = 2 * m_controller->devicePixelRatio();
     float targetScale = m_controller->innerBoundedViewportScale(editingFixedScale);
     const QRectF viewportRect = m_viewportItem->boundingRect();
 
     qreal x;
-    const qreal borderOffset = 10;
+    const qreal borderOffset = 10 * m_controller->devicePixelRatio();
     if ((targetArea.width() + borderOffset) * targetScale <= viewportRect.width()) {
         // Center the input field in the middle of the view, if it is smaller than
         // the view at the scale target.
@@ -248,12 +248,12 @@ void PageViewportControllerClientQt::zoomToAreaGestureEnded(const QPointF& touch
     if (m_scrollChange.inProgress() || m_scaleChange.inProgress())
         return;
 
-    const float margin = 10; // We want at least a little bit of margin.
+    const float margin = 10 * m_controller->devicePixelRatio(); // We want at least a little bit of margin.
     QRectF endArea = targetArea.adjusted(-margin, -margin, margin, margin);
 
     const QRectF viewportRect = m_viewportItem->boundingRect();
 
-    qreal minViewportScale = qreal(2.5);
+    qreal minViewportScale = qreal(2.5) * m_controller->devicePixelRatio();
     qreal targetScale = viewportRect.size().width() / endArea.size().width();
     targetScale = m_controller->innerBoundedViewportScale(qMin(minViewportScale, targetScale));
     qreal currentScale = m_pageItem->contentsScale();
@@ -295,7 +295,7 @@ void PageViewportControllerClientQt::zoomToAreaGestureEnded(const QPointF& touch
         break;
     case ZoomBack: {
         if (m_scaleStack.isEmpty()) {
-            targetScale = m_controller->minimumContentsScale();
+            targetScale = m_controller->minimumContentsScale() * m_controller->devicePixelRatio();
             endPosition.setY(hotspot.y() - viewportHotspot.y() / targetScale);
             endPosition.setX(0);
             m_zoomOutScale = 0;
diff --git a/Source/WebKit2/UIProcess/qt/QtWebPageSGNode.cpp b/Source/WebKit2/UIProcess/qt/QtWebPageSGNode.cpp
index f536c42..98b4423 100644
--- a/Source/WebKit2/UIProcess/qt/QtWebPageSGNode.cpp
+++ b/Source/WebKit2/UIProcess/qt/QtWebPageSGNode.cpp
@@ -48,13 +48,7 @@ public:
 
     virtual void render(const RenderState& state)
     {
-        TransformationMatrix renderMatrix;
-        if (pageNode()->devicePixelRatio() != 1.0) {
-            renderMatrix.scale(pageNode()->devicePixelRatio());
-            if (matrix())
-                renderMatrix.multiply(*matrix());
-        } else if (matrix())
-            renderMatrix = *matrix();
+        QMatrix4x4 renderMatrix = matrix() ? *matrix() : QMatrix4x4();
 
         // When rendering to an intermediate surface, Qt will
         // mirror the projection matrix to fit on the destination coordinate system.
@@ -70,13 +64,6 @@ public:
         layerTreeRenderer()->purgeGLResources();
     }
 
-    const QtWebPageSGNode* pageNode() const
-    {
-        const QtWebPageSGNode* parent = static_cast<QtWebPageSGNode*>(this->parent());
-        ASSERT(parent);
-        return parent;
-    }
-
     LayerTreeRenderer* layerTreeRenderer() const { return m_renderer.get(); }
 
 private:
@@ -87,11 +74,7 @@ private:
 
         for (const QSGClipNode* clip = clipList(); clip; clip = clip->clipList()) {
             QMatrix4x4 clipMatrix;
-            if (pageNode()->devicePixelRatio() != 1.0) {
-                clipMatrix.scale(pageNode()->devicePixelRatio());
-                if (clip->matrix())
-                    clipMatrix *= (*clip->matrix());
-            } else if (clip->matrix())
+            if (clip->matrix())
                 clipMatrix = *clip->matrix();
 
             QRectF currentClip;
@@ -132,7 +115,6 @@ private:
 QtWebPageSGNode::QtWebPageSGNode()
     : m_contentsNode(0)
     , m_backgroundNode(new QSGSimpleRectNode)
-    , m_devicePixelRatio(1)
 {
     appendChildNode(m_backgroundNode);
 }
diff --git a/Source/WebKit2/UIProcess/qt/QtWebPageSGNode.h b/Source/WebKit2/UIProcess/qt/QtWebPageSGNode.h
index 1bcc28e..8516803 100644
--- a/Source/WebKit2/UIProcess/qt/QtWebPageSGNode.h
+++ b/Source/WebKit2/UIProcess/qt/QtWebPageSGNode.h
@@ -40,13 +40,10 @@ class QtWebPageSGNode : public QSGTransformNode {
         void setBackground(const QRectF&, const QColor&);
         void setScale(float);
         void setRenderer(PassRefPtr<LayerTreeRenderer>);
-        qreal devicePixelRatio() const { return m_devicePixelRatio; }
-        void setDevicePixelRatio(qreal devicePixelRatio) { m_devicePixelRatio = devicePixelRatio; }
 
     private:
         ContentsSGNode* m_contentsNode;
         QSGSimpleRectNode* m_backgroundNode;
-        qreal m_devicePixelRatio;
 };
 
 } // namespace WebKit
diff --git a/Source/WebKit2/WebProcess/WebPage/WebPage.cpp b/Source/WebKit2/WebProcess/WebPage/WebPage.cpp
index 849c1c1..8c54692 100644
--- a/Source/WebKit2/WebProcess/WebPage/WebPage.cpp
+++ b/Source/WebKit2/WebProcess/WebPage/WebPage.cpp
@@ -1021,13 +1021,13 @@ void WebPage::sendViewportAttributesChanged()
     // Recalculate the recommended layout size, when the available size (device pixel) changes.
     Settings* settings = m_page->settings();
 
-    int minimumLayoutFallbackWidth = std::max(settings->layoutFallbackWidth(), m_viewportSize.width());
+    int minimumLayoutFallbackWidth = std::max(settings->layoutFallbackWidth(), int(m_viewportSize.width() / m_page->deviceScaleFactor()));
 
     // If unset  we use the viewport dimensions. This fits with the behavior of desktop browsers.
     int deviceWidth = (settings->deviceWidth() > 0) ? settings->deviceWidth() : m_viewportSize.width();
     int deviceHeight = (settings->deviceHeight() > 0) ? settings->deviceHeight() : m_viewportSize.height();
 
-    ViewportAttributes attr = computeViewportAttributes(m_page->viewportArguments(), minimumLayoutFallbackWidth, deviceWidth, deviceHeight, 1, m_viewportSize);
+    ViewportAttributes attr = computeViewportAttributes(m_page->viewportArguments(), minimumLayoutFallbackWidth, deviceWidth, deviceHeight, m_page->deviceScaleFactor(), m_viewportSize);
     attr.initialScale = m_page->viewportArguments().zoom; // Resets auto (-1) if no value was set by user.
 
     // This also takes care of the relayout.
