<!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>[166380] 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/166380">166380</a></dd>
<dt>Author</dt> <dd>benjamin@webkit.org</dd>
<dt>Date</dt> <dd>2014-03-27 16:22:55 -0700 (Thu, 27 Mar 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>[iOS][WK2] Compute a good exposed rect when scaling WKContentView
https://bugs.webkit.org/show_bug.cgi?id=130761

Patch by Benjamin Poulain &lt;bpoulain@apple.com&gt; on 2014-03-27
Reviewed by Simon Fraser.

Source/WebCore: 

* WebCore.exp.in:
* platform/ScrollView.h:
* platform/ios/ScrollViewIOS.mm:
(WebCore::ScrollView::setScrollVelocity):
(WebCore::ScrollView::computeCoverageRect):
While scaling in, do not add margins tiles. When scaling out, add 1 margin tile size
all around.

Source/WebKit2: 

Add a simple heuristic to improve tiling while zooming. In theory we could take the zoom
center and scaleRate to split the speed between scrolling and pinching. In practice,
zoom is transitory and is not as predictable as scrolling, so this patch just does a very
simple heuristic:
-When zooming in, do not expand coverage.
-When zooming out, add half a tile size on every side.

* Shared/VisibleContentRectUpdateInfo.cpp:
(WebKit::VisibleContentRectUpdateInfo::encode):
(WebKit::VisibleContentRectUpdateInfo::decode):
* Shared/VisibleContentRectUpdateInfo.h:
(WebKit::VisibleContentRectUpdateInfo::VisibleContentRectUpdateInfo):
(WebKit::VisibleContentRectUpdateInfo::timestamp):
(WebKit::VisibleContentRectUpdateInfo::horizontalVelocity):
(WebKit::VisibleContentRectUpdateInfo::verticalVelocity):
(WebKit::VisibleContentRectUpdateInfo::scaleChangeRate):
* UIProcess/ios/WKContentView.mm:
(WebKit::HistoricalVelocityData::VelocityData::VelocityData):
(WebKit::HistoricalVelocityData::velocityForNewData):
(WebKit::HistoricalVelocityData::append):
(-[WKContentView didUpdateVisibleRect:unobscuredRect:scale:inStableState:]):
* WebProcess/WebPage/ios/WebPageIOS.mm:

(WebKit::adjustExposedRectForBoundedScale):
When zooming past the maximum size, adjust the exposed rect to continue tiling the area
at maximum size. Otherwise, we tile a tiny area, and have to retile larger when the animation
pull back the view to maximum scale.

(WebKit::adjustVelocityDataForBoundedScale):
Since we do not split the velocity from scrolling from the scaling, just clear the velocity when zooming.
Also clear the scaleChangeRate when the scale is out of bounds. There is no reason to add tiles for
temporary state.

(WebKit::WebPage::updateVisibleContentRects):</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="#trunkSourceWebCoreplatformScrollViewh">trunk/Source/WebCore/platform/ScrollView.h</a></li>
<li><a href="#trunkSourceWebCoreplatformiosScrollViewIOSmm">trunk/Source/WebCore/platform/ios/ScrollViewIOS.mm</a></li>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2SharedVisibleContentRectUpdateInfocpp">trunk/Source/WebKit2/Shared/VisibleContentRectUpdateInfo.cpp</a></li>
<li><a href="#trunkSourceWebKit2SharedVisibleContentRectUpdateInfoh">trunk/Source/WebKit2/Shared/VisibleContentRectUpdateInfo.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessiosWKContentViewmm">trunk/Source/WebKit2/UIProcess/ios/WKContentView.mm</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPageiosWebPageIOSmm">trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (166379 => 166380)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-03-27 22:59:07 UTC (rev 166379)
+++ trunk/Source/WebCore/ChangeLog        2014-03-27 23:22:55 UTC (rev 166380)
</span><span class="lines">@@ -1,3 +1,18 @@
</span><ins>+2014-03-27  Benjamin Poulain  &lt;bpoulain@apple.com&gt;
+
+        [iOS][WK2] Compute a good exposed rect when scaling WKContentView
+        https://bugs.webkit.org/show_bug.cgi?id=130761
+
+        Reviewed by Simon Fraser.
+
+        * WebCore.exp.in:
+        * platform/ScrollView.h:
+        * platform/ios/ScrollViewIOS.mm:
+        (WebCore::ScrollView::setScrollVelocity):
+        (WebCore::ScrollView::computeCoverageRect):
+        While scaling in, do not add margins tiles. When scaling out, add 1 margin tile size
+        all around.
+
</ins><span class="cx"> 2014-03-27  Commit Queue  &lt;commit-queue@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, rolling out r166360.
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCoreexpin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.exp.in (166379 => 166380)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.exp.in        2014-03-27 22:59:07 UTC (rev 166379)
+++ trunk/Source/WebCore/WebCore.exp.in        2014-03-27 23:22:55 UTC (rev 166380)
</span><span class="lines">@@ -2412,7 +2412,7 @@
</span><span class="cx"> _WebUIApplicationWillResignActiveNotification
</span><span class="cx"> __ZN7WebCore10FloatPointC1ERK7CGPoint
</span><span class="cx"> __ZN7WebCore10ScrollView15setScrollOffsetERKNS_8IntPointE
</span><del>-__ZN7WebCore10ScrollView17setScrollVelocityEddd
</del><ins>+__ZN7WebCore10ScrollView17setScrollVelocityEdddd
</ins><span class="cx"> __ZN7WebCore10ScrollView21setExposedContentRectERKNS_7IntRectE
</span><span class="cx"> __ZN7WebCore10ScrollView24setUnobscuredContentRectERKNS_7IntRectE
</span><span class="cx"> __ZN7WebCore10XLinkNames4initEv
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformScrollViewh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/ScrollView.h (166379 => 166380)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/ScrollView.h        2014-03-27 22:59:07 UTC (rev 166379)
+++ trunk/Source/WebCore/platform/ScrollView.h        2014-03-27 23:22:55 UTC (rev 166380)
</span><span class="lines">@@ -186,7 +186,7 @@
</span><span class="cx">     void setExposedContentRect(const IntRect&amp;);
</span><span class="cx">     void setUnobscuredContentRect(const IntRect&amp;);
</span><span class="cx"> 
</span><del>-    void setScrollVelocity(double horizontalVelocity, double verticalVelocity, double timestamp);
</del><ins>+    void setScrollVelocity(double horizontalVelocity, double verticalVelocity, double scaleChangeRate, double timestamp);
</ins><span class="cx">     FloatRect computeCoverageRect(double horizontalMargin, double verticalMargin) const;
</span><span class="cx"> 
</span><span class="cx">     void setActualScrollPosition(const IntPoint&amp;);
</span><span class="lines">@@ -420,6 +420,7 @@
</span><span class="cx"> 
</span><span class="cx">     double m_horizontalVelocity;
</span><span class="cx">     double m_verticalVelocity;
</span><ins>+    double m_scaleChangeRate;
</ins><span class="cx">     double m_lastVelocityUpdateTime;
</span><span class="cx"> #else
</span><span class="cx">     IntRect m_fixedVisibleContentRect;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformiosScrollViewIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/ios/ScrollViewIOS.mm (166379 => 166380)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/ios/ScrollViewIOS.mm        2014-03-27 22:59:07 UTC (rev 166379)
+++ trunk/Source/WebCore/platform/ios/ScrollViewIOS.mm        2014-03-27 23:22:55 UTC (rev 166380)
</span><span class="lines">@@ -119,10 +119,11 @@
</span><span class="cx">     m_unobscuredContentRect = rect;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void ScrollView::setScrollVelocity(double horizontalVelocity, double verticalVelocity, double timestamp)
</del><ins>+void ScrollView::setScrollVelocity(double horizontalVelocity, double verticalVelocity, double scaleChangeRate, double timestamp)
</ins><span class="cx"> {
</span><span class="cx">     m_horizontalVelocity = horizontalVelocity;
</span><span class="cx">     m_verticalVelocity = verticalVelocity;
</span><ins>+    m_scaleChangeRate = scaleChangeRate;
</ins><span class="cx">     m_lastVelocityUpdateTime = timestamp;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -148,7 +149,7 @@
</span><span class="cx">             futureRect.setY(std::max(futureRect.y() - verticalMargin, 0.));
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (!m_horizontalVelocity &amp;&amp; !m_verticalVelocity) {
</del><ins>+    if (m_scaleChangeRate &lt;= 0 &amp;&amp; !m_horizontalVelocity &amp;&amp; !m_verticalVelocity) {
</ins><span class="cx">         futureRect.setWidth(futureRect.width() + horizontalMargin);
</span><span class="cx">         futureRect.setHeight(futureRect.height() + verticalMargin);
</span><span class="cx">         futureRect.setX(std::max(futureRect.x() - horizontalMargin / 2, 0.));
</span></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (166379 => 166380)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2014-03-27 22:59:07 UTC (rev 166379)
+++ trunk/Source/WebKit2/ChangeLog        2014-03-27 23:22:55 UTC (rev 166380)
</span><span class="lines">@@ -1,3 +1,45 @@
</span><ins>+2014-03-27  Benjamin Poulain  &lt;bpoulain@apple.com&gt;
+
+        [iOS][WK2] Compute a good exposed rect when scaling WKContentView
+        https://bugs.webkit.org/show_bug.cgi?id=130761
+
+        Reviewed by Simon Fraser.
+
+        Add a simple heuristic to improve tiling while zooming. In theory we could take the zoom
+        center and scaleRate to split the speed between scrolling and pinching. In practice,
+        zoom is transitory and is not as predictable as scrolling, so this patch just does a very
+        simple heuristic:
+        -When zooming in, do not expand coverage.
+        -When zooming out, add half a tile size on every side.
+
+        * Shared/VisibleContentRectUpdateInfo.cpp:
+        (WebKit::VisibleContentRectUpdateInfo::encode):
+        (WebKit::VisibleContentRectUpdateInfo::decode):
+        * Shared/VisibleContentRectUpdateInfo.h:
+        (WebKit::VisibleContentRectUpdateInfo::VisibleContentRectUpdateInfo):
+        (WebKit::VisibleContentRectUpdateInfo::timestamp):
+        (WebKit::VisibleContentRectUpdateInfo::horizontalVelocity):
+        (WebKit::VisibleContentRectUpdateInfo::verticalVelocity):
+        (WebKit::VisibleContentRectUpdateInfo::scaleChangeRate):
+        * UIProcess/ios/WKContentView.mm:
+        (WebKit::HistoricalVelocityData::VelocityData::VelocityData):
+        (WebKit::HistoricalVelocityData::velocityForNewData):
+        (WebKit::HistoricalVelocityData::append):
+        (-[WKContentView didUpdateVisibleRect:unobscuredRect:scale:inStableState:]):
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+
+        (WebKit::adjustExposedRectForBoundedScale):
+        When zooming past the maximum size, adjust the exposed rect to continue tiling the area
+        at maximum size. Otherwise, we tile a tiny area, and have to retile larger when the animation
+        pull back the view to maximum scale.
+
+        (WebKit::adjustVelocityDataForBoundedScale):
+        Since we do not split the velocity from scrolling from the scaling, just clear the velocity when zooming.
+        Also clear the scaleChangeRate when the scale is out of bounds. There is no reason to add tiles for
+        temporary state.
+
+        (WebKit::WebPage::updateVisibleContentRects):
+
</ins><span class="cx"> 2014-03-27  Anders Carlsson  &lt;andersca@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Add _ prefix to WKRemoteObjectRegistery and WKRemoteObjectInterface
</span></span></pre></div>
<a id="trunkSourceWebKit2SharedVisibleContentRectUpdateInfocpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Shared/VisibleContentRectUpdateInfo.cpp (166379 => 166380)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Shared/VisibleContentRectUpdateInfo.cpp        2014-03-27 22:59:07 UTC (rev 166379)
+++ trunk/Source/WebKit2/Shared/VisibleContentRectUpdateInfo.cpp        2014-03-27 23:22:55 UTC (rev 166380)
</span><span class="lines">@@ -41,6 +41,7 @@
</span><span class="cx">     encoder &lt;&lt; m_timestamp;
</span><span class="cx">     encoder &lt;&lt; m_horizontalVelocity;
</span><span class="cx">     encoder &lt;&lt; m_verticalVelocity;
</span><ins>+    encoder &lt;&lt; m_scaleChangeRate;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool VisibleContentRectUpdateInfo::decode(IPC::ArgumentDecoder&amp; decoder, VisibleContentRectUpdateInfo&amp; result)
</span><span class="lines">@@ -63,6 +64,8 @@
</span><span class="cx">         return false;
</span><span class="cx">     if (!decoder.decode(result.m_verticalVelocity))
</span><span class="cx">         return false;
</span><ins>+    if (!decoder.decode(result.m_scaleChangeRate))
+        return false;
</ins><span class="cx"> 
</span><span class="cx">     return true;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebKit2SharedVisibleContentRectUpdateInfoh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Shared/VisibleContentRectUpdateInfo.h (166379 => 166380)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Shared/VisibleContentRectUpdateInfo.h        2014-03-27 22:59:07 UTC (rev 166379)
+++ trunk/Source/WebKit2/Shared/VisibleContentRectUpdateInfo.h        2014-03-27 23:22:55 UTC (rev 166380)
</span><span class="lines">@@ -44,7 +44,7 @@
</span><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    VisibleContentRectUpdateInfo(uint64_t updateID, const WebCore::FloatRect&amp; exposedRect, const WebCore::FloatRect&amp; unobscuredRect, const WebCore::FloatRect&amp; customFixedPositionRect, double scale, bool inStableState, double timestamp, double horizontalVelocity, double verticalVelocity)
</del><ins>+    VisibleContentRectUpdateInfo(uint64_t updateID, const WebCore::FloatRect&amp; exposedRect, const WebCore::FloatRect&amp; unobscuredRect, const WebCore::FloatRect&amp; customFixedPositionRect, double scale, bool inStableState, double timestamp, double horizontalVelocity, double verticalVelocity, double scaleChangeRate)
</ins><span class="cx">         : m_exposedRect(exposedRect)
</span><span class="cx">         , m_unobscuredRect(unobscuredRect)
</span><span class="cx">         , m_customFixedPositionRect(customFixedPositionRect)
</span><span class="lines">@@ -54,6 +54,7 @@
</span><span class="cx">         , m_timestamp(timestamp)
</span><span class="cx">         , m_horizontalVelocity(horizontalVelocity)
</span><span class="cx">         , m_verticalVelocity(verticalVelocity)
</span><ins>+        , m_scaleChangeRate(scaleChangeRate)
</ins><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -64,6 +65,11 @@
</span><span class="cx">     uint64_t updateID() const { return m_updateID; }
</span><span class="cx">     bool inStableState() const { return m_inStableState; }
</span><span class="cx"> 
</span><ins>+    double timestamp() const { return m_timestamp; }
+    double horizontalVelocity() const { return m_horizontalVelocity; }
+    double verticalVelocity() const { return m_verticalVelocity; }
+    double scaleChangeRate() const { return m_scaleChangeRate; }
+
</ins><span class="cx">     void encode(IPC::ArgumentEncoder&amp;) const;
</span><span class="cx">     static bool decode(IPC::ArgumentDecoder&amp;, VisibleContentRectUpdateInfo&amp;);
</span><span class="cx"> 
</span><span class="lines">@@ -74,10 +80,10 @@
</span><span class="cx">     double m_scale;
</span><span class="cx">     uint64_t m_updateID;
</span><span class="cx">     bool m_inStableState;
</span><del>-public:
</del><span class="cx">     double m_timestamp;
</span><span class="cx">     double m_horizontalVelocity;
</span><span class="cx">     double m_verticalVelocity;
</span><ins>+    double m_scaleChangeRate;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> inline bool operator==(const VisibleContentRectUpdateInfo&amp; a, const VisibleContentRectUpdateInfo&amp; b)
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessiosWKContentViewmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/ios/WKContentView.mm (166379 => 166380)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/ios/WKContentView.mm        2014-03-27 22:59:07 UTC (rev 166379)
+++ trunk/Source/WebKit2/UIProcess/ios/WKContentView.mm        2014-03-27 23:22:55 UTC (rev 166380)
</span><span class="lines">@@ -65,6 +65,26 @@
</span><span class="cx"> namespace WebKit {
</span><span class="cx"> class HistoricalVelocityData {
</span><span class="cx"> public:
</span><ins>+    struct VelocityData {
+        VelocityData()
+            : horizontalVelocity(0)
+            , verticalVelocity(0)
+            , scaleChangeRate(0)
+        {
+        }
+
+        VelocityData(double horizontalVelocity, double verticalVelocity, double scaleChangeRate)
+            : horizontalVelocity(horizontalVelocity)
+            , verticalVelocity(verticalVelocity)
+            , scaleChangeRate(scaleChangeRate)
+        {
+        }
+
+        double horizontalVelocity;
+        double verticalVelocity;
+        double scaleChangeRate;
+    };
+
</ins><span class="cx">     HistoricalVelocityData()
</span><span class="cx">         : m_historySize(0)
</span><span class="cx">         , m_latestDataIndex(0)
</span><span class="lines">@@ -72,13 +92,13 @@
</span><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    CGSize velocityForNewData(CGPoint newPosition, double timestamp)
</del><ins>+    VelocityData velocityForNewData(CGPoint newPosition, double scale, double timestamp)
</ins><span class="cx">     {
</span><span class="cx">         // Due to all the source of rect update, the input is very noisy. To smooth the output, we accumulate all changes
</span><span class="cx">         // within 1 frame as a single update. No speed computation is ever done on data within the same frame.
</span><span class="cx">         const double filteringThreshold = 1 / 60.;
</span><span class="cx"> 
</span><del>-        CGSize velocity = CGSizeZero;
</del><ins>+        VelocityData velocityData;
</ins><span class="cx">         if (m_historySize &gt; 0) {
</span><span class="cx">             unsigned oldestDataIndex;
</span><span class="cx">             unsigned distanceToLastHistoricalData = m_historySize - 1;
</span><span class="lines">@@ -88,25 +108,27 @@
</span><span class="cx">                 oldestDataIndex = m_historySize - (distanceToLastHistoricalData - m_latestDataIndex);
</span><span class="cx"> 
</span><span class="cx">             double timeDelta = timestamp - m_history[oldestDataIndex].timestamp;
</span><del>-            if (timeDelta &gt; filteringThreshold)
-                velocity =  CGSizeMake((newPosition.x - m_history[oldestDataIndex].position.x) / timeDelta, (newPosition.y - m_history[oldestDataIndex].position.y) / timeDelta);
</del><ins>+            if (timeDelta &gt; filteringThreshold) {
+                Data&amp; oldestData = m_history[oldestDataIndex];
+                velocityData = VelocityData((newPosition.x - oldestData.position.x) / timeDelta, (newPosition.y - oldestData.position.y) / timeDelta, (scale - oldestData.scale) / timeDelta);
+            }
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         double timeSinceLastAppend = timestamp - m_lastAppendTimestamp;
</span><span class="cx">         if (timeSinceLastAppend &gt; filteringThreshold)
</span><del>-            append(newPosition, timestamp);
</del><ins>+            append(newPosition, scale, timestamp);
</ins><span class="cx">         else
</span><del>-            m_history[m_latestDataIndex] = { timestamp, newPosition };
-        return velocity;
</del><ins>+            m_history[m_latestDataIndex] = { timestamp, newPosition, scale };
+        return velocityData;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     void clear() { m_historySize = 0; }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    void append(CGPoint newPosition, double timestamp)
</del><ins>+    void append(CGPoint newPosition, double scale, double timestamp)
</ins><span class="cx">     {
</span><span class="cx">         m_latestDataIndex = (m_latestDataIndex + 1) % maxHistoryDepth;
</span><del>-        m_history[m_latestDataIndex] = { timestamp, newPosition };
</del><ins>+        m_history[m_latestDataIndex] = { timestamp, newPosition, scale };
</ins><span class="cx"> 
</span><span class="cx">         unsigned size = m_historySize + 1;
</span><span class="cx">         if (size &lt;= maxHistoryDepth)
</span><span class="lines">@@ -122,10 +144,10 @@
</span><span class="cx">     unsigned m_latestDataIndex;
</span><span class="cx">     double m_lastAppendTimestamp;
</span><span class="cx"> 
</span><del>-    // FIXME: add scale information.
</del><span class="cx">     struct Data {
</span><span class="cx">         double timestamp;
</span><span class="cx">         CGPoint position;
</span><ins>+        double scale;
</ins><span class="cx">     } m_history[maxHistoryDepth];
</span><span class="cx"> };
</span><span class="cx"> } // namespace WebKit
</span><span class="lines">@@ -279,9 +301,9 @@
</span><span class="cx"> - (void)didUpdateVisibleRect:(CGRect)visibleRect unobscuredRect:(CGRect)unobscuredRect scale:(CGFloat)zoomScale inStableState:(BOOL)isStableState
</span><span class="cx"> {
</span><span class="cx">     double timestamp = monotonicallyIncreasingTime();
</span><del>-    CGSize velocity = CGSizeZero;
</del><ins>+    HistoricalVelocityData::VelocityData velocityData;
</ins><span class="cx">     if (!isStableState)
</span><del>-        velocity = _historicalKinematicData.velocityForNewData(visibleRect.origin, timestamp);
</del><ins>+        velocityData = _historicalKinematicData.velocityForNewData(visibleRect.origin, zoomScale, timestamp);
</ins><span class="cx">     else
</span><span class="cx">         _historicalKinematicData.clear();
</span><span class="cx"> 
</span><span class="lines">@@ -294,7 +316,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     FloatRect customFixedPositionRect = fixedPositionRectFromExposedRect(unobscuredRect, [self bounds].size, zoomScale);
</span><del>-    _page-&gt;updateVisibleContentRects(VisibleContentRectUpdateInfo(_page-&gt;nextVisibleContentRectUpdateID(), visibleRect, unobscuredRect, customFixedPositionRect, filteredScale, isStableState, timestamp, velocity.width, velocity.height));
</del><ins>+    _page-&gt;updateVisibleContentRects(VisibleContentRectUpdateInfo(_page-&gt;nextVisibleContentRectUpdateID(), visibleRect, unobscuredRect, customFixedPositionRect, filteredScale, isStableState, timestamp, velocityData.horizontalVelocity, velocityData.verticalVelocity, velocityData.scaleChangeRate));
</ins><span class="cx">     
</span><span class="cx">     RemoteScrollingCoordinatorProxy* scrollingCoordinator = _page-&gt;scrollingCoordinatorProxy();
</span><span class="cx">     scrollingCoordinator-&gt;viewportChangedViaDelegatedScrolling(scrollingCoordinator-&gt;rootScrollingNodeID(), unobscuredRect, zoomScale);
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPageiosWebPageIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm (166379 => 166380)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm        2014-03-27 22:59:07 UTC (rev 166379)
+++ trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm        2014-03-27 23:22:55 UTC (rev 166380)
</span><span class="lines">@@ -1711,7 +1711,7 @@
</span><span class="cx"> 
</span><span class="cx">         IntRect unobscuredContentRect(scrollPosition, minimumLayoutSizeInDocumentCoordinate);
</span><span class="cx">         frameView.setUnobscuredContentRect(unobscuredContentRect);
</span><del>-        frameView.setScrollVelocity(0, 0, monotonicallyIncreasingTime());
</del><ins>+        frameView.setScrollVelocity(0, 0, 0, monotonicallyIncreasingTime());
</ins><span class="cx"> 
</span><span class="cx">         // FIXME: We could send down the obscured margins to find a better exposed rect and unobscured rect.
</span><span class="cx">         // It is not a big deal at the moment because the tile coverage will always extend past the obscured bottom inset.
</span><span class="lines">@@ -1735,18 +1735,45 @@
</span><span class="cx">     [[NSNotificationCenter defaultCenter] postNotificationName:WebUIApplicationDidBecomeActiveNotification object:nil];
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static inline FloatRect adjustExposedRectForBoundedScale(const FloatRect&amp; exposedRect, double exposedRectScale, double boundedScale)
+{
+    if (exposedRectScale &lt; boundedScale)
+        return exposedRect;
+
+    double overscaledWidth = exposedRect.width();
+    double missingHorizonalMargin = exposedRect.width() * exposedRectScale / boundedScale - overscaledWidth;
+
+    double overscaledHeight = exposedRect.height();
+    double missingVerticalMargin = exposedRect.height() * exposedRectScale / boundedScale - overscaledHeight;
+
+    return FloatRect(exposedRect.x() - missingHorizonalMargin / 2, exposedRect.y() - missingVerticalMargin / 2, exposedRect.width() + missingHorizonalMargin, exposedRect.height() + missingVerticalMargin);
+}
+
+static inline void adjustVelocityDataForBoundedScale(double&amp; horizontalVelocity, double&amp; verticalVelocity, double&amp; scaleChangeRate, double exposedRectScale, double boundedScale)
+{
+    if (scaleChangeRate) {
+        horizontalVelocity = 0;
+        verticalVelocity = 0;
+    }
+
+    if (exposedRectScale != boundedScale)
+        scaleChangeRate = 0;
+}
+
</ins><span class="cx"> void WebPage::updateVisibleContentRects(const VisibleContentRectUpdateInfo&amp; visibleContentRectUpdateInfo)
</span><span class="cx"> {
</span><span class="cx">     m_hasReceivedVisibleContentRectsAfterDidCommitLoad = true;
</span><span class="cx">     m_lastVisibleContentRectUpdateID = visibleContentRectUpdateInfo.updateID();
</span><span class="cx"> 
</span><ins>+    double boundedScale = std::min(m_viewportConfiguration.maximumScale(), std::max(m_viewportConfiguration.minimumScale(), visibleContentRectUpdateInfo.scale()));
+
</ins><span class="cx">     FloatRect exposedRect = visibleContentRectUpdateInfo.exposedRect();
</span><del>-    m_drawingArea-&gt;setExposedContentRect(enclosingIntRect(exposedRect));
</del><ins>+    FloatRect adjustedExposedRect = adjustExposedRectForBoundedScale(exposedRect, visibleContentRectUpdateInfo.scale(), boundedScale);
+    m_drawingArea-&gt;setExposedContentRect(enclosingIntRect(adjustedExposedRect));
</ins><span class="cx"> 
</span><span class="cx">     IntRect roundedUnobscuredRect = roundedIntRect(visibleContentRectUpdateInfo.unobscuredRect());
</span><span class="cx">     IntPoint scrollPosition = roundedUnobscuredRect.location();
</span><span class="cx"> 
</span><del>-    double boundedScale = std::min(m_viewportConfiguration.maximumScale(), std::max(m_viewportConfiguration.minimumScale(), visibleContentRectUpdateInfo.scale()));
</del><span class="cx">     float floatBoundedScale = boundedScale;
</span><span class="cx">     if (floatBoundedScale != m_page-&gt;pageScaleFactor()) {
</span><span class="cx">         m_scaleWasSetByUIProcess = true;
</span><span class="lines">@@ -1759,8 +1786,14 @@
</span><span class="cx"> 
</span><span class="cx">     m_page-&gt;mainFrame().view()-&gt;setScrollOffset(scrollPosition);
</span><span class="cx">     m_page-&gt;mainFrame().view()-&gt;setUnobscuredContentRect(roundedUnobscuredRect);
</span><del>-    m_page-&gt;mainFrame().view()-&gt;setScrollVelocity(visibleContentRectUpdateInfo.m_horizontalVelocity, visibleContentRectUpdateInfo.m_verticalVelocity, visibleContentRectUpdateInfo.m_timestamp);
</del><span class="cx"> 
</span><ins>+    double horizontalVelocity = visibleContentRectUpdateInfo.horizontalVelocity();
+    double verticalVelocity = visibleContentRectUpdateInfo.verticalVelocity();
+    double scaleChangeRate = visibleContentRectUpdateInfo.scaleChangeRate();
+    adjustVelocityDataForBoundedScale(horizontalVelocity, verticalVelocity, scaleChangeRate, visibleContentRectUpdateInfo.scale(), boundedScale);
+
+    m_page-&gt;mainFrame().view()-&gt;setScrollVelocity(horizontalVelocity, verticalVelocity, scaleChangeRate, visibleContentRectUpdateInfo.timestamp());
+
</ins><span class="cx">     if (visibleContentRectUpdateInfo.inStableState())
</span><span class="cx">         m_page-&gt;mainFrame().view()-&gt;setCustomFixedPositionLayoutRect(enclosingIntRect(visibleContentRectUpdateInfo.customFixedPositionRect()));
</span><span class="cx"> }
</span></span></pre>
</div>
</div>

</body>
</html>