Make page scale shrink FrameView in applyPageScaleInCompositor mode
authoraelias@chromium.org <aelias@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 29 Jan 2013 06:19:10 +0000 (06:19 +0000)
committeraelias@chromium.org <aelias@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 29 Jan 2013 06:19:10 +0000 (06:19 +0000)
https://bugs.webkit.org/show_bug.cgi?id=107424

Reviewed by Levi Weintraub.

If applyPageScaleFactorInCompositor is enabled (Chromium-only setting),
instead of the entire document expanding as the user pinch zooms, the
viewport shrinks instead. This patch applies the pageScaleFactor to
visibleContentRect to get this behavior, and simplifies Chromium's
resize logic to stop hiding the true viewport size from WebCore.

I verified that the scaling makes sense for all the callers of
visibleContentRect. The exceptions are clip-layer size,
layout size in non-fixed-layout mode, and text autosizing, which need
the original unscaled size. Therefore I added a new method
unscaledVisibleContentSize() to ScrollView/FrameView.

This patch also modifies Page::setPageScaleFactor to perform no
invalidates or layout when applyPageScaleFactorInCompositor is true,
and also writes pageScaleFactor into HistoryItems instead of using
frameScaleFactor.

Since all behavior changes are tied to applyPageScaleFactorInCompositor,
this patch should be a no-op for non-Chromium ports.

Source/Platform:

* chromium/public/WebLayerTreeView.h:
(WebLayerTreeView):
(WebKit::WebLayerTreeView::adjustEventPointForPinchZoom):

Source/WebCore:

New unit tests in WebFrameTest.cpp.

* loader/HistoryController.cpp:
(WebCore::HistoryController::saveScrollPositionAndViewStateToItem):
Use pageScaleFactor here because frameScaleFactor always returns 1
with our setting.
* page/FrameView.cpp:
(WebCore::FrameView::visibleContentScaleFactor):
(WebCore):
* page/FrameView.h:
(FrameView):
* page/Page.cpp:
(WebCore::Page::setPageScaleFactor): Make setPageScaleFactor stop
invalidating/layouting as this is handled by our compositor.
* platform/ScrollView.cpp:
(WebCore::ScrollView::unscaledVisibleContentSize): This new method
just returns the original visible rect without pageScaleFactor being
applied.
(WebCore):
(WebCore::ScrollView::visibleContentRect): This now is divided by
pageScaleFactor if our setting is active.
(WebCore::ScrollView::layoutSize):
* platform/ScrollView.h:
(WebCore::ScrollView::visibleContentScaleFactor): Returns
pageScaleFactor if the visible rect is scaled, 1 normally.
(ScrollView):
(WebCore::ScrollView::layoutWidth):
(WebCore::ScrollView::layoutHeight):
* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::frameViewDidChangeSize):
(WebCore::RenderLayerCompositor::updateRootLayerPosition): Clip layer
should use unscaled size, because it's above the root scroll layer
on the layer tree (i.e. page scale isn't applied on it).
* rendering/TextAutosizer.cpp:
(WebCore::TextAutosizer::processSubtree): Text autosizer should use
unscaled size, because it cares about physical screen size.

Source/WebKit/chromium:

* src/WebViewImpl.cpp:
(WebKit::WebViewImpl::scaledSize): Returns the post page-scale size
similar to what visibleContentRect() now returns, except that it may
be at a different scale than the current one.
(WebKit::WebViewImpl::size): Back to returning density-independent
size without any tricks, not the "layoutSize()" fake viewport.
(WebKit::WebViewImpl::resize):
(WebKit::WebViewImpl::handleInputEvent): No need to apply
implTransform anymore as WebKit knows the true scroll offset; just
divide event coords by pageScaleFactor.
(WebKit::WebViewImpl::clampOffsetAtScale): Make this method support
applyPageScaleFactorInCompositor.  This is used to pre-clamp scroll
offsets at a given viewport size.
(WebKit::WebViewImpl::setPageScaleFactorPreservingScrollOffset): Make
this method support applyPageScaleFactorInCompositor (don't scale
scroll offsets as they are now scale-independent).
(WebKit::WebViewImpl::setPageScaleFactor): Make this method always use
clampOffsetAtScale instead of bypassing it, since it's now supported.
Also notify the compositor to update its state.
(WebKit::WebViewImpl::contentsSize): Convenience method, removed
difference between scaled and unscaled.
(WebKit::WebViewImpl::layoutSize): This method returned the "fake"
size we used to give FrameView.  Now no longer used for much.
(WebKit::WebViewImpl::computePageScaleFactorLimits):
(WebKit::WebViewImpl::didChangeContentsSize): Remove unnecessary
resize() now that we can give the true size to FrameView.
(WebKit::WebViewImpl::updateLayerTreeViewport): Use layoutSize()
directly now that FrameView no longer uses it.
* src/WebViewImpl.h:
(WebViewImpl):
* tests/WebFrameTest.cpp:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@141053 268f45cc-cd09-0410-ab3c-d52691b4dbfc

15 files changed:
Source/Platform/ChangeLog
Source/Platform/chromium/public/WebLayerTreeView.h
Source/WebCore/ChangeLog
Source/WebCore/loader/HistoryController.cpp
Source/WebCore/page/FrameView.cpp
Source/WebCore/page/FrameView.h
Source/WebCore/page/Page.cpp
Source/WebCore/platform/ScrollView.cpp
Source/WebCore/platform/ScrollView.h
Source/WebCore/rendering/RenderLayerCompositor.cpp
Source/WebCore/rendering/TextAutosizer.cpp
Source/WebKit/chromium/ChangeLog
Source/WebKit/chromium/src/WebViewImpl.cpp
Source/WebKit/chromium/src/WebViewImpl.h
Source/WebKit/chromium/tests/WebFrameTest.cpp

index 9d48464..3ff60b1 100644 (file)
@@ -1,3 +1,34 @@
+2013-01-28  Alexandre Elias  <aelias@chromium.org>
+
+        Make page scale shrink FrameView in applyPageScaleInCompositor mode
+        https://bugs.webkit.org/show_bug.cgi?id=107424
+
+        Reviewed by Levi Weintraub.
+
+        If applyPageScaleFactorInCompositor is enabled (Chromium-only setting),
+        instead of the entire document expanding as the user pinch zooms, the
+        viewport shrinks instead. This patch applies the pageScaleFactor to
+        visibleContentRect to get this behavior, and simplifies Chromium's
+        resize logic to stop hiding the true viewport size from WebCore.
+
+        I verified that the scaling makes sense for all the callers of
+        visibleContentRect. The exceptions are clip-layer size,
+        layout size in non-fixed-layout mode, and text autosizing, which need
+        the original unscaled size. Therefore I added a new method
+        unscaledVisibleContentSize() to ScrollView/FrameView.
+
+        This patch also modifies Page::setPageScaleFactor to perform no
+        invalidates or layout when applyPageScaleFactorInCompositor is true,
+        and also writes pageScaleFactor into HistoryItems instead of using
+        frameScaleFactor.
+
+        Since all behavior changes are tied to applyPageScaleFactorInCompositor,
+        this patch should be a no-op for non-Chromium ports.
+
+        * chromium/public/WebLayerTreeView.h:
+        (WebLayerTreeView):
+        (WebKit::WebLayerTreeView::adjustEventPointForPinchZoom):
+
 2013-01-26  James Simonsen  <simonjam@chromium.org>
 
         [chromium] Export ResourceRequest's priority through WebURLRequest
index 6354702..85231a9 100644 (file)
@@ -102,9 +102,8 @@ public:
     // mode).
     virtual WebSize deviceViewportSize() const = 0;
 
-    // Gives the corrected location for an event, accounting for the pinch-zoom transformation
-    // in the compositor.
-    virtual WebFloatPoint adjustEventPointForPinchZoom(const WebFloatPoint&) const = 0;
+    // FIXME: remove this after WebKit roll
+    virtual WebFloatPoint adjustEventPointForPinchZoom(const WebFloatPoint& p) const { return p; }
 
     virtual void setDeviceScaleFactor(float) = 0;
     virtual float deviceScaleFactor() const = 0;
index 3f5d3c3..724f4c0 100644 (file)
@@ -1,3 +1,67 @@
+2013-01-28  Alexandre Elias  <aelias@chromium.org>
+
+        Make page scale shrink FrameView in applyPageScaleInCompositor mode
+        https://bugs.webkit.org/show_bug.cgi?id=107424
+
+        Reviewed by Levi Weintraub.
+
+        If applyPageScaleFactorInCompositor is enabled (Chromium-only setting),
+        instead of the entire document expanding as the user pinch zooms, the
+        viewport shrinks instead. This patch applies the pageScaleFactor to
+        visibleContentRect to get this behavior, and simplifies Chromium's
+        resize logic to stop hiding the true viewport size from WebCore.
+
+        I verified that the scaling makes sense for all the callers of
+        visibleContentRect. The exceptions are clip-layer size,
+        layout size in non-fixed-layout mode, and text autosizing, which need
+        the original unscaled size. Therefore I added a new method
+        unscaledVisibleContentSize() to ScrollView/FrameView.
+
+        This patch also modifies Page::setPageScaleFactor to perform no
+        invalidates or layout when applyPageScaleFactorInCompositor is true,
+        and also writes pageScaleFactor into HistoryItems instead of using
+        frameScaleFactor.
+
+        Since all behavior changes are tied to applyPageScaleFactorInCompositor,
+        this patch should be a no-op for non-Chromium ports.
+
+        New unit tests in WebFrameTest.cpp.
+
+        * loader/HistoryController.cpp:
+        (WebCore::HistoryController::saveScrollPositionAndViewStateToItem):
+        Use pageScaleFactor here because frameScaleFactor always returns 1
+        with our setting.
+        * page/FrameView.cpp:
+        (WebCore::FrameView::visibleContentScaleFactor):
+        (WebCore):
+        * page/FrameView.h:
+        (FrameView):
+        * page/Page.cpp:
+        (WebCore::Page::setPageScaleFactor): Make setPageScaleFactor stop
+        invalidating/layouting as this is handled by our compositor.
+        * platform/ScrollView.cpp:
+        (WebCore::ScrollView::unscaledVisibleContentSize): This new method
+        just returns the original visible rect without pageScaleFactor being
+        applied.
+        (WebCore):
+        (WebCore::ScrollView::visibleContentRect): This now is divided by
+        pageScaleFactor if our setting is active.
+        (WebCore::ScrollView::layoutSize):
+        * platform/ScrollView.h:
+        (WebCore::ScrollView::visibleContentScaleFactor): Returns
+        pageScaleFactor if the visible rect is scaled, 1 normally.
+        (ScrollView):
+        (WebCore::ScrollView::layoutWidth):
+        (WebCore::ScrollView::layoutHeight):
+        * rendering/RenderLayerCompositor.cpp:
+        (WebCore::RenderLayerCompositor::frameViewDidChangeSize):
+        (WebCore::RenderLayerCompositor::updateRootLayerPosition): Clip layer
+        should use unscaled size, because it's above the root scroll layer
+        on the layer tree (i.e. page scale isn't applied on it).
+        * rendering/TextAutosizer.cpp:
+        (WebCore::TextAutosizer::processSubtree): Text autosizer should use
+        unscaled size, because it cares about physical screen size.
+
 2013-01-28  Geoffrey Garen  <ggaren@apple.com>
 
         Static size inference for JavaScript objects
index a2f72d0..456635c 100644 (file)
@@ -87,8 +87,10 @@ void HistoryController::saveScrollPositionAndViewStateToItem(HistoryItem* item)
     else
         item->setScrollPoint(m_frame->view()->scrollPosition());
 
-    item->setPageScaleFactor(m_frame->frameScaleFactor());
-    
+    Page* page = m_frame->page();
+    if (page && page->mainFrame() == m_frame)
+        item->setPageScaleFactor(page->pageScaleFactor());
+
     // FIXME: It would be great to work out a way to put this code in WebCore instead of calling through to the client.
     m_frame->loader()->client()->saveViewStateToItem(item);
 }
index ebfe1c8..a58d6a0 100644 (file)
@@ -2837,6 +2837,17 @@ IntRect FrameView::windowResizerRect() const
     return page->chrome()->windowResizerRect();
 }
 
+float FrameView::visibleContentScaleFactor() const
+{
+    if (!m_frame || !m_frame->page())
+        return 1;
+
+    if (!m_frame->settings()->applyPageScaleFactorInCompositor() || m_frame != m_frame->page()->mainFrame())
+        return 1;
+
+    return m_frame->page()->pageScaleFactor();
+}
+
 void FrameView::setVisibleScrollerThumbRect(const IntRect& scrollerThumb)
 {
     Page* page = m_frame->page();
index 51c64f3..d13a767 100644 (file)
@@ -183,6 +183,8 @@ public:
 
     virtual IntRect windowResizerRect() const;
 
+    virtual float visibleContentScaleFactor() const OVERRIDE;
+
     virtual void setFixedVisibleContentRect(const IntRect&) OVERRIDE;
     virtual void setScrollPosition(const IntPoint&) OVERRIDE;
     void scrollPositionChangedViaPlatformWidget();
index 3a39196..aecba33 100644 (file)
@@ -725,7 +725,8 @@ void Page::setPageScaleFactor(float scale, const IntPoint& origin)
 
     if (scale == m_pageScaleFactor) {
         if (view && (view->scrollPosition() != origin || view->delegatesScrolling())) {
-            document->updateLayoutIgnorePendingStylesheets();
+            if (!m_settings->applyPageScaleFactorInCompositor())
+                document->updateLayoutIgnorePendingStylesheets();
             view->setScrollPosition(origin);
         }
         return;
@@ -733,20 +734,22 @@ void Page::setPageScaleFactor(float scale, const IntPoint& origin)
 
     m_pageScaleFactor = scale;
 
-    if (document->renderer())
-        document->renderer()->setNeedsLayout(true);
+    if (!m_settings->applyPageScaleFactorInCompositor()) {
+        if (document->renderer())
+            document->renderer()->setNeedsLayout(true);
 
-    document->recalcStyle(Node::Force);
+        document->recalcStyle(Node::Force);
 
-    // Transform change on RenderView doesn't trigger repaint on non-composited contents.
-    mainFrame()->view()->invalidateRect(IntRect(LayoutRect::infiniteRect()));
+        // Transform change on RenderView doesn't trigger repaint on non-composited contents.
+        mainFrame()->view()->invalidateRect(IntRect(LayoutRect::infiniteRect()));
+    }
 
 #if USE(ACCELERATED_COMPOSITING)
     mainFrame()->deviceOrPageScaleFactorChanged();
 #endif
 
     if (view && view->scrollPosition() != origin) {
-        if (document->renderer() && document->renderer()->needsLayout() && view->didFirstLayout())
+        if (!m_settings->applyPageScaleFactorInCompositor() && document->renderer() && document->renderer()->needsLayout() && view->didFirstLayout())
             view->layout();
         view->setScrollPosition(origin);
     }
index 8a69769..0472791 100644 (file)
@@ -225,14 +225,13 @@ void ScrollView::setDelegatesScrolling(bool delegatesScrolling)
     delegatesScrollingDidChange();
 }
 
-#if !PLATFORM(GTK)
-IntRect ScrollView::visibleContentRect(bool includeScrollbars) const
+IntSize ScrollView::unscaledVisibleContentSize(bool includeScrollbars) const
 {
     if (platformWidget())
-        return platformVisibleContentRect(includeScrollbars);
+        return platformVisibleContentRect(includeScrollbars).size();
 
     if (!m_fixedVisibleContentRect.isEmpty())
-        return m_fixedVisibleContentRect;
+        return m_fixedVisibleContentRect.size();
 
     int verticalScrollbarWidth = 0;
     int horizontalScrollbarHeight = 0;
@@ -244,26 +243,28 @@ IntRect ScrollView::visibleContentRect(bool includeScrollbars) const
             horizontalScrollbarHeight = !horizontalBar->isOverlayScrollbar() ? horizontalBar->height() : 0;
     }
 
-    return IntRect(m_scrollOffset.width(),
-                   m_scrollOffset.height(),
-                   max(0, width() - verticalScrollbarWidth), 
+    return IntSize(max(0, width() - verticalScrollbarWidth),
                    max(0, height() - horizontalScrollbarHeight));
 }
-#endif
 
-IntSize ScrollView::layoutSize() const
+#if !PLATFORM(GTK)
+IntRect ScrollView::visibleContentRect(bool includeScrollbars) const
 {
-    return m_fixedLayoutSize.isEmpty() || !m_useFixedLayout ? visibleSize() : m_fixedLayoutSize;
-}
+    if (platformWidget())
+        return platformVisibleContentRect(includeScrollbars);
 
-int ScrollView::layoutWidth() const
-{
-    return m_fixedLayoutSize.isEmpty() || !m_useFixedLayout ? visibleWidth() : m_fixedLayoutSize.width();
+    if (!m_fixedVisibleContentRect.isEmpty())
+        return m_fixedVisibleContentRect;
+
+    FloatSize visibleContentSize = unscaledVisibleContentSize(includeScrollbars);
+    visibleContentSize.scale(1 / visibleContentScaleFactor());
+    return IntRect(IntPoint(m_scrollOffset), expandedIntSize(visibleContentSize));
 }
+#endif
 
-int ScrollView::layoutHeight() const
+IntSize ScrollView::layoutSize() const
 {
-    return m_fixedLayoutSize.isEmpty() || !m_useFixedLayout ? visibleHeight() : m_fixedLayoutSize.height();
+    return m_fixedLayoutSize.isEmpty() || !m_useFixedLayout ? unscaledVisibleContentSize(false) : m_fixedLayoutSize;
 }
 
 IntSize ScrollView::fixedLayoutSize() const
index e043f6e..fe7b010 100644 (file)
@@ -151,11 +151,18 @@ public:
     virtual int visibleWidth() const OVERRIDE { return visibleContentRect().width(); }
     virtual int visibleHeight() const OVERRIDE { return visibleContentRect().height(); }
 
+    // visibleContentRect().size() is computed from unscaledVisibleContentSize() divided by the value of visibleContentScaleFactor.
+    // visibleContentScaleFactor is usually 1, except when the setting applyPageScaleFactorInCompositor is true and the
+    // ScrollView is the main frame; in that case, visibleContentScaleFactor is equal to the page's pageScaleFactor.
+    // Ports that don't use pageScaleFactor can treat unscaledVisibleContentSize and visibleContentRect().size() as equivalent.
+    IntSize unscaledVisibleContentSize(bool includeScrollbars) const;
+    virtual float visibleContentScaleFactor() const { return 1; }
+
     // Functions for getting/setting the size webkit should use to layout the contents. By default this is the same as the visible
     // content size. Explicitly setting a layout size value will cause webkit to layout the contents using this size instead.
     IntSize layoutSize() const;
-    int layoutWidth() const;
-    int layoutHeight() const;
+    int layoutWidth() const { return layoutSize().width(); }
+    int layoutHeight() const { return layoutSize().height(); }
     IntSize fixedLayoutSize() const;
     void setFixedLayoutSize(const IntSize&);
     bool useFixedLayout() const;
index c292487..3bc9f59 100644 (file)
@@ -1169,7 +1169,7 @@ void RenderLayerCompositor::frameViewDidChangeSize()
 {
     if (m_clipLayer) {
         FrameView* frameView = m_renderView->frameView();
-        m_clipLayer->setSize(frameView->visibleContentRect(false /* exclude scrollbars */).size());
+        m_clipLayer->setSize(frameView->unscaledVisibleContentSize(false /* exclude scrollbars */));
 
         frameViewDidScroll();
         updateOverflowControlsLayers();
@@ -1543,7 +1543,7 @@ void RenderLayerCompositor::updateRootLayerPosition()
     }
     if (m_clipLayer) {
         FrameView* frameView = m_renderView->frameView();
-        m_clipLayer->setSize(frameView->visibleContentRect(false /* exclude scrollbars */).size());
+        m_clipLayer->setSize(frameView->unscaledVisibleContentSize(false /* exclude scrollbars */));
     }
 
 #if ENABLE(RUBBER_BANDING)
index 79eb19a..bede284 100644 (file)
@@ -84,7 +84,7 @@ bool TextAutosizer::processSubtree(RenderObject* layoutRoot)
     windowInfo.windowSize = m_document->settings()->textAutosizingWindowSizeOverride();
     if (windowInfo.windowSize.isEmpty()) {
         bool includeScrollbars = !InspectorInstrumentation::shouldApplyScreenWidthOverride(mainFrame);
-        windowInfo.windowSize = mainFrame->view()->visibleContentRect(includeScrollbars).size();
+        windowInfo.windowSize = mainFrame->view()->unscaledVisibleContentSize(includeScrollbars);
         if (!m_document->settings()->applyDeviceScaleFactorInCompositor())
             windowInfo.windowSize.scale(1 / m_document->page()->deviceScaleFactor());
     }
index afe12b4..daca145 100644 (file)
@@ -1,3 +1,62 @@
+2013-01-28  Alexandre Elias  <aelias@chromium.org>
+
+        Make page scale shrink FrameView in applyPageScaleInCompositor mode
+        https://bugs.webkit.org/show_bug.cgi?id=107424
+
+        Reviewed by Levi Weintraub.
+
+        If applyPageScaleFactorInCompositor is enabled (Chromium-only setting),
+        instead of the entire document expanding as the user pinch zooms, the
+        viewport shrinks instead. This patch applies the pageScaleFactor to
+        visibleContentRect to get this behavior, and simplifies Chromium's
+        resize logic to stop hiding the true viewport size from WebCore.
+
+        I verified that the scaling makes sense for all the callers of
+        visibleContentRect. The exceptions are clip-layer size,
+        layout size in non-fixed-layout mode, and text autosizing, which need
+        the original unscaled size. Therefore I added a new method
+        unscaledVisibleContentSize() to ScrollView/FrameView.
+
+        This patch also modifies Page::setPageScaleFactor to perform no
+        invalidates or layout when applyPageScaleFactorInCompositor is true,
+        and also writes pageScaleFactor into HistoryItems instead of using
+        frameScaleFactor.
+
+        Since all behavior changes are tied to applyPageScaleFactorInCompositor,
+        this patch should be a no-op for non-Chromium ports.
+
+        * src/WebViewImpl.cpp:
+        (WebKit::WebViewImpl::scaledSize): Returns the post page-scale size
+        similar to what visibleContentRect() now returns, except that it may
+        be at a different scale than the current one.
+        (WebKit::WebViewImpl::size): Back to returning density-independent
+        size without any tricks, not the "layoutSize()" fake viewport.
+        (WebKit::WebViewImpl::resize):
+        (WebKit::WebViewImpl::handleInputEvent): No need to apply
+        implTransform anymore as WebKit knows the true scroll offset; just
+        divide event coords by pageScaleFactor.
+        (WebKit::WebViewImpl::clampOffsetAtScale): Make this method support
+        applyPageScaleFactorInCompositor.  This is used to pre-clamp scroll
+        offsets at a given viewport size.
+        (WebKit::WebViewImpl::setPageScaleFactorPreservingScrollOffset): Make
+        this method support applyPageScaleFactorInCompositor (don't scale
+        scroll offsets as they are now scale-independent).
+        (WebKit::WebViewImpl::setPageScaleFactor): Make this method always use
+        clampOffsetAtScale instead of bypassing it, since it's now supported.
+        Also notify the compositor to update its state.
+        (WebKit::WebViewImpl::contentsSize): Convenience method, removed
+        difference between scaled and unscaled.
+        (WebKit::WebViewImpl::layoutSize): This method returned the "fake"
+        size we used to give FrameView.  Now no longer used for much.
+        (WebKit::WebViewImpl::computePageScaleFactorLimits):
+        (WebKit::WebViewImpl::didChangeContentsSize): Remove unnecessary
+        resize() now that we can give the true size to FrameView.
+        (WebKit::WebViewImpl::updateLayerTreeViewport): Use layoutSize()
+        directly now that FrameView no longer uses it.
+        * src/WebViewImpl.h:
+        (WebViewImpl):
+        * tests/WebFrameTest.cpp:
+
 2013-01-28  Alec Flett  <alecflett@chromium.org>
 
         IndexedDB: Pass metadata in to IDBOpenDBRequest.onUpgradeNeeded/onSuccess
index b827a56..93940c1 100644 (file)
@@ -1626,11 +1626,15 @@ void WebViewImpl::willStartLiveResize()
         pluginContainer->willStartLiveResize();
 }
 
-WebSize WebViewImpl::size()
+IntSize WebViewImpl::scaledSize(float pageScaleFactor) const
 {
-    if (isFixedLayoutModeEnabled() && settingsImpl()->applyPageScaleFactorInCompositor())
-        return layoutSize();
+    FloatSize scaledSize = dipSize();
+    scaledSize.scale(1 / pageScaleFactor);
+    return expandedIntSize(scaledSize);
+}
 
+WebSize WebViewImpl::size()
+{
     return m_size;
 }
 
@@ -1661,7 +1665,7 @@ void WebViewImpl::resize(const WebSize& newSize)
     if (!agentPrivate || !agentPrivate->metricsOverridden()) {
         WebFrameImpl* webFrame = mainFrameImpl();
         if (webFrame->frameView())
-            webFrame->frameView()->resize(size());
+            webFrame->frameView()->resize(m_size);
     }
 
 #if ENABLE(VIEWPORT)
@@ -2097,30 +2101,24 @@ bool WebViewImpl::handleInputEvent(const WebInputEvent& inputEvent)
         return true;
     }
 
-    if (!m_layerTreeView)
-        return PageWidgetDelegate::handleInputEvent(m_page.get(), *this, inputEvent);
-
     const WebInputEvent* inputEventTransformed = &inputEvent;
-    WebMouseEvent mouseEvent;
-    WebGestureEvent gestureEvent;
-    if (WebInputEvent::isMouseEventType(inputEvent.type)) {
-        mouseEvent = *static_cast<const WebMouseEvent*>(&inputEvent);
-
-        IntPoint transformedLocation = roundedIntPoint(m_layerTreeView->adjustEventPointForPinchZoom(WebFloatPoint(mouseEvent.x, mouseEvent.y)));
-        mouseEvent.x = transformedLocation.x();
-        mouseEvent.y = transformedLocation.y();
-        inputEventTransformed = static_cast<const WebInputEvent*>(&mouseEvent);
-    } else if (WebInputEvent::isGestureEventType(inputEvent.type)) {
-        gestureEvent = *static_cast<const WebGestureEvent*>(&inputEvent);
-
-        IntPoint transformedLocation = roundedIntPoint(m_layerTreeView->adjustEventPointForPinchZoom(WebFloatPoint(gestureEvent.x, gestureEvent.y)));
-        gestureEvent.x = transformedLocation.x();
-        gestureEvent.y = transformedLocation.y();
-        inputEventTransformed = static_cast<const WebInputEvent*>(&gestureEvent);
+    if (m_page->settings()->applyPageScaleFactorInCompositor()) {
+        WebMouseEvent mouseEvent;
+        WebGestureEvent gestureEvent;
+        if (WebInputEvent::isMouseEventType(inputEvent.type)) {
+            mouseEvent = *static_cast<const WebMouseEvent*>(&inputEvent);
+            mouseEvent.x = mouseEvent.x / pageScaleFactor();
+            mouseEvent.y = mouseEvent.y / pageScaleFactor();
+            inputEventTransformed = static_cast<const WebInputEvent*>(&mouseEvent);
+        } else if (WebInputEvent::isGestureEventType(inputEvent.type)) {
+            gestureEvent = *static_cast<const WebGestureEvent*>(&inputEvent);
+            gestureEvent.x = gestureEvent.x / pageScaleFactor();
+            gestureEvent.y = gestureEvent.y / pageScaleFactor();
+            inputEventTransformed = static_cast<const WebInputEvent*>(&gestureEvent);
+        }
     }
 
-    bool handled = PageWidgetDelegate::handleInputEvent(m_page.get(), *this, *inputEventTransformed);
-    return handled;
+    return PageWidgetDelegate::handleInputEvent(m_page.get(), *this, *inputEventTransformed);
 }
 
 void WebViewImpl::mouseCaptureLost()
@@ -2935,34 +2933,40 @@ float WebViewImpl::clampPageScaleFactorToLimits(float scaleFactor)
     return min(max(scaleFactor, m_minimumPageScaleFactor), m_maximumPageScaleFactor);
 }
 
-WebPoint WebViewImpl::clampOffsetAtScale(const WebPoint& offset, float scale)
+IntPoint WebViewImpl::clampOffsetAtScale(const IntPoint& offset, float scale) const
 {
-    // This is the scaled content size. We need to convert it to the new scale factor.
-    WebSize contentSize = mainFrame()->contentsSize();
-    float deltaScale = scale / pageScaleFactor();
-    int docWidthAtNewScale = contentSize.width * deltaScale;
-    int docHeightAtNewScale = contentSize.height * deltaScale;
-    int viewWidth = m_size.width;
-    int viewHeight = m_size.height;
-
-    // Enforce the maximum and minimum scroll positions at the new scale.
     IntPoint clampedOffset = offset;
-    clampedOffset = clampedOffset.shrunkTo(IntPoint(docWidthAtNewScale - viewWidth, docHeightAtNewScale - viewHeight));
-    clampedOffset.clampNegativeToZero();
+    if (!m_page->settings()->applyPageScaleFactorInCompositor()) {
+        // This is the scaled content size. We need to convert it to the new scale factor.
+        WebSize contentSize = contentsSize();
+        int docWidthAtNewScale = contentSize.width * scale;
+        int docHeightAtNewScale = contentSize.height * scale;
+        int viewWidth = m_size.width;
+        int viewHeight = m_size.height;
+
+        // Enforce the maximum and minimum scroll positions at the new scale.
+        clampedOffset = clampedOffset.shrunkTo(IntPoint(docWidthAtNewScale - viewWidth, docHeightAtNewScale - viewHeight));
+        clampedOffset.clampNegativeToZero();
+    } else {
+        clampedOffset = clampedOffset.shrunkTo(IntPoint(contentsSize() - scaledSize(scale)));
+        clampedOffset.clampNegativeToZero();
+    }
+
     return clampedOffset;
 }
 
 void WebViewImpl::setPageScaleFactorPreservingScrollOffset(float scaleFactor)
 {
-    // Pick a scale factor that is within the expected limits
     scaleFactor = clampPageScaleFactorToLimits(scaleFactor);
 
-    IntPoint scrollOffsetAtNewScale(mainFrame()->scrollOffset().width, mainFrame()->scrollOffset().height);
-    float deltaScale = scaleFactor / pageScaleFactor();
-    scrollOffsetAtNewScale.scale(deltaScale, deltaScale);
+    IntPoint scrollOffset(mainFrame()->scrollOffset().width, mainFrame()->scrollOffset().height);
+    if (!m_page->settings()->applyPageScaleFactorInCompositor()) {
+        float deltaScale = scaleFactor / pageScaleFactor();
+        scrollOffset.scale(deltaScale, deltaScale);
+    }
+    scrollOffset = clampOffsetAtScale(scrollOffset, scaleFactor);
 
-    WebPoint clampedOffsetAtNewScale = clampOffsetAtScale(scrollOffsetAtNewScale, scaleFactor);
-    setPageScaleFactor(scaleFactor, clampedOffsetAtNewScale);
+    setPageScaleFactor(scaleFactor, scrollOffset);
 }
 
 void WebViewImpl::setPageScaleFactor(float scaleFactor, const WebPoint& origin)
@@ -2973,22 +2977,17 @@ void WebViewImpl::setPageScaleFactor(float scaleFactor, const WebPoint& origin)
     if (!scaleFactor)
         scaleFactor = 1;
 
+    IntPoint scrollOffset = origin;
     scaleFactor = clampPageScaleFactorToLimits(scaleFactor);
-    WebPoint scrollOffset;
-    if (!m_page->settings()->applyPageScaleFactorInCompositor()) {
-        // If page scale is not applied in the compositor, then the scroll offsets should
-        // be modified by the scale factor.
-        scrollOffset = clampOffsetAtScale(origin, scaleFactor);
-    } else {
-        IntPoint offset = origin;
-        WebSize contentSize = mainFrame()->contentsSize();
-        offset.shrunkTo(IntPoint(contentSize.width - m_size.width, contentSize.height - m_size.height));
-        offset.clampNegativeToZero();
-        scrollOffset = offset;
-    }
+    scrollOffset = clampOffsetAtScale(scrollOffset, scaleFactor);
+
+    page()->setPageScaleFactor(scaleFactor, IntPoint(scrollOffset));
 
-    page()->setPageScaleFactor(scaleFactor, scrollOffset);
     m_pageScaleFactorIsSet = true;
+
+#if USE(ACCELERATED_COMPOSITING)
+    updateLayerTreeViewport();
+#endif
 }
 
 float WebViewImpl::deviceScaleFactor() const
@@ -3072,12 +3071,14 @@ void WebViewImpl::setIgnoreViewportTagMaximumScale(bool flag)
     m_page->chrome()->client()->dispatchViewportPropertiesDidChange(page()->mainFrame()->document()->viewportArguments());
 }
 
-static IntSize unscaledContentsSize(Frame* frame)
+IntSize WebViewImpl::contentsSize() const
 {
+    Frame* frame = page()->mainFrame();
     RenderView* root = frame->contentRenderer();
     if (!root)
         return IntSize();
-    return root->unscaledDocumentRect().size();
+
+    return root->documentRect().size();
 }
 
 IntSize WebViewImpl::layoutSize() const
@@ -3085,7 +3086,8 @@ IntSize WebViewImpl::layoutSize() const
     if (!isFixedLayoutModeEnabled())
         return m_size;
 
-    IntSize contentSize = unscaledContentsSize(page()->mainFrame());
+    IntSize contentSize = contentsSize();
+
     if (fixedLayoutSize().width >= contentSize.width())
         return fixedLayoutSize();
 
@@ -3113,7 +3115,7 @@ bool WebViewImpl::computePageScaleFactorLimits()
     int viewWidthNotIncludingScrollbars = m_size.width;
     if (viewWidthNotIncludingScrollbars && view->verticalScrollbar() && !view->verticalScrollbar()->isOverlayScrollbar())
         viewWidthNotIncludingScrollbars -= view->verticalScrollbar()->width();
-    int unscaledContentsWidth = unscaledContentsSize(page()->mainFrame()).width();
+    int unscaledContentsWidth = contentsSize().width();
     if (viewWidthNotIncludingScrollbars && unscaledContentsWidth) {
         // Limit page scaling down to the document width.
         m_minimumPageScaleFactor = max(m_minimumPageScaleFactor, static_cast<float>(viewWidthNotIncludingScrollbars) / unscaledContentsWidth);
@@ -3765,15 +3767,10 @@ void WebViewImpl::didChangeContentsSize()
     } else
         mayNeedLayout = computePageScaleFactorLimits();
 
-    FrameView* view = mainFrameImpl()->frameView();
-    if (settingsImpl()->applyPageScaleFactorInCompositor() && view && view->visibleContentRect(true).width() != layoutSize().width()) {
-        view->resize(layoutSize());
-        mayNeedLayout = true;
-    }
-
     // didChangeContentsSize() may be called from FrameView::layout; we need to
     // relayout to avoid triggering the assertion that needsLayout() isn't set
     // at the end of a layout.
+    FrameView* view = mainFrameImpl()->frameView();
     if (mayNeedLayout && view && view->needsLayout())
         view->layout();
 #endif
@@ -4249,16 +4246,14 @@ void WebViewImpl::updateLayerTreeViewport()
         return;
 
     FrameView* view = page()->mainFrame()->view();
-    IntRect visibleRect = view->visibleContentRect(true /* include scrollbars */);
-    IntPoint scroll(view->scrollX(), view->scrollY());
 
-    m_nonCompositedContentHost->setViewport(visibleRect.size(), view->contentsSize(), scroll, view->scrollOrigin());
-
-    IntSize layoutViewportSize = visibleRect.size();
+    IntSize layoutViewportSize = layoutSize();
     IntSize deviceViewportSize = m_size;
     if (m_webSettings->applyDeviceScaleFactorInCompositor())
         deviceViewportSize.scale(deviceScaleFactor());
 
+    m_nonCompositedContentHost->setViewport(deviceViewportSize, view->contentsSize(), view->scrollPosition(), view->scrollOrigin());
+
     m_layerTreeView->setViewportSize(layoutViewportSize, deviceViewportSize);
     m_layerTreeView->setPageScaleFactorAndLimits(pageScaleFactor(), m_minimumPageScaleFactor, m_maximumPageScaleFactor);
 }
index 0f6a2aa..e7ce0e7 100644 (file)
@@ -461,6 +461,7 @@ public:
 
     WebCore::IntSize dipSize() const;
     WebCore::IntSize layoutSize() const;
+    WebCore::IntSize scaledSize(float) const;
 
     // Set the disposition for how this webview is to be initially shown.
     void setInitialNavigationPolicy(WebNavigationPolicy policy)
@@ -615,7 +616,8 @@ public:
 private:
     bool computePageScaleFactorLimits();
     float clampPageScaleFactorToLimits(float scale);
-    WebPoint clampOffsetAtScale(const WebPoint& offset, float scale);
+    WebCore::IntPoint clampOffsetAtScale(const WebCore::IntPoint& offset, float scale) const;
+    WebCore::IntSize contentsSize() const;
 
     void resetSavedScrollAndScaleState();
 
index 53ff2c7..ec5dc65 100644 (file)
@@ -37,6 +37,7 @@
 #include "FrameTestHelpers.h"
 #include "FrameView.h"
 #include "Range.h"
+#include "RenderView.h"
 #include "ResourceError.h"
 #include "Settings.h"
 #include "URLTestHelpers.h"
@@ -307,6 +308,110 @@ TEST_F(WebFrameTest, ScaleFactorShouldNotOscillate)
     webViewImpl->layout();
 }
 
+TEST_F(WebFrameTest, setPageScaleFactorDoesNotLayout)
+{
+    registerMockedHttpURLLoad("fixed_layout.html");
+
+    FixedLayoutTestWebViewClient client;
+    client.m_screenInfo.deviceScaleFactor = 1;
+    int viewportWidth = 640;
+    int viewportHeight = 480;
+
+    WebViewImpl* webViewImpl = static_cast<WebViewImpl*>(FrameTestHelpers::createWebViewAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client));
+    webViewImpl->settings()->setApplyDeviceScaleFactorInCompositor(true);
+    webViewImpl->settings()->setApplyPageScaleFactorInCompositor(true);
+    webViewImpl->enableFixedLayoutMode(true);
+    webViewImpl->settings()->setViewportEnabled(true);
+    webViewImpl->resize(WebSize(viewportWidth, viewportHeight));
+    webViewImpl->layout();
+
+    int prevLayoutCount = webViewImpl->mainFrameImpl()->frameView()->layoutCount();
+    webViewImpl->setPageScaleFactor(3, WebPoint());
+    EXPECT_EQ(false, webViewImpl->mainFrameImpl()->frameView()->needsLayout());
+    EXPECT_EQ(prevLayoutCount, webViewImpl->mainFrameImpl()->frameView()->layoutCount());
+}
+
+TEST_F(WebFrameTest, pageScaleFactorWrittenToHistoryItem)
+{
+    registerMockedHttpURLLoad("fixed_layout.html");
+
+    FixedLayoutTestWebViewClient client;
+    client.m_screenInfo.deviceScaleFactor = 1;
+    int viewportWidth = 640;
+    int viewportHeight = 480;
+
+    WebViewImpl* webViewImpl = static_cast<WebViewImpl*>(FrameTestHelpers::createWebViewAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client));
+    webViewImpl->settings()->setApplyDeviceScaleFactorInCompositor(true);
+    webViewImpl->settings()->setApplyPageScaleFactorInCompositor(true);
+    webViewImpl->enableFixedLayoutMode(true);
+    webViewImpl->settings()->setViewportEnabled(true);
+    webViewImpl->resize(WebSize(viewportWidth, viewportHeight));
+    webViewImpl->layout();
+
+    webViewImpl->setPageScaleFactor(3, WebPoint());
+    webViewImpl->page()->mainFrame()->loader()->history()->saveDocumentAndScrollState();
+    webViewImpl->setPageScaleFactor(1, WebPoint());
+    webViewImpl->page()->mainFrame()->loader()->history()->restoreScrollPositionAndViewState();
+    EXPECT_EQ(3, webViewImpl->pageScaleFactor());
+}
+
+TEST_F(WebFrameTest, pageScaleFactorShrinksViewport)
+{
+    registerMockedHttpURLLoad("fixed_layout.html");
+
+    FixedLayoutTestWebViewClient client;
+    client.m_screenInfo.deviceScaleFactor = 1;
+    int viewportWidth = 640;
+    int viewportHeight = 480;
+    int viewportWidthMinusScrollbar = 640 - 15;
+    int viewportHeightMinusScrollbar = 480 - 15;
+
+    WebViewImpl* webViewImpl = static_cast<WebViewImpl*>(FrameTestHelpers::createWebViewAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client));
+    webViewImpl->settings()->setApplyDeviceScaleFactorInCompositor(true);
+    webViewImpl->settings()->setApplyPageScaleFactorInCompositor(true);
+    webViewImpl->enableFixedLayoutMode(true);
+    webViewImpl->settings()->setViewportEnabled(true);
+    webViewImpl->resize(WebSize(viewportWidth, viewportHeight));
+    webViewImpl->layout();
+
+    webViewImpl->setPageScaleFactor(2, WebPoint());
+
+    WebCore::IntSize unscaledSize = webViewImpl->mainFrameImpl()->frameView()->unscaledVisibleContentSize(true);
+    EXPECT_EQ(viewportWidth, unscaledSize.width());
+    EXPECT_EQ(viewportHeight, unscaledSize.height());
+
+    WebCore::IntSize unscaledSizeMinusScrollbar = webViewImpl->mainFrameImpl()->frameView()->unscaledVisibleContentSize(false);
+    EXPECT_EQ(viewportWidthMinusScrollbar, unscaledSizeMinusScrollbar.width());
+    EXPECT_EQ(viewportHeightMinusScrollbar, unscaledSizeMinusScrollbar.height());
+
+    WebCore::IntSize scaledSize = webViewImpl->mainFrameImpl()->frameView()->visibleContentRect().size();
+    EXPECT_EQ(ceil(viewportWidthMinusScrollbar / 2.0), scaledSize.width());
+    EXPECT_EQ(ceil(viewportHeightMinusScrollbar / 2.0), scaledSize.height());
+}
+
+TEST_F(WebFrameTest, pageScaleFactorDoesNotApplyCssTransform)
+{
+    registerMockedHttpURLLoad("fixed_layout.html");
+
+    FixedLayoutTestWebViewClient client;
+    client.m_screenInfo.deviceScaleFactor = 1;
+    int viewportWidth = 640;
+    int viewportHeight = 480;
+
+    WebViewImpl* webViewImpl = static_cast<WebViewImpl*>(FrameTestHelpers::createWebViewAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client));
+    webViewImpl->settings()->setApplyDeviceScaleFactorInCompositor(true);
+    webViewImpl->settings()->setApplyPageScaleFactorInCompositor(true);
+    webViewImpl->enableFixedLayoutMode(true);
+    webViewImpl->settings()->setViewportEnabled(true);
+    webViewImpl->resize(WebSize(viewportWidth, viewportHeight));
+    webViewImpl->layout();
+
+    webViewImpl->setPageScaleFactor(2, WebPoint());
+
+    EXPECT_EQ(1, webViewImpl->page()->mainFrame()->frameScaleFactor());
+    EXPECT_EQ(980, webViewImpl->page()->mainFrame()->contentRenderer()->unscaledDocumentRect().width());
+    EXPECT_EQ(980, webViewImpl->mainFrameImpl()->frameView()->contentsSize().width());
+}
 #endif
 
 TEST_F(WebFrameTest, CanOverrideMaximumScaleFactor)
@@ -784,7 +889,7 @@ TEST_F(WebFrameTest, DivAutoZoomScaleFontScaleFactorTestCompositorScaling)
     // Zoom in to reset double_tap_zoom_in_effect flag.
     webViewImpl->applyScrollAndScale(WebSize(), 1.1f);
     // 1 < textAutosizingFontScaleFactor < minimumPageScale < doubleTapZoomAlreadyLegibleScale
-    webView->setPageScaleFactorLimits(1.2f, 4);
+    webView->setPageScaleFactorLimits(1.0f, 4);
     doubleTapZoomAlreadyLegibleScale = webViewImpl->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
     setScaleAndScrollAndLayout(webViewImpl, WebPoint(0, 0), (webViewImpl->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
     simulateDoubleTap(webViewImpl, doubleTapPoint, scale);