Changeset 170463 in webkit


Ignore:
Timestamp:
Jun 25, 2014 9:15:52 PM (10 years ago)
Author:
Simon Fraser
Message:

[iOS WK2] Page jumps when rubber-banding on azuremagazine.com
https://bugs.webkit.org/show_bug.cgi?id=134238
<rdar://problem/16918228>

Reviewed by Benjamin Poulain.

If the scroll view is in the process of rubber-banding when -setContentSize: is called,
it clamps the scroll offsets between zero and the max value, which visibly interrupts the
rubberband. This can easily happen now that we continually send scroll events to the page
on scrolling, especially when pages like azuremagazine.com do fake sticky by toggling
in-flow elements into position:fixed.

Fix by computing the amount of rubber-band before calling -setContentSize:, and then
restoring the contentOffset with the same amount of rubber-band even when the content size
is different, for top/left rubberbands.

  • UIProcess/API/Cocoa/WKWebView.mm:

(-[WKWebView _didCommitLayerTree:WebKit::]):

  • UIProcess/ios/WKScrollView.h:
  • UIProcess/ios/WKScrollView.mm:

(-[WKScrollView _currentTopLeftRubberbandAmount]):
(-[WKScrollView _restoreContentOffsetWithRubberbandAmount:]):
(-[WKScrollView _setContentSizePreservingContentOffsetDuringRubberband:]):

Location:
trunk/Source/WebKit2
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit2/ChangeLog

    r170462 r170463  
     12014-06-25  Simon Fraser  <simon.fraser@apple.com>
     2
     3        [iOS WK2] Page jumps when rubber-banding on azuremagazine.com
     4        https://bugs.webkit.org/show_bug.cgi?id=134238
     5        <rdar://problem/16918228>
     6
     7        Reviewed by Benjamin Poulain.
     8       
     9        If the scroll view is in the process of rubber-banding when -setContentSize: is called,
     10        it clamps the scroll offsets between zero and the max value, which visibly interrupts the
     11        rubberband. This can easily happen now that we continually send scroll events to the page
     12        on scrolling, especially when pages like azuremagazine.com do fake sticky by toggling
     13        in-flow elements into position:fixed.
     14       
     15        Fix by computing the amount of rubber-band before calling -setContentSize:, and then
     16        restoring the contentOffset with the same amount of rubber-band even when the content size
     17        is different, for top/left rubberbands.
     18       
     19        * UIProcess/API/Cocoa/WKWebView.mm:
     20        (-[WKWebView _didCommitLayerTree:WebKit::]):
     21        * UIProcess/ios/WKScrollView.h:
     22        * UIProcess/ios/WKScrollView.mm:
     23        (-[WKScrollView _currentTopLeftRubberbandAmount]):
     24        (-[WKScrollView _restoreContentOffsetWithRubberbandAmount:]):
     25        (-[WKScrollView _setContentSizePreservingContentOffsetDuringRubberband:]):
     26
    1272014-06-25  Simon Fraser  <simon.fraser@apple.com>
    228
  • trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm

    r170450 r170463  
    775775    }
    776776
    777     [_scrollView setContentSize:roundScrollViewContentSize(*_page, [_contentView frame].size)];
     777    CGSize newContentSize = roundScrollViewContentSize(*_page, [_contentView frame].size);
     778    [_scrollView _setContentSizePreservingContentOffsetDuringRubberband:newContentSize];
     779
    778780    [_scrollView setMinimumZoomScale:layerTreeTransaction.minimumScaleFactor()];
    779781    [_scrollView setMaximumZoomScale:layerTreeTransaction.maximumScaleFactor()];
  • trunk/Source/WebKit2/UIProcess/ios/WKScrollView.h

    r168747 r170463  
    3434@property (nonatomic, assign) WKWebView <UIScrollViewDelegate> *internalDelegate;
    3535
     36- (void)_setContentSizePreservingContentOffsetDuringRubberband:(CGSize)contentSize;
     37
    3638@end
    3739
  • trunk/Source/WebKit2/UIProcess/ios/WKScrollView.mm

    r170361 r170463  
    199199}
    200200
     201// Fetch top/left rubberband amounts (as negative values).
     202- (CGSize)_currentTopLeftRubberbandAmount
     203{
     204    UIEdgeInsets edgeInsets = [self contentInset];
     205
     206    CGSize rubberbandAmount = CGSizeZero;
     207
     208    CGPoint contentOffset = [self contentOffset];
     209    if (contentOffset.x < -edgeInsets.left)
     210        rubberbandAmount.width = std::min<CGFloat>(contentOffset.x + -edgeInsets.left, 0);
     211
     212    if (contentOffset.y < -edgeInsets.top)
     213        rubberbandAmount.height = std::min<CGFloat>(contentOffset.y + edgeInsets.top, 0);
     214   
     215    return rubberbandAmount;
     216}
     217
     218- (void)_restoreContentOffsetWithRubberbandAmount:(CGSize)rubberbandAmount
     219{
     220    UIEdgeInsets edgeInsets = [self contentInset];
     221    CGPoint adjustedOffset = [self contentOffset];
     222
     223    if (rubberbandAmount.width < 0)
     224        adjustedOffset.x = -edgeInsets.left + rubberbandAmount.width;
     225
     226    if (rubberbandAmount.height < 0)
     227        adjustedOffset.y = -edgeInsets.top + rubberbandAmount.height;
     228
     229    [self setContentOffset:adjustedOffset];
     230}
     231
     232- (void)_setContentSizePreservingContentOffsetDuringRubberband:(CGSize)contentSize
     233{
     234    CGSize currentContentSize = [self contentSize];
     235
     236    if (CGSizeEqualToSize(currentContentSize, CGSizeZero) || CGSizeEqualToSize(currentContentSize, contentSize) || self.zoomScale < self.minimumZoomScale) {
     237        [self setContentSize:contentSize];
     238        return;
     239    }
     240
     241    CGSize rubberbandAmount = [self _currentTopLeftRubberbandAmount];
     242
     243    [self setContentSize:contentSize];
     244
     245    if (!CGSizeEqualToSize(rubberbandAmount, CGSizeZero))
     246        [self _restoreContentOffsetWithRubberbandAmount:rubberbandAmount];
     247}
     248
    201249@end
    202250
Note: See TracChangeset for help on using the changeset viewer.