Title: [171201] trunk/Source/WebKit2
Revision
171201
Author
[email protected]
Date
2014-07-17 15:08:41 -0700 (Thu, 17 Jul 2014)

Log Message

[iOS][WK2] Add SPI to do a dynamic viewport update without showing any content
https://bugs.webkit.org/show_bug.cgi?id=135010

Reviewed by Darin Adler.

This patch add a new SPI, [WKWebView _resizeWhileHidingContentWithUpdates:] to perform all the work
of a dynamic viewport size update, but instead of animating the old content, it is hidden.

The patch is built on top of the animated resize mechanism. Instead of having an animation driving
the beginning and end, we let the content do that. The dynamic resize begins, it runs for as long as
the WebProcess needs, and it ends when first layer tree commit with the new content is processed.

The attribute "_isAnimatingResize" is generalized to support two modes of resizing: animated and
hiding content.

The attribute "_hasCommittedLoadForMainFrame" is rather silly. It is only needed because
[WKWebView _resizeWhileHidingContentWithUpdates:] is intended to be called a lot before the page
is initialized, and doing an animated resize would trash the WebProcess state.
I wish I had a better solution, this is not great.

* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _processDidExit]):
(-[WKWebView _didCommitLoadForMainFrame]):
(-[WKWebView _didCommitLayerTree:]):
This is the key to make this work properly. We want _resizeWhileHidingContentWithUpdates: to behave
exactly like an animated resize to avoid bugs. So we went to the whole update mechanism using
_resizeAnimationTransformAdjustments to accumulate the adjustments, now we need to restore a correct
view state.

Calling [WKWebView _endAnimatedResize] will do exactly that, but we need to make sure we do not hit
the synchronization path or we would be blocked there for a while, which is what we are trying to avoid.

After r171154, WebPageProxy keeps track of what stage of dynamic viewport update we are in. Since we are
executing the layer tree update stage, with the right transaction ID, WebPageProxy already knows we have
everything we need and does not use any synchronous messages.

(-[WKWebView _dynamicViewportUpdateChangedTargetToScale:position:nextValidLayerTreeTransactionID:]):
(-[WKWebView _restorePageStateToExposedRect:scale:]):
(-[WKWebView _restorePageStateToUnobscuredCenter:scale:]):
(-[WKWebView _scrollToContentOffset:]):
(-[WKWebView _frameOrBoundsChanged]):
(-[WKWebView _updateVisibleContentRects]):
(-[WKWebView _setMinimumLayoutSizeOverride:]):
(-[WKWebView _setMinimumLayoutSizeOverrideForMinimalUI:]):
(-[WKWebView _setInterfaceOrientationOverride:]):
(-[WKWebView _setMaximumUnobscuredSizeOverride:]):
(-[WKWebView _beginAnimatedResizeWithUpdates:]):
(-[WKWebView _endAnimatedResize]):
(-[WKWebView _resizeWhileHidingContentWithUpdates:]):
* UIProcess/API/Cocoa/WKWebViewPrivate.h:

Modified Paths

Diff

Modified: trunk/Source/WebKit2/ChangeLog (171200 => 171201)


--- trunk/Source/WebKit2/ChangeLog	2014-07-17 22:02:26 UTC (rev 171200)
+++ trunk/Source/WebKit2/ChangeLog	2014-07-17 22:08:41 UTC (rev 171201)
@@ -1,3 +1,56 @@
+2014-07-17  Benjamin Poulain  <[email protected]>
+
+        [iOS][WK2] Add SPI to do a dynamic viewport update without showing any content
+        https://bugs.webkit.org/show_bug.cgi?id=135010
+
+        Reviewed by Darin Adler.
+
+        This patch add a new SPI, [WKWebView _resizeWhileHidingContentWithUpdates:] to perform all the work
+        of a dynamic viewport size update, but instead of animating the old content, it is hidden.
+
+        The patch is built on top of the animated resize mechanism. Instead of having an animation driving
+        the beginning and end, we let the content do that. The dynamic resize begins, it runs for as long as
+        the WebProcess needs, and it ends when first layer tree commit with the new content is processed.
+
+        The attribute "_isAnimatingResize" is generalized to support two modes of resizing: animated and
+        hiding content.
+
+        The attribute "_hasCommittedLoadForMainFrame" is rather silly. It is only needed because
+        [WKWebView _resizeWhileHidingContentWithUpdates:] is intended to be called a lot before the page
+        is initialized, and doing an animated resize would trash the WebProcess state.
+        I wish I had a better solution, this is not great.
+
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView _processDidExit]):
+        (-[WKWebView _didCommitLoadForMainFrame]):
+        (-[WKWebView _didCommitLayerTree:]):
+        This is the key to make this work properly. We want _resizeWhileHidingContentWithUpdates: to behave
+        exactly like an animated resize to avoid bugs. So we went to the whole update mechanism using
+        _resizeAnimationTransformAdjustments to accumulate the adjustments, now we need to restore a correct
+        view state.
+
+        Calling [WKWebView _endAnimatedResize] will do exactly that, but we need to make sure we do not hit
+        the synchronization path or we would be blocked there for a while, which is what we are trying to avoid.
+
+        After r171154, WebPageProxy keeps track of what stage of dynamic viewport update we are in. Since we are
+        executing the layer tree update stage, with the right transaction ID, WebPageProxy already knows we have
+        everything we need and does not use any synchronous messages.
+
+        (-[WKWebView _dynamicViewportUpdateChangedTargetToScale:position:nextValidLayerTreeTransactionID:]):
+        (-[WKWebView _restorePageStateToExposedRect:scale:]):
+        (-[WKWebView _restorePageStateToUnobscuredCenter:scale:]):
+        (-[WKWebView _scrollToContentOffset:]):
+        (-[WKWebView _frameOrBoundsChanged]):
+        (-[WKWebView _updateVisibleContentRects]):
+        (-[WKWebView _setMinimumLayoutSizeOverride:]):
+        (-[WKWebView _setMinimumLayoutSizeOverrideForMinimalUI:]):
+        (-[WKWebView _setInterfaceOrientationOverride:]):
+        (-[WKWebView _setMaximumUnobscuredSizeOverride:]):
+        (-[WKWebView _beginAnimatedResizeWithUpdates:]):
+        (-[WKWebView _endAnimatedResize]):
+        (-[WKWebView _resizeWhileHidingContentWithUpdates:]):
+        * UIProcess/API/Cocoa/WKWebViewPrivate.h:
+
 2014-07-17  Brent Fulgham  <[email protected]>
 
         [Mac] Full screen video not always animating in the correct Space

Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm (171200 => 171201)


--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm	2014-07-17 22:02:26 UTC (rev 171200)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm	2014-07-17 22:08:41 UTC (rev 171201)
@@ -118,6 +118,13 @@
 - (UIViewController *)_rootAncestorViewController;
 - (UIViewController *)_viewControllerForSupportedInterfaceOrientations;
 @end
+
+enum class DynamicViewportUpdateMode {
+    NotResizing,
+    ResizingWithAnimation,
+    ResizingWithDocumentHidden,
+};
+
 #endif
 
 #if PLATFORM(MAC)
@@ -166,9 +173,10 @@
     UIInterfaceOrientation _interfaceOrientationOverride;
     BOOL _overridesInterfaceOrientation;
 
+    BOOL _hasCommittedLoadForMainFrame;
     BOOL _needsResetViewStateAfterCommitLoadForMainFrame;
     uint64_t _firstPaintAfterCommitLoadTransactionID;
-    BOOL _isAnimatingResize;
+    DynamicViewportUpdateMode _dynamicViewportUpdateMode;
     CATransform3D _resizeAnimationTransformAdjustments;
     uint64_t _resizeAnimationTransformTransactionID;
     RetainPtr<UIView> _resizeAnimationView;
@@ -740,14 +748,13 @@
 
 - (void)_processDidExit
 {
-    if (!_customContentView && _isAnimatingResize) {
+    if (!_customContentView && _dynamicViewportUpdateMode != DynamicViewportUpdateMode::NotResizing) {
         NSUInteger indexOfResizeAnimationView = [[_scrollView subviews] indexOfObject:_resizeAnimationView.get()];
         [_scrollView insertSubview:_contentView.get() atIndex:indexOfResizeAnimationView];
         [_scrollView insertSubview:[_contentView unscaledView] atIndex:indexOfResizeAnimationView + 1];
         [_resizeAnimationView removeFromSuperview];
         _resizeAnimationView = nil;
 
-        _isAnimatingResize = NO;
         _resizeAnimationTransformAdjustments = CATransform3DIdentity;
     }
     [_contentView setFrame:self.bounds];
@@ -756,7 +763,10 @@
     [_scrollView setZoomScale:1];
 
     _viewportMetaTagWidth = -1;
+    _hasCommittedLoadForMainFrame = NO;
     _needsResetViewStateAfterCommitLoadForMainFrame = NO;
+    _dynamicViewportUpdateMode = DynamicViewportUpdateMode::NotResizing;
+    [_contentView setHidden:NO];
     _needsToRestoreExposedRect = NO;
     _needsToRestoreUnobscuredCenter = NO;
     _scrollViewBackgroundColor = WebCore::Color();
@@ -768,6 +778,7 @@
 {
     _firstPaintAfterCommitLoadTransactionID = toRemoteLayerTreeDrawingAreaProxy(_page->drawingArea())->nextLayerTreeTransactionID();
 
+    _hasCommittedLoadForMainFrame = YES;
     _needsResetViewStateAfterCommitLoadForMainFrame = YES;
     _usesMinimalUI = NO;
 }
@@ -804,9 +815,14 @@
     if (_customContentView)
         return;
 
-    if (_isAnimatingResize) {
-        if (layerTreeTransaction.transactionID() >= _resizeAnimationTransformTransactionID)
+    if (_dynamicViewportUpdateMode != DynamicViewportUpdateMode::NotResizing) {
+        if (layerTreeTransaction.transactionID() >= _resizeAnimationTransformTransactionID) {
             [_resizeAnimationView layer].sublayerTransform = _resizeAnimationTransformAdjustments;
+            if (_dynamicViewportUpdateMode == DynamicViewportUpdateMode::ResizingWithDocumentHidden) {
+                [_contentView setHidden:NO];
+                [self _endAnimatedResize];
+            }
+        }
         return;
     }
 
@@ -869,7 +885,7 @@
 
 - (void)_dynamicViewportUpdateChangedTargetToScale:(double)newScale position:(CGPoint)newScrollPosition nextValidLayerTreeTransactionID:(uint64_t)nextValidLayerTreeTransactionID
 {
-    if (_isAnimatingResize) {
+    if (_dynamicViewportUpdateMode != DynamicViewportUpdateMode::NotResizing) {
         CGFloat animatingScaleTarget = [[_resizeAnimationView layer] transform].m11;
         double currentTargetScale = animatingScaleTarget * [[_contentView layer] transform].m11;
         double scale = newScale / currentTargetScale;
@@ -886,7 +902,7 @@
 
 - (void)_restorePageStateToExposedRect:(WebCore::FloatRect)exposedRect scale:(double)scale
 {
-    if (_isAnimatingResize)
+    if (_dynamicViewportUpdateMode != DynamicViewportUpdateMode::NotResizing)
         return;
 
     if (_customContentView)
@@ -901,7 +917,7 @@
 
 - (void)_restorePageStateToUnobscuredCenter:(WebCore::FloatPoint)center scale:(double)scale
 {
-    if (_isAnimatingResize)
+    if (_dynamicViewportUpdateMode != DynamicViewportUpdateMode::NotResizing)
         return;
 
     if (_customContentView)
@@ -987,7 +1003,7 @@
 
 - (void)_scrollToContentOffset:(WebCore::FloatPoint)contentOffset
 {
-    if (_isAnimatingResize)
+    if (_dynamicViewportUpdateMode != DynamicViewportUpdateMode::NotResizing)
         return;
 
     WebCore::FloatPoint scaledOffset = contentOffset;
@@ -1332,7 +1348,7 @@
     CGRect bounds = self.bounds;
     [_scrollView setFrame:bounds];
 
-    if (!_isAnimatingResize) {
+    if (_dynamicViewportUpdateMode == DynamicViewportUpdateMode::NotResizing) {
         if (!_overridesMinimumLayoutSize)
             _page->setViewportConfigurationMinimumLayoutSize(WebCore::FloatSize(bounds.size));
         if (!_overridesMinimumLayoutSizeForMinimalUI)
@@ -1368,7 +1384,7 @@
         return;
     }
 
-    if (_isAnimatingResize)
+    if (_dynamicViewportUpdateMode != DynamicViewportUpdateMode::NotResizing)
         return;
 
     if (_needsResetViewStateAfterCommitLoadForMainFrame)
@@ -2027,7 +2043,7 @@
         return;
 
     _minimumLayoutSizeOverride = minimumLayoutSizeOverride;
-    if (!_isAnimatingResize)
+    if (_dynamicViewportUpdateMode == DynamicViewportUpdateMode::NotResizing)
         _page->setViewportConfigurationMinimumLayoutSize(WebCore::FloatSize(minimumLayoutSizeOverride));
 }
 
@@ -2044,7 +2060,7 @@
         return;
 
     _minimumLayoutSizeOverrideForMinimalUI = size;
-    if (!_isAnimatingResize)
+    if (_dynamicViewportUpdateMode == DynamicViewportUpdateMode::NotResizing)
         _page->setViewportConfigurationMinimumLayoutSizeForMinimalUI(WebCore::FloatSize(size));
 }
 
@@ -2080,7 +2096,7 @@
 
     _interfaceOrientationOverride = interfaceOrientation;
 
-    if (!_isAnimatingResize)
+    if (_dynamicViewportUpdateMode == DynamicViewportUpdateMode::NotResizing)
         _page->setDeviceOrientation(deviceOrientationForUIInterfaceOrientation(_interfaceOrientationOverride));
 }
 
@@ -2104,7 +2120,7 @@
         return;
 
     _maximumUnobscuredSizeOverride = size;
-    if (!_isAnimatingResize)
+    if (_dynamicViewportUpdateMode == DynamicViewportUpdateMode::NotResizing)
         _page->setMaximumUnobscuredSize(WebCore::FloatSize(size));
 }
 
@@ -2133,12 +2149,12 @@
 
 - (void)_beginAnimatedResizeWithUpdates:(void (^)(void))updateBlock
 {
-    if (_customContentView) {
+    if (_customContentView || !_hasCommittedLoadForMainFrame) {
         updateBlock();
         return;
     }
 
-    _isAnimatingResize = YES;
+    _dynamicViewportUpdateMode = DynamicViewportUpdateMode::ResizingWithAnimation;
 
     CGRect oldBounds = self.bounds;
     WebCore::FloatSize oldMinimumLayoutSize = activeMinimumLayoutSize(self, oldBounds);
@@ -2163,7 +2179,7 @@
         && oldMaximumUnobscuredSize == newMaximumUnobscuredSize
         && oldOrientation == newOrientation
         && UIEdgeInsetsEqualToEdgeInsets(oldObscuredInsets, newObscuredInsets)) {
-        _isAnimatingResize = NO;
+        _dynamicViewportUpdateMode = DynamicViewportUpdateMode::NotResizing;
         [self _updateVisibleContentRects];
         return;
     }
@@ -2227,7 +2243,7 @@
 
 - (void)_endAnimatedResize
 {
-    if (!_isAnimatingResize)
+    if (_dynamicViewportUpdateMode == DynamicViewportUpdateMode::NotResizing)
         return;
 
     _page->synchronizeDynamicViewportUpdate();
@@ -2265,10 +2281,20 @@
     _resizeAnimationView = nil;
     _resizeAnimationTransformAdjustments = CATransform3DIdentity;
 
-    _isAnimatingResize = NO;
+    _dynamicViewportUpdateMode = DynamicViewportUpdateMode::NotResizing;
+    [_contentView setHidden:NO];
     [self _updateVisibleContentRects];
 }
 
+- (void)_resizeWhileHidingContentWithUpdates:(void (^)(void))updateBlock
+{
+    [self _beginAnimatedResizeWithUpdates:updateBlock];
+    if (_dynamicViewportUpdateMode == DynamicViewportUpdateMode::ResizingWithAnimation) {
+        [_contentView setHidden:YES];
+        _dynamicViewportUpdateMode = DynamicViewportUpdateMode::ResizingWithDocumentHidden;
+    }
+}
+
 - (void)_setOverlaidAccessoryViewsInset:(CGSize)inset
 {
     [_customContentView web_setOverlaidAccessoryViewsInset:inset];

Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebViewPrivate.h (171200 => 171201)


--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebViewPrivate.h	2014-07-17 22:02:26 UTC (rev 171200)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebViewPrivate.h	2014-07-17 22:08:41 UTC (rev 171201)
@@ -137,6 +137,7 @@
 
 - (void)_beginAnimatedResizeWithUpdates:(void (^)(void))updateBlock;
 - (void)_endAnimatedResize;
+- (void)_resizeWhileHidingContentWithUpdates:(void (^)(void))updateBlock;
 
 - (void)_snapshotRect:(CGRect)rectInViewCoordinates intoImageOfWidth:(CGFloat)imageWidth completionHandler:(void(^)(CGImageRef))completionHandler;
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to