<!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>[163093] 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/163093">163093</a></dd>
<dt>Author</dt> <dd>timothy_horton@apple.com</dd>
<dt>Date</dt> <dd>2014-01-30 11:29:48 -0800 (Thu, 30 Jan 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>WebKit2 View Gestures (Swipe): Provide a way for clients to provide views to swipe
https://bugs.webkit.org/show_bug.cgi?id=127891
&lt;rdar://problem/15931413&gt;

Reviewed by Anders Carlsson.

* UIProcess/API/Cocoa/WKViewPrivate.h: Add the SPI.

* UIProcess/API/ios/PageClientImplIOS.h:
* UIProcess/API/ios/PageClientImplIOS.mm:
(WebKit::PageClientImpl::clearCustomSwipeViews):
* UIProcess/API/mac/PageClientImpl.h:
* UIProcess/API/mac/PageClientImpl.mm:
(WebKit::PageClientImpl::clearCustomSwipeViews):
* UIProcess/PageClient.h:
Plumb clearCustomSwipeViews() so that WebPageProxy can clear
ViewGestureController's list of custom views when the current
back-forward item changes.

* UIProcess/API/mac/WKView.mm:
(-[WKView _takeViewSnapshot]):
If we have custom swipe views, use the union of their bounds as the snapshot region.

(-[WKView _setCustomSwipeViews:]):
Forward along to ViewGestureController.

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::didChangeBackForwardList):
When the current back forward list item changes, clear the custom swipe views.

* UIProcess/mac/ViewGestureController.h:
(WebKit::ViewGestureController::setCustomSwipeViews):
(WebKit::ViewGestureController::customSwipeViews):
* UIProcess/mac/ViewGestureController.mm:
(WebKit::ViewGestureController::windowRelativeBoundsForCustomSwipeViews):
Compute the union of the custom swipe view bounds in the window's coordinate space.

(WebKit::ViewGestureController::beginSwipeGesture):
Store the layers we'll be swiping as the &quot;live&quot; layers in m_currentSwipeLiveLayers.
Don't set a shadow (yet) if we have custom swipe views, because it's not clear where to put it.

(WebKit::ViewGestureController::handleSwipeGesture):
Compute the swipe distance ('width') based on the union of the custom views bounds if needed.
Update the transform of all of the live layers. We use transform instead of position now
so that clients can set the position (having an identity transform is one of the SPI caveats).

(WebKit::ViewGestureController::removeSwipeSnapshot):
Reset the transform on all of the live layers.
Clear the list of live layers.

* WebCore.exp.in:
A surprising export.</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="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPICocoaWKViewPrivateh">trunk/Source/WebKit2/UIProcess/API/Cocoa/WKViewPrivate.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIiosPageClientImplIOSh">trunk/Source/WebKit2/UIProcess/API/ios/PageClientImplIOS.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIiosPageClientImplIOSmm">trunk/Source/WebKit2/UIProcess/API/ios/PageClientImplIOS.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPImacPageClientImplh">trunk/Source/WebKit2/UIProcess/API/mac/PageClientImpl.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPImacPageClientImplmm">trunk/Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPImacWKViewmm">trunk/Source/WebKit2/UIProcess/API/mac/WKView.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessPageClienth">trunk/Source/WebKit2/UIProcess/PageClient.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessWebPageProxycpp">trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessmacViewGestureControllerh">trunk/Source/WebKit2/UIProcess/mac/ViewGestureController.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessmacViewGestureControllermm">trunk/Source/WebKit2/UIProcess/mac/ViewGestureController.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (163092 => 163093)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-01-30 19:25:25 UTC (rev 163092)
+++ trunk/Source/WebCore/ChangeLog        2014-01-30 19:29:48 UTC (rev 163093)
</span><span class="lines">@@ -1,3 +1,14 @@
</span><ins>+2014-01-30  Tim Horton  &lt;timothy_horton@apple.com&gt;
+
+        WebKit2 View Gestures (Swipe): Provide a way for clients to provide views to swipe
+        https://bugs.webkit.org/show_bug.cgi?id=127891
+        &lt;rdar://problem/15931413&gt;
+
+        Reviewed by Anders Carlsson.
+
+        * WebCore.exp.in:
+        A surprising export.
+
</ins><span class="cx"> 2014-01-30  Beth Dakin  &lt;bdakin@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=127371
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCoreexpin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.exp.in (163092 => 163093)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.exp.in        2014-01-30 19:25:25 UTC (rev 163092)
+++ trunk/Source/WebCore/WebCore.exp.in        2014-01-30 19:29:48 UTC (rev 163093)
</span><span class="lines">@@ -1244,6 +1244,7 @@
</span><span class="cx"> __ZN7WebCore9DOMWindow30dispatchAllPendingUnloadEventsEv
</span><span class="cx"> __ZN7WebCore9DOMWindow36dispatchAllPendingBeforeUnloadEventsEv
</span><span class="cx"> __ZN7WebCore9FloatRect5scaleEff
</span><ins>+__ZN7WebCore9FloatRect5uniteERKS0_
</ins><span class="cx"> __ZN7WebCore9FloatRect9intersectERKS0_
</span><span class="cx"> __ZN7WebCore9FloatRectC1ERK6CGRect
</span><span class="cx"> __ZN7WebCore9FloatRectC1ERKNS_7IntRectE
</span></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (163092 => 163093)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2014-01-30 19:25:25 UTC (rev 163092)
+++ trunk/Source/WebKit2/ChangeLog        2014-01-30 19:29:48 UTC (rev 163093)
</span><span class="lines">@@ -1,3 +1,55 @@
</span><ins>+2014-01-30  Tim Horton  &lt;timothy_horton@apple.com&gt;
+
+        WebKit2 View Gestures (Swipe): Provide a way for clients to provide views to swipe
+        https://bugs.webkit.org/show_bug.cgi?id=127891
+        &lt;rdar://problem/15931413&gt;
+
+        Reviewed by Anders Carlsson.
+
+        * UIProcess/API/Cocoa/WKViewPrivate.h: Add the SPI.
+
+        * UIProcess/API/ios/PageClientImplIOS.h:
+        * UIProcess/API/ios/PageClientImplIOS.mm:
+        (WebKit::PageClientImpl::clearCustomSwipeViews):
+        * UIProcess/API/mac/PageClientImpl.h:
+        * UIProcess/API/mac/PageClientImpl.mm:
+        (WebKit::PageClientImpl::clearCustomSwipeViews):
+        * UIProcess/PageClient.h:
+        Plumb clearCustomSwipeViews() so that WebPageProxy can clear
+        ViewGestureController's list of custom views when the current
+        back-forward item changes.
+
+        * UIProcess/API/mac/WKView.mm:
+        (-[WKView _takeViewSnapshot]):
+        If we have custom swipe views, use the union of their bounds as the snapshot region.
+
+        (-[WKView _setCustomSwipeViews:]):
+        Forward along to ViewGestureController.
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::didChangeBackForwardList):
+        When the current back forward list item changes, clear the custom swipe views.
+
+        * UIProcess/mac/ViewGestureController.h:
+        (WebKit::ViewGestureController::setCustomSwipeViews):
+        (WebKit::ViewGestureController::customSwipeViews):
+        * UIProcess/mac/ViewGestureController.mm:
+        (WebKit::ViewGestureController::windowRelativeBoundsForCustomSwipeViews):
+        Compute the union of the custom swipe view bounds in the window's coordinate space.
+
+        (WebKit::ViewGestureController::beginSwipeGesture):
+        Store the layers we'll be swiping as the &quot;live&quot; layers in m_currentSwipeLiveLayers.
+        Don't set a shadow (yet) if we have custom swipe views, because it's not clear where to put it.
+
+        (WebKit::ViewGestureController::handleSwipeGesture):
+        Compute the swipe distance ('width') based on the union of the custom views bounds if needed.
+        Update the transform of all of the live layers. We use transform instead of position now
+        so that clients can set the position (having an identity transform is one of the SPI caveats).
+
+        (WebKit::ViewGestureController::removeSwipeSnapshot):
+        Reset the transform on all of the live layers.
+        Clear the list of live layers.
+
</ins><span class="cx"> 2014-01-30  Brady Eidson  &lt;beidson@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         IDB: Add no-op plumbing for deleteDatabase and deleteRange
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPICocoaWKViewPrivateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKViewPrivate.h (163092 => 163093)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKViewPrivate.h        2014-01-30 19:25:25 UTC (rev 163092)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKViewPrivate.h        2014-01-30 19:29:48 UTC (rev 163093)
</span><span class="lines">@@ -92,6 +92,9 @@
</span><span class="cx"> 
</span><span class="cx"> - (void)saveBackForwardSnapshotForCurrentItem;
</span><span class="cx"> 
</span><ins>+// Views must be layer-backed, have no transform applied, be in back-to-front z-order, and the whole set must be a contiguous opaque rectangle.
+- (void)_setCustomSwipeViews:(NSArray *)customSwipeViews;
+
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> @end
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIiosPageClientImplIOSh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/ios/PageClientImplIOS.h (163092 => 163093)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/ios/PageClientImplIOS.h        2014-01-30 19:25:25 UTC (rev 163092)
+++ trunk/Source/WebKit2/UIProcess/API/ios/PageClientImplIOS.h        2014-01-30 19:29:48 UTC (rev 163093)
</span><span class="lines">@@ -98,6 +98,7 @@
</span><span class="cx"> 
</span><span class="cx">     virtual RetainPtr&lt;CGImageRef&gt; takeViewSnapshot() override;
</span><span class="cx">     virtual void wheelEventWasNotHandledByWebCore(const NativeWebWheelEvent&amp;) override;
</span><ins>+    virtual void clearCustomSwipeViews() override;
</ins><span class="cx"> 
</span><span class="cx">     virtual void mainDocumentDidReceiveMobileDocType() override;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIiosPageClientImplIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/ios/PageClientImplIOS.mm (163092 => 163093)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/ios/PageClientImplIOS.mm        2014-01-30 19:25:25 UTC (rev 163092)
+++ trunk/Source/WebKit2/UIProcess/API/ios/PageClientImplIOS.mm        2014-01-30 19:29:48 UTC (rev 163093)
</span><span class="lines">@@ -331,6 +331,11 @@
</span><span class="cx">     notImplemented();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void PageClientImpl::clearCustomSwipeViews()
+{
+    notImplemented();
+}
+
</ins><span class="cx"> void PageClientImpl::mainDocumentDidReceiveMobileDocType()
</span><span class="cx"> {
</span><span class="cx">     [m_view _didReceiveMobileDocTypeForMainFrame];
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPImacPageClientImplh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/mac/PageClientImpl.h (163092 => 163093)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/mac/PageClientImpl.h        2014-01-30 19:25:25 UTC (rev 163092)
+++ trunk/Source/WebKit2/UIProcess/API/mac/PageClientImpl.h        2014-01-30 19:29:48 UTC (rev 163093)
</span><span class="lines">@@ -117,6 +117,7 @@
</span><span class="cx"> 
</span><span class="cx">     virtual RetainPtr&lt;CGImageRef&gt; takeViewSnapshot() override;
</span><span class="cx">     virtual void wheelEventWasNotHandledByWebCore(const NativeWebWheelEvent&amp;) override;
</span><ins>+    virtual void clearCustomSwipeViews() override;
</ins><span class="cx"> 
</span><span class="cx">     virtual void accessibilityWebProcessTokenReceived(const IPC::DataReference&amp;);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPImacPageClientImplmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm (163092 => 163093)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm        2014-01-30 19:25:25 UTC (rev 163092)
+++ trunk/Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm        2014-01-30 19:29:48 UTC (rev 163093)
</span><span class="lines">@@ -548,6 +548,11 @@
</span><span class="cx">     return [m_wkView _executeSavedCommandBySelector:NSSelectorFromString(selectorString)];
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void PageClientImpl::clearCustomSwipeViews()
+{
+    return [m_wkView _setCustomSwipeViews:@[]];
+}
+
</ins><span class="cx"> #if USE(DICTATION_ALTERNATIVES)
</span><span class="cx"> uint64_t PageClientImpl::addDictationAlternatives(const RetainPtr&lt;NSTextAlternatives&gt;&amp; alternatives)
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPImacWKViewmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/mac/WKView.mm (163092 => 163093)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/mac/WKView.mm        2014-01-30 19:25:25 UTC (rev 163092)
+++ trunk/Source/WebKit2/UIProcess/API/mac/WKView.mm        2014-01-30 19:29:48 UTC (rev 163093)
</span><span class="lines">@@ -2547,7 +2547,13 @@
</span><span class="cx">     CGSCaptureWindowsContentsToRect(CGSMainConnectionID(), &amp;windowID, 1, CGRectNull, &amp;cgWindowImage);
</span><span class="cx">     RetainPtr&lt;CGImageRef&gt; windowSnapshotImage = adoptCF(cgWindowImage);
</span><span class="cx"> 
</span><del>-    NSRect windowCaptureRect = [self convertRect:self.bounds toView:nil];
</del><ins>+    NSRect windowCaptureRect;
+    FloatRect boundsForCustomSwipeViews = _data-&gt;_gestureController-&gt;windowRelativeBoundsForCustomSwipeViews();
+    if (!boundsForCustomSwipeViews.isEmpty())
+        windowCaptureRect = boundsForCustomSwipeViews;
+    else
+        windowCaptureRect = [self convertRect:self.bounds toView:nil];
+
</ins><span class="cx">     NSRect windowCaptureScreenRect = [window convertRectToScreen:windowCaptureRect];
</span><span class="cx">     CGRect windowScreenRect;
</span><span class="cx">     CGSGetScreenRectForWindow(CGSMainConnectionID(), (CGSWindowID)[window windowNumber], &amp;windowScreenRect);
</span><span class="lines">@@ -3330,6 +3336,17 @@
</span><span class="cx">     return _data-&gt;_page-&gt;pageScaleFactor();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+- (void)_setCustomSwipeViews:(NSArray *)customSwipeViews
+{
+    [self _ensureGestureController];
+
+    Vector&lt;RetainPtr&lt;NSView&gt;&gt; views;
+    for (NSView *view in customSwipeViews)
+        views.append(view);
+
+    _data-&gt;_gestureController-&gt;setCustomSwipeViews(views);
+}
+
</ins><span class="cx"> @end
</span><span class="cx"> 
</span><span class="cx"> @implementation WKResponderChainSink
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessPageClienth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/PageClient.h (163092 => 163093)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/PageClient.h        2014-01-30 19:25:25 UTC (rev 163092)
+++ trunk/Source/WebKit2/UIProcess/PageClient.h        2014-01-30 19:29:48 UTC (rev 163093)
</span><span class="lines">@@ -178,6 +178,7 @@
</span><span class="cx">     virtual CALayer *acceleratedCompositingRootLayer() const = 0;
</span><span class="cx">     virtual RetainPtr&lt;CGImageRef&gt; takeViewSnapshot() = 0;
</span><span class="cx">     virtual void wheelEventWasNotHandledByWebCore(const NativeWebWheelEvent&amp;) = 0;
</span><ins>+    virtual void clearCustomSwipeViews() = 0;
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if USE(APPKIT)
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebPageProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp (163092 => 163093)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp        2014-01-30 19:25:25 UTC (rev 163092)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp        2014-01-30 19:29:48 UTC (rev 163093)
</span><span class="lines">@@ -824,6 +824,10 @@
</span><span class="cx"> void WebPageProxy::didChangeBackForwardList(WebBackForwardListItem* added, Vector&lt;RefPtr&lt;API::Object&gt;&gt;* removed)
</span><span class="cx"> {
</span><span class="cx">     m_loaderClient-&gt;didChangeBackForwardList(this, added, removed);
</span><ins>+
+#if PLATFORM(MAC) &amp;&amp; !PLATFORM(IOS)
+    m_pageClient.clearCustomSwipeViews();
+#endif
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebPageProxy::willGoToBackForwardListItem(uint64_t itemID, IPC::MessageDecoder&amp; decoder)
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessmacViewGestureControllerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/mac/ViewGestureController.h (163092 => 163093)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/mac/ViewGestureController.h        2014-01-30 19:25:25 UTC (rev 163092)
+++ trunk/Source/WebKit2/UIProcess/mac/ViewGestureController.h        2014-01-30 19:29:48 UTC (rev 163093)
</span><span class="lines">@@ -35,6 +35,7 @@
</span><span class="cx"> 
</span><span class="cx"> OBJC_CLASS CALayer;
</span><span class="cx"> OBJC_CLASS NSEvent;
</span><ins>+OBJC_CLASS NSView;
</ins><span class="cx"> 
</span><span class="cx"> namespace WebKit {
</span><span class="cx"> 
</span><span class="lines">@@ -57,6 +58,9 @@
</span><span class="cx"> 
</span><span class="cx">     void wheelEventWasNotHandledByWebCore(NSEvent *);
</span><span class="cx"> 
</span><ins>+    void setCustomSwipeViews(Vector&lt;RetainPtr&lt;NSView&gt;&gt; views) { m_customSwipeViews = std::move(views); }
+    WebCore::FloatRect windowRelativeBoundsForCustomSwipeViews() const;
+
</ins><span class="cx">     void endActiveGesture();
</span><span class="cx"> 
</span><span class="cx">     enum class ViewGestureType {
</span><span class="lines">@@ -105,8 +109,12 @@
</span><span class="cx">     bool m_frameHandlesMagnificationGesture;
</span><span class="cx"> 
</span><span class="cx">     RetainPtr&lt;CALayer&gt; m_swipeSnapshotLayer;
</span><ins>+    Vector&lt;RetainPtr&lt;CALayer&gt;&gt; m_currentSwipeLiveLayers;
+
</ins><span class="cx">     SwipeTransitionStyle m_swipeTransitionStyle;
</span><span class="cx">     WebCore::Timer&lt;ViewGestureController&gt; m_swipeWatchdogTimer;
</span><ins>+    Vector&lt;RetainPtr&lt;NSView&gt;&gt; m_customSwipeViews;
+    WebCore::FloatRect m_currentSwipeCustomViewBounds;
</ins><span class="cx"> 
</span><span class="cx">     // If we need to wait for content to decide if it is going to consume
</span><span class="cx">     // the scroll event that would have started a swipe, we'll fill these in.
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessmacViewGestureControllermm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/mac/ViewGestureController.mm (163092 => 163093)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/mac/ViewGestureController.mm        2014-01-30 19:25:25 UTC (rev 163092)
+++ trunk/Source/WebKit2/UIProcess/mac/ViewGestureController.mm        2014-01-30 19:29:48 UTC (rev 163093)
</span><span class="lines">@@ -310,11 +310,47 @@
</span><span class="cx">     }];
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+FloatRect ViewGestureController::windowRelativeBoundsForCustomSwipeViews() const
+{
+    FloatRect swipeArea;
+    for (const auto&amp; view : m_customSwipeViews)
+        swipeArea.unite([view convertRect:[view bounds] toView:nil]);
+    return swipeArea;
+}
+
+static CALayer *leastCommonAncestorLayer(Vector&lt;RetainPtr&lt;CALayer&gt;&gt;&amp; layers)
+{
+    Vector&lt;Vector&lt;CALayer *&gt;&gt; liveLayerPathsFromRoot(layers.size());
+
+    size_t shortestPathLength = std::numeric_limits&lt;size_t&gt;::max();
+
+    for (size_t layerIndex = 0; layerIndex &lt; layers.size(); layerIndex++) {
+        CALayer *parent = [layers[layerIndex] superlayer];
+        while (parent) {
+            liveLayerPathsFromRoot[layerIndex].insert(0, parent);
+            shortestPathLength = std::min(shortestPathLength, liveLayerPathsFromRoot[layerIndex].size());
+            parent = parent.superlayer;
+        }
+    }
+
+    for (size_t pathIndex = 0; pathIndex &lt; shortestPathLength; pathIndex++) {
+        CALayer *firstPathLayer = liveLayerPathsFromRoot[0][pathIndex];
+        for (size_t layerIndex = 1; layerIndex &lt; layers.size(); layerIndex++) {
+            if (liveLayerPathsFromRoot[layerIndex][pathIndex] != firstPathLayer)
+                return firstPathLayer;
+        }
+    }
+
+    return liveLayerPathsFromRoot[0][shortestPathLength];
+}
+
</ins><span class="cx"> void ViewGestureController::beginSwipeGesture(WebBackForwardListItem* targetItem, SwipeDirection direction)
</span><span class="cx"> {
</span><ins>+    ASSERT(m_currentSwipeLiveLayers.isEmpty());
+
</ins><span class="cx">     m_activeGestureType = ViewGestureType::Swipe;
</span><span class="cx"> 
</span><del>-    CALayer *rootLayer = m_webPageProxy.acceleratedCompositingRootLayer();
</del><ins>+    CALayer *rootContentLayer = m_webPageProxy.acceleratedCompositingRootLayer();
</ins><span class="cx"> 
</span><span class="cx">     m_swipeSnapshotLayer = adoptNS([[CALayer alloc] init]);
</span><span class="cx">     [m_swipeSnapshotLayer setBackgroundColor:CGColorGetConstantColor(kCGColorWhite)];
</span><span class="lines">@@ -333,11 +369,26 @@
</span><span class="cx"> #endif
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    m_currentSwipeCustomViewBounds = windowRelativeBoundsForCustomSwipeViews();
+
+    FloatRect swipeArea;
+    if (!m_customSwipeViews.isEmpty()) {
+        swipeArea = m_currentSwipeCustomViewBounds;
+
+        for (const auto&amp; view : m_customSwipeViews) {
+            CALayer *layer = [view layer];
+            ASSERT(layer);
+            m_currentSwipeLiveLayers.append(layer);
+        }
+    } else {
+        swipeArea = rootContentLayer.frame;
+        m_currentSwipeLiveLayers.append(rootContentLayer);
+    }
+
</ins><span class="cx">     [m_swipeSnapshotLayer setContentsGravity:kCAGravityTopLeft];
</span><span class="cx">     [m_swipeSnapshotLayer setContentsScale:m_webPageProxy.deviceScaleFactor()];
</span><del>-    [m_swipeSnapshotLayer setFrame:rootLayer.frame];
</del><span class="cx">     [m_swipeSnapshotLayer setAnchorPoint:CGPointZero];
</span><del>-    [m_swipeSnapshotLayer setPosition:CGPointZero];
</del><ins>+    [m_swipeSnapshotLayer setFrame:swipeArea];
</ins><span class="cx">     [m_swipeSnapshotLayer setName:@&quot;Gesture Swipe Snapshot Layer&quot;];
</span><span class="cx">     [m_swipeSnapshotLayer web_disableAllActions];
</span><span class="cx"> 
</span><span class="lines">@@ -347,42 +398,68 @@
</span><span class="cx">         [m_swipeSnapshotLayer setFilters:@[filter]];
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (m_swipeTransitionStyle == SwipeTransitionStyle::Overlap) {
-        RetainPtr&lt;CGPathRef&gt; shadowPath = adoptCF(CGPathCreateWithRect([rootLayer bounds], 0));
</del><ins>+    // We don't know enough about the custom views' hierarchy to apply a shadow.
+    if (m_swipeTransitionStyle == SwipeTransitionStyle::Overlap &amp;&amp; m_customSwipeViews.isEmpty()) {
+        RetainPtr&lt;CGPathRef&gt; shadowPath = adoptCF(CGPathCreateWithRect([m_swipeSnapshotLayer bounds], 0));
</ins><span class="cx"> 
</span><del>-        [m_swipeSnapshotLayer setShadowColor:CGColorGetConstantColor(kCGColorBlack)];
-        [m_swipeSnapshotLayer setShadowOpacity:swipeOverlayShadowOpacity];
-        [m_swipeSnapshotLayer setShadowRadius:swipeOverlayShadowRadius];
-        [m_swipeSnapshotLayer setShadowPath:shadowPath.get()];
</del><ins>+        if (direction == SwipeDirection::Left) {
+            [rootContentLayer setShadowColor:CGColorGetConstantColor(kCGColorBlack)];
+            [rootContentLayer setShadowOpacity:swipeOverlayShadowOpacity];
+            [rootContentLayer setShadowRadius:swipeOverlayShadowRadius];
+            [rootContentLayer setShadowPath:shadowPath.get()];
+        } else {
+            [m_swipeSnapshotLayer setShadowColor:CGColorGetConstantColor(kCGColorBlack)];
+            [m_swipeSnapshotLayer setShadowOpacity:swipeOverlayShadowOpacity];
+            [m_swipeSnapshotLayer setShadowRadius:swipeOverlayShadowRadius];
+            [m_swipeSnapshotLayer setShadowPath:shadowPath.get()];
+        }
+    }
</ins><span class="cx"> 
</span><del>-        [rootLayer setShadowColor:CGColorGetConstantColor(kCGColorBlack)];
-        [rootLayer setShadowOpacity:swipeOverlayShadowOpacity];
-        [rootLayer setShadowRadius:swipeOverlayShadowRadius];
-        [rootLayer setShadowPath:shadowPath.get()];
</del><ins>+    // If we have custom swiping views, we assume that the views were passed to us in back-to-front z-order.
+    CALayer *layerAdjacentToSnapshot = direction == SwipeDirection::Left ? m_currentSwipeLiveLayers.first().get() : m_currentSwipeLiveLayers.last().get();
+    CALayer *snapshotLayerParent;
+
+    if (m_currentSwipeLiveLayers.size() == 1)
+        snapshotLayerParent = [m_currentSwipeLiveLayers[0] superlayer];
+    else {
+        // We insert our snapshot into the first shared superlayer of the custom views' layer, above the frontmost or below the bottommost layer.
+        snapshotLayerParent = leastCommonAncestorLayer(m_currentSwipeLiveLayers);
+
+        // If the layers are not all siblings, find the child of the layer we're going to insert the snapshot into which has the frontmost/bottommost layer as a child.
+        while (snapshotLayerParent != layerAdjacentToSnapshot.superlayer)
+            layerAdjacentToSnapshot = layerAdjacentToSnapshot.superlayer;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (direction == SwipeDirection::Left)
</span><del>-        [rootLayer.superlayer insertSublayer:m_swipeSnapshotLayer.get() below:rootLayer];
</del><ins>+        [snapshotLayerParent insertSublayer:m_swipeSnapshotLayer.get() below:layerAdjacentToSnapshot];
</ins><span class="cx">     else
</span><del>-        [rootLayer.superlayer insertSublayer:m_swipeSnapshotLayer.get() above:rootLayer];
</del><ins>+        [snapshotLayerParent insertSublayer:m_swipeSnapshotLayer.get() above:layerAdjacentToSnapshot];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void ViewGestureController::handleSwipeGesture(WebBackForwardListItem* targetItem, double progress, SwipeDirection direction)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(m_activeGestureType == ViewGestureType::Swipe);
</span><span class="cx"> 
</span><del>-    CALayer *rootLayer = m_webPageProxy.acceleratedCompositingRootLayer();
-    double width = rootLayer.bounds.size.width;
</del><ins>+    double width;
+    if (!m_customSwipeViews.isEmpty())
+        width = m_currentSwipeCustomViewBounds.width();
+    else
+        width = m_webPageProxy.acceleratedCompositingRootLayer().frame.size.width;
+
</ins><span class="cx">     double swipingLayerOffset = floor(width * progress);
</span><span class="cx"> 
</span><span class="cx">     if (m_swipeTransitionStyle == SwipeTransitionStyle::Overlap) {
</span><del>-        if (direction == SwipeDirection::Left)
-            [rootLayer setPosition:CGPointMake(swipingLayerOffset, 0)];
-        else
-            [m_swipeSnapshotLayer setPosition:CGPointMake(width + swipingLayerOffset, 0)];
-    } else if (m_swipeTransitionStyle == SwipeTransitionStyle::Push) {
-        [rootLayer setPosition:CGPointMake(swipingLayerOffset, 0)];
-        [m_swipeSnapshotLayer setPosition:CGPointMake((direction == SwipeDirection::Left ? -width : width) + swipingLayerOffset, 0)];
</del><ins>+        if (direction == SwipeDirection::Right)
+            [m_swipeSnapshotLayer setTransform:CATransform3DMakeTranslation(width + swipingLayerOffset, 0, 0)];
+    } else if (m_swipeTransitionStyle == SwipeTransitionStyle::Push)
+        [m_swipeSnapshotLayer setTransform:CATransform3DMakeTranslation((direction == SwipeDirection::Left ? -width : width) + swipingLayerOffset, 0, 0)];
+
+    for (const auto&amp; layer : m_currentSwipeLiveLayers) {
+        if (m_swipeTransitionStyle == SwipeTransitionStyle::Overlap) {
+            if (direction == SwipeDirection::Left)
+                [layer setTransform:CATransform3DMakeTranslation(swipingLayerOffset, 0, 0)];
+        } else if (m_swipeTransitionStyle == SwipeTransitionStyle::Push)
+            [layer setTransform:CATransform3DMakeTranslation(swipingLayerOffset, 0, 0)];
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -441,10 +518,14 @@
</span><span class="cx">         IOSurfaceSetPurgeable(snapshotSurface, kIOSurfacePurgeableVolatile, nullptr);
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    [m_webPageProxy.acceleratedCompositingRootLayer() setPosition:CGPointZero];
</del><ins>+    for (const auto&amp; layer : m_currentSwipeLiveLayers)
+        [layer setTransform:CATransform3DIdentity];
+
</ins><span class="cx">     [m_swipeSnapshotLayer removeFromSuperlayer];
</span><span class="cx">     m_swipeSnapshotLayer = nullptr;
</span><span class="cx"> 
</span><ins>+    m_currentSwipeLiveLayers.clear();
+
</ins><span class="cx">     m_activeGestureType = ViewGestureType::None;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>