<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[170568] trunk/Source</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/170568">170568</a></dd>
<dt>Author</dt> <dd>simon.fraser@apple.com</dd>
<dt>Date</dt> <dd>2014-06-28 07:50:39 -0700 (Sat, 28 Jun 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>[iOS WK2] position:fixed inside accelerated overflow:scroll is jumpy
https://bugs.webkit.org/show_bug.cgi?id=134426
&lt;rdar://problem/17474523&gt;

Reviewed by Tim Horton.

After committing a new layer tree (with possibly stale position:fixed layer
positions), we need the scrolling tree to update those positions based on
the current scroll offset.

Source/WebCore:
Give ScrollingTreeScrollingNode an implementation of updateLayersAfterAncestorChange()
which is required to update fixed/sticky child nodes.

* WebCore.exp.in:
* page/scrolling/ScrollingTreeScrollingNode.cpp:
(WebCore::ScrollingTreeScrollingNode::updateLayersAfterAncestorChange):
* page/scrolling/ScrollingTreeScrollingNode.h:

Source/WebKit2:
To achieve that, implement ScrollingTreeOverflowScrollingNodeIOS::updateLayersAfterAncestorChange()
and have it add to the cumulative delta the difference between the last committed scroll
position and the current scroll position.

Also make sure that ScrollingTreeOverflowScrollingNodeIOS doesn't call back to scrollViewDidScroll()
when we're updating its scroll position inside a scrolling tree commit.

* UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.h:
* UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm:
(WebKit::ScrollingTreeOverflowScrollingNodeIOS::ScrollingTreeOverflowScrollingNodeIOS):
(WebKit::ScrollingTreeOverflowScrollingNodeIOS::updateAfterChildren):
(WebKit::ScrollingTreeOverflowScrollingNodeIOS::updateLayersAfterAncestorChange):
(WebKit::ScrollingTreeOverflowScrollingNodeIOS::scrollViewDidScroll):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreWebCoreexpin">trunk/Source/WebCore/WebCore.exp.in</a></li>
<li><a href="#trunkSourceWebCorepagescrollingScrollingTreeScrollingNodecpp">trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp</a></li>
<li><a href="#trunkSourceWebCorepagescrollingScrollingTreeScrollingNodeh">trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h</a></li>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2UIProcessScrollingiosScrollingTreeOverflowScrollingNodeIOSh">trunk/Source/WebKit2/UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessScrollingiosScrollingTreeOverflowScrollingNodeIOSmm">trunk/Source/WebKit2/UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (170567 => 170568)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-06-28 09:06:09 UTC (rev 170567)
+++ trunk/Source/WebCore/ChangeLog        2014-06-28 14:50:39 UTC (rev 170568)
</span><span class="lines">@@ -1,3 +1,23 @@
</span><ins>+2014-06-27  Simon Fraser  &lt;simon.fraser@apple.com&gt;
+
+        [iOS WK2] position:fixed inside accelerated overflow:scroll is jumpy
+        https://bugs.webkit.org/show_bug.cgi?id=134426
+        &lt;rdar://problem/17474523&gt;
+
+        Reviewed by Tim Horton.
+
+        After committing a new layer tree (with possibly stale position:fixed layer
+        positions), we need the scrolling tree to update those positions based on
+        the current scroll offset.
+        
+        Give ScrollingTreeScrollingNode an implementation of updateLayersAfterAncestorChange()
+        which is required to update fixed/sticky child nodes.
+
+        * WebCore.exp.in:
+        * page/scrolling/ScrollingTreeScrollingNode.cpp:
+        (WebCore::ScrollingTreeScrollingNode::updateLayersAfterAncestorChange):
+        * page/scrolling/ScrollingTreeScrollingNode.h:
+
</ins><span class="cx"> 2014-06-28  Juan A. Suarez Romero  &lt;jasuarez@igalia.com&gt;  and  Carlos Garcia Campos  &lt;cgarcia@igalia.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [GTK] Use public getter/setter in GObject DOM bindings properties implementation.
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCoreexpin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.exp.in (170567 => 170568)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.exp.in        2014-06-28 09:06:09 UTC (rev 170567)
+++ trunk/Source/WebCore/WebCore.exp.in        2014-06-28 14:50:39 UTC (rev 170568)
</span><span class="lines">@@ -2878,6 +2878,7 @@
</span><span class="cx"> __ZN7WebCore26ScrollingTreeScrollingNode17setScrollPositionERKNS_10FloatPointE
</span><span class="cx"> __ZN7WebCore26ScrollingTreeScrollingNode19updateAfterChildrenERKNS_18ScrollingStateNodeE
</span><span class="cx"> __ZN7WebCore26ScrollingTreeScrollingNode20updateBeforeChildrenERKNS_18ScrollingStateNodeE
</span><ins>+__ZN7WebCore26ScrollingTreeScrollingNode31updateLayersAfterAncestorChangeERKNS_17ScrollingTreeNodeERKNS_9FloatRectERKNS_9FloatSizeE
</ins><span class="cx"> __ZN7WebCore26ScrollingTreeScrollingNode46setScrollPositionWithoutContentEdgeConstraintsERKNS_10FloatPointE
</span><span class="cx"> __ZN7WebCore27ScrollingStateScrollingNode15setScrollOriginERKNS_8IntPointE
</span><span class="cx"> __ZN7WebCore27ScrollingStateScrollingNode17setScrollPositionERKNS_10FloatPointE
</span><span class="lines">@@ -3024,6 +3025,12 @@
</span><span class="cx"> __ZNK7WebCore7Element25containsFullScreenElementEv
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if ENABLE(GAMEPAD)
+__ZN7WebCore15GamepadProvider17setSharedProviderERS0_
+__ZN7WebCore15GamepadProvider6sharedEv
+__ZN7WebCore18HIDGamepadProvider6sharedEv
+#endif
+
</ins><span class="cx"> #if ENABLE(GEOLOCATION)
</span><span class="cx"> __ZN7WebCore11Geolocation12setIsAllowedEb
</span><span class="cx"> __ZN7WebCore11GeolocationD1Ev
</span><span class="lines">@@ -3442,9 +3449,3 @@
</span><span class="cx"> #if ENABLE(WEB_TIMING)
</span><span class="cx"> __ZNK7WebCore20ResourceResponseBase18resourceLoadTimingEv
</span><span class="cx"> #endif
</span><del>-
-#if ENABLE(GAMEPAD)
-__ZN7WebCore15GamepadProvider17setSharedProviderERS0_
-__ZN7WebCore15GamepadProvider6sharedEv
-__ZN7WebCore18HIDGamepadProvider6sharedEv
-#endif
</del></span></pre></div>
<a id="trunkSourceWebCorepagescrollingScrollingTreeScrollingNodecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp (170567 => 170568)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp        2014-06-28 09:06:09 UTC (rev 170567)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp        2014-06-28 14:50:39 UTC (rev 170568)
</span><span class="lines">@@ -78,6 +78,15 @@
</span><span class="cx">         scrollingTree().scrollingTreeNodeRequestsScroll(scrollingNodeID(), scrollingStateNode.requestedScrollPosition(), scrollingStateNode.requestedScrollPositionRepresentsProgrammaticScroll());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void ScrollingTreeScrollingNode::updateLayersAfterAncestorChange(const ScrollingTreeNode&amp; changedNode, const FloatRect&amp; fixedPositionRect, const FloatSize&amp; cumulativeDelta)
+{
+    if (!m_children)
+        return;
+
+    for (auto&amp; child : *m_children)
+        child-&gt;updateLayersAfterAncestorChange(changedNode, fixedPositionRect, cumulativeDelta);
+}
+
</ins><span class="cx"> void ScrollingTreeScrollingNode::setScrollPosition(const FloatPoint&amp; scrollPosition)
</span><span class="cx"> {
</span><span class="cx">     FloatPoint newScrollPosition = scrollPosition;
</span></span></pre></div>
<a id="trunkSourceWebCorepagescrollingScrollingTreeScrollingNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h (170567 => 170568)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h        2014-06-28 09:06:09 UTC (rev 170567)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h        2014-06-28 14:50:39 UTC (rev 170568)
</span><span class="lines">@@ -46,8 +46,7 @@
</span><span class="cx">     virtual void updateBeforeChildren(const ScrollingStateNode&amp;) override;
</span><span class="cx">     virtual void updateAfterChildren(const ScrollingStateNode&amp;) override;
</span><span class="cx"> 
</span><del>-    // FIXME: We should implement this when we support ScrollingTreeScrollingNodes as children.
-    virtual void updateLayersAfterAncestorChange(const ScrollingTreeNode&amp; /*changedNode*/, const FloatRect&amp; /*fixedPositionRect*/, const FloatSize&amp; /*cumulativeDelta*/) override { }
</del><ins>+    virtual void updateLayersAfterAncestorChange(const ScrollingTreeNode&amp; changedNode, const FloatRect&amp; fixedPositionRect, const FloatSize&amp; cumulativeDelta) override;
</ins><span class="cx"> 
</span><span class="cx">     virtual void handleWheelEvent(const PlatformWheelEvent&amp;) = 0;
</span><span class="cx">     virtual void setScrollPosition(const FloatPoint&amp;);
</span></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (170567 => 170568)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2014-06-28 09:06:09 UTC (rev 170567)
+++ trunk/Source/WebKit2/ChangeLog        2014-06-28 14:50:39 UTC (rev 170568)
</span><span class="lines">@@ -1,3 +1,29 @@
</span><ins>+2014-06-27  Simon Fraser  &lt;simon.fraser@apple.com&gt;
+
+        [iOS WK2] position:fixed inside accelerated overflow:scroll is jumpy
+        https://bugs.webkit.org/show_bug.cgi?id=134426
+        &lt;rdar://problem/17474523&gt;
+
+        Reviewed by Tim Horton.
+
+        After committing a new layer tree (with possibly stale position:fixed layer
+        positions), we need the scrolling tree to update those positions based on
+        the current scroll offset.
+        
+        To achieve that, implement ScrollingTreeOverflowScrollingNodeIOS::updateLayersAfterAncestorChange()
+        and have it add to the cumulative delta the difference between the last committed scroll
+        position and the current scroll position.
+        
+        Also make sure that ScrollingTreeOverflowScrollingNodeIOS doesn't call back to scrollViewDidScroll()
+        when we're updating its scroll position inside a scrolling tree commit.
+
+        * UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.h:
+        * UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm:
+        (WebKit::ScrollingTreeOverflowScrollingNodeIOS::ScrollingTreeOverflowScrollingNodeIOS):
+        (WebKit::ScrollingTreeOverflowScrollingNodeIOS::updateAfterChildren):
+        (WebKit::ScrollingTreeOverflowScrollingNodeIOS::updateLayersAfterAncestorChange):
+        (WebKit::ScrollingTreeOverflowScrollingNodeIOS::scrollViewDidScroll):
+
</ins><span class="cx"> 2014-06-27  Antti Koivisto  &lt;antti@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Flush throttling with remote layers
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessScrollingiosScrollingTreeOverflowScrollingNodeIOSh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.h (170567 => 170568)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.h        2014-06-28 09:06:09 UTC (rev 170567)
+++ trunk/Source/WebKit2/UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.h        2014-06-28 14:50:39 UTC (rev 170568)
</span><span class="lines">@@ -58,6 +58,8 @@
</span><span class="cx">     virtual void updateLayersAfterViewportChange(const WebCore::FloatRect&amp; fixedPositionRect, double scale) { }
</span><span class="cx">     virtual void updateLayersAfterDelegatedScroll(const WebCore::FloatPoint&amp; scrollPosition) override;
</span><span class="cx"> 
</span><ins>+    virtual void updateLayersAfterAncestorChange(const WebCore::ScrollingTreeNode&amp; changedNode, const WebCore::FloatRect&amp; fixedPositionRect, const WebCore::FloatSize&amp; cumulativeDelta) override;
+
</ins><span class="cx">     virtual void handleWheelEvent(const WebCore::PlatformWheelEvent&amp;) override { }
</span><span class="cx"> 
</span><span class="cx">     void updateChildNodesAfterScroll(const WebCore::FloatPoint&amp;);
</span><span class="lines">@@ -66,6 +68,7 @@
</span><span class="cx">     RetainPtr&lt;CALayer&gt; m_scrolledContentsLayer;
</span><span class="cx"> 
</span><span class="cx">     RetainPtr&lt;WKOverflowScrollViewDelegate&gt; m_scrollViewDelegate;
</span><ins>+    bool m_updatingFromStateNode;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebKit
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessScrollingiosScrollingTreeOverflowScrollingNodeIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm (170567 => 170568)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm        2014-06-28 09:06:09 UTC (rev 170567)
+++ trunk/Source/WebKit2/UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm        2014-06-28 14:50:39 UTC (rev 170568)
</span><span class="lines">@@ -35,6 +35,7 @@
</span><span class="cx"> #import &lt;WebCore/ScrollingTree.h&gt;
</span><span class="cx"> #import &lt;UIKit/UIPanGestureRecognizer.h&gt;
</span><span class="cx"> #import &lt;UIKit/UIScrollView.h&gt;
</span><ins>+#import &lt;wtf/TemporaryChange.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> using namespace WebCore;
</span><span class="cx"> 
</span><span class="lines">@@ -98,6 +99,7 @@
</span><span class="cx"> 
</span><span class="cx"> ScrollingTreeOverflowScrollingNodeIOS::ScrollingTreeOverflowScrollingNodeIOS(WebCore::ScrollingTree&amp; scrollingTree, WebCore::ScrollingNodeID nodeID)
</span><span class="cx">     : ScrollingTreeOverflowScrollingNode(scrollingTree, nodeID)
</span><ins>+    , m_updatingFromStateNode(false)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -136,6 +138,8 @@
</span><span class="cx"> {
</span><span class="cx">     ScrollingTreeOverflowScrollingNode::updateAfterChildren(stateNode);
</span><span class="cx"> 
</span><ins>+    TemporaryChange&lt;bool&gt; updatingChange(m_updatingFromStateNode, true);
+
</ins><span class="cx">     const auto&amp; scrollingStateNode = toScrollingStateOverflowScrollingNode(stateNode);
</span><span class="cx"> 
</span><span class="cx">     if (scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::ScrollLayer)
</span><span class="lines">@@ -166,7 +170,7 @@
</span><span class="cx">             scrollView.contentOffset = scrollingStateNode.scrollPosition() + scrollOrigin();
</span><span class="cx">             recomputeInsets = true;
</span><span class="cx">         }
</span><del>-        
</del><ins>+
</ins><span class="cx">         if (recomputeInsets) {
</span><span class="cx">             UIEdgeInsets insets = UIEdgeInsetsMake(0, 0, 0, 0);
</span><span class="cx">             // With RTL or bottom-to-top scrolling (non-zero origin), we need extra space on the left or top.
</span><span class="lines">@@ -183,6 +187,17 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void ScrollingTreeOverflowScrollingNodeIOS::updateLayersAfterAncestorChange(const ScrollingTreeNode&amp; changedNode, const FloatRect&amp; fixedPositionRect, const FloatSize&amp; cumulativeDelta)
+{
+    if (!m_children)
+        return;
+
+    FloatSize scrollDelta = lastCommittedScrollPosition() - scrollPosition();
+
+    for (auto&amp; child : *m_children)
+        child-&gt;updateLayersAfterAncestorChange(changedNode, fixedPositionRect, cumulativeDelta + scrollDelta);
+}
+
</ins><span class="cx"> FloatPoint ScrollingTreeOverflowScrollingNodeIOS::scrollPosition() const
</span><span class="cx"> {
</span><span class="cx">     BEGIN_BLOCK_OBJC_EXCEPTIONS
</span><span class="lines">@@ -223,6 +238,9 @@
</span><span class="cx"> 
</span><span class="cx"> void ScrollingTreeOverflowScrollingNodeIOS::scrollViewDidScroll(const FloatPoint&amp; scrollPosition, bool inUserInteration)
</span><span class="cx"> {
</span><ins>+    if (m_updatingFromStateNode)
+        return;
+
</ins><span class="cx">     scrollingTree().scrollPositionChangedViaDelegatedScrolling(scrollingNodeID(), scrollPosition, inUserInteration);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>