https://bugs.webkit.org/show_bug.cgi?id=101001
authorbdakin@apple.com <bdakin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 5 Nov 2012 23:31:58 +0000 (23:31 +0000)
committerbdakin@apple.com <bdakin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 5 Nov 2012 23:31:58 +0000 (23:31 +0000)
Pages with position:fixed elements should still be able to scroll on
the scrolling thread
-and corresponding-
<rdar://problem/10857315>

Reviewed by Simon Fraser.

Source/WebCore:

This patch adds two new classes. ScrollingStateFixedNode is a class
to represent fixed nodes in the state tree, and
ScrollingTreeFixedNode represents fixed node in the scrolling tree
over on the scrolling thread.
* WebCore.xcodeproj/project.pbxproj:

When we are (non-programatically) scrolling fixed objects on the
scrolling thread, we do not want to do any work here.
* page/FrameView.cpp:
(WebCore::FrameView::updateFixedElementsAfterScrolling):

Whenever we sync the position of the main frame's layer, we have to
do the same for scrolling tree children.
* page/scrolling/ScrollingCoordinator.cpp:
(WebCore::ScrollingCoordinator::updateMainFrameScrollPosition):

New ScrollingNodeType -- FixedNode, yay! And two new functions
specific to dealing with FixedNodes.
* page/scrolling/ScrollingCoordinator.h:
(WebCore::ScrollingCoordinator::updateViewportConstrainedNode):
(WebCore::ScrollingCoordinator::syncChildPositions):

This is the new class that represents fixed nodes in the state tree.
All of the changed properties are stored within
FixedPositionViewportConstraints.
* page/scrolling/ScrollingStateFixedNode.cpp: Added.
(WebCore):
(WebCore::ScrollingStateFixedNode::create):
(WebCore::ScrollingStateFixedNode::ScrollingStateFixedNode):
(WebCore::ScrollingStateFixedNode::~ScrollingStateFixedNode):
(WebCore::ScrollingStateFixedNode::updateConstraints):
(WebCore::ScrollingStateFixedNode::dumpProperties):
* page/scrolling/ScrollingStateFixedNode.h: Added.
(WebCore):
(ScrollingStateFixedNode):
(WebCore::ScrollingStateFixedNode::viewportConstraints):
(WebCore::toScrollingStateFixedNode):

Make sure to create the right type of clone for each node.
* page/scrolling/ScrollingStateNode.cpp:
(WebCore::ScrollingStateNode::cloneAndReset):

Now that m_children may be anything other than null, I found this
bug. We encounter it when the parameter to removeChild is this and we
want to remove all of our children. In that case, this is obviously
not found in its own child array.
(WebCore::ScrollingStateNode::removeChild):

ScrollingStateNode now caches the GraphicsLayer in addition to the
PlatformLayer. This will allow us to sync the GraphicsLayer position
at the appropriate times.
* page/scrolling/ScrollingStateNode.h:
(WebCore::ScrollingStateNode::isScrollingStateFixedNode):
(WebCore::ScrollingStateNode::graphicsLayer):
(ScrollingStateNode):

Handle fixed nodes.
* page/scrolling/ScrollingTree.cpp:
(WebCore::ScrollingTree::updateTreeFromStateNode):

New function parentScrollPositionDidChange() is called on children
when the parent has scrolled.
* page/scrolling/ScrollingTreeNode.h:
(ScrollingTreeNode):
* page/scrolling/ScrollingTreeScrollingNode.h:
(ScrollingTreeScrollingNode):

Return true for supportsFixedPositionLayers().
* page/scrolling/mac/ScrollingCoordinatorMac.h:
(ScrollingCoordinatorMac):

Handle fixed nodes.
* page/scrolling/mac/ScrollingCoordinatorMac.mm:
(WebCore::ScrollingCoordinatorMac::attachToStateTree):

Now that m_children can be non-null I caught this pre-existing bug
where we would come times remove a node without updating the HashMap.
This patch fixes that by consolidating the removal into one function.
(WebCore::ScrollingCoordinatorMac::removeNode):
(WebCore::ScrollingCoordinatorMac::detachFromStateTree):
(WebCore::ScrollingCoordinatorMac::clearStateTree):

Update the GraphicsLayers to reflect the new position that the
Scrolling thread has moved the underlying CALayer to already.
(WebCore::ScrollingCoordinatorMac::syncChildPositions):

Pass new constraints over to the appropriate state node.
(WebCore::ScrollingCoordinatorMac::updateViewportConstrainedNode):

Cache the GraphicsLayer in addition to the PlatformLayer.
* page/scrolling/mac/ScrollingStateNodeMac.mm:
(WebCore::ScrollingStateNode::setScrollLayer):

Here is the new class that represents fixed nodes over on the
scrolling thread.
* page/scrolling/mac/ScrollingTreeFixedNode.h: Added.
(WebCore):
(ScrollingTreeFixedNode):
* page/scrolling/mac/ScrollingTreeFixedNode.mm: Added.
(WebCore):
(WebCore::ScrollingTreeFixedNode::create):
(WebCore::ScrollingTreeFixedNode::ScrollingTreeFixedNode):
(WebCore::ScrollingTreeFixedNode::~ScrollingTreeFixedNode):
(WebCore::ScrollingTreeFixedNode::update):

This is where the magic happens. re-position the fixed object when
its parent has scrolled so that it appears to have not moved at all.
(WebCore::ScrollingTreeFixedNode::parentScrollPositionDidChange):

Whenever we change the position of a scrolling layer, tell our
children.
* page/scrolling/mac/ScrollingTreeScrollingNodeMac.mm:
(WebCore::ScrollingTreeScrollingNodeMac::setScrollLayerPosition):

Handle fixed nodes.
* rendering/RenderLayerBacking.cpp:
(WebCore::RenderLayerBacking::attachToScrollingCoordinator):

detachFromScrollingCoordinator() needs to be public so that it can be
called from RenderLayerCompositor for fixed nodes.
* rendering/RenderLayerBacking.h:
(RenderLayerBacking):

RenderLayerCompositor takes control of attaching and detaching fixed
nodes to/from the ScrollingCoordinator.
* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::flushPendingLayerChanges):
(WebCore::RenderLayerCompositor::didFlushChangesForLayer):
(WebCore::RenderLayerCompositor::updateBacking):
(WebCore::RenderLayerCompositor::layerWillBeRemoved):
(WebCore::RenderLayerCompositor::didMoveOnscreen):
(WebCore::RenderLayerCompositor::willMoveOffscreen):
(WebCore::RenderLayerCompositor::clearBackingForLayerIncludingDescendants):
(WebCore::isRootmostFixedOrStickyLayer):
(WebCore):
(WebCore::RenderLayerCompositor::updateViewportConstraintStatus):
(WebCore::RenderLayerCompositor::addViewportConstrainedLayer):
(WebCore::RenderLayerCompositor::removeViewportConstrainedLayer):
(WebCore::RenderLayerCompositor::computeViewportConstraints):
(WebCore::nearestScrollingCoordinatorAncestor):
(WebCore::RenderLayerCompositor::registerOrUpdateViewportConstrainedLayer):
(WebCore::RenderLayerCompositor::unregisterViewportConstrainedLayer):
(WebCore::RenderLayerCompositor::registerAllViewportConstrainedLayers):
(WebCore::RenderLayerCompositor::unregisterAllViewportConstrainedLayers):
* rendering/RenderLayerCompositor.h:
(WebCore):
(RenderLayerCompositor):

LayoutTests:

New tests.
* platform/mac/tiled-drawing/fixed: Added.
* platform/mac/tiled-drawing/fixed/absolute-inside-fixed-expected.txt: Added.
* platform/mac/tiled-drawing/fixed/absolute-inside-fixed.html: Added.
* platform/mac/tiled-drawing/fixed/fixed-position-out-of-view-expected.txt: Added.
* platform/mac/tiled-drawing/fixed/fixed-position-out-of-view-negative-zindex-expected.txt: Added.
* platform/mac/tiled-drawing/fixed/fixed-position-out-of-view-negative-zindex.html: Added.
* platform/mac/tiled-drawing/fixed/fixed-position-out-of-view.html: Added.
* platform/mac/tiled-drawing/fixed/four-bars-expected.txt: Added.
* platform/mac/tiled-drawing/fixed/four-bars.html: Added.
* platform/mac/tiled-drawing/fixed/nested-fixed-expected.txt: Added.
* platform/mac/tiled-drawing/fixed/nested-fixed.html: Added.
* platform/mac/tiled-drawing/fixed/percentage-inside-fixed-expected.txt: Added.
* platform/mac/tiled-drawing/fixed/percentage-inside-fixed.html: Added.

These two tests are supposed to be in "slow scrolling" mode. Now that
fixed elements can scroll "fast," we need something else to force
slow scrolling. We should probably just add something to
window.internals to do that, but in the meantime,
background-attachment:fixed will work.
* platform/mac/tiled-drawing/scrolling-tree-slow-scrolling-expected.txt:
* platform/mac/tiled-drawing/scrolling-tree-slow-scrolling.html:
* platform/mac/tiled-drawing/tile-coverage-slow-scrolling-expected.txt:
* platform/mac/tiled-drawing/tile-coverage-slow-scrolling.html:

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

46 files changed:
LayoutTests/ChangeLog
LayoutTests/platform/mac/tiled-drawing/fixed/absolute-inside-fixed-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/tiled-drawing/fixed/absolute-inside-fixed.html [new file with mode: 0644]
LayoutTests/platform/mac/tiled-drawing/fixed/fixed-in-overflow-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/tiled-drawing/fixed/fixed-in-overflow.html [new file with mode: 0644]
LayoutTests/platform/mac/tiled-drawing/fixed/fixed-position-out-of-view-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/tiled-drawing/fixed/fixed-position-out-of-view-negative-zindex-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/tiled-drawing/fixed/fixed-position-out-of-view-negative-zindex.html [new file with mode: 0644]
LayoutTests/platform/mac/tiled-drawing/fixed/fixed-position-out-of-view.html [new file with mode: 0644]
LayoutTests/platform/mac/tiled-drawing/fixed/four-bars-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/tiled-drawing/fixed/four-bars.html [new file with mode: 0644]
LayoutTests/platform/mac/tiled-drawing/fixed/nested-fixed-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/tiled-drawing/fixed/nested-fixed.html [new file with mode: 0644]
LayoutTests/platform/mac/tiled-drawing/fixed/percentage-inside-fixed-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/tiled-drawing/fixed/percentage-inside-fixed.html [new file with mode: 0644]
LayoutTests/platform/mac/tiled-drawing/scrolling-tree-slow-scrolling-expected.txt
LayoutTests/platform/mac/tiled-drawing/scrolling-tree-slow-scrolling.html
LayoutTests/platform/mac/tiled-drawing/tile-coverage-slow-scrolling-expected.txt
LayoutTests/platform/mac/tiled-drawing/tile-coverage-slow-scrolling.html
Source/WebCore/ChangeLog
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/page/FrameView.cpp
Source/WebCore/page/FrameView.h
Source/WebCore/page/scrolling/ScrollingConstraints.h
Source/WebCore/page/scrolling/ScrollingCoordinator.cpp
Source/WebCore/page/scrolling/ScrollingCoordinator.h
Source/WebCore/page/scrolling/ScrollingStateFixedNode.cpp [new file with mode: 0644]
Source/WebCore/page/scrolling/ScrollingStateFixedNode.h [new file with mode: 0644]
Source/WebCore/page/scrolling/ScrollingStateNode.cpp
Source/WebCore/page/scrolling/ScrollingStateNode.h
Source/WebCore/page/scrolling/ScrollingStateScrollingNode.cpp
Source/WebCore/page/scrolling/ScrollingStateScrollingNode.h
Source/WebCore/page/scrolling/ScrollingTree.cpp
Source/WebCore/page/scrolling/ScrollingTree.h
Source/WebCore/page/scrolling/ScrollingTreeNode.h
Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h
Source/WebCore/page/scrolling/mac/ScrollingCoordinatorMac.h
Source/WebCore/page/scrolling/mac/ScrollingCoordinatorMac.mm
Source/WebCore/page/scrolling/mac/ScrollingStateNodeMac.mm
Source/WebCore/page/scrolling/mac/ScrollingTreeFixedNode.h [new file with mode: 0644]
Source/WebCore/page/scrolling/mac/ScrollingTreeFixedNode.mm [new file with mode: 0644]
Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeMac.mm
Source/WebCore/rendering/RenderLayerBacking.cpp
Source/WebCore/rendering/RenderLayerBacking.h
Source/WebCore/rendering/RenderLayerCompositor.cpp
Source/WebCore/rendering/RenderLayerCompositor.h

index d6ca6d1..d0be6d0 100644 (file)
@@ -1,3 +1,38 @@
+2012-11-05  Beth Dakin  <bdakin@apple.com>
+
+        https://bugs.webkit.org/show_bug.cgi?id=101001
+        Pages with position:fixed elements should still be able to scroll on 
+        the scrolling thread
+        -and corresponding-
+        <rdar://problem/10857315>
+
+        Reviewed by Simon Fraser.
+
+        New tests.
+        * platform/mac/tiled-drawing/fixed: Added.
+        * platform/mac/tiled-drawing/fixed/absolute-inside-fixed-expected.txt: Added.
+        * platform/mac/tiled-drawing/fixed/absolute-inside-fixed.html: Added.
+        * platform/mac/tiled-drawing/fixed/fixed-position-out-of-view-expected.txt: Added.
+        * platform/mac/tiled-drawing/fixed/fixed-position-out-of-view-negative-zindex-expected.txt: Added.
+        * platform/mac/tiled-drawing/fixed/fixed-position-out-of-view-negative-zindex.html: Added.
+        * platform/mac/tiled-drawing/fixed/fixed-position-out-of-view.html: Added.
+        * platform/mac/tiled-drawing/fixed/four-bars-expected.txt: Added.
+        * platform/mac/tiled-drawing/fixed/four-bars.html: Added.
+        * platform/mac/tiled-drawing/fixed/nested-fixed-expected.txt: Added.
+        * platform/mac/tiled-drawing/fixed/nested-fixed.html: Added.
+        * platform/mac/tiled-drawing/fixed/percentage-inside-fixed-expected.txt: Added.
+        * platform/mac/tiled-drawing/fixed/percentage-inside-fixed.html: Added.
+
+        These two tests are supposed to be in "slow scrolling" mode. Now that 
+        fixed elements can scroll "fast," we need something else to force 
+        slow scrolling. We should probably just add something to 
+        window.internals to do that, but in the meantime, 
+        background-attachment:fixed will work.
+        * platform/mac/tiled-drawing/scrolling-tree-slow-scrolling-expected.txt:
+        * platform/mac/tiled-drawing/scrolling-tree-slow-scrolling.html:
+        * platform/mac/tiled-drawing/tile-coverage-slow-scrolling-expected.txt:
+        * platform/mac/tiled-drawing/tile-coverage-slow-scrolling.html:
+
 2012-11-05  Alice Boxhall  <aboxhall@chromium.org>
 
         Unreviewed gardening. Mark fonts/cursive.html as flaky on MountainLion as well as Lion.
diff --git a/LayoutTests/platform/mac/tiled-drawing/fixed/absolute-inside-fixed-expected.txt b/LayoutTests/platform/mac/tiled-drawing/fixed/absolute-inside-fixed-expected.txt
new file mode 100644 (file)
index 0000000..3eef04f
--- /dev/null
@@ -0,0 +1,13 @@
+(Scrolling node
+  (viewport rect 0 0 785 600)
+  (contents size 785 2710)
+  (requested scroll position 0 200)
+  (children 1
+    (Fixed node
+      (anchor edges: AnchorEdgeLeft AnchorEdgeTop)
+      (viewport rect at last layout: 0.00 200.00 785.00 600.00)
+      (layer position at last layout 8.00 8.00)
+    )
+  )
+)
+
diff --git a/LayoutTests/platform/mac/tiled-drawing/fixed/absolute-inside-fixed.html b/LayoutTests/platform/mac/tiled-drawing/fixed/absolute-inside-fixed.html
new file mode 100644 (file)
index 0000000..c990188
--- /dev/null
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <style>
+        body {
+            margin: 0;
+            height: 2500px;
+        }
+
+        .box {
+          height: 100px;
+          width: 100px;
+        }
+
+        .outer {
+            position: fixed;
+            left: 10px;
+            top: 10px;
+            width: 100px;
+            height: 100px;
+            outline: 2px solid black;
+        }
+
+        .wrapper {
+          position: absolute;
+          background-color: green;
+        }
+        
+        .indicator {
+          margin-left: 10px;
+          margin-top: 210px;
+          background-color: red;
+        }
+    </style>
+    <script>
+      if (window.testRunner) {
+        testRunner.waitUntilDone();
+        testRunner.dumpAsText();
+      }
+
+      function doScroll()
+      {
+        window.setTimeout(function() {
+          window.scrollTo(0, 200);
+          if (window.internals) {
+            document.getElementById('results').innerText = internals.scrollingStateTreeAsText(document);
+            testRunner.notifyDone();
+          }
+        }, 10);
+      }
+      
+      window.addEventListener('load', doScroll, false);
+    </script>
+</head>
+<body>
+  <!-- The green box should obscure the red box -->
+  <pre id="results"></pre>
+  <div class="indicator box"></div>
+  <div class="outer box">
+    <div class="wrapper box">
+    </div>
+  </div>
+</body>
+</html>
diff --git a/LayoutTests/platform/mac/tiled-drawing/fixed/fixed-in-overflow-expected.txt b/LayoutTests/platform/mac/tiled-drawing/fixed/fixed-in-overflow-expected.txt
new file mode 100644 (file)
index 0000000..ab8e2e6
--- /dev/null
@@ -0,0 +1,13 @@
+(Scrolling node
+  (viewport rect 0 0 785 600)
+  (contents size 785 2213)
+  (requested scroll position 0 200)
+  (children 1
+    (Fixed node
+      (anchor edges: AnchorEdgeLeft AnchorEdgeTop)
+      (viewport rect at last layout: 0.00 200.00 785.00 600.00)
+      (layer position at last layout 2.00 15.00)
+    )
+  )
+)
+
diff --git a/LayoutTests/platform/mac/tiled-drawing/fixed/fixed-in-overflow.html b/LayoutTests/platform/mac/tiled-drawing/fixed/fixed-in-overflow.html
new file mode 100644 (file)
index 0000000..7c4614b
--- /dev/null
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <style type="text/css" media="screen">
+        body {
+            margin: 0;
+            height: 2200px;
+        }
+
+        .scrolly {
+            overflow: scroll;
+            width:200px;
+            height:200px;
+            border: 2px solid black;
+        }
+        
+        .big {
+            border:1px solid purple;
+            height: 500px;
+            width:50px;
+        }
+
+        .fixed {
+            height: 100px;
+            width: 100px;
+            position: fixed;
+            background: green;
+        }
+    </style>
+    <script type="text/javascript" charset="utf-8">
+      if (window.testRunner) {
+        testRunner.waitUntilDone();
+        testRunner.dumpAsText();
+      }
+
+      function doScroll()
+      {
+        window.setTimeout(function() {
+        window.scrollTo(0, 200);
+          if (window.testRunner) {
+            document.getElementById('results').innerText = window.internals.scrollingStateTreeAsText(document);
+            testRunner.notifyDone();
+          }
+        }, 10);
+      }
+      
+      window.addEventListener('load', doScroll, false);
+    </script>
+</head>
+<body>
+    <pre id="results"></pre>
+    <div class="scrolly">
+        <div class="fixed"></div>
+        <div class="big"></div>
+    </div>
+</body>
+</html>
diff --git a/LayoutTests/platform/mac/tiled-drawing/fixed/fixed-position-out-of-view-expected.txt b/LayoutTests/platform/mac/tiled-drawing/fixed/fixed-position-out-of-view-expected.txt
new file mode 100644 (file)
index 0000000..6c39844
--- /dev/null
@@ -0,0 +1,12 @@
+(Scrolling node
+  (viewport rect 0 0 785 600)
+  (contents size 785 1021)
+  (Scrolling on main thread because: Has non-layer fixed objects, )
+  (children 1
+    (Fixed node
+      (anchor edges: AnchorEdgeLeft AnchorEdgeTop)
+      (viewport rect at last layout: 0.00 0.00 785.00 600.00)
+    )
+  )
+)
+
diff --git a/LayoutTests/platform/mac/tiled-drawing/fixed/fixed-position-out-of-view-negative-zindex-expected.txt b/LayoutTests/platform/mac/tiled-drawing/fixed/fixed-position-out-of-view-negative-zindex-expected.txt
new file mode 100644 (file)
index 0000000..6c39844
--- /dev/null
@@ -0,0 +1,12 @@
+(Scrolling node
+  (viewport rect 0 0 785 600)
+  (contents size 785 1021)
+  (Scrolling on main thread because: Has non-layer fixed objects, )
+  (children 1
+    (Fixed node
+      (anchor edges: AnchorEdgeLeft AnchorEdgeTop)
+      (viewport rect at last layout: 0.00 0.00 785.00 600.00)
+    )
+  )
+)
+
diff --git a/LayoutTests/platform/mac/tiled-drawing/fixed/fixed-position-out-of-view-negative-zindex.html b/LayoutTests/platform/mac/tiled-drawing/fixed/fixed-position-out-of-view-negative-zindex.html
new file mode 100644 (file)
index 0000000..ba57534
--- /dev/null
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+  <style>
+    .fixed {
+      position: fixed;
+      width: 10px;
+      height: 10px;
+    }
+  </style>
+
+  <script type="text/javascript">
+    if (window.testRunner) {
+      testRunner.dumpAsText();
+      testRunner.waitUntilDone();
+
+      window.addEventListener("load", function() {
+        window.setTimeout(function() {
+          document.getElementById("scrollingTree").innerText = window.internals.scrollingStateTreeAsText(document);
+          testRunner.notifyDone();
+        }, 10);
+      }, false);
+    }
+  </script>
+</head>
+
+<body>
+  <div style="height: 1000px">
+    <pre id="scrollingTree"></pre>
+  </div>
+
+  <div class="fixed" style="z-index: -1; top: -100px"></div>
+  <div class="fixed" style="z-index: -1; top: 0px; left: 1000px"></div>
+
+  <div class="fixed" style="top: 0px; left: 0px"></div>
+</body>
+</html>
+
diff --git a/LayoutTests/platform/mac/tiled-drawing/fixed/fixed-position-out-of-view.html b/LayoutTests/platform/mac/tiled-drawing/fixed/fixed-position-out-of-view.html
new file mode 100644 (file)
index 0000000..344788b
--- /dev/null
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+  <style>
+    .fixed {
+      position: fixed;
+      width: 10px;
+      height: 10px;
+    }
+  </style>
+
+  <script type="text/javascript">
+        if (window.testRunner)
+            testRunner.dumpAsText();
+
+        function doTest()
+        {
+            if (window.internals) {
+                document.getElementById('scrollingTree').innerText = internals.scrollingStateTreeAsText(document);
+            }
+        }
+        window.addEventListener('load', doTest, false);
+  </script>
+</head>
+
+<body>
+  <div style="height: 1000px">
+    <pre id="scrollingTree"></pre>
+  </div>
+
+  <div class="fixed" style="top: -100px"></div>
+  <div class="fixed" style="top: 0px; left: 1000px"></div>
+
+  <div class="fixed" style="top: 0px; left: 0px"></div>
+</body>
+</html>
+
diff --git a/LayoutTests/platform/mac/tiled-drawing/fixed/four-bars-expected.txt b/LayoutTests/platform/mac/tiled-drawing/fixed/four-bars-expected.txt
new file mode 100644 (file)
index 0000000..5c44ecb
--- /dev/null
@@ -0,0 +1,27 @@
+(Scrolling node
+  (viewport rect 0 0 785 600)
+  (contents size 785 2221)
+  (requested scroll position 0 200)
+  (children 4
+    (Fixed node
+      (anchor edges: AnchorEdgeLeft AnchorEdgeTop)
+      (viewport rect at last layout: 0.00 200.00 785.00 600.00)
+    )
+    (Fixed node
+      (anchor edges: AnchorEdgeLeft AnchorEdgeTop)
+      (viewport rect at last layout: 0.00 200.00 785.00 600.00)
+      (layer position at last layout 10.00 200.00)
+    )
+    (Fixed node
+      (anchor edges: AnchorEdgeRight AnchorEdgeTop)
+      (viewport rect at last layout: 0.00 200.00 785.00 600.00)
+      (layer position at last layout 601.00 200.00)
+    )
+    (Fixed node
+      (anchor edges: AnchorEdgeLeft AnchorEdgeBottom)
+      (viewport rect at last layout: 0.00 200.00 785.00 600.00)
+      (layer position at last layout 0.00 516.00)
+    )
+  )
+)
+This is the top bar. This is the left bar. This is the right bar. This is the bottom bar.
diff --git a/LayoutTests/platform/mac/tiled-drawing/fixed/four-bars.html b/LayoutTests/platform/mac/tiled-drawing/fixed/four-bars.html
new file mode 100644 (file)
index 0000000..de7af57
--- /dev/null
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <meta name="apple-mobile-web-app-capable" content="yes">
+    <style type="text/css" media="screen">
+      body {
+        height: 2200px;
+      }
+      
+      .fixed {
+        position: fixed;
+        top: 0;
+        left: 0;
+        margin: 10px;
+        height: 50px;
+        background-color: rgba(0, 128, 0, 0.8);
+        border: 2px solid black;
+        -webkit-box-shadow: 0 0 10px black;
+      }
+      
+      .top, .bottom {
+        width: 96%;
+      }
+
+      .left {
+        top: 200px;
+        left: 10px;
+        width: 150px;
+        height: 300px;
+      }
+
+      .right {
+        top: 200px;
+        left: auto;
+        right: 10px;
+        width: 150px;
+        height: 300px;
+      }
+      
+      .bottom {
+        top: auto;
+        bottom: 10px;
+      }
+      
+    </style>
+    <script type="text/javascript" charset="utf-8">
+      if (window.testRunner) {
+        testRunner.waitUntilDone();
+        testRunner.dumpAsText();
+      }
+
+      function doScroll()
+      {
+        window.setTimeout(function() {
+          window.scrollTo(0, 200);
+          if (window.testRunner) {
+            document.getElementById('results').innerText = window.internals.scrollingStateTreeAsText(document);
+            testRunner.notifyDone();
+          }
+        }, 10);
+      }
+      
+      window.addEventListener('load', doScroll, false);
+    </script>
+</head>
+<body>
+
+<pre id="results"></pre>
+
+<div class="fixed top">
+  This is the top bar.
+</div>
+<div class="fixed left">
+  This is the left bar.
+</div>
+<div class="fixed right">
+  This is the right bar.
+</div>
+<div class="fixed bottom">
+  This is the bottom bar.
+</div>
+
+</body>
+</html>
diff --git a/LayoutTests/platform/mac/tiled-drawing/fixed/nested-fixed-expected.txt b/LayoutTests/platform/mac/tiled-drawing/fixed/nested-fixed-expected.txt
new file mode 100644 (file)
index 0000000..e26173d
--- /dev/null
@@ -0,0 +1,12 @@
+(Scrolling node
+  (viewport rect 0 0 785 600)
+  (contents size 785 2213)
+  (requested scroll position 0 200)
+  (children 1
+    (Fixed node
+      (anchor edges: AnchorEdgeLeft AnchorEdgeTop)
+      (viewport rect at last layout: 0.00 200.00 785.00 600.00)
+    )
+  )
+)
+
diff --git a/LayoutTests/platform/mac/tiled-drawing/fixed/nested-fixed.html b/LayoutTests/platform/mac/tiled-drawing/fixed/nested-fixed.html
new file mode 100644 (file)
index 0000000..009d0a5
--- /dev/null
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <style type="text/css" media="screen">
+        body {
+            margin: 0;
+            height: 2200px;
+        }
+
+        .box {
+          height: 100px;
+          width: 100px;
+        }
+
+        .outer {
+            position: fixed;
+            top: 0px;
+            z-index: 1; /* makes this a stacking context */
+            background: blue;
+        }
+
+        .inner {
+            position: fixed;
+            top: 120px;
+            left: 120px;
+            background: green;
+        }
+    </style>
+    <script type="text/javascript" charset="utf-8">
+      if (window.testRunner) {
+        testRunner.waitUntilDone();
+        testRunner.dumpAsText();
+      }
+
+      function doScroll()
+      {
+        window.setTimeout(function() {
+          window.scrollTo(0, 200);
+          if (window.testRunner) {
+            document.getElementById('results').innerText = window.internals.scrollingStateTreeAsText(document);
+            testRunner.notifyDone();
+          }
+        }, 10);
+      }
+      
+      window.addEventListener('load', doScroll, false);
+    </script>
+</head>
+<body>
+    <pre id="results"></pre>
+    <div class="outer box">
+        <div class="inner box"></div>
+    </div>
+</body>
+</html>
diff --git a/LayoutTests/platform/mac/tiled-drawing/fixed/percentage-inside-fixed-expected.txt b/LayoutTests/platform/mac/tiled-drawing/fixed/percentage-inside-fixed-expected.txt
new file mode 100644 (file)
index 0000000..69280bf
--- /dev/null
@@ -0,0 +1,13 @@
+(Scrolling node
+  (viewport rect 0 0 785 600)
+  (contents size 785 2513)
+  (requested scroll position 0 200)
+  (children 1
+    (Fixed node
+      (anchor edges: AnchorEdgeLeft AnchorEdgeTop)
+      (viewport rect at last layout: 0.00 200.00 785.00 600.00)
+      (layer position at last layout 0.00 13.00)
+    )
+  )
+)
+
diff --git a/LayoutTests/platform/mac/tiled-drawing/fixed/percentage-inside-fixed.html b/LayoutTests/platform/mac/tiled-drawing/fixed/percentage-inside-fixed.html
new file mode 100644 (file)
index 0000000..a3f89cb
--- /dev/null
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <style>
+        body {
+            margin: 0;
+            height: 2500px;
+        }
+
+        .box {
+          height: 100px;
+          width: 100px;
+        }
+
+        .wrapper {
+          position: fixed;
+          width: 50%;
+          height: 50%;
+          border: 20px solid gray;
+          background-color: silver;
+          z-index: 0;
+        }
+
+        .inner {
+            position: relative;
+            margin-left:-50px;
+            margin-top:-100px;
+            top: 100%;
+            left: 50%;
+            background: green;
+        }
+    </style>
+    <script>
+      if (window.testRunner) {
+        testRunner.waitUntilDone();
+        testRunner.dumpAsText();
+      }
+
+      function doScroll()
+      {
+        window.setTimeout(function() {
+          window.scrollTo(0, 200);
+          if (window.testRunner) {
+            document.getElementById('results').innerText = window.internals.scrollingStateTreeAsText(document);
+            testRunner.notifyDone();
+          }
+        }, 10);
+      }
+      
+      window.addEventListener('load', doScroll, false);
+    </script>
+</head>
+<body>
+    <!-- The gray box should take up the top left quadrant of the web area.
+         The green box should be aligned with the inside edge of the paler gray box, in the bottom middle.
+    -->
+    <pre id="results"></pre>
+    <div class="wrapper">
+      <div class="inner box"></div>
+    </div>
+</body>
+</html>
index 7db6087..be4080c 100644 (file)
@@ -1,6 +1,6 @@
 (Scrolling node
   (viewport rect 0 0 800 600)
   (contents size 800 600)
-  (Scrolling on main thread because: Has viewport constrained objects without supporting fixed layers, )
+  (Scrolling on main thread because: Has slow repaint objects, )
 )
 
index 924ff4c..65a11b7 100644 (file)
@@ -6,7 +6,8 @@
         .box {
             height: 100px;
             width: 100px;
-            position: fixed; /* At this time, position:fixed forces slow mode. */
+            background-image: -webkit-repeating-linear-gradient(red 10%, green 10%, green 30%);
+            background-attachment: fixed; /* At this time, background-attachment:fixed forces slow mode. */
         }
     </style>
     <script>
index 769693b..7452929 100644 (file)
       (children 1
         (GraphicsLayer
           (visible rect 0.00, 0.00 0.00 x 0.00)
-          (children 1
-            (GraphicsLayer
-              (position 8.00 13.00)
-              (bounds 100.00 100.00)
-              (visible rect 0.00, 0.00 100.00 x 100.00)
-            )
-          )
         )
       )
     )
index 3faf9cf..437d1de 100644 (file)
@@ -6,7 +6,8 @@
         .box {
             height: 100px;
             width: 100px;
-            position: fixed; /* At this time, position:fixed forces slow mode. */
+            background-image: -webkit-repeating-linear-gradient(red 10%, green 10%, green 30%);
+            background-attachment: fixed; /* At this time, background-attachment:fixed forces slow mode. */
         }
     </style>
     <script>
index c45aca8..3fd7e6f 100644 (file)
@@ -1,3 +1,161 @@
+2012-11-05  Beth Dakin  <bdakin@apple.com>
+
+        https://bugs.webkit.org/show_bug.cgi?id=101001
+        Pages with position:fixed elements should still be able to scroll on 
+        the scrolling thread
+        -and corresponding-
+        <rdar://problem/10857315>
+
+        Reviewed by Simon Fraser.
+
+        This patch adds two new classes. ScrollingStateFixedNode is a class 
+        to represent fixed nodes in the state tree, and 
+        ScrollingTreeFixedNode represents fixed node in the scrolling tree 
+        over on the scrolling thread.
+        * WebCore.xcodeproj/project.pbxproj:
+
+        When we are (non-programatically) scrolling fixed objects on the 
+        scrolling thread, we do not want to do any work here. 
+        * page/FrameView.cpp:
+        (WebCore::FrameView::updateFixedElementsAfterScrolling):
+
+        Whenever we sync the position of the main frame's layer, we have to 
+        do the same for scrolling tree children.
+        * page/scrolling/ScrollingCoordinator.cpp:
+        (WebCore::ScrollingCoordinator::updateMainFrameScrollPosition):
+
+        New ScrollingNodeType -- FixedNode, yay! And two new functions 
+        specific to dealing with FixedNodes.
+        * page/scrolling/ScrollingCoordinator.h:
+        (WebCore::ScrollingCoordinator::updateViewportConstrainedNode):
+        (WebCore::ScrollingCoordinator::syncChildPositions):
+
+        This is the new class that represents fixed nodes in the state tree. 
+        All of the changed properties are stored within 
+        FixedPositionViewportConstraints.
+        * page/scrolling/ScrollingStateFixedNode.cpp: Added.
+        (WebCore):
+        (WebCore::ScrollingStateFixedNode::create):
+        (WebCore::ScrollingStateFixedNode::ScrollingStateFixedNode):
+        (WebCore::ScrollingStateFixedNode::~ScrollingStateFixedNode):
+        (WebCore::ScrollingStateFixedNode::updateConstraints):
+        (WebCore::ScrollingStateFixedNode::dumpProperties):
+        * page/scrolling/ScrollingStateFixedNode.h: Added.
+        (WebCore):
+        (ScrollingStateFixedNode):
+        (WebCore::ScrollingStateFixedNode::viewportConstraints):
+        (WebCore::toScrollingStateFixedNode):
+
+        Make sure to create the right type of clone for each node.
+        * page/scrolling/ScrollingStateNode.cpp:
+        (WebCore::ScrollingStateNode::cloneAndReset):
+
+        Now that m_children may be anything other than null, I found this 
+        bug. We encounter it when the parameter to removeChild is this and we 
+        want to remove all of our children. In that case, this is obviously 
+        not found in its own child array.
+        (WebCore::ScrollingStateNode::removeChild):
+
+        ScrollingStateNode now caches the GraphicsLayer in addition to the 
+        PlatformLayer. This will allow us to sync the GraphicsLayer position 
+        at the appropriate times.
+        * page/scrolling/ScrollingStateNode.h:
+        (WebCore::ScrollingStateNode::isScrollingStateFixedNode):
+        (WebCore::ScrollingStateNode::graphicsLayer):
+        (ScrollingStateNode):
+
+        Handle fixed nodes.
+        * page/scrolling/ScrollingTree.cpp:
+        (WebCore::ScrollingTree::updateTreeFromStateNode):
+
+        New function parentScrollPositionDidChange() is called on children 
+        when the parent has scrolled.
+        * page/scrolling/ScrollingTreeNode.h:
+        (ScrollingTreeNode):
+        * page/scrolling/ScrollingTreeScrollingNode.h:
+        (ScrollingTreeScrollingNode):
+
+        Return true for supportsFixedPositionLayers(). 
+        * page/scrolling/mac/ScrollingCoordinatorMac.h:
+        (ScrollingCoordinatorMac):
+
+        Handle fixed nodes.
+        * page/scrolling/mac/ScrollingCoordinatorMac.mm:
+        (WebCore::ScrollingCoordinatorMac::attachToStateTree):
+
+        Now that m_children can be non-null I caught this pre-existing bug 
+        where we would come times remove a node without updating the HashMap. 
+        This patch fixes that by consolidating the removal into one function.
+        (WebCore::ScrollingCoordinatorMac::removeNode):
+        (WebCore::ScrollingCoordinatorMac::detachFromStateTree):
+        (WebCore::ScrollingCoordinatorMac::clearStateTree):
+
+        Update the GraphicsLayers to reflect the new position that the 
+        Scrolling thread has moved the underlying CALayer to already.
+        (WebCore::ScrollingCoordinatorMac::syncChildPositions):
+
+        Pass new constraints over to the appropriate state node.
+        (WebCore::ScrollingCoordinatorMac::updateViewportConstrainedNode):
+
+        Cache the GraphicsLayer in addition to the PlatformLayer.
+        * page/scrolling/mac/ScrollingStateNodeMac.mm:
+        (WebCore::ScrollingStateNode::setScrollLayer):
+
+        Here is the new class that represents fixed nodes over on the 
+        scrolling thread. 
+        * page/scrolling/mac/ScrollingTreeFixedNode.h: Added.
+        (WebCore):
+        (ScrollingTreeFixedNode):
+        * page/scrolling/mac/ScrollingTreeFixedNode.mm: Added.
+        (WebCore):
+        (WebCore::ScrollingTreeFixedNode::create):
+        (WebCore::ScrollingTreeFixedNode::ScrollingTreeFixedNode):
+        (WebCore::ScrollingTreeFixedNode::~ScrollingTreeFixedNode):
+        (WebCore::ScrollingTreeFixedNode::update):
+
+        This is where the magic happens. re-position the fixed object when 
+        its parent has scrolled so that it appears to have not moved at all.
+        (WebCore::ScrollingTreeFixedNode::parentScrollPositionDidChange):
+
+        Whenever we change the position of a scrolling layer, tell our 
+        children.
+        * page/scrolling/mac/ScrollingTreeScrollingNodeMac.mm:
+        (WebCore::ScrollingTreeScrollingNodeMac::setScrollLayerPosition):
+
+        Handle fixed nodes.
+        * rendering/RenderLayerBacking.cpp:
+        (WebCore::RenderLayerBacking::attachToScrollingCoordinator):
+
+        detachFromScrollingCoordinator() needs to be public so that it can be 
+        called from RenderLayerCompositor for fixed nodes.
+        * rendering/RenderLayerBacking.h:
+        (RenderLayerBacking):
+
+        RenderLayerCompositor takes control of attaching and detaching fixed 
+        nodes to/from the ScrollingCoordinator. 
+        * rendering/RenderLayerCompositor.cpp:
+        (WebCore::RenderLayerCompositor::flushPendingLayerChanges):
+        (WebCore::RenderLayerCompositor::didFlushChangesForLayer):
+        (WebCore::RenderLayerCompositor::updateBacking):
+        (WebCore::RenderLayerCompositor::layerWillBeRemoved):
+        (WebCore::RenderLayerCompositor::didMoveOnscreen):
+        (WebCore::RenderLayerCompositor::willMoveOffscreen):
+        (WebCore::RenderLayerCompositor::clearBackingForLayerIncludingDescendants):
+        (WebCore::isRootmostFixedOrStickyLayer):
+        (WebCore):
+        (WebCore::RenderLayerCompositor::updateViewportConstraintStatus):
+        (WebCore::RenderLayerCompositor::addViewportConstrainedLayer):
+        (WebCore::RenderLayerCompositor::removeViewportConstrainedLayer):
+        (WebCore::RenderLayerCompositor::computeViewportConstraints):
+        (WebCore::nearestScrollingCoordinatorAncestor):
+        (WebCore::RenderLayerCompositor::registerOrUpdateViewportConstrainedLayer):
+        (WebCore::RenderLayerCompositor::unregisterViewportConstrainedLayer):
+        (WebCore::RenderLayerCompositor::registerAllViewportConstrainedLayers):
+        (WebCore::RenderLayerCompositor::unregisterAllViewportConstrainedLayers):
+        * rendering/RenderLayerCompositor.h:
+        (WebCore):
+        (RenderLayerCompositor):
+
 2012-11-05  Geoffrey Garen  <ggaren@apple.com>
 
         Cleaned up the Font class in preparation for optimizing kerning and ligatures
index fe18f29..c712a12 100644 (file)
                93C09A7F0B064EEF005ABD4D /* EventHandlerMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 93C09A7E0B064EEF005ABD4D /* EventHandlerMac.mm */; };
                93C09A810B064F00005ABD4D /* EventHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93C09A800B064F00005ABD4D /* EventHandler.cpp */; };
                93C09C860B0657AA005ABD4D /* ScrollTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 93C09C850B0657AA005ABD4D /* ScrollTypes.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               93C38BFE164473C700091EB2 /* ScrollingStateFixedNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93C38BFC164473C700091EB2 /* ScrollingStateFixedNode.cpp */; };
+               93C38BFF164473C700091EB2 /* ScrollingStateFixedNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 93C38BFD164473C700091EB2 /* ScrollingStateFixedNode.h */; };
+               93C38C03164473DD00091EB2 /* ScrollingTreeFixedNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 93C38C01164473DD00091EB2 /* ScrollingTreeFixedNode.h */; };
+               93C38C04164473DD00091EB2 /* ScrollingTreeFixedNode.mm in Sources */ = {isa = PBXBuildFile; fileRef = 93C38C02164473DD00091EB2 /* ScrollingTreeFixedNode.mm */; };
                93C442000F813AE100C1A634 /* CollectionType.h in Headers */ = {isa = PBXBuildFile; fileRef = 93C441FF0F813AE100C1A634 /* CollectionType.h */; settings = {ATTRIBUTES = (Private, ); }; };
                93C4A4151629DF5A00C3EB6E /* ScrollingTreeScrollingNodeMac.h in Headers */ = {isa = PBXBuildFile; fileRef = 93C4A4131629DF5A00C3EB6E /* ScrollingTreeScrollingNodeMac.h */; };
                93C4A4161629DF5A00C3EB6E /* ScrollingTreeScrollingNodeMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 93C4A4141629DF5A00C3EB6E /* ScrollingTreeScrollingNodeMac.mm */; };
                93C09A7E0B064EEF005ABD4D /* EventHandlerMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = EventHandlerMac.mm; sourceTree = "<group>"; };
                93C09A800B064F00005ABD4D /* EventHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EventHandler.cpp; sourceTree = "<group>"; };
                93C09C850B0657AA005ABD4D /* ScrollTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScrollTypes.h; sourceTree = "<group>"; };
+               93C38BFC164473C700091EB2 /* ScrollingStateFixedNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScrollingStateFixedNode.cpp; sourceTree = "<group>"; };
+               93C38BFD164473C700091EB2 /* ScrollingStateFixedNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScrollingStateFixedNode.h; sourceTree = "<group>"; };
+               93C38C01164473DD00091EB2 /* ScrollingTreeFixedNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScrollingTreeFixedNode.h; sourceTree = "<group>"; };
+               93C38C02164473DD00091EB2 /* ScrollingTreeFixedNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ScrollingTreeFixedNode.mm; sourceTree = "<group>"; };
                93C441FF0F813AE100C1A634 /* CollectionType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CollectionType.h; sourceTree = "<group>"; };
                93C4A4131629DF5A00C3EB6E /* ScrollingTreeScrollingNodeMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScrollingTreeScrollingNodeMac.h; sourceTree = "<group>"; };
                93C4A4141629DF5A00C3EB6E /* ScrollingTreeScrollingNodeMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ScrollingTreeScrollingNodeMac.mm; sourceTree = "<group>"; };
                                0F605AEB15F94848004DF0C0 /* ScrollingConstraints.h */,
                                1AF62EE414DA22A70041556C /* ScrollingCoordinator.cpp */,
                                1AF62EE514DA22A70041556C /* ScrollingCoordinator.h */,
+                               93C38BFC164473C700091EB2 /* ScrollingStateFixedNode.cpp */,
+                               93C38BFD164473C700091EB2 /* ScrollingStateFixedNode.h */,
                                931CBD06161A44E900E4C874 /* ScrollingStateNode.cpp */,
                                931CBD07161A44E900E4C874 /* ScrollingStateNode.h */,
                                931CBD08161A44E900E4C874 /* ScrollingStateScrollingNode.cpp */,
                                1AF62EE314DA22A70041556C /* ScrollingCoordinatorMac.mm */,
                                931CBD12161A44F800E4C874 /* ScrollingStateNodeMac.mm */,
                                1AF62F2314DAFE910041556C /* ScrollingThreadMac.mm */,
+                               93C38C01164473DD00091EB2 /* ScrollingTreeFixedNode.h */,
+                               93C38C02164473DD00091EB2 /* ScrollingTreeFixedNode.mm */,
                                1A35862A152522540022A659 /* ScrollingTreeMac.mm */,
                                93C4A4131629DF5A00C3EB6E /* ScrollingTreeScrollingNodeMac.h */,
                                93C4A4141629DF5A00C3EB6E /* ScrollingTreeScrollingNodeMac.mm */,
                                50933350163B0E4300099A60 /* CustomFilterParameterList.h in Headers */,
                                50D32858163B313F0016111E /* ValidatedCustomFilterOperation.h in Headers */,
                                3FFFF9A9159D9A550020BBD5 /* WebKitCSSViewportRule.h in Headers */,
+                               93C38BFF164473C700091EB2 /* ScrollingStateFixedNode.h in Headers */,
+                               93C38C03164473DD00091EB2 /* ScrollingTreeFixedNode.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                3FFFF9A8159D9A550020BBD5 /* WebKitCSSViewportRule.cpp in Sources */,
                                4FFC022B1643B710004E1638 /* NodeRareData.cpp in Sources */,
                                4FFC022D1643B726004E1638 /* ElementRareData.cpp in Sources */,
+                               93C38BFE164473C700091EB2 /* ScrollingStateFixedNode.cpp in Sources */,
+                               93C38C04164473DD00091EB2 /* ScrollingTreeFixedNode.mm in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 30d6ef5..c9fca43 100644 (file)
@@ -1845,13 +1845,44 @@ void FrameView::repaintFixedElementsAfterScrolling()
     }
 }
 
+bool FrameView::shouldUpdateFixedElementsAfterScrolling()
+{
+#if ENABLE(THREADED_SCROLLING)
+    Page* page = m_frame->page();
+    if (!page)
+        return true;
+
+    // If the scrolling thread is updating the fixed elements, then the FrameView should not update them as well.
+    if (page->mainFrame() != m_frame)
+        return true;
+
+    ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator();
+    if (!scrollingCoordinator)
+        return true;
+
+    if (!scrollingCoordinator->supportsFixedPositionLayers())
+        return true;
+
+    if (scrollingCoordinator->shouldUpdateScrollLayerPositionOnMainThread())
+        return true;
+
+    if (inProgrammaticScroll())
+        return true;
+
+    return false;
+#endif
+    return true;
+}
+
 void FrameView::updateFixedElementsAfterScrolling()
 {
 #if USE(ACCELERATED_COMPOSITING)
+    if (!shouldUpdateFixedElementsAfterScrolling())
+        return;
+
     if (m_nestedLayoutCount <= 1 && hasViewportConstrainedObjects()) {
-        if (RenderView* root = rootRenderer(this)) {
+        if (RenderView* root = rootRenderer(this))
             root->compositor()->updateCompositingLayers(CompositingUpdateOnScroll);
-        }
     }
 #endif
 }
index 545e22b..c2d7e2b 100644 (file)
@@ -390,6 +390,8 @@ private:
     void updateCanBlitOnScrollRecursively();
     bool contentsInCompositedLayer() const;
 
+    bool shouldUpdateFixedElementsAfterScrolling();
+
     void applyOverflowToViewport(RenderObject*, ScrollbarMode& hMode, ScrollbarMode& vMode);
     void applyPaginationToViewport();
 
index 70b974a..e5d04bd 100644 (file)
@@ -46,15 +46,6 @@ public:
         AnchorEdgeBottom = 1 << 3
     };
     typedef unsigned AnchorEdges;
-    
-    ViewportConstraints()
-        : m_anchorEdges(0)
-    { }
-
-    ViewportConstraints(ViewportConstraints* constraints)
-        : m_alignmentOffset(constraints->alignmentOffset())
-        , m_anchorEdges(constraints->anchorEdges())
-    { }
 
     virtual ~ViewportConstraints() { }
     
@@ -69,6 +60,15 @@ public:
     void setAlignmentOffset(const FloatSize& offset) { m_alignmentOffset = offset; }
 
 protected:
+    ViewportConstraints()
+        : m_anchorEdges(0)
+    { }
+
+    ViewportConstraints(const ViewportConstraints& constraints)
+        : m_alignmentOffset(constraints.alignmentOffset())
+        , m_anchorEdges(constraints.anchorEdges())
+    { }
+
     FloatSize m_alignmentOffset;
     AnchorEdges m_anchorEdges;
 };
@@ -78,10 +78,10 @@ public:
     FixedPositionViewportConstraints()
     { }
 
-    FixedPositionViewportConstraints(FixedPositionViewportConstraints* constraints)
+    FixedPositionViewportConstraints(const FixedPositionViewportConstraints& constraints)
         : ViewportConstraints(constraints)
-        , m_viewportRectAtLastLayout(constraints->viewportRectAtLastLayout())
-        , m_layerPositionAtLastLayout(constraints->layerPositionAtLastLayout())
+        , m_viewportRectAtLastLayout(constraints.viewportRectAtLastLayout())
+        , m_layerPositionAtLastLayout(constraints.layerPositionAtLastLayout())
     { }
 
     virtual ConstraintType constraintType() const OVERRIDE { return FixedPositionConstaint; };
@@ -94,6 +94,16 @@ public:
     const FloatPoint& layerPositionAtLastLayout() const { return m_layerPositionAtLastLayout; }
     void setLayerPositionAtLastLayout(const FloatPoint& point) { m_layerPositionAtLastLayout = point; }
 
+    bool operator==(const FixedPositionViewportConstraints& other) const
+    {
+        return m_alignmentOffset == other.m_alignmentOffset
+            && m_anchorEdges == other.m_anchorEdges
+            && m_viewportRectAtLastLayout == other.m_viewportRectAtLastLayout
+            && m_layerPositionAtLastLayout == other.m_layerPositionAtLastLayout;
+    }
+
+    bool operator!=(const FixedPositionViewportConstraints& other) const { return !(*this == other); }
+
 private:
     FloatRect m_viewportRectAtLastLayout;
     FloatPoint m_layerPositionAtLastLayout;
index 9eb7b88..3446859 100644 (file)
@@ -240,8 +240,10 @@ void ScrollingCoordinator::updateMainFrameScrollPosition(const IntPoint& scrollP
     if (GraphicsLayer* scrollLayer = scrollLayerForFrameView(frameView)) {
         if (programmaticScroll)
             scrollLayer->setPosition(-frameView->scrollPosition());
-        else
+        else {
             scrollLayer->syncPosition(-frameView->scrollPosition());
+            syncChildPositions(frameView->visibleContentRect());
+        }
     }
 #endif
 }
index 1b386ef..b008f9b 100644 (file)
@@ -27,6 +27,7 @@
 #define ScrollingCoordinator_h
 
 #include "IntRect.h"
+#include "LayoutTypes.h"
 #include "PlatformWheelEvent.h"
 #include "ScrollTypes.h"
 #include "Timer.h"
@@ -47,10 +48,7 @@ namespace WebCore {
 typedef unsigned MainThreadScrollingReasons;
 typedef uint64_t ScrollingNodeID;
 
-enum ScrollingNodeType {
-    ScrollingNode
-    // FIXME: This will soon contain other types such as FixedNode.
-};
+enum ScrollingNodeType { ScrollingNode, FixedNode };
 
 class Frame;
 class FrameView;
@@ -58,9 +56,7 @@ class GraphicsLayer;
 class Page;
 class Region;
 class ScrollableArea;
-class ScrollingStateNode;
-class ScrollingStateScrollingNode;
-class ScrollingStateTree;
+class ViewportConstraints;
 
 #if ENABLE(THREADED_SCROLLING)
 class ScrollingTree;
@@ -117,6 +113,8 @@ public:
     virtual ScrollingNodeID attachToStateTree(ScrollingNodeType, ScrollingNodeID newNodeID, ScrollingNodeID /*parentID*/) { return newNodeID; }
     virtual void detachFromStateTree(ScrollingNodeID) { }
     virtual void clearStateTree() { }
+    virtual void updateViewportConstrainedNode(ScrollingNodeID, const ViewportConstraints&, GraphicsLayer*) { }
+    virtual void syncChildPositions(const LayoutRect&) { }
     virtual String scrollingStateTreeAsText() const;
 
     // Generated a unique id for scroll layers.
diff --git a/Source/WebCore/page/scrolling/ScrollingStateFixedNode.cpp b/Source/WebCore/page/scrolling/ScrollingStateFixedNode.cpp
new file mode 100644 (file)
index 0000000..bc60aa8
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2012 Apple 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 INC. 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 INC. 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.
+ */
+
+#include "config.h"
+#include "ScrollingStateFixedNode.h"
+
+#include "ScrollingStateTree.h"
+#include "TextStream.h"
+#include <wtf/OwnPtr.h>
+
+#if ENABLE(THREADED_SCROLLING)
+
+namespace WebCore {
+
+PassOwnPtr<ScrollingStateFixedNode> ScrollingStateFixedNode::create(ScrollingStateTree* stateTree, ScrollingNodeID nodeID)
+{
+    return adoptPtr(new ScrollingStateFixedNode(stateTree, nodeID));
+}
+
+ScrollingStateFixedNode::ScrollingStateFixedNode(ScrollingStateTree* tree, ScrollingNodeID nodeID)
+    : ScrollingStateNode(tree, nodeID)
+    , m_changedProperties(0)
+{
+}
+
+ScrollingStateFixedNode::ScrollingStateFixedNode(const ScrollingStateFixedNode& node)
+    : ScrollingStateNode(node)
+    , m_constraints(FixedPositionViewportConstraints(node.viewportConstraints()))
+    , m_changedProperties(node.changedProperties())
+{
+}
+
+ScrollingStateFixedNode::~ScrollingStateFixedNode()
+{
+}
+
+PassOwnPtr<ScrollingStateNode> ScrollingStateFixedNode::clone()
+{
+    return adoptPtr(new ScrollingStateFixedNode(*this));
+}
+
+void ScrollingStateFixedNode::updateConstraints(const FixedPositionViewportConstraints& constraints)
+{
+    if (m_constraints == constraints)
+        return;
+
+    m_constraints = constraints;
+    m_changedProperties = ViewportConstraints;
+    m_scrollingStateTree->setHasChangedProperties(true);
+}
+
+void ScrollingStateFixedNode::dumpProperties(TextStream& ts, int indent) const
+{
+    ts << "(" << "Fixed node" << "\n";
+
+    if (m_constraints.anchorEdges()) {
+        writeIndent(ts, indent + 1);
+        ts << "(anchor edges: ";
+        if (m_constraints.hasAnchorEdge(ViewportConstraints::AnchorEdgeLeft))
+            ts << "AnchorEdgeLeft ";
+        if (m_constraints.hasAnchorEdge(ViewportConstraints::AnchorEdgeRight))
+            ts << "AnchorEdgeRight ";
+        if (m_constraints.hasAnchorEdge(ViewportConstraints::AnchorEdgeTop))
+            ts << "AnchorEdgeTop";
+        if (m_constraints.hasAnchorEdge(ViewportConstraints::AnchorEdgeBottom))
+            ts << "AnchorEdgeBottom";
+        ts << ")\n";
+    }
+
+    if (!m_constraints.alignmentOffset().isEmpty()) {
+        writeIndent(ts, indent + 1);
+        ts << "(alignment offset " << m_constraints.alignmentOffset().width() << " " << m_constraints.alignmentOffset().height() << ")\n";
+    }
+
+    if (!m_constraints.viewportRectAtLastLayout().isEmpty()) {
+        writeIndent(ts, indent + 1);
+        FloatRect viewportRect = m_constraints.viewportRectAtLastLayout();
+        ts << "(viewport rect at last layout: " << viewportRect.x() << " " << viewportRect.y() << " " << viewportRect.width() << " " << viewportRect.height() << ")\n";
+    }
+
+    if (m_constraints.layerPositionAtLastLayout() != FloatPoint()) {
+        writeIndent(ts, indent + 1);
+        ts << "(layer position at last layout " << m_constraints.layerPositionAtLastLayout().x() << " " << m_constraints.layerPositionAtLastLayout().y() << ")\n";
+    }
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(THREADED_SCROLLING)
diff --git a/Source/WebCore/page/scrolling/ScrollingStateFixedNode.h b/Source/WebCore/page/scrolling/ScrollingStateFixedNode.h
new file mode 100644 (file)
index 0000000..7c86397
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2012 Apple 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 INC. 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 INC. 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 ScrollingStateFixedNode_h
+#define ScrollingStateFixedNode_h
+
+#if ENABLE(THREADED_SCROLLING)
+
+#include "ScrollingConstraints.h"
+#include "ScrollingStateNode.h"
+
+#include <wtf/Forward.h>
+
+namespace WebCore {
+
+class FixedPositionViewportConstraints;
+
+class ScrollingStateFixedNode : public ScrollingStateNode {
+public:
+    static PassOwnPtr<ScrollingStateFixedNode> create(ScrollingStateTree*, ScrollingNodeID);
+
+    virtual PassOwnPtr<ScrollingStateNode> clone();
+
+    virtual ~ScrollingStateFixedNode();
+
+    enum ChangedPropertyForFixed {
+        ViewportConstraints = 1 << 0
+    };
+
+    virtual unsigned changedProperties() const OVERRIDE { return m_changedProperties; }
+
+    void updateConstraints(const FixedPositionViewportConstraints&);
+    const FixedPositionViewportConstraints& viewportConstraints() const { return m_constraints; }
+
+private:
+    ScrollingStateFixedNode(ScrollingStateTree*, ScrollingNodeID);
+    ScrollingStateFixedNode(const ScrollingStateFixedNode&);
+
+    virtual bool isFixedNode() OVERRIDE { return true; }
+
+    virtual bool hasChangedProperties() const OVERRIDE { return m_changedProperties; }
+    virtual void resetChangedProperties() OVERRIDE { m_changedProperties = 0; }
+
+    virtual void dumpProperties(TextStream&, int indent) const OVERRIDE;
+
+    FixedPositionViewportConstraints m_constraints;
+    unsigned m_changedProperties;
+};
+
+inline ScrollingStateFixedNode* toScrollingStateFixedNode(ScrollingStateNode* node)
+{
+    ASSERT(!node || node->isFixedNode());
+    return static_cast<ScrollingStateFixedNode*>(node);
+}
+    
+// This will catch anyone doing an unnecessary cast.
+void toScrollingStateFixedNode(const ScrollingStateFixedNode*);
+
+} // namespace WebCore
+
+#endif // ENABLE(THREADED_SCROLLING)
+
+#endif // ScrollingStateFixedNode_h
index 62c4181..b2aa836 100644 (file)
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "ScrollingStateNode.h"
 
+#include "ScrollingStateFixedNode.h"
 #include "ScrollingStateTree.h"
 #include "TextStream.h"
 
@@ -61,7 +62,7 @@ ScrollingStateNode::~ScrollingStateNode()
 
 PassOwnPtr<ScrollingStateNode> ScrollingStateNode::cloneAndReset()
 {
-    OwnPtr<ScrollingStateScrollingNode> clone = adoptPtr(new ScrollingStateScrollingNode(*toScrollingStateScrollingNode(this)));
+    OwnPtr<ScrollingStateNode> clone = this->clone();
 
     // Now that this node is cloned, reset our change properties.
     setScrollLayerDidChange(false);
@@ -96,7 +97,11 @@ void ScrollingStateNode::removeChild(ScrollingStateNode* node)
     if (!m_children)
         return;
 
-    if (size_t index = m_children->find(node)) {
+    size_t index = m_children->find(node);
+
+    // The index will be notFound if the node to remove is a deeper-than-1-level descendant or
+    // if node is the root state node.
+    if (index != notFound) {
         m_scrollingStateTree->didRemoveNode(node->scrollingNodeID());
         m_children->remove(index);
         return;
index 734cc8c..60b9ef9 100644 (file)
@@ -49,8 +49,10 @@ public:
     ScrollingStateNode(ScrollingStateTree*, ScrollingNodeID);
     virtual ~ScrollingStateNode();
 
-    virtual bool isScrollingStateScrollingNode() { return false; }
+    virtual bool isScrollingNode() { return false; }
+    virtual bool isFixedNode() { return false; }
 
+    virtual PassOwnPtr<ScrollingStateNode> clone() = 0;
     PassOwnPtr<ScrollingStateNode> cloneAndReset();
     void cloneAndResetChildren(ScrollingStateNode*);
 
@@ -59,8 +61,9 @@ public:
     virtual void resetChangedProperties() = 0;
     virtual void setHasChangedProperties() { setScrollLayerDidChange(true); }
 
+    GraphicsLayer* graphicsLayer() { return m_graphicsLayer; }
     PlatformLayer* platformScrollLayer() const;
-    void setScrollLayer(const GraphicsLayer*);
+    void setScrollLayer(GraphicsLayer*);
     void setScrollLayer(PlatformLayer*);
 
     bool scrollLayerDidChange() const { return m_scrollLayerDidChange; }
@@ -103,6 +106,7 @@ private:
 #if PLATFORM(MAC)
     RetainPtr<PlatformLayer> m_platformScrollLayer;
 #endif
+    GraphicsLayer* m_graphicsLayer;
 
 };
 
index 0456f63..5d37be2 100644 (file)
@@ -78,6 +78,11 @@ ScrollingStateScrollingNode::~ScrollingStateScrollingNode()
 {
 }
 
+PassOwnPtr<ScrollingStateNode> ScrollingStateScrollingNode::clone()
+{
+    return adoptPtr(new ScrollingStateScrollingNode(*this));
+}
+
 void ScrollingStateScrollingNode::setViewportRect(const IntRect& viewportRect)
 {
     if (m_viewportRect == viewportRect)
index 71803eb..5902e27 100644 (file)
@@ -41,7 +41,8 @@ class ScrollingStateScrollingNode : public ScrollingStateNode {
 public:
     static PassOwnPtr<ScrollingStateScrollingNode> create(ScrollingStateTree*, ScrollingNodeID);
 
-    ScrollingStateScrollingNode(const ScrollingStateScrollingNode&);
+    virtual PassOwnPtr<ScrollingStateNode> clone();
+
     virtual ~ScrollingStateScrollingNode();
 
     enum ChangedProperty {
@@ -60,7 +61,7 @@ public:
         RequestedScrollPosition = 1 << 12,
     };
 
-    virtual bool isScrollingStateScrollingNode() OVERRIDE { return true; }
+    virtual bool isScrollingNode() OVERRIDE { return true; }
 
     virtual bool hasChangedProperties() const OVERRIDE { return m_changedProperties; }
     virtual unsigned changedProperties() const OVERRIDE { return m_changedProperties; }
@@ -111,6 +112,7 @@ public:
 
 private:
     ScrollingStateScrollingNode(ScrollingStateTree*, ScrollingNodeID);
+    ScrollingStateScrollingNode(const ScrollingStateScrollingNode&);
 
     unsigned m_changedProperties;
 
@@ -139,7 +141,7 @@ private:
 
 inline ScrollingStateScrollingNode* toScrollingStateScrollingNode(ScrollingStateNode* node)
 {
-    ASSERT(!node || node->isScrollingStateScrollingNode());
+    ASSERT(!node || node->isScrollingNode());
     return static_cast<ScrollingStateScrollingNode*>(node);
 }
     
index 5a332f0..a1d4a48 100644 (file)
@@ -32,6 +32,7 @@
 #include "ScrollingCoordinator.h"
 #include "ScrollingStateTree.h"
 #include "ScrollingThread.h"
+#include "ScrollingTreeFixedNode.h"
 #include "ScrollingTreeNode.h"
 #include "ScrollingTreeScrollingNode.h"
 #include <wtf/MainThread.h>
@@ -162,9 +163,13 @@ void ScrollingTree::updateTreeFromStateNode(ScrollingStateNode* stateNode)
             m_nodeMap.set(stateNode->scrollingNodeID(), m_rootNode.get());
             m_rootNode->update(stateNode);
         } else {
-            // FIXME: In the future, we will have more than just ScrollingTreeScrollingNode, so we'll have to
-            // figure out which type of node to create.
-            OwnPtr<ScrollingTreeNode> newNode = ScrollingTreeScrollingNode::create(this);
+            OwnPtr<ScrollingTreeNode> newNode;
+            if (stateNode->isScrollingNode())
+                newNode = ScrollingTreeScrollingNode::create(this);
+            else if (stateNode->isFixedNode())
+                newNode = ScrollingTreeFixedNode::create(this);
+            else
+                ASSERT_NOT_REACHED();
             ScrollingTreeNode* newNodeRawPtr = newNode.get();
             m_nodeMap.set(stateNode->scrollingNodeID(), newNodeRawPtr);
             ScrollingTreeNodeMap::const_iterator it = m_nodeMap.find(stateNode->parent()->scrollingNodeID());
index b0c51ca..525af3f 100644 (file)
@@ -47,9 +47,10 @@ OBJC_CLASS CALayer;
 namespace WebCore {
 
 class IntPoint;
+class ScrollingStateNode;
+class ScrollingStateTree;
 class ScrollingTreeNode;
 class ScrollingTreeScrollingNode;
-class ScrollingStateTree;
 
 // The ScrollingTree class lives almost exclusively on the scrolling thread and manages the
 // hierarchy of scrollable regions on the page. It's also responsible for dispatching events
index 46addc4..06027ad 100644 (file)
 
 namespace WebCore {
 
+class ScrollingStateFixedNode;
+class ScrollingStateNode;
+class ScrollingStateScrollingNode;
+
 class ScrollingTreeNode {
 public:
     explicit ScrollingTreeNode(ScrollingTree*);
@@ -42,6 +46,8 @@ public:
 
     virtual void update(ScrollingStateNode*) = 0;
 
+    virtual void parentScrollPositionDidChange(const IntRect& viewportRect) = 0;
+
     ScrollingNodeID scrollingNodeID() const { return m_nodeID; }
     void setScrollingNodeID(ScrollingNodeID nodeID) { m_nodeID = nodeID; }
 
@@ -54,13 +60,15 @@ public:
 protected:
     ScrollingTree* scrollingTree() const { return m_scrollingTree; }
 
+    typedef Vector<OwnPtr<ScrollingTreeNode> > ScrollingTreeChildrenVector;
+    OwnPtr<ScrollingTreeChildrenVector> m_children;
+
 private:
     ScrollingTree* m_scrollingTree;
 
     ScrollingNodeID m_nodeID;
 
     ScrollingTreeNode* m_parent;
-    OwnPtr<Vector<OwnPtr<ScrollingTreeNode> > > m_children;
 };
 
 } // namespace WebCore
index 23e0fde..7b62fd8 100644 (file)
@@ -46,6 +46,10 @@ public:
     virtual ~ScrollingTreeScrollingNode();
 
     virtual void update(ScrollingStateNode*) OVERRIDE;
+
+    // FIXME: We should implement this when we support ScrollingTreeScrollingNodes as children.
+    virtual void parentScrollPositionDidChange(const IntRect& /*viewportRect*/) OVERRIDE { }
+
     virtual void handleWheelEvent(const PlatformWheelEvent&) = 0;
     virtual void setScrollPosition(const IntPoint&) = 0;
 
index a408f13..46e1249 100644 (file)
 
 namespace WebCore {
 
+class ScrollingStateNode;
+class ScrollingStateScrollingNode;
+class ScrollingStateTree;
+
 class ScrollingCoordinatorMac : public ScrollingCoordinator {
 public:
     explicit ScrollingCoordinatorMac(Page*);
@@ -75,6 +79,16 @@ public:
     virtual String scrollingStateTreeAsText() const OVERRIDE;
 
 private:
+    // Return whether this scrolling coordinator can keep fixed position layers fixed to their
+    // containers while scrolling.
+    virtual bool supportsFixedPositionLayers() const OVERRIDE { return true; }
+
+    // This function will update the ScrollingStateNode for the given viewport constrained object.
+    virtual void updateViewportConstrainedNode(ScrollingNodeID, const ViewportConstraints&, GraphicsLayer*) OVERRIDE;
+
+    // Called to synch the GraphicsLayer positions for child layers when their CALayers have been moved by the scrolling thread.
+    virtual void syncChildPositions(const LayoutRect& viewportRect) OVERRIDE;
+
     virtual void recomputeWheelEventHandlerCountForFrameView(FrameView*);
     virtual void setShouldUpdateScrollLayerPositionOnMainThread(MainThreadScrollingReasons);
 
@@ -109,6 +123,8 @@ private:
     void scrollingStateTreeCommitterTimerFired(Timer<ScrollingCoordinatorMac>*);
     void commitTreeState();
 
+    void removeNode(ScrollingStateNode*);
+
     OwnPtr<ScrollingStateTree> m_scrollingStateTree;
     RefPtr<ScrollingTree> m_scrollingTree;
     Timer<ScrollingCoordinatorMac> m_scrollingStateTreeCommitterTimer;
index 1687dcf..6f0de44 100644 (file)
@@ -39,6 +39,8 @@
 #include "RenderLayerCompositor.h"
 #include "RenderView.h"
 #include "ScrollAnimator.h"
+#include "ScrollingConstraints.h"
+#include "ScrollingStateFixedNode.h"
 #include "ScrollingStateScrollingNode.h"
 #include "ScrollingStateTree.h"
 #include "ScrollingThread.h"
@@ -251,12 +253,19 @@ ScrollingNodeID ScrollingCoordinatorMac::attachToStateTree(ScrollingNodeType nod
     } else {
         ScrollingStateNode* parent = stateNodeForID(parentID);
         switch (nodeType) {
+        case FixedNode: {
+            ASSERT(supportsFixedPositionLayers());
+            OwnPtr<ScrollingStateFixedNode> fixedNode = ScrollingStateFixedNode::create(m_scrollingStateTree.get(), newNodeID);
+            newNode = fixedNode.get();
+            parent->appendChild(fixedNode.release());
+            break;
+        }
         case ScrollingNode: {
-            // FIXME: We currently do not support child nodes. This assertion should be removed when we do.
+            // FIXME: We currently only support child nodes that are fixed.
             ASSERT_NOT_REACHED();
-            PassOwnPtr<ScrollingStateScrollingNode> scrollingNode = ScrollingStateScrollingNode::create(m_scrollingStateTree.get(), newNodeID);
+            OwnPtr<ScrollingStateScrollingNode> scrollingNode = ScrollingStateScrollingNode::create(m_scrollingStateTree.get(), newNodeID);
             newNode = scrollingNode.get();
-            parent->appendChild(scrollingNode);
+            parent->appendChild(scrollingNode.release());
             break;
         }
         default:
@@ -268,6 +277,18 @@ ScrollingNodeID ScrollingCoordinatorMac::attachToStateTree(ScrollingNodeType nod
     return newNodeID;
 }
 
+void ScrollingCoordinatorMac::removeNode(ScrollingStateNode* node)
+{
+    m_scrollingStateTree->removeNode(node);
+
+    // ScrollingStateTree::removeNode() will destroy children, so we have to make sure we remove those children
+    // from the HashMap.
+    const Vector<ScrollingNodeID>& removedNodes = m_scrollingStateTree->removedNodes();
+    size_t size = removedNodes.size();
+    for (size_t i = 0; i < size; ++i)
+        m_stateNodeMap.remove(removedNodes[i]);
+}
+
 void ScrollingCoordinatorMac::detachFromStateTree(ScrollingNodeID scrollLayerID)
 {
     if (!scrollLayerID)
@@ -278,20 +299,12 @@ void ScrollingCoordinatorMac::detachFromStateTree(ScrollingNodeID scrollLayerID)
     if (!node)
         return;
 
-    m_scrollingStateTree->removeNode(node);
-
-    // ScrollingStateTree::removeNode() will destroy children, so we have to make sure we remove those children
-    // from the HashMap.
-    const Vector<ScrollingNodeID>& removedNodes = m_scrollingStateTree->removedNodes();
-    size_t size = removedNodes.size();
-    for (size_t i = 0; i < size; ++i)
-        m_stateNodeMap.remove(removedNodes[i]);
+    removeNode(node);
 }
 
 void ScrollingCoordinatorMac::clearStateTree()
 {
-    m_stateNodeMap.clear();
-    m_scrollingStateTree->removeNode(m_scrollingStateTree->rootStateNode());
+    removeNode(m_scrollingStateTree->rootStateNode());
 }
 
 ScrollingStateNode* ScrollingCoordinatorMac::stateNodeForID(ScrollingNodeID scrollLayerID)
@@ -370,6 +383,34 @@ void ScrollingCoordinatorMac::updateMainFrameScrollLayerPosition()
         scrollLayer->setPosition(-frameView->scrollPosition());
 }
 
+void ScrollingCoordinatorMac::syncChildPositions(const LayoutRect& viewportRect)
+{
+    Vector<OwnPtr<ScrollingStateNode> >* children = m_scrollingStateTree->rootStateNode()->children();
+    if (!children)
+        return;
+
+    // FIXME: We'll have to traverse deeper into the tree at some point.
+    size_t size = children->size();
+    for (size_t i = 0; i < size; ++i) {
+        ScrollingStateFixedNode* child = toScrollingStateFixedNode(children->at(i).get());
+        FloatPoint position = child->viewportConstraints().layerPositionForViewportRect(viewportRect);
+        child->graphicsLayer()->setPosition(position);
+    }
+}
+
+void ScrollingCoordinatorMac::updateViewportConstrainedNode(ScrollingNodeID nodeID, const ViewportConstraints& constraints, GraphicsLayer* graphicsLayer)
+{
+    ASSERT(supportsFixedPositionLayers());
+
+    // FIXME: We should support sticky position here!
+    if (constraints.constraintType() == ViewportConstraints::StickyPositionConstraint)
+        return;
+
+    ScrollingStateFixedNode* node = toScrollingStateFixedNode(stateNodeForID(nodeID));
+    setScrollLayerForNode(graphicsLayer, node);
+    node->updateConstraints((const FixedPositionViewportConstraints&)constraints);
+}
+
 void ScrollingCoordinatorMac::scheduleTreeStateCommit()
 {
     if (m_scrollingStateTreeCommitterTimer.isActive())
index d4658dd..41f381b 100644 (file)
@@ -43,7 +43,7 @@ void ScrollingStateNode::setScrollLayer(PlatformLayer* platformLayer)
     m_platformScrollLayer = platformLayer;
 }
 
-void ScrollingStateNode::setScrollLayer(const GraphicsLayer* graphicsLayer)
+void ScrollingStateNode::setScrollLayer(GraphicsLayer* graphicsLayer)
 {
     PlatformLayer* platformScrollLayer = graphicsLayer ? graphicsLayer->platformLayer() : nil;
 
@@ -51,6 +51,8 @@ void ScrollingStateNode::setScrollLayer(const GraphicsLayer* graphicsLayer)
         return;
 
     m_platformScrollLayer = platformScrollLayer;
+    m_graphicsLayer = graphicsLayer;
+
     m_scrollLayerDidChange = true;
     m_scrollingStateTree->setHasChangedProperties(true);
 }
diff --git a/Source/WebCore/page/scrolling/mac/ScrollingTreeFixedNode.h b/Source/WebCore/page/scrolling/mac/ScrollingTreeFixedNode.h
new file mode 100644 (file)
index 0000000..c3acfc6
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2012 Apple 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 INC. 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 INC. 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 ScrollingTreeFixedNode_h
+#define ScrollingTreeFixedNode_h
+
+#if ENABLE(THREADED_SCROLLING)
+
+#include "ScrollingConstraints.h"
+#include "ScrollingTreeNode.h"
+#include <wtf/RetainPtr.h>
+
+OBJC_CLASS CALayer;
+
+namespace WebCore {
+
+class FixedPositionViewportConstraints;
+
+class ScrollingTreeFixedNode : public ScrollingTreeNode {
+public:
+    static PassOwnPtr<ScrollingTreeFixedNode> create(ScrollingTree*);
+
+    virtual ~ScrollingTreeFixedNode();
+
+private:
+    ScrollingTreeFixedNode(ScrollingTree*);
+
+    virtual void update(ScrollingStateNode*) OVERRIDE;
+    virtual void parentScrollPositionDidChange(const IntRect& viewportRect) OVERRIDE;
+
+    FixedPositionViewportConstraints m_constraints;
+    RetainPtr<CALayer> m_layer;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(THREADED_SCROLLING)
+
+#endif // ScrollingTreeFixedNode_h
diff --git a/Source/WebCore/page/scrolling/mac/ScrollingTreeFixedNode.mm b/Source/WebCore/page/scrolling/mac/ScrollingTreeFixedNode.mm
new file mode 100644 (file)
index 0000000..c4edfc2
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2012 Apple 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 INC. 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 INC. 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.
+ */
+
+#include "config.h"
+#include "ScrollingTreeFixedNode.h"
+
+#if ENABLE(THREADED_SCROLLING)
+
+#include "ScrollingStateFixedNode.h"
+#include "ScrollingTree.h"
+
+namespace WebCore {
+
+PassOwnPtr<ScrollingTreeFixedNode> ScrollingTreeFixedNode::create(ScrollingTree* scrollingTree)
+{
+    return adoptPtr(new ScrollingTreeFixedNode(scrollingTree));
+}
+
+ScrollingTreeFixedNode::ScrollingTreeFixedNode(ScrollingTree* scrollingTree)
+    : ScrollingTreeNode(scrollingTree)
+    , m_constraints(FixedPositionViewportConstraints())
+{
+}
+
+ScrollingTreeFixedNode::~ScrollingTreeFixedNode()
+{
+}
+
+void ScrollingTreeFixedNode::update(ScrollingStateNode* stateNode)
+{
+    ScrollingStateFixedNode* state = toScrollingStateFixedNode(stateNode);
+
+    if (state->scrollLayerDidChange())
+        m_layer = state->platformScrollLayer();
+
+    if (stateNode->changedProperties() & ScrollingStateFixedNode::ViewportConstraints)
+        m_constraints = state->viewportConstraints();
+}
+
+static inline CGPoint operator*(CGPoint& a, const CGSize& b)
+{
+    return CGPointMake(a.x * b.width, a.y * b.height);
+}
+
+void ScrollingTreeFixedNode::parentScrollPositionDidChange(const IntRect& viewportRect)
+{
+    FloatPoint layerPosition = m_constraints.layerPositionForViewportRect(viewportRect);
+
+    CGRect layerBounds = [m_layer.get() bounds];
+    CGPoint anchorPoint = [m_layer.get() anchorPoint];
+    CGPoint newPosition = layerPosition - m_constraints.alignmentOffset() + anchorPoint * layerBounds.size;
+    [m_layer.get() setPosition:newPosition];
+
+    if (!m_children)
+        return;
+
+    size_t size = m_children->size();
+    for (size_t i = 0; i < size; ++i)
+        m_children->at(i)->parentScrollPositionDidChange(viewportRect);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(THREADED_SCROLLING)
index efa23f9..bd6d728 100644 (file)
@@ -275,6 +275,13 @@ void ScrollingTreeScrollingNodeMac::setScrollLayerPosition(const IntPoint& posit
 {
     ASSERT(!shouldUpdateScrollLayerPositionOnMainThread());
     m_scrollLayer.get().position = CGPointMake(-position.x() + scrollOrigin().x(), -position.y() + scrollOrigin().y());
+
+    if (!m_children)
+        return;
+
+    size_t size = m_children->size();
+    for (size_t i = 0; i < size; ++i)
+        m_children->at(i)->parentScrollPositionDidChange(IntRect(position, viewportRect().size()));
 }
 
 IntPoint ScrollingTreeScrollingNodeMac::minimumScrollPosition() const
index 8267bc3..1f2a647 100644 (file)
@@ -1037,7 +1037,14 @@ void RenderLayerBacking::attachToScrollingCoordinator(RenderLayerBacking* parent
     if (!scrollingCoordinator)
         return;
 
-    ScrollingNodeType nodeType = ScrollingNode;
+    // FIXME: When we support overflow areas, we will have to refine this for overflow areas that are also
+    // positon:fixed.
+    ScrollingNodeType nodeType;
+    if (renderer()->style()->position() == FixedPosition)
+        nodeType = FixedNode;
+    else
+        nodeType = ScrollingNode;
+
     ScrollingNodeID parentID = parent ? parent->scrollLayerID() : 0;
     m_scrollLayerID = scrollingCoordinator->attachToStateTree(nodeType, scrollingCoordinator->uniqueScrollLayerID(), parentID);
 }
index 39abaea..39f6ac5 100644 (file)
@@ -90,6 +90,7 @@ public:
     GraphicsLayer* scrollingContentsLayer() const { return m_scrollingContentsLayer.get(); }
 
     void attachToScrollingCoordinator(RenderLayerBacking* parent);
+    void detachFromScrollingCoordinator();
     uint64_t scrollLayerID() const { return m_scrollLayerID; }
     
     bool hasMaskLayer() const { return m_maskLayer != 0; }
@@ -203,8 +204,6 @@ private:
     bool requiresScrollCornerLayer() const;
     bool updateScrollingLayers(bool scrollingLayers);
 
-    void detachFromScrollingCoordinator();
-
     GraphicsLayerPaintingPhase paintingPhaseForPrimaryLayer() const;
     
     IntSize contentOffsetInCompostingLayer() const;
index d02e5e4..7fa6da5 100644 (file)
@@ -52,6 +52,7 @@
 #include "RenderVideo.h"
 #include "RenderView.h"
 #include "ScrollbarTheme.h"
+#include "ScrollingConstraints.h"
 #include "ScrollingCoordinator.h"
 #include "Settings.h"
 #include "TiledBacking.h"
@@ -312,10 +313,20 @@ void RenderLayerCompositor::flushPendingLayerChanges(bool isFlushRoot)
     
     ASSERT(m_flushingLayers);
     m_flushingLayers = false;
+
+    if (!m_viewportConstrainedLayersNeedingUpdate.isEmpty()) {
+        HashSet<RenderLayer*>::const_iterator end = m_viewportConstrainedLayersNeedingUpdate.end();
+        for (HashSet<RenderLayer*>::const_iterator it = m_viewportConstrainedLayersNeedingUpdate.begin(); it != end; ++it)
+            registerOrUpdateViewportConstrainedLayer(*it);
+        
+        m_viewportConstrainedLayersNeedingUpdate.clear();
+    }
 }
 
-void RenderLayerCompositor::didFlushChangesForLayer(RenderLayer*)
+void RenderLayerCompositor::didFlushChangesForLayer(RenderLayer* layer)
 {
+    if (m_viewportConstrainedLayers.contains(layer))
+        m_viewportConstrainedLayersNeedingUpdate.add(layer);
 }
 
 void RenderLayerCompositor::notifyFlushBeforeDisplayRefresh(const GraphicsLayer*)
@@ -535,6 +546,9 @@ bool RenderLayerCompositor::updateBacking(RenderLayer* layer, CompositingChangeR
 
             layerChanged = true;
         }
+
+        // Need to add for every compositing layer, because a composited layer may change from being non-fixed to fixed.
+        updateViewportConstraintStatus(layer);
     } else {
         if (layer->backing()) {
             // If we're removing backing on a reflection, clear the source GraphicsLayer's pointer to
@@ -547,6 +561,8 @@ bool RenderLayerCompositor::updateBacking(RenderLayer* layer, CompositingChangeR
                     backing->graphicsLayer()->setReplicatedByLayer(0);
                 }
             }
+
+            removeViewportConstrainedLayer(layer);
             
             layer->clearBacking();
             layerChanged = true;
@@ -662,6 +678,7 @@ void RenderLayerCompositor::layerWillBeRemoved(RenderLayer* parent, RenderLayer*
     if (!child->isComposited() || parent->renderer()->documentBeingDestroyed())
         return;
 
+    removeViewportConstrainedLayer(child);
     repaintInCompositedAncestor(child, child->backing()->compositedBounds());
 
     setCompositingParent(child, 0);
@@ -1408,8 +1425,10 @@ void RenderLayerCompositor::clearBackingForLayerIncludingDescendants(RenderLayer
     if (!layer)
         return;
 
-    if (layer->isComposited())
+    if (layer->isComposited()) {
+        removeViewportConstrainedLayer(layer);
         layer->clearBacking();
+    }
     
     for (RenderLayer* currLayer = layer->firstChild(); currLayer; currLayer = currLayer->nextSibling())
         clearBackingForLayerIncludingDescendants(currLayer);
@@ -2524,6 +2543,163 @@ void RenderLayerCompositor::deviceOrPageScaleFactorChanged()
         rootLayer->noteDeviceOrPageScaleFactorChangedIncludingDescendants();
 }
 
+static bool isRootmostFixedOrStickyLayer(RenderLayer* layer)
+{
+    if (layer->renderer()->isStickyPositioned())
+        return true;
+
+    if (layer->renderer()->style()->position() != FixedPosition)
+        return false;
+
+    for (RenderLayer* stackingContext = layer->stackingContext(); stackingContext; stackingContext = stackingContext->stackingContext()) {
+        if (stackingContext->isComposited() && stackingContext->renderer()->style()->position() == FixedPosition)
+            return false;
+    }
+
+    return true;
+}
+
+void RenderLayerCompositor::updateViewportConstraintStatus(RenderLayer* layer)
+{
+    if (isRootmostFixedOrStickyLayer(layer))
+        addViewportConstrainedLayer(layer);
+    else
+        removeViewportConstrainedLayer(layer);
+}
+
+void RenderLayerCompositor::addViewportConstrainedLayer(RenderLayer* layer)
+{
+    m_viewportConstrainedLayers.add(layer);
+    registerOrUpdateViewportConstrainedLayer(layer);
+}
+
+void RenderLayerCompositor::removeViewportConstrainedLayer(RenderLayer* layer)
+{
+    if (!m_viewportConstrainedLayers.contains(layer))
+        return;
+
+    unregisterViewportConstrainedLayer(layer);
+    m_viewportConstrainedLayers.remove(layer);
+}
+
+const FixedPositionViewportConstraints RenderLayerCompositor::computeFixedViewportConstraints(RenderLayer* layer)
+{
+    ASSERT(layer->isComposited());
+
+    FrameView* frameView = m_renderView->frameView();
+    LayoutRect viewportRect = frameView->visibleContentRect();
+
+    FixedPositionViewportConstraints constraints = FixedPositionViewportConstraints();
+
+    GraphicsLayer* graphicsLayer = layer->backing()->graphicsLayer();
+
+    constraints.setLayerPositionAtLastLayout(graphicsLayer->position());
+    constraints.setViewportRectAtLastLayout(viewportRect);
+        
+    RenderStyle* style = layer->renderer()->style();
+    if (!style->left().isAuto())
+        constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeLeft);
+
+    if (!style->right().isAuto())
+        constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeRight);
+
+    if (!style->top().isAuto())
+        constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeTop);
+
+    if (!style->bottom().isAuto())
+        constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeBottom);
+
+    // If left and right are auto, use left.
+    if (style->left().isAuto() && style->right().isAuto())
+        constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeLeft);
+
+    // If top and bottom are auto, use top.
+    if (style->top().isAuto() && style->bottom().isAuto())
+        constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeTop);
+        
+    return constraints;
+}
+
+const StickyPositionViewportConstraints RenderLayerCompositor::computeStickyViewportConstraints(RenderLayer* layer)
+{
+    ASSERT(layer->isComposited());
+
+    FrameView* frameView = m_renderView->frameView();
+    LayoutRect viewportRect = frameView->visibleContentRect();
+
+    StickyPositionViewportConstraints constraints = StickyPositionViewportConstraints();
+
+    RenderBoxModelObject* renderer = toRenderBoxModelObject(layer->renderer());
+
+    renderer->computeStickyPositionConstraints(constraints, viewportRect);
+
+    GraphicsLayer* graphicsLayer = layer->backing()->graphicsLayer();
+
+    constraints.setLayerPositionAtLastLayout(graphicsLayer->position());
+    constraints.setStickyOffsetAtLastLayout(renderer->stickyPositionOffset());
+
+    return constraints;
+}
+
+static RenderLayerBacking* nearestScrollingCoordinatorAncestor(RenderLayer* layer)
+{
+    RenderLayer* ancestor = layer->parent();
+    while (ancestor) {
+        if (RenderLayerBacking* backing = ancestor->backing()) {
+            if (backing->scrollLayerID() && !ancestor->scrollsOverflow())
+                return backing;
+        }
+        ancestor = ancestor->parent();
+    }
+
+    return 0;
+}
+
+void RenderLayerCompositor::registerOrUpdateViewportConstrainedLayer(RenderLayer* layer)
+{
+    // FIXME: We should support sticky position here! And we should eventuall support fixed/sticky elements
+    // that are inside non-main frames once we get non-main frames scrolling with the ScrollingCoordinator.
+    if (layer->renderer()->isStickyPositioned() || m_renderView->document()->ownerElement())
+        return;
+
+    ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator();
+    if (!scrollingCoordinator)
+        return;
+
+    if (!scrollingCoordinator->supportsFixedPositionLayers() || !layer->parent())
+        return;
+
+    ASSERT(layer->renderer()->style()->position() == FixedPosition);
+    ASSERT(m_viewportConstrainedLayers.contains(layer));
+    ASSERT(layer->isComposited());
+
+    RenderLayerBacking* backing = layer->backing();
+    if (!backing)
+        return;
+
+    ScrollingNodeID nodeID = backing->scrollLayerID();
+    if (!nodeID) {
+        RenderLayerBacking* parent = nearestScrollingCoordinatorAncestor(layer);
+        if (!parent)
+            return;
+        backing->attachToScrollingCoordinator(parent);
+        nodeID = backing->scrollLayerID();
+    }
+
+    if (layer->renderer()->isStickyPositioned())
+        scrollingCoordinator->updateViewportConstrainedNode(nodeID, computeStickyViewportConstraints(layer), backing->graphicsLayer());
+    else
+        scrollingCoordinator->updateViewportConstrainedNode(nodeID, computeFixedViewportConstraints(layer), backing->graphicsLayer());
+}
+
+void RenderLayerCompositor::unregisterViewportConstrainedLayer(RenderLayer* layer)
+{
+    ASSERT(m_viewportConstrainedLayers.contains(layer));
+
+    if (RenderLayerBacking* backing = layer->backing())
+        backing->detachFromScrollingCoordinator();
+}
+
 void RenderLayerCompositor::windowScreenDidChange(PlatformDisplayID displayID)
 {
     if (m_layerUpdater)
index 81aaf41..87380ac 100644 (file)
 
 namespace WebCore {
 
+class FixedPositionViewportConstraints;
 class GraphicsLayer;
 class GraphicsLayerUpdater;
 class RenderEmbeddedObject;
 class RenderPart;
 class ScrollingCoordinator;
+class StickyPositionViewportConstraints;
 #if ENABLE(VIDEO)
 class RenderVideo;
 #endif
@@ -223,6 +225,9 @@ public:
 
     void documentBackgroundColorDidChange();
 
+    void updateViewportConstraintStatus(RenderLayer*);
+    void removeViewportConstrainedLayer(RenderLayer*);
+
     void resetTrackedRepaintRects();
     void setTracksRepaints(bool);
 
@@ -311,6 +316,13 @@ private:
     bool requiresCompositingForOverflowScrolling(const RenderLayer*) const;
     bool requiresCompositingForIndirectReason(RenderObject*, bool hasCompositedDescendants, bool has3DTransformedDescendants, RenderLayer::IndirectCompositingReason&) const;
 
+    void addViewportConstrainedLayer(RenderLayer*);
+    void registerOrUpdateViewportConstrainedLayer(RenderLayer*);
+    void unregisterViewportConstrainedLayer(RenderLayer*);
+
+    const FixedPositionViewportConstraints computeFixedViewportConstraints(RenderLayer*);
+    const StickyPositionViewportConstraints computeStickyViewportConstraints(RenderLayer*);
+
     bool requiresScrollLayer(RootLayerAttachment) const;
     bool requiresHorizontalScrollbarLayer() const;
     bool requiresVerticalScrollbarLayer() const;
@@ -357,6 +369,9 @@ private:
     OwnPtr<GraphicsLayer> m_clipLayer;
     OwnPtr<GraphicsLayer> m_scrollLayer;
 
+    HashSet<RenderLayer*> m_viewportConstrainedLayers;
+    HashSet<RenderLayer*> m_viewportConstrainedLayersNeedingUpdate;
+
     // Enclosing layer for overflow controls and the clipping layer
     OwnPtr<GraphicsLayer> m_overflowControlsHostLayer;