Changeset 171201 in webkit


Ignore:
Timestamp:
Jul 17, 2014 3:08:41 PM (10 years ago)
Author:
benjamin@webkit.org
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:
Location:
trunk/Source/WebKit2
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit2/ChangeLog

    r171197 r171201  
     12014-07-17  Benjamin Poulain  <benjamin@webkit.org>
     2
     3        [iOS][WK2] Add SPI to do a dynamic viewport update without showing any content
     4        https://bugs.webkit.org/show_bug.cgi?id=135010
     5
     6        Reviewed by Darin Adler.
     7
     8        This patch add a new SPI, [WKWebView _resizeWhileHidingContentWithUpdates:] to perform all the work
     9        of a dynamic viewport size update, but instead of animating the old content, it is hidden.
     10
     11        The patch is built on top of the animated resize mechanism. Instead of having an animation driving
     12        the beginning and end, we let the content do that. The dynamic resize begins, it runs for as long as
     13        the WebProcess needs, and it ends when first layer tree commit with the new content is processed.
     14
     15        The attribute "_isAnimatingResize" is generalized to support two modes of resizing: animated and
     16        hiding content.
     17
     18        The attribute "_hasCommittedLoadForMainFrame" is rather silly. It is only needed because
     19        [WKWebView _resizeWhileHidingContentWithUpdates:] is intended to be called a lot before the page
     20        is initialized, and doing an animated resize would trash the WebProcess state.
     21        I wish I had a better solution, this is not great.
     22
     23        * UIProcess/API/Cocoa/WKWebView.mm:
     24        (-[WKWebView _processDidExit]):
     25        (-[WKWebView _didCommitLoadForMainFrame]):
     26        (-[WKWebView _didCommitLayerTree:]):
     27        This is the key to make this work properly. We want _resizeWhileHidingContentWithUpdates: to behave
     28        exactly like an animated resize to avoid bugs. So we went to the whole update mechanism using
     29        _resizeAnimationTransformAdjustments to accumulate the adjustments, now we need to restore a correct
     30        view state.
     31
     32        Calling [WKWebView _endAnimatedResize] will do exactly that, but we need to make sure we do not hit
     33        the synchronization path or we would be blocked there for a while, which is what we are trying to avoid.
     34
     35        After r171154, WebPageProxy keeps track of what stage of dynamic viewport update we are in. Since we are
     36        executing the layer tree update stage, with the right transaction ID, WebPageProxy already knows we have
     37        everything we need and does not use any synchronous messages.
     38
     39        (-[WKWebView _dynamicViewportUpdateChangedTargetToScale:position:nextValidLayerTreeTransactionID:]):
     40        (-[WKWebView _restorePageStateToExposedRect:scale:]):
     41        (-[WKWebView _restorePageStateToUnobscuredCenter:scale:]):
     42        (-[WKWebView _scrollToContentOffset:]):
     43        (-[WKWebView _frameOrBoundsChanged]):
     44        (-[WKWebView _updateVisibleContentRects]):
     45        (-[WKWebView _setMinimumLayoutSizeOverride:]):
     46        (-[WKWebView _setMinimumLayoutSizeOverrideForMinimalUI:]):
     47        (-[WKWebView _setInterfaceOrientationOverride:]):
     48        (-[WKWebView _setMaximumUnobscuredSizeOverride:]):
     49        (-[WKWebView _beginAnimatedResizeWithUpdates:]):
     50        (-[WKWebView _endAnimatedResize]):
     51        (-[WKWebView _resizeWhileHidingContentWithUpdates:]):
     52        * UIProcess/API/Cocoa/WKWebViewPrivate.h:
     53
    1542014-07-17  Brent Fulgham  <bfulgham@apple.com>
    255
  • trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm

    r171154 r171201  
    119119- (UIViewController *)_viewControllerForSupportedInterfaceOrientations;
    120120@end
     121
     122enum class DynamicViewportUpdateMode {
     123    NotResizing,
     124    ResizingWithAnimation,
     125    ResizingWithDocumentHidden,
     126};
     127
    121128#endif
    122129
     
    167174    BOOL _overridesInterfaceOrientation;
    168175
     176    BOOL _hasCommittedLoadForMainFrame;
    169177    BOOL _needsResetViewStateAfterCommitLoadForMainFrame;
    170178    uint64_t _firstPaintAfterCommitLoadTransactionID;
    171     BOOL _isAnimatingResize;
     179    DynamicViewportUpdateMode _dynamicViewportUpdateMode;
    172180    CATransform3D _resizeAnimationTransformAdjustments;
    173181    uint64_t _resizeAnimationTransformTransactionID;
     
    741749- (void)_processDidExit
    742750{
    743     if (!_customContentView && _isAnimatingResize) {
     751    if (!_customContentView && _dynamicViewportUpdateMode != DynamicViewportUpdateMode::NotResizing) {
    744752        NSUInteger indexOfResizeAnimationView = [[_scrollView subviews] indexOfObject:_resizeAnimationView.get()];
    745753        [_scrollView insertSubview:_contentView.get() atIndex:indexOfResizeAnimationView];
     
    748756        _resizeAnimationView = nil;
    749757
    750         _isAnimatingResize = NO;
    751758        _resizeAnimationTransformAdjustments = CATransform3DIdentity;
    752759    }
     
    757764
    758765    _viewportMetaTagWidth = -1;
     766    _hasCommittedLoadForMainFrame = NO;
    759767    _needsResetViewStateAfterCommitLoadForMainFrame = NO;
     768    _dynamicViewportUpdateMode = DynamicViewportUpdateMode::NotResizing;
     769    [_contentView setHidden:NO];
    760770    _needsToRestoreExposedRect = NO;
    761771    _needsToRestoreUnobscuredCenter = NO;
     
    769779    _firstPaintAfterCommitLoadTransactionID = toRemoteLayerTreeDrawingAreaProxy(_page->drawingArea())->nextLayerTreeTransactionID();
    770780
     781    _hasCommittedLoadForMainFrame = YES;
    771782    _needsResetViewStateAfterCommitLoadForMainFrame = YES;
    772783    _usesMinimalUI = NO;
     
    805816        return;
    806817
    807     if (_isAnimatingResize) {
    808         if (layerTreeTransaction.transactionID() >= _resizeAnimationTransformTransactionID)
     818    if (_dynamicViewportUpdateMode != DynamicViewportUpdateMode::NotResizing) {
     819        if (layerTreeTransaction.transactionID() >= _resizeAnimationTransformTransactionID) {
    809820            [_resizeAnimationView layer].sublayerTransform = _resizeAnimationTransformAdjustments;
     821            if (_dynamicViewportUpdateMode == DynamicViewportUpdateMode::ResizingWithDocumentHidden) {
     822                [_contentView setHidden:NO];
     823                [self _endAnimatedResize];
     824            }
     825        }
    810826        return;
    811827    }
     
    870886- (void)_dynamicViewportUpdateChangedTargetToScale:(double)newScale position:(CGPoint)newScrollPosition nextValidLayerTreeTransactionID:(uint64_t)nextValidLayerTreeTransactionID
    871887{
    872     if (_isAnimatingResize) {
     888    if (_dynamicViewportUpdateMode != DynamicViewportUpdateMode::NotResizing) {
    873889        CGFloat animatingScaleTarget = [[_resizeAnimationView layer] transform].m11;
    874890        double currentTargetScale = animatingScaleTarget * [[_contentView layer] transform].m11;
     
    887903- (void)_restorePageStateToExposedRect:(WebCore::FloatRect)exposedRect scale:(double)scale
    888904{
    889     if (_isAnimatingResize)
     905    if (_dynamicViewportUpdateMode != DynamicViewportUpdateMode::NotResizing)
    890906        return;
    891907
     
    902918- (void)_restorePageStateToUnobscuredCenter:(WebCore::FloatPoint)center scale:(double)scale
    903919{
    904     if (_isAnimatingResize)
     920    if (_dynamicViewportUpdateMode != DynamicViewportUpdateMode::NotResizing)
    905921        return;
    906922
     
    9881004- (void)_scrollToContentOffset:(WebCore::FloatPoint)contentOffset
    9891005{
    990     if (_isAnimatingResize)
     1006    if (_dynamicViewportUpdateMode != DynamicViewportUpdateMode::NotResizing)
    9911007        return;
    9921008
     
    13331349    [_scrollView setFrame:bounds];
    13341350
    1335     if (!_isAnimatingResize) {
     1351    if (_dynamicViewportUpdateMode == DynamicViewportUpdateMode::NotResizing) {
    13361352        if (!_overridesMinimumLayoutSize)
    13371353            _page->setViewportConfigurationMinimumLayoutSize(WebCore::FloatSize(bounds.size));
     
    13691385    }
    13701386
    1371     if (_isAnimatingResize)
     1387    if (_dynamicViewportUpdateMode != DynamicViewportUpdateMode::NotResizing)
    13721388        return;
    13731389
     
    20282044
    20292045    _minimumLayoutSizeOverride = minimumLayoutSizeOverride;
    2030     if (!_isAnimatingResize)
     2046    if (_dynamicViewportUpdateMode == DynamicViewportUpdateMode::NotResizing)
    20312047        _page->setViewportConfigurationMinimumLayoutSize(WebCore::FloatSize(minimumLayoutSizeOverride));
    20322048}
     
    20452061
    20462062    _minimumLayoutSizeOverrideForMinimalUI = size;
    2047     if (!_isAnimatingResize)
     2063    if (_dynamicViewportUpdateMode == DynamicViewportUpdateMode::NotResizing)
    20482064        _page->setViewportConfigurationMinimumLayoutSizeForMinimalUI(WebCore::FloatSize(size));
    20492065}
     
    20812097    _interfaceOrientationOverride = interfaceOrientation;
    20822098
    2083     if (!_isAnimatingResize)
     2099    if (_dynamicViewportUpdateMode == DynamicViewportUpdateMode::NotResizing)
    20842100        _page->setDeviceOrientation(deviceOrientationForUIInterfaceOrientation(_interfaceOrientationOverride));
    20852101}
     
    21052121
    21062122    _maximumUnobscuredSizeOverride = size;
    2107     if (!_isAnimatingResize)
     2123    if (_dynamicViewportUpdateMode == DynamicViewportUpdateMode::NotResizing)
    21082124        _page->setMaximumUnobscuredSize(WebCore::FloatSize(size));
    21092125}
     
    21342150- (void)_beginAnimatedResizeWithUpdates:(void (^)(void))updateBlock
    21352151{
    2136     if (_customContentView) {
     2152    if (_customContentView || !_hasCommittedLoadForMainFrame) {
    21372153        updateBlock();
    21382154        return;
    21392155    }
    21402156
    2141     _isAnimatingResize = YES;
     2157    _dynamicViewportUpdateMode = DynamicViewportUpdateMode::ResizingWithAnimation;
    21422158
    21432159    CGRect oldBounds = self.bounds;
     
    21642180        && oldOrientation == newOrientation
    21652181        && UIEdgeInsetsEqualToEdgeInsets(oldObscuredInsets, newObscuredInsets)) {
    2166         _isAnimatingResize = NO;
     2182        _dynamicViewportUpdateMode = DynamicViewportUpdateMode::NotResizing;
    21672183        [self _updateVisibleContentRects];
    21682184        return;
     
    22282244- (void)_endAnimatedResize
    22292245{
    2230     if (!_isAnimatingResize)
     2246    if (_dynamicViewportUpdateMode == DynamicViewportUpdateMode::NotResizing)
    22312247        return;
    22322248
     
    22662282    _resizeAnimationTransformAdjustments = CATransform3DIdentity;
    22672283
    2268     _isAnimatingResize = NO;
     2284    _dynamicViewportUpdateMode = DynamicViewportUpdateMode::NotResizing;
     2285    [_contentView setHidden:NO];
    22692286    [self _updateVisibleContentRects];
     2287}
     2288
     2289- (void)_resizeWhileHidingContentWithUpdates:(void (^)(void))updateBlock
     2290{
     2291    [self _beginAnimatedResizeWithUpdates:updateBlock];
     2292    if (_dynamicViewportUpdateMode == DynamicViewportUpdateMode::ResizingWithAnimation) {
     2293        [_contentView setHidden:YES];
     2294        _dynamicViewportUpdateMode = DynamicViewportUpdateMode::ResizingWithDocumentHidden;
     2295    }
    22702296}
    22712297
  • trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebViewPrivate.h

    r171050 r171201  
    138138- (void)_beginAnimatedResizeWithUpdates:(void (^)(void))updateBlock;
    139139- (void)_endAnimatedResize;
     140- (void)_resizeWhileHidingContentWithUpdates:(void (^)(void))updateBlock;
    140141
    141142- (void)_snapshotRect:(CGRect)rectInViewCoordinates intoImageOfWidth:(CGFloat)imageWidth completionHandler:(void(^)(CGImageRef))completionHandler;
Note: See TracChangeset for help on using the changeset viewer.