<!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>[160685] 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/160685">160685</a></dd>
<dt>Author</dt> <dd>timothy_horton@apple.com</dd>
<dt>Date</dt> <dd>2013-12-16 18:12:31 -0800 (Mon, 16 Dec 2013)</dd>
</dl>

<h3>Log Message</h3>
<pre>WebKit2 View Gestures: Pinching beyond the extremes doesn't animate back to the min/max
https://bugs.webkit.org/show_bug.cgi?id=125750

Reviewed by Simon Fraser.

When you let go of a pinch where you exceeded the maximum or minimum scale,
the view should animate back to the limit instead of snapping back.

* UIProcess/mac/ViewGestureController.cpp:
(WebKit::ViewGestureController::endMagnificationGesture):
Unscrolling the scaled origin here is wrong; we should send the same
value for 'origin' for commitTransientZoom that we do for adjustTransientZoom.
The drawing area can deal with transforming that however it needs to call scalePage().

* WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h:
* WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
(WebKit::TiledCoreAnimationDrawingArea::beginTransientZoom):
Drive-by use WebPage::mainFrameView().

(WebKit::TiledCoreAnimationDrawingArea::adjustTransientZoom):
Update the shadow layer's bounds, position, and shadow path while zooming,
instead of hiding it.

(WebKit::transientZoomSnapAnimationForKeyPath):
Create a CABasicAnimation that stays applied to its target when it finishes,
lasts for a quarter second, and uses the ease-in-ease-out timing function.

(WebKit::constrainZoomOriginForFrameView):
When we land a transient zoom, there may be overhang areas (linen, in the case of Mac)
visible. During the commit animation, we should move the RenderView layer appropriately
so that the page covers the entire view and there are no overhang areas visible.
Adapt some code from ScrollableArea to constrain the zoom origin to do so.

(WebKit::TiledCoreAnimationDrawingArea::commitTransientZoom):
Animate the RenderView layer's transform, and the shadow layer's bounds, position, and path.
When they complete, apply the zoom via scalePage() and flush the layer tree (otherwise there
can be a flash between removing the animations and the next flush with the new scale).

(WebKit::TiledCoreAnimationDrawingArea::applyTransientZoomToPage):
Move the code to land the transient zoom (via scalePage) and to put the shadow back
in the state WebCore left it out into its own function, so it can be called both from the
animation completion callback and from the short-circuit in the case where we don't need to animate.

* WebCore.exp.in:
Export a few things so WebKit2 can use them.</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="#trunkSourceWebCoreplatformKeyedCodingh">trunk/Source/WebCore/platform/KeyedCoding.h</a></li>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2UIProcessmacViewGestureControllercpp">trunk/Source/WebKit2/UIProcess/mac/ViewGestureController.cpp</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPagemacTiledCoreAnimationDrawingAreah">trunk/Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPagemacTiledCoreAnimationDrawingAreamm">trunk/Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (160684 => 160685)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2013-12-17 02:02:42 UTC (rev 160684)
+++ trunk/Source/WebCore/ChangeLog        2013-12-17 02:12:31 UTC (rev 160685)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2013-12-16  Tim Horton  &lt;timothy_horton@apple.com&gt;
+
+        WebKit2 View Gestures: Pinching beyond the extremes doesn't animate back to the min/max
+        https://bugs.webkit.org/show_bug.cgi?id=125750
+
+        Reviewed by Simon Fraser.
+
+        * WebCore.exp.in:
+        Export a few things so WebKit2 can use them.
+
</ins><span class="cx"> 2013-12-16  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Fix some whitespace issues in inspector code
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCoreexpin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.exp.in (160684 => 160685)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.exp.in        2013-12-17 02:02:42 UTC (rev 160684)
+++ trunk/Source/WebCore/WebCore.exp.in        2013-12-17 02:12:31 UTC (rev 160685)
</span><span class="lines">@@ -399,6 +399,7 @@
</span><span class="cx"> __ZN7WebCore14ScrollableArea27notifyScrollPositionChangedERKNS_8IntPointE
</span><span class="cx"> __ZN7WebCore14ScrollableArea28setScrollOffsetFromInternalsERKNS_8IntPointE
</span><span class="cx"> __ZN7WebCore14ScrollableArea30scrollToOffsetWithoutAnimationERKNS_10FloatPointE
</span><ins>+__ZN7WebCore14ScrollableArea34constrainScrollPositionForOverhangERKNS_7IntRectERKNS_7IntSizeERKNS_8IntPointES9_ii
</ins><span class="cx"> __ZN7WebCore14ScrollableArea6scrollENS_15ScrollDirectionENS_17ScrollGranularityEf
</span><span class="cx"> __ZN7WebCore14ScrollableAreaC2Ev
</span><span class="cx"> __ZN7WebCore14ScrollableAreaD2Ev
</span><span class="lines">@@ -437,6 +438,7 @@
</span><span class="cx"> __ZN7WebCore14decodeHostNameEP8NSString
</span><span class="cx"> __ZN7WebCore14encodeHostNameEP8NSString
</span><span class="cx"> __ZN7WebCore14endOfParagraphERKNS_15VisiblePositionENS_27EditingBoundaryCrossingRuleE
</span><ins>+__ZN7WebCore14roundedIntRectERKNS_9FloatRectE
</ins><span class="cx"> __ZN7WebCore14setMetadataURLERN3WTF6StringERKS1_S4_
</span><span class="cx"> __ZN7WebCore15AffineTransform5flipYEv
</span><span class="cx"> __ZN7WebCore15AffineTransform5scaleEd
</span><span class="lines">@@ -757,6 +759,9 @@
</span><span class="cx"> __ZN7WebCore19ResourceRequestBase25setDefaultTimeoutIntervalEd
</span><span class="cx"> __ZN7WebCore19ResourceRequestBase50setResponseContentDispositionEncodingFallbackArrayERKN3WTF6StringES4_S4_
</span><span class="cx"> __ZN7WebCore19ResourceRequestBase6setURLERKNS_3URLE
</span><ins>+__ZN7WebCore19PlatformCAAnimation6createEP19CAPropertyAnimation
+__ZN7WebCore19PlatformCAAnimation10setToValueERKNS_20TransformationMatrixE
+__ZN7WebCore19PlatformCAAnimationD1Ev
</ins><span class="cx"> __ZN7WebCore19TextResourceDecoder5flushEv
</span><span class="cx"> __ZN7WebCore19TextResourceDecoder6decodeEPKcm
</span><span class="cx"> __ZN7WebCore19TextResourceDecoderC1ERKN3WTF6StringERKNS_12TextEncodingEb
</span><span class="lines">@@ -1232,6 +1237,7 @@
</span><span class="cx"> __ZN7WebCore9DOMWindow30dispatchAllPendingUnloadEventsEv
</span><span class="cx"> __ZN7WebCore9DOMWindow36dispatchAllPendingBeforeUnloadEventsEv
</span><span class="cx"> __ZN7WebCore9FloatRect5scaleEff
</span><ins>+__ZN7WebCore9FloatRect9intersectERKS0_
</ins><span class="cx"> __ZN7WebCore9FloatRectC1ERK6CGRect
</span><span class="cx"> __ZN7WebCore9FloatRectC1ERKNS_7IntRectE
</span><span class="cx"> __ZN7WebCore9FloatSizeC1ERK6CGSize
</span><span class="lines">@@ -1393,6 +1399,7 @@
</span><span class="cx"> __ZNK7WebCore10RenderText9firstRunXEv
</span><span class="cx"> __ZNK7WebCore10RenderText9firstRunYEv
</span><span class="cx"> __ZNK7WebCore10RenderView12documentRectEv
</span><ins>+__ZNK7WebCore10RenderView20unscaledDocumentRectEv
</ins><span class="cx"> __ZNK7WebCore10ScrollView12contentsSizeEv
</span><span class="cx"> __ZNK7WebCore10ScrollView12documentViewEv
</span><span class="cx"> __ZNK7WebCore10ScrollView14scrollbarModesERNS_13ScrollbarModeES2_
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformKeyedCodingh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/KeyedCoding.h (160684 => 160685)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/KeyedCoding.h        2013-12-17 02:02:42 UTC (rev 160684)
+++ trunk/Source/WebCore/platform/KeyedCoding.h        2013-12-17 02:12:31 UTC (rev 160685)
</span><span class="lines">@@ -35,63 +35,7 @@
</span><span class="cx">     virtual ~KeyedEncoder() { }
</span><span class="cx"> 
</span><span class="cx"> public:
</span><del>-    virtual void encodeBytes(const String&amp; key, const uint8_t*, size_t) = 0;
-    virtual void encodeBool(const String&amp; key, bool) = 0;
</del><span class="cx">     virtual void encodeUInt32(const String&amp; key, uint32_t) = 0;
</span><del>-    virtual void encodeInt32(const String&amp; key, int32_t) = 0;
-    virtual void encodeInt64(const String&amp; key, int64_t) = 0;
-    virtual void encodeFloat(const String&amp; key, float) = 0;
-    virtual void encodeDouble(const String&amp; key, double) = 0;
-    virtual void encodeString(const String&amp; key, const String&amp;) = 0;
-
-    template&lt;typename T&gt;
-    void encodeEnum(const String&amp; key, T value)
-    {
-        static_assert(std::is_enum&lt;T&gt;::value, &quot;T must be an enum type&quot;);
-
-        encodeInt64(key, static_cast&lt;int64_t&gt;(value));
-    }
-
-    template&lt;typename T, typename F&gt;
-    void encodeObject(const String&amp; key, const T&amp; object, F&amp;&amp; function)
-    {
-        beginObject(key);
-        function(*this, object);
-        endObject();
-    }
-
-    template&lt;typename T, typename F&gt;
-    void encodeConditionalObject(const String&amp; key, const T* object, F&amp;&amp; function)
-    {
-        if (!object)
-            return;
-
-        encodeObject(key, *object, std::forward&lt;F&gt;(function));
-    }
-
-    template&lt;typename T, typename F&gt;
-    void encodeObjects(const String&amp; key, T begin, T end, F&amp;&amp; function)
-    {
-        if (begin == end)
-            return;
-
-        beginArray(key);
-        for (T it = begin; it != end; ++it) {
-            beginArrayElement();
-            function(*this, *it);
-            endArrayElement();
-        }
-        endArray();
-    }
-
-private:
-    virtual void beginObject(const String&amp; key) = 0;
-    virtual void endObject() = 0;
-
-    virtual void beginArray(const String&amp; key) = 0;
-    virtual void beginArrayElement() = 0;
-    virtual void endArrayElement() = 0;
-    virtual void endArray() = 0;
</del><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (160684 => 160685)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2013-12-17 02:02:42 UTC (rev 160684)
+++ trunk/Source/WebKit2/ChangeLog        2013-12-17 02:12:31 UTC (rev 160685)
</span><span class="lines">@@ -1,3 +1,48 @@
</span><ins>+2013-12-16  Tim Horton  &lt;timothy_horton@apple.com&gt;
+
+        WebKit2 View Gestures: Pinching beyond the extremes doesn't animate back to the min/max
+        https://bugs.webkit.org/show_bug.cgi?id=125750
+
+        Reviewed by Simon Fraser.
+
+        When you let go of a pinch where you exceeded the maximum or minimum scale,
+        the view should animate back to the limit instead of snapping back.
+
+        * UIProcess/mac/ViewGestureController.cpp:
+        (WebKit::ViewGestureController::endMagnificationGesture):
+        Unscrolling the scaled origin here is wrong; we should send the same
+        value for 'origin' for commitTransientZoom that we do for adjustTransientZoom.
+        The drawing area can deal with transforming that however it needs to call scalePage().
+
+        * WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h:
+        * WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
+        (WebKit::TiledCoreAnimationDrawingArea::beginTransientZoom):
+        Drive-by use WebPage::mainFrameView().
+
+        (WebKit::TiledCoreAnimationDrawingArea::adjustTransientZoom):
+        Update the shadow layer's bounds, position, and shadow path while zooming,
+        instead of hiding it.
+
+        (WebKit::transientZoomSnapAnimationForKeyPath):
+        Create a CABasicAnimation that stays applied to its target when it finishes,
+        lasts for a quarter second, and uses the ease-in-ease-out timing function.
+
+        (WebKit::constrainZoomOriginForFrameView):
+        When we land a transient zoom, there may be overhang areas (linen, in the case of Mac)
+        visible. During the commit animation, we should move the RenderView layer appropriately
+        so that the page covers the entire view and there are no overhang areas visible.
+        Adapt some code from ScrollableArea to constrain the zoom origin to do so.
+
+        (WebKit::TiledCoreAnimationDrawingArea::commitTransientZoom):
+        Animate the RenderView layer's transform, and the shadow layer's bounds, position, and path.
+        When they complete, apply the zoom via scalePage() and flush the layer tree (otherwise there
+        can be a flash between removing the animations and the next flush with the new scale).
+
+        (WebKit::TiledCoreAnimationDrawingArea::applyTransientZoomToPage):
+        Move the code to land the transient zoom (via scalePage) and to put the shadow back
+        in the state WebCore left it out into its own function, so it can be called both from the
+        animation completion callback and from the short-circuit in the case where we don't need to animate.
+
</ins><span class="cx"> 2013-12-16  Ryuan Choi  &lt;ryuan.choi@samsung.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed. Fix GTK+ build after r160653.
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessmacViewGestureControllercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/mac/ViewGestureController.cpp (160684 => 160685)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/mac/ViewGestureController.cpp        2013-12-17 02:02:42 UTC (rev 160684)
+++ trunk/Source/WebKit2/UIProcess/mac/ViewGestureController.cpp        2013-12-17 02:12:31 UTC (rev 160685)
</span><span class="lines">@@ -122,13 +122,8 @@
</span><span class="cx"> {
</span><span class="cx">     ASSERT(m_activeGestureType == ViewGestureType::Magnification);
</span><span class="cx"> 
</span><del>-    // FIXME: Should rubber-band back when zoomed in or out past the limit.
</del><span class="cx">     double newMagnification = std::min(std::max(m_magnification, minMagnification), maxMagnification);
</span><del>-
-    FloatPoint scaledOrigin = scaledMagnificationOrigin(m_magnificationOrigin, newMagnification);
-    scaledOrigin.moveBy(-m_visibleContentRect.location());
-
-    m_webPageProxy.drawingArea()-&gt;commitTransientZoom(newMagnification, -scaledOrigin);
</del><ins>+    m_webPageProxy.drawingArea()-&gt;commitTransientZoom(newMagnification, scaledMagnificationOrigin(m_magnificationOrigin, newMagnification));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void ViewGestureController::endActiveGesture()
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPagemacTiledCoreAnimationDrawingAreah"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h (160684 => 160685)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h        2013-12-17 02:02:42 UTC (rev 160684)
+++ trunk/Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h        2013-12-17 02:12:31 UTC (rev 160685)
</span><span class="lines">@@ -107,6 +107,7 @@
</span><span class="cx">     virtual void beginTransientZoom() OVERRIDE;
</span><span class="cx">     virtual void adjustTransientZoom(double scale, WebCore::FloatPoint origin) OVERRIDE;
</span><span class="cx">     virtual void commitTransientZoom(double scale, WebCore::FloatPoint origin) OVERRIDE;
</span><ins>+    void applyTransientZoomToPage(double scale, WebCore::FloatPoint origin);
</ins><span class="cx"> 
</span><span class="cx">     void updateLayerHostingContext();
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPagemacTiledCoreAnimationDrawingAreamm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm (160684 => 160685)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm        2013-12-17 02:02:42 UTC (rev 160684)
+++ trunk/Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm        2013-12-17 02:12:31 UTC (rev 160685)
</span><span class="lines">@@ -47,6 +47,7 @@
</span><span class="cx"> #import &lt;WebCore/RenderLayerBacking.h&gt;
</span><span class="cx"> #import &lt;WebCore/RenderLayerCompositor.h&gt;
</span><span class="cx"> #import &lt;WebCore/RenderView.h&gt;
</span><ins>+#import &lt;WebCore/ScrollbarTheme.h&gt;
</ins><span class="cx"> #import &lt;WebCore/Settings.h&gt;
</span><span class="cx"> #import &lt;WebCore/TiledBacking.h&gt;
</span><span class="cx"> #import &lt;wtf/MainThread.h&gt;
</span><span class="lines">@@ -702,7 +703,7 @@
</span><span class="cx"> 
</span><span class="cx"> void TiledCoreAnimationDrawingArea::beginTransientZoom()
</span><span class="cx"> {
</span><del>-    FloatRect visibleContentRect = m_webPage-&gt;corePage()-&gt;mainFrame().view()-&gt;visibleContentRect(ScrollableArea::IncludeScrollbars);
</del><ins>+    FloatRect visibleContentRect = m_webPage-&gt;mainFrameView()-&gt;visibleContentRect(ScrollableArea::IncludeScrollbars);
</ins><span class="cx">     m_webPage-&gt;send(Messages::ViewGestureController::DidBeginTransientZoom(visibleContentRect));
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -715,38 +716,153 @@
</span><span class="cx">     if (!m_rootLayer)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    RenderView* renderView = m_webPage-&gt;corePage()-&gt;mainFrame().view()-&gt;renderView();
-
</del><span class="cx">     TransformationMatrix transform;
</span><span class="cx">     transform.translate(origin.x(), origin.y());
</span><span class="cx">     transform.scale(scale);
</span><span class="cx"> 
</span><ins>+    RenderView* renderView = m_webPage-&gt;mainFrameView()-&gt;renderView();
</ins><span class="cx">     PlatformCALayer* renderViewLayer = static_cast&lt;GraphicsLayerCA*&gt;(renderView-&gt;layer()-&gt;backing()-&gt;graphicsLayer())-&gt;platformCALayer();
</span><span class="cx">     renderViewLayer-&gt;setTransform(transform);
</span><span class="cx">     renderViewLayer-&gt;setAnchorPoint(FloatPoint3D());
</span><span class="cx">     renderViewLayer-&gt;setPosition(FloatPoint3D());
</span><span class="cx"> 
</span><del>-    // FIXME: We should transform the shadow layer as well, instead of hiding it.
</del><span class="cx">     PlatformCALayer* shadowLayer = static_cast&lt;GraphicsLayerCA*&gt;(renderView-&gt;compositor().layerForContentShadow())-&gt;platformCALayer();
</span><del>-    shadowLayer-&gt;setHidden(true);
</del><span class="cx"> 
</span><ins>+    FloatRect shadowBounds = FloatRect(FloatPoint(), toFloatSize(renderView-&gt;layoutOverflowRect().maxXMaxYCorner()));
+    shadowBounds.scale(scale);
+
+    shadowLayer-&gt;setBounds(shadowBounds);
+    shadowLayer-&gt;setPosition(origin + shadowBounds.center());
+    shadowLayer-&gt;platformLayer().shadowPath = adoptCF(CGPathCreateWithRect(shadowBounds, NULL)).get();
+
</ins><span class="cx">     m_transientZoomScale = scale;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static RetainPtr&lt;CABasicAnimation&gt; transientZoomSnapAnimationForKeyPath(String keyPath)
+{
+    const float transientZoomSnapBackDuration = 0.25;
+
+    RetainPtr&lt;CABasicAnimation&gt; animation = [CABasicAnimation animationWithKeyPath:keyPath];
+    [animation setDuration:transientZoomSnapBackDuration];
+    [animation setFillMode:kCAFillModeForwards];
+    [animation setRemovedOnCompletion:false];
+    [animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
+
+    return animation;
+}
+
+/*static FloatPoint constrainZoomOriginForFrameView(double scale, FloatPoint origin, FrameView* frameView)
+{
+    // Scaling may have exposed the overhang area, so we need to constrain the final
+    // layer position exactly like scrolling will once it's committed, to ensure that
+    // scrolling doesn't make the view jump; this is borrowed from ScrollableArea.
+    FloatRect visibleContentRect = frameView-&gt;visibleContentRect(ScrollableArea::IncludeScrollbars);
+
+    FloatRect zoomContentRect = visibleContentRect;
+    zoomContentRect.moveBy(-origin);
+
+    FloatRect documentRect = frameView-&gt;renderView()-&gt;unscaledDocumentRect();
+    documentRect.scale(scale);
+    zoomContentRect.intersect(documentRect);
+
+    if (zoomContentRect.size() != visibleContentRect.size()) {
+        zoomContentRect.setSize(visibleContentRect.size());
+        zoomContentRect.intersect(documentRect);
+        if (zoomContentRect.width() &lt; visibleContentRect.width())
+            zoomContentRect.move(-(visibleContentRect.width() - zoomContentRect.width()), 0);
+        if (zoomContentRect.height() &lt; visibleContentRect.height())
+            zoomContentRect.move(0, -(visibleContentRect.height() - zoomContentRect.height()));
+    }
+
+    FloatPoint constrainedOrigin = zoomContentRect.location();
+    constrainedOrigin.moveBy(-visibleContentRect.location());
+
+    return -constrainedOrigin;
+}*/
+
</ins><span class="cx"> void TiledCoreAnimationDrawingArea::commitTransientZoom(double scale, FloatPoint origin)
</span><span class="cx"> {
</span><del>-    RenderView* renderView = m_webPage-&gt;corePage()-&gt;mainFrame().view()-&gt;renderView();
</del><ins>+    FrameView* frameView = m_webPage-&gt;mainFrameView();
+    RenderView* renderView = frameView-&gt;renderView();
+    PlatformCALayer* renderViewLayer = static_cast&lt;GraphicsLayerCA*&gt;(renderView-&gt;layer()-&gt;backing()-&gt;graphicsLayer())-&gt;platformCALayer();
</ins><span class="cx"> 
</span><del>-    // If the page scale is already the target scale, scalePage() will short-circuit
-    // and not apply the transform, so we can't depend on it to do so.
</del><ins>+    FloatRect visibleContentRect = frameView-&gt;visibleContentRect(ScrollableArea::IncludeScrollbars);
+
+    FloatPoint constrainedOrigin = visibleContentRect.location();
+    constrainedOrigin.moveBy(-origin);
+
+    IntRect documentRect = frameView-&gt;renderView()-&gt;unscaledDocumentRect();
+    documentRect.scale(scale);
+
+    constrainedOrigin = ScrollableArea::constrainScrollPositionForOverhang(roundedIntRect(visibleContentRect), documentRect.size(), roundedIntPoint(constrainedOrigin), IntPoint(), 0, 0);
+    constrainedOrigin.moveBy(-visibleContentRect.location());
+    constrainedOrigin = -constrainedOrigin;
+
+    if (m_transientZoomScale == scale &amp;&amp; roundedIntPoint(origin) == roundedIntPoint(constrainedOrigin)) {
+        // We're already at the right scale and position, so we don't need to animate.
+        applyTransientZoomToPage(scale, origin);
+        return;
+    }
+
</ins><span class="cx">     TransformationMatrix transform;
</span><ins>+    transform.translate(constrainedOrigin.x(), constrainedOrigin.y());
</ins><span class="cx">     transform.scale(scale);
</span><del>-    static_cast&lt;GraphicsLayerCA*&gt;(renderView-&gt;layer()-&gt;backing()-&gt;graphicsLayer())-&gt;platformCALayer()-&gt;setTransform(transform);
</del><span class="cx"> 
</span><ins>+    RetainPtr&lt;CABasicAnimation&gt; renderViewAnimationCA = transientZoomSnapAnimationForKeyPath(&quot;transform&quot;);
+    RefPtr&lt;PlatformCAAnimation&gt; renderViewAnimation = PlatformCAAnimation::create(renderViewAnimationCA.get());
+    renderViewAnimation-&gt;setToValue(transform);
+
+    RetainPtr&lt;CALayer&gt; shadowLayer = static_cast&lt;GraphicsLayerCA*&gt;(renderView-&gt;compositor().layerForContentShadow())-&gt;platformCALayer()-&gt;platformLayer();
+
+    FloatRect shadowBounds = FloatRect(FloatPoint(), toFloatSize(renderView-&gt;layoutOverflowRect().maxXMaxYCorner()));
+    shadowBounds.scale(scale);
+    RetainPtr&lt;CGPathRef&gt; shadowPath = adoptCF(CGPathCreateWithRect(shadowBounds, NULL)).get();
+
+    RetainPtr&lt;CABasicAnimation&gt; shadowBoundsAnimation = transientZoomSnapAnimationForKeyPath(&quot;bounds&quot;);
+    [shadowBoundsAnimation setToValue:[NSValue valueWithRect:shadowBounds]];
+    RetainPtr&lt;CABasicAnimation&gt; shadowPositionAnimation = transientZoomSnapAnimationForKeyPath(&quot;position&quot;);
+    [shadowBoundsAnimation setToValue:[NSValue valueWithPoint:constrainedOrigin + shadowBounds.center()]];
+    RetainPtr&lt;CABasicAnimation&gt; shadowPathAnimation = transientZoomSnapAnimationForKeyPath(&quot;shadowPath&quot;);
+    [shadowBoundsAnimation setToValue:(id)shadowPath.get()];
+
+    [CATransaction begin];
+    [CATransaction setCompletionBlock:^(void) {
+        renderViewLayer-&gt;removeAnimationForKey(&quot;transientZoomCommit&quot;);
+        [shadowLayer removeAllAnimations];
+        applyTransientZoomToPage(scale, origin);
+    }];
+
+    renderViewLayer-&gt;addAnimationForKey(&quot;transientZoomCommit&quot;, renderViewAnimation.get());
+    [shadowLayer addAnimation:shadowBoundsAnimation.get() forKey:@&quot;transientZoomCommitShadowBounds&quot;];
+    [shadowLayer addAnimation:shadowPositionAnimation.get() forKey:@&quot;transientZoomCommitShadowPosition&quot;];
+    [shadowLayer addAnimation:shadowPathAnimation.get() forKey:@&quot;transientZoomCommitShadowPath&quot;];
+
+    [CATransaction commit];
+}
+
+void TiledCoreAnimationDrawingArea::applyTransientZoomToPage(double scale, FloatPoint origin)
+{
+    RenderView* renderView = m_webPage-&gt;mainFrameView()-&gt;renderView();
+    PlatformCALayer* renderViewLayer = static_cast&lt;GraphicsLayerCA*&gt;(renderView-&gt;layer()-&gt;backing()-&gt;graphicsLayer())-&gt;platformCALayer();
+
+    TransformationMatrix finalTransform;
+    finalTransform.scale(scale);
+
+    // If the page scale is already the target scale, setPageScaleFactor() will short-circuit
+    // and not apply the transform, so we can't depend on it to do so.
+    renderViewLayer-&gt;setTransform(finalTransform);
+
</ins><span class="cx">     PlatformCALayer* shadowLayer = static_cast&lt;GraphicsLayerCA*&gt;(renderView-&gt;compositor().layerForContentShadow())-&gt;platformCALayer();
</span><del>-    shadowLayer-&gt;setHidden(false);
</del><ins>+    IntRect overflowRect = renderView-&gt;pixelSnappedLayoutOverflowRect();
+    shadowLayer-&gt;setBounds(IntRect(IntPoint(), toIntSize(overflowRect.maxXMaxYCorner())));
+    shadowLayer-&gt;setPosition(shadowLayer-&gt;bounds().center());
+    ScrollbarTheme::theme()-&gt;setUpContentShadowLayer(renderView-&gt;compositor().layerForContentShadow());
</ins><span class="cx"> 
</span><del>-    m_webPage-&gt;scalePage(scale, roundedIntPoint(origin));
</del><ins>+    FloatPoint unscrolledOrigin(origin);
+    FloatRect visibleContentRect = m_webPage-&gt;mainFrameView()-&gt;visibleContentRect(ScrollableArea::IncludeScrollbars);
+    unscrolledOrigin.moveBy(-visibleContentRect.location());
+    m_webPage-&gt;scalePage(scale, roundedIntPoint(-unscrolledOrigin));
+    flushLayers();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebKit
</span></span></pre>
</div>
</div>

</body>
</html>