<!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>[172649] 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/172649">172649</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2014-08-15 14:09:13 -0700 (Fri, 15 Aug 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Implement snapping behavior for iOS
https://bugs.webkit.org/show_bug.cgi?id=135769

Patch by Wenson Hsieh &lt;wenson_hsieh@apple.com&gt; on 2014-08-15
Reviewed by Brent Fulgham.

Source/WebCore:

Added support for snap points on iOS. This entails sending snap points from the web process to the UI process
by encoding and decoding snap points and updating ScrollingTreeOverflowScrollingNodeIOS and WKWebView to support
animation to snap points in the cases of mainframe and overflow scrolling, respectively.

There are no new tests yet -- we'll need to find a way to test this!

* WebCore.exp.in:
* page/scrolling/AsyncScrollingCoordinator.cpp:
(WebCore::setStateScrollingNodeSnapOffsetsAsFloat): Helper functions used to convert LayoutUnits to floats for snap offsets.
(WebCore::AsyncScrollingCoordinator::frameViewLayoutUpdated): Update snap offsets for mainframe scrolling, as well as the state node.
(WebCore::AsyncScrollingCoordinator::updateOverflowScrollingNode): Added snap offsets.
* page/scrolling/AxisScrollSnapOffsets.h:
(WebCore::closestSnapOffset): Computes the closest snap offset given a sorted vector of comparable types (e.g. float, LayoutUnit).
* page/scrolling/ScrollingCoordinator.h:
* page/scrolling/ScrollingStateScrollingNode.cpp:
(WebCore::ScrollingStateScrollingNode::ScrollingStateScrollingNode):
(WebCore::ScrollingStateScrollingNode::setHorizontalSnapOffsets):
(WebCore::ScrollingStateScrollingNode::setVerticalSnapOffsets):
* page/scrolling/ScrollingStateScrollingNode.h:
(WebCore::ScrollingStateScrollingNode::horizontalSnapOffsets):
(WebCore::ScrollingStateScrollingNode::verticalSnapOffsets):
* page/scrolling/ScrollingTreeScrollingNode.cpp:
(WebCore::ScrollingTreeScrollingNode::updateBeforeChildren):
* page/scrolling/ScrollingTreeScrollingNode.h:
(WebCore::ScrollingTreeScrollingNode::horizontalSnapOffsets):
(WebCore::ScrollingTreeScrollingNode::verticalSnapOffsets):
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::updateScrollInfoAfterLayout): Update snap offsets for overflow scrolling.
* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::updateScrollCoordinatedLayer): Updates the state node's snap offsets for overflow scrolling.

Source/WebKit2:

Added support for snap points on iOS.

* Shared/Scrolling/RemoteScrollingCoordinatorTransaction.cpp:
(ArgumentCoder&lt;ScrollingStateScrollingNode&gt;::encode): Added snap offset encoding.
(ArgumentCoder&lt;ScrollingStateScrollingNode&gt;::decode): Added snap offset decoding.
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView scrollViewWillEndDragging:withVelocity:targetContentOffset:]): For mainframe scrolling, retargets the scroll destination to the appropriate snap point.
* UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h: Added methods to extract relevant information for WKWebView from snap offsets in mainframe scrolling.
* UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm:
(-[WKOverflowScrollViewDelegate scrollViewWillEndDragging:withVelocity:targetContentOffset:]): For overflow scrolling, retargets the scroll destination to the appropriate snap point.
(WebKit::ScrollingTreeOverflowScrollingNodeIOS::updateAfterChildren): Sets the deceleration factor to FAST if snap points are active.
* UIProcess/ios/RemoteScrollingCoordinatorProxyIOS.mm:
(WebKit::RemoteScrollingCoordinatorProxy::adjustTargetContentOffsetForSnapping): Used by WKWebView for mainframe scrolling to retarget the scroll destination, if necessary.
(WebKit::RemoteScrollingCoordinatorProxy::shouldSetScrollViewDecelerationRateFast): Used by WKWebView for mainframe scrolling to determine whether to set deceleration rate to the fast value.
(WebKit::RemoteScrollingCoordinatorProxy::shouldSnapForMainFrameScrolling): Helper method.
(WebKit::RemoteScrollingCoordinatorProxy::closestSnapOffsetForMainFrameScrolling): Helper method.</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="#trunkSourceWebCorepagescrollingAsyncScrollingCoordinatorcpp">trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp</a></li>
<li><a href="#trunkSourceWebCorepagescrollingAxisScrollSnapOffsetscpp">trunk/Source/WebCore/page/scrolling/AxisScrollSnapOffsets.cpp</a></li>
<li><a href="#trunkSourceWebCorepagescrollingAxisScrollSnapOffsetsh">trunk/Source/WebCore/page/scrolling/AxisScrollSnapOffsets.h</a></li>
<li><a href="#trunkSourceWebCorepagescrollingScrollingCoordinatorh">trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.h</a></li>
<li><a href="#trunkSourceWebCorepagescrollingScrollingStateScrollingNodecpp">trunk/Source/WebCore/page/scrolling/ScrollingStateScrollingNode.cpp</a></li>
<li><a href="#trunkSourceWebCorepagescrollingScrollingStateScrollingNodeh">trunk/Source/WebCore/page/scrolling/ScrollingStateScrollingNode.h</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="#trunkSourceWebCoreplatformmacAxisScrollSnapAnimatormm">trunk/Source/WebCore/platform/mac/AxisScrollSnapAnimator.mm</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderLayercpp">trunk/Source/WebCore/rendering/RenderLayer.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderLayerCompositorcpp">trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp</a></li>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2SharedScrollingRemoteScrollingCoordinatorTransactioncpp">trunk/Source/WebKit2/Shared/Scrolling/RemoteScrollingCoordinatorTransaction.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPICocoaWKWebViewmm">trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessScrollingRemoteScrollingCoordinatorProxyh">trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessScrollingiosScrollingTreeOverflowScrollingNodeIOSmm">trunk/Source/WebKit2/UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessiosRemoteScrollingCoordinatorProxyIOSmm">trunk/Source/WebKit2/UIProcess/ios/RemoteScrollingCoordinatorProxyIOS.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (172648 => 172649)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebCore/ChangeLog        2014-08-15 21:09:13 UTC (rev 172649)
</span><span class="lines">@@ -1,3 +1,41 @@
</span><ins>+2014-08-15  Wenson Hsieh  &lt;wenson_hsieh@apple.com&gt;
+
+        Implement snapping behavior for iOS
+        https://bugs.webkit.org/show_bug.cgi?id=135769
+
+        Reviewed by Brent Fulgham.
+
+        Added support for snap points on iOS. This entails sending snap points from the web process to the UI process
+        by encoding and decoding snap points and updating ScrollingTreeOverflowScrollingNodeIOS and WKWebView to support
+        animation to snap points in the cases of mainframe and overflow scrolling, respectively.
+
+        There are no new tests yet -- we'll need to find a way to test this!
+
+        * WebCore.exp.in:
+        * page/scrolling/AsyncScrollingCoordinator.cpp:
+        (WebCore::setStateScrollingNodeSnapOffsetsAsFloat): Helper functions used to convert LayoutUnits to floats for snap offsets.
+        (WebCore::AsyncScrollingCoordinator::frameViewLayoutUpdated): Update snap offsets for mainframe scrolling, as well as the state node.
+        (WebCore::AsyncScrollingCoordinator::updateOverflowScrollingNode): Added snap offsets.
+        * page/scrolling/AxisScrollSnapOffsets.h:
+        (WebCore::closestSnapOffset): Computes the closest snap offset given a sorted vector of comparable types (e.g. float, LayoutUnit).
+        * page/scrolling/ScrollingCoordinator.h:
+        * page/scrolling/ScrollingStateScrollingNode.cpp:
+        (WebCore::ScrollingStateScrollingNode::ScrollingStateScrollingNode):
+        (WebCore::ScrollingStateScrollingNode::setHorizontalSnapOffsets):
+        (WebCore::ScrollingStateScrollingNode::setVerticalSnapOffsets):
+        * page/scrolling/ScrollingStateScrollingNode.h:
+        (WebCore::ScrollingStateScrollingNode::horizontalSnapOffsets):
+        (WebCore::ScrollingStateScrollingNode::verticalSnapOffsets):
+        * page/scrolling/ScrollingTreeScrollingNode.cpp:
+        (WebCore::ScrollingTreeScrollingNode::updateBeforeChildren):
+        * page/scrolling/ScrollingTreeScrollingNode.h:
+        (WebCore::ScrollingTreeScrollingNode::horizontalSnapOffsets):
+        (WebCore::ScrollingTreeScrollingNode::verticalSnapOffsets):
+        * rendering/RenderLayer.cpp:
+        (WebCore::RenderLayer::updateScrollInfoAfterLayout): Update snap offsets for overflow scrolling.
+        * rendering/RenderLayerCompositor.cpp:
+        (WebCore::RenderLayerCompositor::updateScrollCoordinatedLayer): Updates the state node's snap offsets for overflow scrolling.
+
</ins><span class="cx"> 2014-08-15  Dirk Schulze  &lt;krit@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Turn r/rx/ry to presentation attributes
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCoreexpin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.exp.in (172648 => 172649)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.exp.in        2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebCore/WebCore.exp.in        2014-08-15 21:09:13 UTC (rev 172649)
</span><span class="lines">@@ -3011,6 +3011,11 @@
</span><span class="cx"> __ZN7WebCore16FilterOperationsaSERKS0_
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if ENABLE(CSS_SCROLL_SNAP)
+__ZN7WebCore27ScrollingStateScrollingNode22setVerticalSnapOffsetsERKN3WTF6VectorIfLm0ENS1_15CrashOnOverflowEEE
+__ZN7WebCore27ScrollingStateScrollingNode24setHorizontalSnapOffsetsERKN3WTF6VectorIfLm0ENS1_15CrashOnOverflowEEE
+#endif
+
</ins><span class="cx"> #if ENABLE(DASHBOARD_SUPPORT)
</span><span class="cx"> __ZNK7WebCore8Document16annotatedRegionsEv
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCorepagescrollingAsyncScrollingCoordinatorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp (172648 => 172649)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp        2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp        2014-08-15 21:09:13 UTC (rev 172649)
</span><span class="lines">@@ -59,6 +59,20 @@
</span><span class="cx">     scheduleTreeStateCommit();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static inline void setStateScrollingNodeSnapOffsetsAsFloat(ScrollingStateScrollingNode&amp; node, ScrollEventAxis axis, const Vector&lt;LayoutUnit&gt;&amp; snapOffsets, float deviceScaleFactor)
+{
+    // FIXME: Incorporate current page scale factor in snapping to device pixel. Perhaps we should just convert to float here and let UI process do the pixel snapping?
+    Vector&lt;float&gt; snapOffsetsAsFloat;
+    snapOffsetsAsFloat.reserveInitialCapacity(snapOffsets.size());
+    for (size_t i = 0; i &lt; snapOffsets.size(); ++i)
+        snapOffsetsAsFloat.append(roundToDevicePixel(snapOffsets[i], deviceScaleFactor, false));
+
+    if (axis == ScrollEventAxis::Horizontal)
+        node.setHorizontalSnapOffsets(snapOffsetsAsFloat);
+    else
+        node.setVerticalSnapOffsets(snapOffsetsAsFloat);
+}
+
</ins><span class="cx"> void AsyncScrollingCoordinator::frameViewLayoutUpdated(FrameView* frameView)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(isMainThread());
</span><span class="lines">@@ -97,6 +111,15 @@
</span><span class="cx">     node-&gt;setTotalContentsSize(frameView-&gt;totalContentsSize());
</span><span class="cx">     node-&gt;setReachableContentsSize(frameView-&gt;totalContentsSize());
</span><span class="cx"> 
</span><ins>+#if ENABLE(CSS_SCROLL_SNAP)
+    frameView-&gt;updateSnapOffsets();
+    if (const Vector&lt;LayoutUnit&gt;* horizontalSnapOffsets = frameView-&gt;horizontalSnapOffsets())
+        setStateScrollingNodeSnapOffsetsAsFloat(*node, ScrollEventAxis::Horizontal, *horizontalSnapOffsets, frameView-&gt;frame().document()-&gt;deviceScaleFactor());
+
+    if (const Vector&lt;LayoutUnit&gt;* verticalSnapOffsets = frameView-&gt;verticalSnapOffsets())
+        setStateScrollingNodeSnapOffsetsAsFloat(*node, ScrollEventAxis::Vertical, *verticalSnapOffsets, frameView-&gt;frame().document()-&gt;deviceScaleFactor());
+#endif
+
</ins><span class="cx">     ScrollableAreaParameters scrollParameters;
</span><span class="cx">     scrollParameters.horizontalScrollElasticity = frameView-&gt;horizontalScrollElasticity();
</span><span class="cx">     scrollParameters.verticalScrollElasticity = frameView-&gt;verticalScrollElasticity();
</span><span class="lines">@@ -399,6 +422,10 @@
</span><span class="cx">         node-&gt;setTotalContentsSize(scrollingGeometry-&gt;contentSize);
</span><span class="cx">         node-&gt;setReachableContentsSize(scrollingGeometry-&gt;reachableContentSize);
</span><span class="cx">         node-&gt;setScrollableAreaSize(scrollingGeometry-&gt;scrollableAreaSize);
</span><ins>+#if ENABLE(CSS_SCROLL_SNAP)
+        setStateScrollingNodeSnapOffsetsAsFloat(*node, ScrollEventAxis::Horizontal, scrollingGeometry-&gt;horizontalSnapOffsets, scrolledContentsLayer-&gt;deviceScaleFactor());
+        setStateScrollingNodeSnapOffsetsAsFloat(*node, ScrollEventAxis::Vertical, scrollingGeometry-&gt;verticalSnapOffsets, scrolledContentsLayer-&gt;deviceScaleFactor());
+#endif
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorepagescrollingAxisScrollSnapOffsetscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/scrolling/AxisScrollSnapOffsets.cpp (172648 => 172649)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/scrolling/AxisScrollSnapOffsets.cpp        2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebCore/page/scrolling/AxisScrollSnapOffsets.cpp        2014-08-15 21:09:13 UTC (rev 172649)
</span><span class="lines">@@ -43,14 +43,22 @@
</span><span class="cx">         if (RenderBox* box = child-&gt;renderBox()) {
</span><span class="cx">             LayoutUnit viewWidth = box-&gt;width();
</span><span class="cx">             LayoutUnit viewHeight = box-&gt;height();
</span><del>-            // FIXME: Check behavior with CSS rotations.
</del><ins>+#if PLATFORM(IOS)
+            // FIXME: Investigate why using localToContainerPoint gives the wrong offsets for iOS mainframe. Also, these offsets won't take transforms into account (make sure to test this!)
+            float left = child-&gt;offsetLeft();
+            float top = child-&gt;offsetTop();
+#else
+            // FIXME: Check that localToContainerPoint works with CSS rotations.
</ins><span class="cx">             FloatPoint position = box-&gt;localToContainerPoint(FloatPoint(), parent.renderBox());
</span><ins>+            float left = position.x();
+            float top = position.y();
+#endif
</ins><span class="cx">             for (SnapCoordinate coordinate : box-&gt;style().scrollSnapCoordinates()) {
</span><del>-                LayoutUnit lastPotentialSnapPositionX = LayoutUnit(position.x()) + valueForLength(coordinate.first, viewWidth);
</del><ins>+                LayoutUnit lastPotentialSnapPositionX = LayoutUnit(left) + valueForLength(coordinate.first, viewWidth);
</ins><span class="cx">                 if (shouldAddHorizontalChildOffsets &amp;&amp; lastPotentialSnapPositionX &gt; 0)
</span><span class="cx">                     horizontalSnapOffsetSubsequence.append(lastPotentialSnapPositionX);
</span><span class="cx"> 
</span><del>-                LayoutUnit lastPotentialSnapPositionY = LayoutUnit(position.y()) + valueForLength(coordinate.second, viewHeight);
</del><ins>+                LayoutUnit lastPotentialSnapPositionY = LayoutUnit(top) + valueForLength(coordinate.second, viewHeight);
</ins><span class="cx">                 if (shouldAddVerticalChildOffsets &amp;&amp; lastPotentialSnapPositionY &gt; 0)
</span><span class="cx">                     verticalSnapOffsetSubsequence.append(lastPotentialSnapPositionY);
</span><span class="cx">             }
</span></span></pre></div>
<a id="trunkSourceWebCorepagescrollingAxisScrollSnapOffsetsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/scrolling/AxisScrollSnapOffsets.h (172648 => 172649)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/scrolling/AxisScrollSnapOffsets.h        2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebCore/page/scrolling/AxisScrollSnapOffsets.h        2014-08-15 21:09:13 UTC (rev 172649)
</span><span class="lines">@@ -41,8 +41,11 @@
</span><span class="cx"> 
</span><span class="cx"> void updateSnapOffsetsForScrollableArea(ScrollableArea&amp;, HTMLElement&amp; scrollingElement, const RenderBox&amp; scrollingElementBox, const RenderStyle&amp; scrollingElementStyle);
</span><span class="cx"> 
</span><del>-template &lt;typename T&gt;
-T closestSnapOffset(const Vector&lt;T&gt;&amp; snapOffsets, T scrollDestination, float velocity)
</del><ins>+// closestSnapOffset is a templated function that takes in a Vector representing snap offsets as LayoutTypes (e.g. LayoutUnit or float) and
+// as well as a VelocityType indicating the velocity (e.g. float, CGFloat, etc.) This function is templated because the UI process will now
+// use pixel snapped floats to represent snap offsets rather than LayoutUnits.
+template &lt;typename LayoutType, typename VelocityType&gt;
+LayoutType closestSnapOffset(const Vector&lt;LayoutType&gt;&amp; snapOffsets, LayoutType scrollDestination, VelocityType velocity)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(snapOffsets.size());
</span><span class="cx">     if (scrollDestination &lt;= snapOffsets.first())
</span><span class="lines">@@ -65,8 +68,8 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">     }
</span><del>-    T lowerSnapPosition = snapOffsets[lowerIndex];
-    T upperSnapPosition = snapOffsets[upperIndex];
</del><ins>+    LayoutType lowerSnapPosition = snapOffsets[lowerIndex];
+    LayoutType upperSnapPosition = snapOffsets[upperIndex];
</ins><span class="cx">     // Nonzero velocity indicates a flick gesture. Even if another snap point is closer, snap to the one in the direction of the flick gesture.
</span><span class="cx">     if (velocity)
</span><span class="cx">         return velocity &lt; 0 ? lowerSnapPosition : upperSnapPosition;
</span></span></pre></div>
<a id="trunkSourceWebCorepagescrollingScrollingCoordinatorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.h (172648 => 172649)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.h        2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.h        2014-08-15 21:09:13 UTC (rev 172649)
</span><span class="lines">@@ -43,6 +43,10 @@
</span><span class="cx"> #include &lt;wtf/RetainPtr.h&gt;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if ENABLE(CSS_SCROLL_SNAP)
+#include &quot;AxisScrollSnapOffsets.h&quot;
+#endif
+
</ins><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="cx"> typedef unsigned SynchronousScrollingReasons;
</span><span class="lines">@@ -164,6 +168,10 @@
</span><span class="cx">         FloatSize reachableContentSize; // Smaller than contentSize when overflow is hidden on one axis.
</span><span class="cx">         FloatPoint scrollPosition;
</span><span class="cx">         IntPoint scrollOrigin;
</span><ins>+#if ENABLE(CSS_SCROLL_SNAP)
+        Vector&lt;LayoutUnit&gt; horizontalSnapOffsets;
+        Vector&lt;LayoutUnit&gt; verticalSnapOffsets;
+#endif
</ins><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     virtual void updateFrameScrollingNode(ScrollingNodeID, GraphicsLayer* /*scrollLayer*/, GraphicsLayer* /*scrolledContentsLayer*/, GraphicsLayer* /*counterScrollingLayer*/, GraphicsLayer* /*insetClipLayer*/, const ScrollingGeometry* = nullptr) { }
</span></span></pre></div>
<a id="trunkSourceWebCorepagescrollingScrollingStateScrollingNodecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/scrolling/ScrollingStateScrollingNode.cpp (172648 => 172649)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/scrolling/ScrollingStateScrollingNode.cpp        2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebCore/page/scrolling/ScrollingStateScrollingNode.cpp        2014-08-15 21:09:13 UTC (rev 172649)
</span><span class="lines">@@ -48,6 +48,10 @@
</span><span class="cx">     , m_scrollPosition(stateNode.scrollPosition())
</span><span class="cx">     , m_requestedScrollPosition(stateNode.requestedScrollPosition())
</span><span class="cx">     , m_scrollOrigin(stateNode.scrollOrigin())
</span><ins>+#if ENABLE(CSS_SCROLL_SNAP)
+    , m_horizontalSnapOffsets(stateNode.horizontalSnapOffsets())
+    , m_verticalSnapOffsets(stateNode.verticalSnapOffsets())
+#endif
</ins><span class="cx">     , m_scrollableAreaParameters(stateNode.scrollableAreaParameters())
</span><span class="cx">     , m_requestedScrollPositionRepresentsProgrammaticScroll(stateNode.requestedScrollPositionRepresentsProgrammaticScroll())
</span><span class="cx"> {
</span><span class="lines">@@ -102,6 +106,26 @@
</span><span class="cx">     setPropertyChanged(ScrollOrigin);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if ENABLE(CSS_SCROLL_SNAP)
+void ScrollingStateScrollingNode::setHorizontalSnapOffsets(const Vector&lt;float&gt;&amp; snapOffsets)
+{
+    if (m_horizontalSnapOffsets == snapOffsets)
+        return;
+
+    m_horizontalSnapOffsets = snapOffsets;
+    setPropertyChanged(HorizontalSnapOffsets);
+}
+
+void ScrollingStateScrollingNode::setVerticalSnapOffsets(const Vector&lt;float&gt;&amp; snapOffsets)
+{
+    if (m_verticalSnapOffsets == snapOffsets)
+        return;
+
+    m_verticalSnapOffsets = snapOffsets;
+    setPropertyChanged(VerticalSnapOffsets);
+}
+#endif
+
</ins><span class="cx"> void ScrollingStateScrollingNode::setScrollableAreaParameters(const ScrollableAreaParameters&amp; parameters)
</span><span class="cx"> {
</span><span class="cx">     if (m_scrollableAreaParameters == parameters)
</span></span></pre></div>
<a id="trunkSourceWebCorepagescrollingScrollingStateScrollingNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/scrolling/ScrollingStateScrollingNode.h (172648 => 172649)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/scrolling/ScrollingStateScrollingNode.h        2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebCore/page/scrolling/ScrollingStateScrollingNode.h        2014-08-15 21:09:13 UTC (rev 172649)
</span><span class="lines">@@ -48,6 +48,10 @@
</span><span class="cx">         ScrollableAreaParams,
</span><span class="cx">         RequestedScrollPosition,
</span><span class="cx">         NumScrollingStateNodeBits,
</span><ins>+#if ENABLE(CSS_SCROLL_SNAP)
+        HorizontalSnapOffsets,
+        VerticalSnapOffsets,
+#endif
</ins><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     const FloatSize&amp; scrollableAreaSize() const { return m_scrollableAreaSize; }
</span><span class="lines">@@ -65,6 +69,14 @@
</span><span class="cx">     const IntPoint&amp; scrollOrigin() const { return m_scrollOrigin; }
</span><span class="cx">     void setScrollOrigin(const IntPoint&amp;);
</span><span class="cx"> 
</span><ins>+#if ENABLE(CSS_SCROLL_SNAP)
+    const Vector&lt;float&gt;&amp; horizontalSnapOffsets() const { return m_horizontalSnapOffsets; }
+    void setHorizontalSnapOffsets(const Vector&lt;float&gt;&amp;);
+
+    const Vector&lt;float&gt;&amp; verticalSnapOffsets() const { return m_verticalSnapOffsets; }
+    void setVerticalSnapOffsets(const Vector&lt;float&gt;&amp;);
+#endif
+
</ins><span class="cx">     const ScrollableAreaParameters&amp; scrollableAreaParameters() const { return m_scrollableAreaParameters; }
</span><span class="cx">     void setScrollableAreaParameters(const ScrollableAreaParameters&amp; params);
</span><span class="cx"> 
</span><span class="lines">@@ -85,6 +97,10 @@
</span><span class="cx">     FloatPoint m_scrollPosition;
</span><span class="cx">     FloatPoint m_requestedScrollPosition;
</span><span class="cx">     IntPoint m_scrollOrigin;
</span><ins>+#if ENABLE(CSS_SCROLL_SNAP)
+    Vector&lt;float&gt; m_horizontalSnapOffsets;
+    Vector&lt;float&gt; m_verticalSnapOffsets;
+#endif
</ins><span class="cx">     ScrollableAreaParameters m_scrollableAreaParameters;
</span><span class="cx">     bool m_requestedScrollPositionRepresentsProgrammaticScroll;
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebCorepagescrollingScrollingTreeScrollingNodecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp (172648 => 172649)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp        2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp        2014-08-15 21:09:13 UTC (rev 172649)
</span><span class="lines">@@ -67,6 +67,14 @@
</span><span class="cx">     if (state.hasChangedProperty(ScrollingStateScrollingNode::ScrollOrigin))
</span><span class="cx">         m_scrollOrigin = state.scrollOrigin();
</span><span class="cx"> 
</span><ins>+#if ENABLE(CSS_SCROLL_SNAP)
+    if (state.hasChangedProperty(ScrollingStateScrollingNode::HorizontalSnapOffsets))
+        m_horizontalSnapOffsets = state.horizontalSnapOffsets();
+
+    if (state.hasChangedProperty(ScrollingStateScrollingNode::VerticalSnapOffsets))
+        m_verticalSnapOffsets = state.verticalSnapOffsets();
+#endif
+
</ins><span class="cx">     if (state.hasChangedProperty(ScrollingStateScrollingNode::ScrollableAreaParams))
</span><span class="cx">         m_scrollableAreaParameters = state.scrollableAreaParameters();
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCorepagescrollingScrollingTreeScrollingNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h (172648 => 172649)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h        2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h        2014-08-15 21:09:13 UTC (rev 172649)
</span><span class="lines">@@ -57,6 +57,11 @@
</span><span class="cx"> 
</span><span class="cx">     virtual FloatPoint scrollPosition() const = 0;
</span><span class="cx"> 
</span><ins>+#if ENABLE(CSS_SCROLL_SNAP)
+    const Vector&lt;float&gt;&amp; horizontalSnapOffsets() const { return m_horizontalSnapOffsets; }
+    const Vector&lt;float&gt;&amp; verticalSnapOffsets() const { return m_verticalSnapOffsets; }
+#endif
+
</ins><span class="cx"> protected:
</span><span class="cx">     ScrollingTreeScrollingNode(ScrollingTree&amp;, ScrollingNodeType, ScrollingNodeID);
</span><span class="cx"> 
</span><span class="lines">@@ -92,7 +97,10 @@
</span><span class="cx">     FloatSize m_reachableContentsSize;
</span><span class="cx">     FloatPoint m_lastCommittedScrollPosition;
</span><span class="cx">     IntPoint m_scrollOrigin;
</span><del>-    
</del><ins>+#if ENABLE(CSS_SCROLL_SNAP)
+    Vector&lt;float&gt; m_horizontalSnapOffsets;
+    Vector&lt;float&gt; m_verticalSnapOffsets;
+#endif
</ins><span class="cx">     ScrollableAreaParameters m_scrollableAreaParameters;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmacAxisScrollSnapAnimatormm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mac/AxisScrollSnapAnimator.mm (172648 => 172649)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mac/AxisScrollSnapAnimator.mm        2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebCore/platform/mac/AxisScrollSnapAnimator.mm        2014-08-15 21:09:13 UTC (rev 172649)
</span><span class="lines">@@ -169,7 +169,7 @@
</span><span class="cx">     LayoutUnit projectedScrollDestination = newState == ScrollSnapState::Gliding ? m_beginTrackingWheelDeltaOffset + LayoutUnit(projectedInertialScrollDistance(initialWheelDelta)) : offset;
</span><span class="cx">     projectedScrollDestination = std::min(std::max(projectedScrollDestination, m_snapOffsets-&gt;first()), m_snapOffsets-&gt;last());
</span><span class="cx">     m_initialOffset = offset;
</span><del>-    m_targetOffset = closestSnapOffset&lt;LayoutUnit&gt;(*m_snapOffsets, projectedScrollDestination, initialWheelDelta);
</del><ins>+    m_targetOffset = closestSnapOffset&lt;LayoutUnit, float&gt;(*m_snapOffsets, projectedScrollDestination, initialWheelDelta);
</ins><span class="cx">     if (m_initialOffset == m_targetOffset)
</span><span class="cx">         return;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderLayercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderLayer.cpp (172648 => 172649)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderLayer.cpp        2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebCore/rendering/RenderLayer.cpp        2014-08-15 21:09:13 UTC (rev 172649)
</span><span class="lines">@@ -3309,6 +3309,12 @@
</span><span class="cx">     // Composited scrolling may need to be enabled or disabled if the amount of overflow changed.
</span><span class="cx">     if (compositor().updateLayerCompositingState(*this))
</span><span class="cx">         compositor().setCompositingLayersNeedRebuild();
</span><ins>+
+#if ENABLE(CSS_SCROLL_SNAP)
+    // FIXME: Ensure that offsets are also updated in case of programmatic style changes.
+    // https://bugs.webkit.org/show_bug.cgi?id=135964
+    updateSnapOffsets();
+#endif
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool RenderLayer::overflowControlsIntersectRect(const IntRect&amp; localRect) const
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderLayerCompositorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp (172648 => 172649)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp        2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp        2014-08-15 21:09:13 UTC (rev 172649)
</span><span class="lines">@@ -3770,6 +3770,12 @@
</span><span class="cx">             scrollingGeometry.scrollableAreaSize = layer.visibleSize();
</span><span class="cx">             scrollingGeometry.contentSize = layer.contentsSize();
</span><span class="cx">             scrollingGeometry.reachableContentSize = layer.scrollableContentsSize();
</span><ins>+#if ENABLE(CSS_SCROLL_SNAP)
+            if (const Vector&lt;LayoutUnit&gt;* offsets = layer.horizontalSnapOffsets())
+                scrollingGeometry.horizontalSnapOffsets = *offsets;
+            if (const Vector&lt;LayoutUnit&gt;* offsets = layer.verticalSnapOffsets())
+                scrollingGeometry.verticalSnapOffsets = *offsets;
+#endif
</ins><span class="cx">             scrollingCoordinator-&gt;updateOverflowScrollingNode(nodeID, backing-&gt;scrollingLayer(), backing-&gt;scrollingContentsLayer(), &amp;scrollingGeometry);
</span><span class="cx">         }
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (172648 => 172649)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebKit2/ChangeLog        2014-08-15 21:09:13 UTC (rev 172649)
</span><span class="lines">@@ -1,3 +1,27 @@
</span><ins>+2014-08-15  Wenson Hsieh  &lt;wenson_hsieh@apple.com&gt;
+
+        Implement snapping behavior for iOS
+        https://bugs.webkit.org/show_bug.cgi?id=135769
+
+        Reviewed by Brent Fulgham.
+
+        Added support for snap points on iOS.
+
+        * Shared/Scrolling/RemoteScrollingCoordinatorTransaction.cpp:
+        (ArgumentCoder&lt;ScrollingStateScrollingNode&gt;::encode): Added snap offset encoding.
+        (ArgumentCoder&lt;ScrollingStateScrollingNode&gt;::decode): Added snap offset decoding.
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView scrollViewWillEndDragging:withVelocity:targetContentOffset:]): For mainframe scrolling, retargets the scroll destination to the appropriate snap point.
+        * UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h: Added methods to extract relevant information for WKWebView from snap offsets in mainframe scrolling.
+        * UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm:
+        (-[WKOverflowScrollViewDelegate scrollViewWillEndDragging:withVelocity:targetContentOffset:]): For overflow scrolling, retargets the scroll destination to the appropriate snap point.
+        (WebKit::ScrollingTreeOverflowScrollingNodeIOS::updateAfterChildren): Sets the deceleration factor to FAST if snap points are active.
+        * UIProcess/ios/RemoteScrollingCoordinatorProxyIOS.mm:
+        (WebKit::RemoteScrollingCoordinatorProxy::adjustTargetContentOffsetForSnapping): Used by WKWebView for mainframe scrolling to retarget the scroll destination, if necessary.
+        (WebKit::RemoteScrollingCoordinatorProxy::shouldSetScrollViewDecelerationRateFast): Used by WKWebView for mainframe scrolling to determine whether to set deceleration rate to the fast value.
+        (WebKit::RemoteScrollingCoordinatorProxy::shouldSnapForMainFrameScrolling): Helper method.
+        (WebKit::RemoteScrollingCoordinatorProxy::closestSnapOffsetForMainFrameScrolling): Helper method.
+
</ins><span class="cx"> 2014-08-15  Gavin Barraclough  &lt;barraclough@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Fix plugin visibility check.
</span></span></pre></div>
<a id="trunkSourceWebKit2SharedScrollingRemoteScrollingCoordinatorTransactioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Shared/Scrolling/RemoteScrollingCoordinatorTransaction.cpp (172648 => 172649)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Shared/Scrolling/RemoteScrollingCoordinatorTransaction.cpp        2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebKit2/Shared/Scrolling/RemoteScrollingCoordinatorTransaction.cpp        2014-08-15 21:09:13 UTC (rev 172649)
</span><span class="lines">@@ -128,6 +128,10 @@
</span><span class="cx">     SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::ReachableContentsSize, reachableContentsSize)
</span><span class="cx">     SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::ScrollPosition, scrollPosition)
</span><span class="cx">     SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::ScrollOrigin, scrollOrigin)
</span><ins>+#if ENABLE(CSS_SCROLL_SNAP)
+    SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::HorizontalSnapOffsets, horizontalSnapOffsets)
+    SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::VerticalSnapOffsets, verticalSnapOffsets)
+#endif
</ins><span class="cx">     SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::ScrollableAreaParams, scrollableAreaParameters)
</span><span class="cx">     SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::RequestedScrollPosition, requestedScrollPosition)
</span><span class="cx">     SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::RequestedScrollPosition, requestedScrollPositionRepresentsProgrammaticScroll)
</span><span class="lines">@@ -193,6 +197,10 @@
</span><span class="cx">     SCROLLING_NODE_DECODE(ScrollingStateScrollingNode::ReachableContentsSize, FloatSize, setReachableContentsSize);
</span><span class="cx">     SCROLLING_NODE_DECODE(ScrollingStateScrollingNode::ScrollPosition, FloatPoint, setScrollPosition);
</span><span class="cx">     SCROLLING_NODE_DECODE(ScrollingStateScrollingNode::ScrollOrigin, IntPoint, setScrollOrigin);
</span><ins>+#if ENABLE(CSS_SCROLL_SNAP)
+    SCROLLING_NODE_DECODE(ScrollingStateScrollingNode::HorizontalSnapOffsets, Vector&lt;float&gt;, setHorizontalSnapOffsets);
+    SCROLLING_NODE_DECODE(ScrollingStateScrollingNode::VerticalSnapOffsets, Vector&lt;float&gt;, setVerticalSnapOffsets);
+#endif
</ins><span class="cx">     SCROLLING_NODE_DECODE(ScrollingStateScrollingNode::ScrollableAreaParams, ScrollableAreaParameters, setScrollableAreaParameters);
</span><span class="cx">     
</span><span class="cx">     if (node.hasChangedProperty(ScrollingStateScrollingNode::RequestedScrollPosition)) {
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPICocoaWKWebViewmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm (172648 => 172649)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm        2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm        2014-08-15 21:09:13 UTC (rev 172649)
</span><span class="lines">@@ -83,6 +83,7 @@
</span><span class="cx"> #import &quot;PrintInfo.h&quot;
</span><span class="cx"> #import &quot;ProcessThrottler.h&quot;
</span><span class="cx"> #import &quot;RemoteLayerTreeDrawingAreaProxy.h&quot;
</span><ins>+#import &quot;RemoteScrollingCoordinatorProxy.h&quot;
</ins><span class="cx"> #import &quot;WKPDFView.h&quot;
</span><span class="cx"> #import &quot;WKScrollView.h&quot;
</span><span class="cx"> #import &quot;WKWebViewContentProviderRegistry.h&quot;
</span><span class="lines">@@ -1282,6 +1283,11 @@
</span><span class="cx">     if (scrollView.panGestureRecognizer.state == UIGestureRecognizerStateBegan)
</span><span class="cx">         [_contentView scrollViewWillStartPanOrPinchGesture];
</span><span class="cx">     [_contentView willStartZoomOrScroll];
</span><ins>+#if ENABLE(CSS_SCROLL_SNAP) &amp;&amp; ENABLE(ASYNC_SCROLLING)
+    // FIXME: We will want to detect whether snapping will occur before beginning to drag. See WebPageProxy::didCommitLayerTree.
+    WebKit::RemoteScrollingCoordinatorProxy* coordinator = _page-&gt;scrollingCoordinatorProxy();
+    scrollView.decelerationRate = (coordinator &amp;&amp; coordinator-&gt;shouldSetScrollViewDecelerationRateFast()) ? UIScrollViewDecelerationRateFast : UIScrollViewDecelerationRateNormal;
+#endif
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (void)_didFinishScrolling
</span><span class="lines">@@ -1299,6 +1305,13 @@
</span><span class="cx">     // zooming. We'll animate to the right place once the zoom finishes.
</span><span class="cx">     if ([scrollView isZooming])
</span><span class="cx">         *targetContentOffset = [scrollView contentOffset];
</span><ins>+#if ENABLE(CSS_SCROLL_SNAP) &amp;&amp; ENABLE(ASYNC_SCROLLING)
+    if (WebKit::RemoteScrollingCoordinatorProxy* coordinator = _page-&gt;scrollingCoordinatorProxy()) {
+        // FIXME: Here, I'm finding the maximum horizontal/vertical scroll offsets. There's probably a better way to do this.
+        CGSize maxScrollOffsets = CGSizeMake(scrollView.contentSize.width - scrollView.bounds.size.width, scrollView.contentSize.height - scrollView.bounds.size.height);
+        coordinator-&gt;adjustTargetContentOffsetForSnapping(maxScrollOffsets, velocity, targetContentOffset);
+    }
+#endif
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessScrollingRemoteScrollingCoordinatorProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h (172648 => 172649)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h        2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h        2014-08-15 21:09:13 UTC (rev 172649)
</span><span class="lines">@@ -84,10 +84,18 @@
</span><span class="cx">     void scrollingTreeNodeWillStartPanGesture();
</span><span class="cx">     void scrollingTreeNodeWillStartScroll();
</span><span class="cx">     void scrollingTreeNodeDidEndScroll();
</span><ins>+#if ENABLE(CSS_SCROLL_SNAP)
+    void adjustTargetContentOffsetForSnapping(CGSize maxScrollDimensions, CGPoint velocity, CGPoint* targetContentOffset) const;
+    bool shouldSetScrollViewDecelerationRateFast() const;
</ins><span class="cx"> #endif
</span><ins>+#endif
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     void connectStateNodeLayers(WebCore::ScrollingStateTree&amp;, const RemoteLayerTreeHost&amp;);
</span><ins>+#if ENABLE(CSS_SCROLL_SNAP)
+    bool shouldSnapForMainFrameScrolling(WebCore::ScrollEventAxis) const;
+    float closestSnapOffsetForMainFrameScrolling(WebCore::ScrollEventAxis, float scrollDestination, float velocity) const;
+#endif
</ins><span class="cx"> 
</span><span class="cx">     WebPageProxy&amp; m_webPageProxy;
</span><span class="cx">     RefPtr&lt;RemoteScrollingTree&gt; m_scrollingTree;
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessScrollingiosScrollingTreeOverflowScrollingNodeIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm (172648 => 172649)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm        2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebKit2/UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm        2014-08-15 21:09:13 UTC (rev 172649)
</span><span class="lines">@@ -37,6 +37,10 @@
</span><span class="cx"> #import &lt;UIKit/UIScrollView.h&gt;
</span><span class="cx"> #import &lt;wtf/TemporaryChange.h&gt;
</span><span class="cx"> 
</span><ins>+#if ENABLE(CSS_SCROLL_SNAP)
+#import &lt;WebCore/AxisScrollSnapOffsets.h&gt;
+#endif
+
</ins><span class="cx"> using namespace WebCore;
</span><span class="cx"> 
</span><span class="cx"> @interface WKOverflowScrollViewDelegate : NSObject &lt;UIScrollViewDelegate&gt; {
</span><span class="lines">@@ -73,6 +77,16 @@
</span><span class="cx">     _scrollingTreeNode-&gt;overflowScrollWillStart();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if ENABLE(CSS_SCROLL_SNAP)
+- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
+{
+    if (!_scrollingTreeNode-&gt;horizontalSnapOffsets().isEmpty())
+        targetContentOffset-&gt;x = closestSnapOffset&lt;float, CGFloat&gt;(_scrollingTreeNode-&gt;horizontalSnapOffsets(), targetContentOffset-&gt;x, velocity.x);
+    if (!_scrollingTreeNode-&gt;verticalSnapOffsets().isEmpty())
+        targetContentOffset-&gt;y = closestSnapOffset&lt;float, CGFloat&gt;(_scrollingTreeNode-&gt;verticalSnapOffsets(), targetContentOffset-&gt;y, velocity.y);
+}
+#endif
+
</ins><span class="cx"> - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)willDecelerate
</span><span class="cx"> {
</span><span class="cx">     if (_inUserInteraction &amp;&amp; !willDecelerate) {
</span><span class="lines">@@ -188,7 +202,12 @@
</span><span class="cx"> 
</span><span class="cx">             scrollView.contentInset = insets;
</span><span class="cx">         }
</span><del>-            
</del><ins>+
+#if ENABLE(CSS_SCROLL_SNAP)
+        // FIXME: If only one axis snaps in 2D scrolling, the other axis will decelerate fast as well. Is this what we want?
+        if (scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::HorizontalSnapOffsets) || scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::VerticalSnapOffsets))
+            scrollView.decelerationRate = horizontalSnapOffsets().size() || verticalSnapOffsets().size() ? UIScrollViewDecelerationRateFast : UIScrollViewDecelerationRateNormal;
+#endif
</ins><span class="cx">         END_BLOCK_OBJC_EXCEPTIONS
</span><span class="cx">     }
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessiosRemoteScrollingCoordinatorProxyIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/ios/RemoteScrollingCoordinatorProxyIOS.mm (172648 => 172649)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/ios/RemoteScrollingCoordinatorProxyIOS.mm        2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebKit2/UIProcess/ios/RemoteScrollingCoordinatorProxyIOS.mm        2014-08-15 21:09:13 UTC (rev 172649)
</span><span class="lines">@@ -23,20 +23,26 @@
</span><span class="cx">  * THE POSSIBILITY OF SUCH DAMAGE.
</span><span class="cx">  */
</span><span class="cx"> 
</span><del>-#include &quot;config.h&quot;
-#include &quot;RemoteScrollingCoordinatorProxy.h&quot;
</del><ins>+#import &quot;config.h&quot;
+#import &quot;RemoteScrollingCoordinatorProxy.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx"> #if ENABLE(ASYNC_SCROLLING)
</span><span class="cx"> 
</span><del>-#include &quot;LayerRepresentation.h&quot;
-#include &quot;RemoteLayerTreeHost.h&quot;
-#include &quot;WebPageProxy.h&quot;
-#include &lt;WebCore/ScrollingStateFrameScrollingNode.h&gt;
-#include &lt;WebCore/ScrollingStateOverflowScrollingNode.h&gt;
-#include &lt;WebCore/ScrollingStateTree.h&gt;
-#include &lt;UIKit/UIView.h&gt;
</del><ins>+#import &quot;LayerRepresentation.h&quot;
+#import &quot;RemoteLayerTreeHost.h&quot;
+#import &quot;WebPageProxy.h&quot;
+#import &lt;UIKit/UIView.h&gt;
+#import &lt;WebCore/ScrollingStateFrameScrollingNode.h&gt;
+#import &lt;WebCore/ScrollingStateOverflowScrollingNode.h&gt;
+#import &lt;WebCore/ScrollingStateTree.h&gt;
</ins><span class="cx"> 
</span><ins>+#if ENABLE(CSS_SCROLL_SNAP)
+#import &lt;WebCore/AxisScrollSnapOffsets.h&gt;
+#import &lt;WebCore/ScrollTypes.h&gt;
+#import &lt;WebCore/ScrollingTreeFrameScrollingNode.h&gt;
+#endif
+
</ins><span class="cx"> using namespace WebCore;
</span><span class="cx"> 
</span><span class="cx"> namespace WebKit {
</span><span class="lines">@@ -106,6 +112,47 @@
</span><span class="cx">     m_webPageProxy.overflowScrollDidEndScroll();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if ENABLE(CSS_SCROLL_SNAP)
+void RemoteScrollingCoordinatorProxy::adjustTargetContentOffsetForSnapping(CGSize maxScrollOffsets, CGPoint velocity, CGPoint* targetContentOffset) const
+{
+    // The bounds checking with maxScrollOffsets is to ensure that we won't interfere with rubber-banding when scrolling to the edge of the page.
+    if (shouldSnapForMainFrameScrolling(WebCore::ScrollEventAxis::Horizontal) &amp;&amp; targetContentOffset-&gt;x &gt; 0 &amp;&amp; targetContentOffset-&gt;x &lt; maxScrollOffsets.width) {
+        float potentialSnapPosition = closestSnapOffsetForMainFrameScrolling(WebCore::ScrollEventAxis::Horizontal, targetContentOffset-&gt;x, velocity.x);
+        targetContentOffset-&gt;x = std::min&lt;float&gt;(maxScrollOffsets.width, potentialSnapPosition);
+    }
+    // FIXME: We need to account for how the top navigation bar changes in size.
+    if (shouldSnapForMainFrameScrolling(WebCore::ScrollEventAxis::Vertical) &amp;&amp; targetContentOffset-&gt;y &gt; 0 &amp;&amp; targetContentOffset-&gt;y &lt; maxScrollOffsets.height) {
+        float potentialSnapPosition = closestSnapOffsetForMainFrameScrolling(WebCore::ScrollEventAxis::Vertical, targetContentOffset-&gt;y, velocity.y);
+        targetContentOffset-&gt;y = std::min&lt;float&gt;(maxScrollOffsets.height, potentialSnapPosition);
+    }
+}
+
+bool RemoteScrollingCoordinatorProxy::shouldSetScrollViewDecelerationRateFast() const
+{
+    return shouldSnapForMainFrameScrolling(ScrollEventAxis::Horizontal) || shouldSnapForMainFrameScrolling(ScrollEventAxis::Vertical);
+}
+
+bool RemoteScrollingCoordinatorProxy::shouldSnapForMainFrameScrolling(ScrollEventAxis axis) const
+{
+    ScrollingTreeNode* root = m_scrollingTree-&gt;rootNode();
+    if (root &amp;&amp; root-&gt;isFrameScrollingNode()) {
+        ScrollingTreeFrameScrollingNode* rootFrame = static_cast&lt;ScrollingTreeFrameScrollingNode*&gt;(root);
+        const Vector&lt;float&gt;&amp; snapOffsets = axis == ScrollEventAxis::Horizontal ? rootFrame-&gt;horizontalSnapOffsets() : rootFrame-&gt;verticalSnapOffsets();
+        return snapOffsets.size() &gt; 0;
+    }
+    return false;
+}
+
+float RemoteScrollingCoordinatorProxy::closestSnapOffsetForMainFrameScrolling(ScrollEventAxis axis, float scrollDestination, float velocity) const
+{
+    ScrollingTreeNode* root = m_scrollingTree-&gt;rootNode();
+    ASSERT(root &amp;&amp; root-&gt;isFrameScrollingNode());
+    ScrollingTreeFrameScrollingNode* rootFrame = static_cast&lt;ScrollingTreeFrameScrollingNode*&gt;(root);
+    const Vector&lt;float&gt;&amp; snapOffsets = axis == ScrollEventAxis::Horizontal ? rootFrame-&gt;horizontalSnapOffsets() : rootFrame-&gt;verticalSnapOffsets();
+    return closestSnapOffset&lt;float, float&gt;(snapOffsets, scrollDestination, velocity);
+}
+#endif
+
</ins><span class="cx"> } // namespace WebKit
</span><span class="cx"> 
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>