WKWebView snapshots have the wrong scale after rotation
authortimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 1 Jul 2015 21:34:58 +0000 (21:34 +0000)
committertimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 1 Jul 2015 21:34:58 +0000 (21:34 +0000)
https://bugs.webkit.org/show_bug.cgi?id=146476
<rdar://problem/18345247>

Reviewed by Anders Carlsson.

* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _didCommitLayerTree:]):
"Coordinate" -> "Coordinates".

(-[WKWebView _snapshotRect:intoImageOfWidth:completionHandler:]):
Defer any snapshotting that happens during a resize until after
the resize completes. This will ensure that (in the case of an IOSurface
snapshot) the tiles are up to date, and (in the case of a software snapshot)
that our understanding of the scale and scroll offset of the WKContentView
are up to date, so that we can correctly convert from view to content coordinates
in the UI process.

(-[WKWebView _endAnimatedResize]):
Perform the deferred snapshotting after the resize completes.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@186194 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebKit2/ChangeLog
Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm

index 77640cb..2a27983 100644 (file)
@@ -1,3 +1,26 @@
+2015-07-01  Tim Horton  <timothy_horton@apple.com>
+
+        WKWebView snapshots have the wrong scale after rotation
+        https://bugs.webkit.org/show_bug.cgi?id=146476
+        <rdar://problem/18345247>
+
+        Reviewed by Anders Carlsson.
+
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView _didCommitLayerTree:]):
+        "Coordinate" -> "Coordinates".
+
+        (-[WKWebView _snapshotRect:intoImageOfWidth:completionHandler:]):
+        Defer any snapshotting that happens during a resize until after
+        the resize completes. This will ensure that (in the case of an IOSurface
+        snapshot) the tiles are up to date, and (in the case of a software snapshot)
+        that our understanding of the scale and scroll offset of the WKContentView
+        are up to date, so that we can correctly convert from view to content coordinates
+        in the UI process.
+
+        (-[WKWebView _endAnimatedResize]):
+        Perform the deferred snapshotting after the resize completes.
+
 2015-07-01  Beth Dakin  <bdakin@apple.com>
 
         This is a quick follow-on to http://trac.webkit.org/changeset/186132
index 3d583bd..e471298 100644 (file)
@@ -213,6 +213,7 @@ WKWebView* fromWebPageProxy(WebKit::WebPageProxy& page)
 
     BOOL _pageIsPrintingToPDF;
     RetainPtr<CGPDFDocumentRef> _printedDocument;
+    Vector<std::function<void ()>> _snapshotsDeferredDuringResize;
 #endif
 #if PLATFORM(MAC)
     RetainPtr<WKView> _wkView;
@@ -995,12 +996,12 @@ static inline bool areEssentiallyEqualAsFloat(float a, float b)
         if (areEssentiallyEqualAsFloat(contentZoomScale(self), _scaleToRestore)) {
             CGRect unobscuredRect = UIEdgeInsetsInsetRect(self.bounds, _obscuredInsets);
             WebCore::FloatSize unobscuredContentSizeAtNewScale(unobscuredRect.size.width / _scaleToRestore, unobscuredRect.size.height / _scaleToRestore);
-            WebCore::FloatPoint topLeftInDocumentCoordinate(_unobscuredCenterToRestore.x() - unobscuredContentSizeAtNewScale.width() / 2, _unobscuredCenterToRestore.y() - unobscuredContentSizeAtNewScale.height() / 2);
+            WebCore::FloatPoint topLeftInDocumentCoordinates(_unobscuredCenterToRestore.x() - unobscuredContentSizeAtNewScale.width() / 2, _unobscuredCenterToRestore.y() - unobscuredContentSizeAtNewScale.height() / 2);
 
-            topLeftInDocumentCoordinate.scale(_scaleToRestore, _scaleToRestore);
-            topLeftInDocumentCoordinate.moveBy(WebCore::FloatPoint(-_obscuredInsets.left, -_obscuredInsets.top));
+            topLeftInDocumentCoordinates.scale(_scaleToRestore, _scaleToRestore);
+            topLeftInDocumentCoordinates.moveBy(WebCore::FloatPoint(-_obscuredInsets.left, -_obscuredInsets.top));
 
-            changeContentOffsetBoundedInValidRange(_scrollView.get(), topLeftInDocumentCoordinate);
+            changeContentOffsetBoundedInValidRange(_scrollView.get(), topLeftInDocumentCoordinates);
             if (_gestureController)
                 _gestureController->didRestoreScrollPosition();
         }
@@ -2831,6 +2832,9 @@ static inline WebKit::FindOptions toFindOptions(_WKFindOptions wkFindOptions)
     _dynamicViewportUpdateMode = DynamicViewportUpdateMode::NotResizing;
     [_contentView setHidden:NO];
     [self _updateVisibleContentRects];
+
+    while (!_snapshotsDeferredDuringResize.isEmpty())
+        _snapshotsDeferredDuringResize.takeLast()();
 }
 
 - (void)_resizeWhileHidingContentWithUpdates:(void (^)(void))updateBlock
@@ -2849,6 +2853,17 @@ static inline WebKit::FindOptions toFindOptions(_WKFindOptions wkFindOptions)
 
 - (void)_snapshotRect:(CGRect)rectInViewCoordinates intoImageOfWidth:(CGFloat)imageWidth completionHandler:(void(^)(CGImageRef))completionHandler
 {
+    if (_dynamicViewportUpdateMode != DynamicViewportUpdateMode::NotResizing) {
+        // Defer snapshotting until after the current resize completes.
+        void (^copiedCompletionHandler)(CGImageRef) = [completionHandler copy];
+        RetainPtr<WKWebView> retainedSelf = self;
+        _snapshotsDeferredDuringResize.append([retainedSelf, rectInViewCoordinates, imageWidth, copiedCompletionHandler] {
+            [retainedSelf _snapshotRect:rectInViewCoordinates intoImageOfWidth:imageWidth completionHandler:copiedCompletionHandler];
+            [copiedCompletionHandler release];
+        });
+        return;
+    }
+
     CGRect snapshotRectInContentCoordinates = [self convertRect:rectInViewCoordinates toView:self._currentContentView];
     CGFloat imageScale = imageWidth / snapshotRectInContentCoordinates.size.width;
     CGFloat imageHeight = imageScale * snapshotRectInContentCoordinates.size.height;
@@ -2886,7 +2901,6 @@ static inline WebKit::FindOptions toFindOptions(_WKFindOptions wkFindOptions)
         return;
     }
 
-
     void(^copiedCompletionHandler)(CGImageRef) = [completionHandler copy];
     _page->takeSnapshot(WebCore::enclosingIntRect(snapshotRectInContentCoordinates), WebCore::expandedIntSize(WebCore::FloatSize(imageSize)), WebKit::SnapshotOptionsExcludeDeviceScaleFactor, [=](const WebKit::ShareableBitmap::Handle& imageHandle, WebKit::CallbackBase::Error) {
         if (imageHandle.isNull()) {