Support bottom-right anchored fixed-position elements during a pinch gesture
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 28 Mar 2013 21:50:39 +0000 (21:50 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 28 Mar 2013 21:50:39 +0000 (21:50 +0000)
https://bugs.webkit.org/show_bug.cgi?id=111670

Patch by Tien-Ren Chen <trchen@chromium.org> on 2013-03-28
Reviewed by James Robinson.

Source/Platform:

Added WebLayerPositionConstraint for layers that need position
adjustment during threaded scrolling.
Currently it is only used for fixed-position layers.

* Platform.gypi:
* chromium/public/WebLayer.h:
(WebKit):
(WebLayer):
(WebKit::WebLayer::setPositionConstraint):
(WebKit::WebLayer::positionConstraint):
(WebKit::WebLayer::setFixedToContainerLayer):
(WebKit::WebLayer::fixedToContainerLayer):
* chromium/public/WebLayerPositionConstraint.h: Added.
(WebKit):
(WebLayerPositionConstraint):
(WebKit::WebLayerPositionConstraint::WebLayerPositionConstraint):
(WebKit::WebLayerPositionConstraint::fixedPosition):

Source/WebCore:

This patch adds support to bottom-right fixed-position elements by
introducing WebLayerPositionConstraint to WebLayer.

No new tests. Can't test until chromium patch landed.

* page/scrolling/ScrollingCoordinator.h:
(WebCore::ScrollingCoordinator::updateLayerPositionConstraint):
* page/scrolling/chromium/ScrollingCoordinatorChromium.cpp:
(WebCore::clearPositionConstraintExceptForLayer):
(WebCore):
(WebCore::computePositionConstraint):
(WebCore::ScrollingCoordinatorChromium::updateLayerPositionConstraint):
* page/scrolling/chromium/ScrollingCoordinatorChromium.h:
(ScrollingCoordinatorChromium):
* rendering/RenderLayerBacking.cpp:
(WebCore::RenderLayerBacking::registerScrollingLayers):
* rendering/RenderLayerBacking.h:
(WebCore::RenderLayerBacking::contentsContainmentLayer):
(RenderLayerBacking):
* rendering/RenderLayerCompositor.cpp:
* rendering/RenderLayerCompositor.h:

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

12 files changed:
Source/Platform/ChangeLog
Source/Platform/Platform.gypi
Source/Platform/chromium/public/WebLayer.h
Source/Platform/chromium/public/WebLayerPositionConstraint.h [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/page/scrolling/ScrollingCoordinator.h
Source/WebCore/page/scrolling/chromium/ScrollingCoordinatorChromium.cpp
Source/WebCore/page/scrolling/chromium/ScrollingCoordinatorChromium.h
Source/WebCore/rendering/RenderLayerBacking.cpp
Source/WebCore/rendering/RenderLayerBacking.h
Source/WebCore/rendering/RenderLayerCompositor.cpp
Source/WebCore/rendering/RenderLayerCompositor.h

index df5820a..92aa156 100644 (file)
@@ -1,3 +1,28 @@
+2013-03-28  Tien-Ren Chen  <trchen@chromium.org>
+
+        Support bottom-right anchored fixed-position elements during a pinch gesture
+        https://bugs.webkit.org/show_bug.cgi?id=111670
+
+        Reviewed by James Robinson.
+
+        Added WebLayerPositionConstraint for layers that need position
+        adjustment during threaded scrolling.
+        Currently it is only used for fixed-position layers.
+
+        * Platform.gypi:
+        * chromium/public/WebLayer.h:
+        (WebKit):
+        (WebLayer):
+        (WebKit::WebLayer::setPositionConstraint):
+        (WebKit::WebLayer::positionConstraint):
+        (WebKit::WebLayer::setFixedToContainerLayer):
+        (WebKit::WebLayer::fixedToContainerLayer):
+        * chromium/public/WebLayerPositionConstraint.h: Added.
+        (WebKit):
+        (WebLayerPositionConstraint):
+        (WebKit::WebLayerPositionConstraint::WebLayerPositionConstraint):
+        (WebKit::WebLayerPositionConstraint::fixedPosition):
+
 2013-03-28  Zan Dobersek  <zdobersek@igalia.com>
 
         [GTK] Build GTK-specific, non-layer-violating source code into WebCore-independent libPlatformGtk.la
index 131a0c1..3fffa2f 100644 (file)
@@ -83,6 +83,7 @@
             'chromium/public/WebImage.h',
             'chromium/public/WebImageLayer.h',
             'chromium/public/WebLayer.h',
+            'chromium/public/WebLayerPositionConstraint.h',
             'chromium/public/WebLayerScrollClient.h',
             'chromium/public/WebLayerTreeView.h',
             'chromium/public/WebLocalizedString.h',
index 52c816a..599e6d8 100644 (file)
 #include "WebAnimation.h"
 #include "WebColor.h"
 #include "WebCommon.h"
+
+// Remove after making setPositionConstraint() pure virtual.
+#include "WebLayerPositionConstraint.h"
+
 #include "WebPoint.h"
 #include "WebPrivatePtr.h"
 #include "WebRect.h"
@@ -44,6 +48,7 @@ class WebFilterOperations;
 class WebLayerScrollClient;
 struct WebFloatPoint;
 struct WebFloatRect;
+struct WebLayerPositionConstraint;
 struct WebSize;
 
 class WebLayerImpl;
@@ -189,8 +194,11 @@ public:
     virtual void setIsContainerForFixedPositionLayers(bool) = 0;
     virtual bool isContainerForFixedPositionLayers() const = 0;
 
-    virtual void setFixedToContainerLayer(bool) = 0;
-    virtual bool fixedToContainerLayer() const = 0;
+    // This function sets layer position constraint. The constraint will be used
+    // to adjust layer position during threaded scrolling.
+    // FIXME: Make pure virtual after implementation lands.
+    virtual void setPositionConstraint(const WebLayerPositionConstraint& constraint) { setFixedToContainerLayer(constraint.isFixedPosition); }
+    virtual WebLayerPositionConstraint positionConstraint() const { return WebLayerPositionConstraint(); }
 
     // The scroll client is notified when the scroll position of the WebLayer
     // changes. Only a single scroll client can be set for a WebLayer at a time.
@@ -205,6 +213,10 @@ public:
 
     // True if the layer is not part of a tree attached to a WebLayerTreeView.
     virtual bool isOrphan() const = 0;
+
+    // DEPRECATED
+    virtual void setFixedToContainerLayer(bool) { }
+    virtual bool fixedToContainerLayer() const { return positionConstraint().isFixedPosition; }
 };
 
 } // namespace WebKit
diff --git a/Source/Platform/chromium/public/WebLayerPositionConstraint.h b/Source/Platform/chromium/public/WebLayerPositionConstraint.h
new file mode 100644 (file)
index 0000000..0f1b9f8
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WebLayerPositionConstraint_h
+#define WebLayerPositionConstraint_h
+
+namespace WebKit {
+
+struct WebLayerPositionConstraint {
+    bool isFixedPosition     : 1;
+    bool isFixedToRightEdge  : 1;
+    bool isFixedToBottomEdge : 1;
+
+    WebLayerPositionConstraint()
+        : isFixedPosition(false)
+        , isFixedToRightEdge(false)
+        , isFixedToBottomEdge(false)
+    {
+    }
+
+    static WebLayerPositionConstraint fixedPosition(bool fixedToRightEdge, bool fixedToBottomEdge)
+    {
+        WebLayerPositionConstraint constraint;
+        constraint.isFixedPosition = true;
+        constraint.isFixedToRightEdge = fixedToRightEdge;
+        constraint.isFixedToBottomEdge = fixedToBottomEdge;
+        return constraint;
+    }
+};
+
+} // namespace WebKit
+
+#endif // WebLayerPositionConstraint_h
index 9ed2f77..2d1c104 100644 (file)
@@ -1,3 +1,32 @@
+2013-03-28  Tien-Ren Chen  <trchen@chromium.org>
+
+        Support bottom-right anchored fixed-position elements during a pinch gesture
+        https://bugs.webkit.org/show_bug.cgi?id=111670
+
+        Reviewed by James Robinson.
+
+        This patch adds support to bottom-right fixed-position elements by
+        introducing WebLayerPositionConstraint to WebLayer.
+
+        No new tests. Can't test until chromium patch landed.
+
+        * page/scrolling/ScrollingCoordinator.h:
+        (WebCore::ScrollingCoordinator::updateLayerPositionConstraint):
+        * page/scrolling/chromium/ScrollingCoordinatorChromium.cpp:
+        (WebCore::clearPositionConstraintExceptForLayer):
+        (WebCore):
+        (WebCore::computePositionConstraint):
+        (WebCore::ScrollingCoordinatorChromium::updateLayerPositionConstraint):
+        * page/scrolling/chromium/ScrollingCoordinatorChromium.h:
+        (ScrollingCoordinatorChromium):
+        * rendering/RenderLayerBacking.cpp:
+        (WebCore::RenderLayerBacking::registerScrollingLayers):
+        * rendering/RenderLayerBacking.h:
+        (WebCore::RenderLayerBacking::contentsContainmentLayer):
+        (RenderLayerBacking):
+        * rendering/RenderLayerCompositor.cpp:
+        * rendering/RenderLayerCompositor.h:
+
 2013-03-28  James Robinson  <jamesr@chromium.org>
 
         Remove unnecessary 1 second sleep on windows from preprocessor.pm
index 14d90e5..2ecb464 100644 (file)
@@ -153,7 +153,7 @@ public:
     virtual void scrollableAreaScrollLayerDidChange(ScrollableArea*) { }
     virtual void scrollableAreaScrollbarLayerDidChange(ScrollableArea*, ScrollbarOrientation) { }
     virtual void setLayerIsContainerForFixedPositionLayers(GraphicsLayer*, bool) { }
-    virtual void setLayerIsFixedToContainerLayer(GraphicsLayer*, bool) { }
+    virtual void updateLayerPositionConstraint(RenderLayer*) { }
     virtual void touchEventTargetRectsDidChange(const Document*) { }
 
 #if ENABLE(TOUCH_EVENT_TRACKING)
index 191c8e0..bce85cd 100644 (file)
@@ -32,6 +32,7 @@
 #include "GraphicsLayerChromium.h"
 #include "Page.h"
 #include "Region.h"
+#include "RenderLayerBacking.h"
 #include "RenderLayerCompositor.h"
 #include "RenderView.h"
 #include "ScrollbarThemeComposite.h"
 #include "WebScrollbarThemeGeometryNative.h"
 #include <public/Platform.h>
 #include <public/WebCompositorSupport.h>
+#include <public/WebLayerPositionConstraint.h>
 #include <public/WebScrollbar.h>
 #include <public/WebScrollbarLayer.h>
 #include <public/WebScrollbarThemeGeometry.h>
 #include <public/WebScrollbarThemePainter.h>
 
 using WebKit::WebLayer;
+using WebKit::WebLayerPositionConstraint;
 using WebKit::WebRect;
 using WebKit::WebScrollbarLayer;
 using WebKit::WebVector;
@@ -233,10 +236,41 @@ void ScrollingCoordinatorChromium::setLayerIsContainerForFixedPositionLayers(Gra
         scrollableLayer->setIsContainerForFixedPositionLayers(enable);
 }
 
-void ScrollingCoordinatorChromium::setLayerIsFixedToContainerLayer(GraphicsLayer* layer, bool enable)
+static void clearPositionConstraintExceptForLayer(GraphicsLayer* layer, GraphicsLayer* except)
 {
-    if (WebLayer* scrollableLayer = scrollingWebLayerForGraphicsLayer(layer))
-        scrollableLayer->setFixedToContainerLayer(enable);
+    if (layer && layer != except && scrollingWebLayerForGraphicsLayer(layer))
+        scrollingWebLayerForGraphicsLayer(layer)->setPositionConstraint(WebLayerPositionConstraint());
+}
+
+static WebLayerPositionConstraint computePositionConstraint(const RenderLayer* layer)
+{
+    ASSERT(layer->isComposited());
+    do {
+        if (layer->renderer()->style()->position() == FixedPosition) {
+            const RenderObject* fixedPositionObject = layer->renderer();
+            bool fixedToRight = !fixedPositionObject->style()->right().isAuto();
+            bool fixedToBottom = !fixedPositionObject->style()->bottom().isAuto();
+            return WebLayerPositionConstraint::fixedPosition(fixedToRight, fixedToBottom);
+        }
+
+        layer = layer->parent();
+    } while (layer && !layer->isComposited());
+    return WebLayerPositionConstraint();
+}
+
+void ScrollingCoordinatorChromium::updateLayerPositionConstraint(RenderLayer* layer)
+{
+    ASSERT(layer->backing());
+    RenderLayerBacking* backing = layer->backing();
+    GraphicsLayer* mainLayer = backing->childForSuperlayers();
+
+    // Avoid unnecessary commits
+    clearPositionConstraintExceptForLayer(backing->ancestorClippingLayer(), mainLayer);
+    clearPositionConstraintExceptForLayer(backing->contentsContainmentLayer(), mainLayer);
+    clearPositionConstraintExceptForLayer(backing->graphicsLayer(), mainLayer);
+
+    if (WebLayer* scrollableLayer = scrollingWebLayerForGraphicsLayer(mainLayer))
+        scrollableLayer->setPositionConstraint(computePositionConstraint(layer));
 }
 
 void ScrollingCoordinatorChromium::scrollableAreaScrollLayerDidChange(ScrollableArea* scrollableArea)
index c1c029a..0fd03be 100644 (file)
@@ -53,7 +53,7 @@ public:
     virtual void setLayerIsContainerForFixedPositionLayers(GraphicsLayer*, bool);
 
     // Attach/detach layer position to ancestor fixed position container.
-    virtual void setLayerIsFixedToContainerLayer(GraphicsLayer*, bool);
+    virtual void updateLayerPositionConstraint(RenderLayer*);
 
     // Should be called when a ScrollableArea is getting destroyed.
     virtual void willDestroyScrollableArea(ScrollableArea*);
index 06fbc40..319fb81 100644 (file)
@@ -860,14 +860,11 @@ void RenderLayerBacking::registerScrollingLayers()
 
     compositor()->updateViewportConstraintStatus(m_owningLayer);
 
-    // FIXME: it would be nice to avoid all this work if the platform doesn't implement setLayerIsFixedToContainerLayer().
-    if (renderer()->style()->position() == FixedPosition || compositor()->fixedPositionedByAncestor(m_owningLayer))
-        scrollingCoordinator->setLayerIsFixedToContainerLayer(childForSuperlayers(), true);
-    else {
-        if (m_ancestorClippingLayer)
-            scrollingCoordinator->setLayerIsFixedToContainerLayer(m_ancestorClippingLayer.get(), false);
-        scrollingCoordinator->setLayerIsFixedToContainerLayer(m_graphicsLayer.get(), false);
-    }
+    if (!scrollingCoordinator->supportsFixedPositionLayers())
+        return;
+
+    scrollingCoordinator->updateLayerPositionConstraint(m_owningLayer);
+
     // Page scale is applied as a transform on the root render view layer. Because the scroll
     // layer is further up in the hierarchy, we need to avoid marking the root render view
     // layer as a container.
index 89d8c14..9c10e5c 100644 (file)
@@ -87,6 +87,8 @@ public:
     bool hasAncestorClippingLayer() const { return m_ancestorClippingLayer != 0; }
     GraphicsLayer* ancestorClippingLayer() const { return m_ancestorClippingLayer.get(); }
 
+    GraphicsLayer* contentsContainmentLayer() const { return m_contentsContainmentLayer.get(); }
+
     bool hasContentsLayer() const { return m_foregroundLayer != 0; }
     GraphicsLayer* foregroundLayer() const { return m_foregroundLayer.get(); }
 
index 945ced0..c1c5428 100644 (file)
@@ -1937,31 +1937,6 @@ bool RenderLayerCompositor::clipsCompositingDescendants(const RenderLayer* layer
     return layer->hasCompositingDescendant() && layer->renderer()->hasClipOrOverflowClip();
 }
 
-// Return true if there is an ancestor layer that is fixed positioned to the view.
-// Note that if the ancestor has a stacking context and is fixed position then this method
-// will return false.
-bool RenderLayerCompositor::fixedPositionedByAncestor(const RenderLayer* layer) const
-{
-    if (!layer->isComposited() || !layer->parent())
-        return false;
-
-    const RenderLayer* compositingAncestor = layer->ancestorCompositingLayer();
-    if (!compositingAncestor)
-        return false;
-
-    const RenderLayer* curr = layer;
-    while (curr) {
-        const RenderLayer* next = curr->parent();
-        if (next == compositingAncestor)
-            return false;
-
-        if (next && next->renderer()->style()->position() == FixedPosition)
-            return true;
-        curr = next;
-    }
-    return false;
-}
-
 bool RenderLayerCompositor::requiresCompositingForScrollableFrame() const
 {
     // Need this done first to determine overflow.
index 67df631..8ded558 100644 (file)
@@ -154,9 +154,6 @@ public:
     // Whether layer's backing needs a graphics layer to clip z-order children of the given layer.
     bool clipsCompositingDescendants(const RenderLayer*) const;
 
-    // Whether the layer is fixed positioned to the view by an ancestor layer.
-    bool fixedPositionedByAncestor(const RenderLayer*) const;
-
     // Whether the given layer needs an extra 'contents' layer.
     bool needsContentsCompositingLayer(const RenderLayer*) const;