<!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>[170783] trunk/Source/WebKit2</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/170783">170783</a></dd>
<dt>Author</dt> <dd>simon.fraser@apple.com</dd>
<dt>Date</dt> <dd>2014-07-03 17:48:14 -0700 (Thu, 03 Jul 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>[iOS WK2] Compositing layers draw outside page bounds
https://bugs.webkit.org/show_bug.cgi?id=134619
&lt;rdar://problem/16953222&gt;

Reviewed by Benjamin Poulain.

With the new rubber-banding behavior, we no longer have the root content layer clipping all
the web layers, but this resulted in web layers which were moved outside the viewport by CSS
transforms not being clipped.

Fix by adding a clipping layer inside the scroll view, above _rootContentView. This layer
normally has the same bounds as the content, but when rubber-banding or pinching,
it takes the union of the content bounds and the rect used for fixed positioning.
To make scrolling work as expected in this scenario, when it has non-zero offset, it
has to compensate by setting its bounds origin.

The bounds of the clipping layer are updated on scrolling/zooming, and when the
layer commit tells us that the content size changed.

* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _updateScrollViewBackground]):
* UIProcess/ios/WKContentView.mm:
(-[WKContentView initWithFrame:context:configuration:webView:]):
(-[WKContentView updateFixedClippingView:]):
(-[WKContentView didUpdateVisibleRect:unobscuredRect:unobscuredRectInScrollViewCoordinates:scale:minimumScale:inStableState:isChangingObscuredInsetsInteractively:]):
(-[WKContentView _didCommitLayerTree:]):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPICocoaWKWebViewmm">trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessiosWKContentViewmm">trunk/Source/WebKit2/UIProcess/ios/WKContentView.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (170782 => 170783)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2014-07-04 00:39:41 UTC (rev 170782)
+++ trunk/Source/WebKit2/ChangeLog        2014-07-04 00:48:14 UTC (rev 170783)
</span><span class="lines">@@ -1,3 +1,32 @@
</span><ins>+2014-07-03  Simon Fraser  &lt;simon.fraser@apple.com&gt;
+
+        [iOS WK2] Compositing layers draw outside page bounds
+        https://bugs.webkit.org/show_bug.cgi?id=134619
+        &lt;rdar://problem/16953222&gt;
+
+        Reviewed by Benjamin Poulain.
+        
+        With the new rubber-banding behavior, we no longer have the root content layer clipping all
+        the web layers, but this resulted in web layers which were moved outside the viewport by CSS
+        transforms not being clipped.
+        
+        Fix by adding a clipping layer inside the scroll view, above _rootContentView. This layer
+        normally has the same bounds as the content, but when rubber-banding or pinching,
+        it takes the union of the content bounds and the rect used for fixed positioning.
+        To make scrolling work as expected in this scenario, when it has non-zero offset, it
+        has to compensate by setting its bounds origin.
+
+        The bounds of the clipping layer are updated on scrolling/zooming, and when the
+        layer commit tells us that the content size changed.
+
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView _updateScrollViewBackground]):
+        * UIProcess/ios/WKContentView.mm:
+        (-[WKContentView initWithFrame:context:configuration:webView:]):
+        (-[WKContentView updateFixedClippingView:]):
+        (-[WKContentView didUpdateVisibleRect:unobscuredRect:unobscuredRectInScrollViewCoordinates:scale:minimumScale:inStableState:isChangingObscuredInsetsInteractively:]):
+        (-[WKContentView _didCommitLayerTree:]):
+
</ins><span class="cx"> 2014-07-03  Brady Eidson  &lt;beidson@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         When showing the selection menu, include menu options for all selected phone numbers.
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPICocoaWKWebViewmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm (170782 => 170783)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm        2014-07-04 00:39:41 UTC (rev 170782)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm        2014-07-04 00:48:14 UTC (rev 170783)
</span><span class="lines">@@ -664,6 +664,7 @@
</span><span class="cx">         color = [_customContentView backgroundColor].CGColor;
</span><span class="cx">     else
</span><span class="cx">         color = _page-&gt;pageExtendedBackgroundColor();
</span><ins>+
</ins><span class="cx">     CGFloat zoomScale = contentZoomScale(self);
</span><span class="cx">     CGFloat minimumZoomScale = [_scrollView minimumZoomScale];
</span><span class="cx">     if (zoomScale &lt; minimumZoomScale) {
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessiosWKContentViewmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/ios/WKContentView.mm (170782 => 170783)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/ios/WKContentView.mm        2014-07-04 00:39:41 UTC (rev 170782)
+++ trunk/Source/WebKit2/UIProcess/ios/WKContentView.mm        2014-07-04 00:48:14 UTC (rev 170783)
</span><span class="lines">@@ -417,6 +417,7 @@
</span><span class="cx">     RetainPtr&lt;WKBrowsingContextController&gt; _browsingContextController;
</span><span class="cx"> 
</span><span class="cx">     RetainPtr&lt;UIView&gt; _rootContentView;
</span><ins>+    RetainPtr&lt;UIView&gt; _fixedClippingView;
</ins><span class="cx">     RetainPtr&lt;WKInspectorIndicationView&gt; _inspectorIndicationView;
</span><span class="cx">     RetainPtr&lt;WKInspectorHighlightView&gt; _inspectorHighlightView;
</span><span class="cx"> 
</span><span class="lines">@@ -444,8 +445,16 @@
</span><span class="cx"> 
</span><span class="cx">     _rootContentView = adoptNS([[UIView alloc] init]);
</span><span class="cx">     [_rootContentView layer].masksToBounds = NO;
</span><ins>+    
+    _fixedClippingView = adoptNS([[UIView alloc] init]);
+    [_fixedClippingView layer].masksToBounds = YES;
+    [_fixedClippingView layer].anchorPoint = CGPointZero;
+#ifndef NDEBUG
+    [[_fixedClippingView layer] setName:@&quot;Fixed clipping&quot;];
+#endif
</ins><span class="cx"> 
</span><del>-    [self addSubview:_rootContentView.get()];
</del><ins>+    [self addSubview:_fixedClippingView.get()];
+    [_fixedClippingView addSubview:_rootContentView.get()];
</ins><span class="cx"> 
</span><span class="cx">     [self setupInteraction];
</span><span class="cx">     [self setUserInteractionEnabled:YES];
</span><span class="lines">@@ -553,6 +562,15 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+- (void)updateFixedClippingView:(FloatRect)fixedPositionRectForUI
+{
+    FloatRect clippingBounds = [self bounds];
+    clippingBounds.unite(fixedPositionRectForUI);
+
+    [_fixedClippingView setCenter:clippingBounds.location()]; // Not really the center since we set an anchor point.
+    [_fixedClippingView setBounds:clippingBounds];
+}
+
</ins><span class="cx"> - (void)didUpdateVisibleRect:(CGRect)visibleRect unobscuredRect:(CGRect)unobscuredRect unobscuredRectInScrollViewCoordinates:(CGRect)unobscuredRectInScrollViewCoordinates
</span><span class="cx">     scale:(CGFloat)zoomScale minimumScale:(CGFloat)minimumScale inStableState:(BOOL)isStableState isChangingObscuredInsetsInteractively:(BOOL)isChangingObscuredInsetsInteractively
</span><span class="cx"> {
</span><span class="lines">@@ -570,13 +588,16 @@
</span><span class="cx">         zoomScale, isStableState, isChangingObscuredInsetsInteractively, timestamp, velocityData.horizontalVelocity, velocityData.verticalVelocity, velocityData.scaleChangeRate);
</span><span class="cx"> 
</span><span class="cx">     RemoteScrollingCoordinatorProxy* scrollingCoordinator = _page-&gt;scrollingCoordinatorProxy();
</span><del>-    scrollingCoordinator-&gt;viewportChangedViaDelegatedScrolling(scrollingCoordinator-&gt;rootScrollingNodeID(), _page-&gt;computeCustomFixedPositionRect(_page-&gt;unobscuredContentRect(), zoomScale), zoomScale);
</del><ins>+    FloatRect fixedPositionRect = _page-&gt;computeCustomFixedPositionRect(_page-&gt;unobscuredContentRect(), zoomScale);
+    scrollingCoordinator-&gt;viewportChangedViaDelegatedScrolling(scrollingCoordinator-&gt;rootScrollingNodeID(), fixedPositionRect, zoomScale);
</ins><span class="cx"> 
</span><span class="cx">     if (auto drawingArea = _page-&gt;drawingArea())
</span><span class="cx">         drawingArea-&gt;updateDebugIndicator();
</span><span class="cx"> 
</span><span class="cx">     if (!withinEpsilon(oldDisplayedContentScale, zoomScale))
</span><span class="cx">         [self _updateUnscaledView];
</span><ins>+        
+    [self updateFixedClippingView:fixedPositionRect];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (void)setMinimumSize:(CGSize)size
</span><span class="lines">@@ -667,12 +688,23 @@
</span><span class="cx"> - (void)_didCommitLayerTree:(const WebKit::RemoteLayerTreeTransaction&amp;)layerTreeTransaction
</span><span class="cx"> {
</span><span class="cx">     CGSize contentsSize = layerTreeTransaction.contentsSize();
</span><ins>+    CGRect contentBounds = { CGPointZero, contentsSize };
+    CGRect oldBounds = [self bounds];
</ins><span class="cx"> 
</span><del>-    [self setBounds:{CGPointZero, contentsSize}];
-    [_rootContentView setFrame:CGRectMake(0, 0, contentsSize.width, contentsSize.height)];
-    [_inspectorIndicationView setFrame:[self bounds]];
</del><ins>+    BOOL boundsChanged = !CGRectEqualToRect(oldBounds, contentBounds);
+    if (boundsChanged) {
+        [self setBounds:contentBounds];
+        [_rootContentView setFrame:contentBounds];
+        [_inspectorIndicationView setFrame:contentBounds];
+    }
</ins><span class="cx"> 
</span><span class="cx">     [_webView _didCommitLayerTree:layerTreeTransaction];
</span><ins>+    
+    if (boundsChanged) {
+        FloatRect fixedPositionRect = _page-&gt;computeCustomFixedPositionRect(_page-&gt;unobscuredContentRect(), [[_webView scrollView] zoomScale]);
+        [self updateFixedClippingView:fixedPositionRect];
+    }
+    
</ins><span class="cx">     [self _updateChangedSelection];
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>