Changeset 172649 in webkit


Ignore:
Timestamp:
Aug 15, 2014 2:09:13 PM (10 years ago)
Author:
commit-queue@webkit.org
Message:

Implement snapping behavior for iOS
https://bugs.webkit.org/show_bug.cgi?id=135769

Patch by Wenson Hsieh <Wenson Hsieh> on 2014-08-15
Reviewed by Brent Fulgham.

Source/WebCore:

Added support for snap points on iOS. This entails sending snap points from the web process to the UI process
by encoding and decoding snap points and updating ScrollingTreeOverflowScrollingNodeIOS and WKWebView to support
animation to snap points in the cases of mainframe and overflow scrolling, respectively.

There are no new tests yet -- we'll need to find a way to test this!

  • WebCore.exp.in:
  • page/scrolling/AsyncScrollingCoordinator.cpp:

(WebCore::setStateScrollingNodeSnapOffsetsAsFloat): Helper functions used to convert LayoutUnits to floats for snap offsets.
(WebCore::AsyncScrollingCoordinator::frameViewLayoutUpdated): Update snap offsets for mainframe scrolling, as well as the state node.
(WebCore::AsyncScrollingCoordinator::updateOverflowScrollingNode): Added snap offsets.

  • page/scrolling/AxisScrollSnapOffsets.h:

(WebCore::closestSnapOffset): Computes the closest snap offset given a sorted vector of comparable types (e.g. float, LayoutUnit).

  • page/scrolling/ScrollingCoordinator.h:
  • page/scrolling/ScrollingStateScrollingNode.cpp:

(WebCore::ScrollingStateScrollingNode::ScrollingStateScrollingNode):
(WebCore::ScrollingStateScrollingNode::setHorizontalSnapOffsets):
(WebCore::ScrollingStateScrollingNode::setVerticalSnapOffsets):

  • page/scrolling/ScrollingStateScrollingNode.h:

(WebCore::ScrollingStateScrollingNode::horizontalSnapOffsets):
(WebCore::ScrollingStateScrollingNode::verticalSnapOffsets):

  • page/scrolling/ScrollingTreeScrollingNode.cpp:

(WebCore::ScrollingTreeScrollingNode::updateBeforeChildren):

  • page/scrolling/ScrollingTreeScrollingNode.h:

(WebCore::ScrollingTreeScrollingNode::horizontalSnapOffsets):
(WebCore::ScrollingTreeScrollingNode::verticalSnapOffsets):

  • rendering/RenderLayer.cpp:

(WebCore::RenderLayer::updateScrollInfoAfterLayout): Update snap offsets for overflow scrolling.

  • rendering/RenderLayerCompositor.cpp:

(WebCore::RenderLayerCompositor::updateScrollCoordinatedLayer): Updates the state node's snap offsets for overflow scrolling.

Source/WebKit2:

Added support for snap points on iOS.

  • Shared/Scrolling/RemoteScrollingCoordinatorTransaction.cpp:

(ArgumentCoder<ScrollingStateScrollingNode>::encode): Added snap offset encoding.
(ArgumentCoder<ScrollingStateScrollingNode>::decode): Added snap offset decoding.

  • UIProcess/API/Cocoa/WKWebView.mm:

(-[WKWebView scrollViewWillEndDragging:withVelocity:targetContentOffset:]): For mainframe scrolling, retargets the scroll destination to the appropriate snap point.

  • UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h: Added methods to extract relevant information for WKWebView from snap offsets in mainframe scrolling.
  • UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm:

(-[WKOverflowScrollViewDelegate scrollViewWillEndDragging:withVelocity:targetContentOffset:]): For overflow scrolling, retargets the scroll destination to the appropriate snap point.
(WebKit::ScrollingTreeOverflowScrollingNodeIOS::updateAfterChildren): Sets the deceleration factor to FAST if snap points are active.

  • UIProcess/ios/RemoteScrollingCoordinatorProxyIOS.mm:

(WebKit::RemoteScrollingCoordinatorProxy::adjustTargetContentOffsetForSnapping): Used by WKWebView for mainframe scrolling to retarget the scroll destination, if necessary.
(WebKit::RemoteScrollingCoordinatorProxy::shouldSetScrollViewDecelerationRateFast): Used by WKWebView for mainframe scrolling to determine whether to set deceleration rate to the fast value.
(WebKit::RemoteScrollingCoordinatorProxy::shouldSnapForMainFrameScrolling): Helper method.
(WebKit::RemoteScrollingCoordinatorProxy::closestSnapOffsetForMainFrameScrolling): Helper method.

Location:
trunk/Source
Files:
19 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r172647 r172649  
     12014-08-15  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        Implement snapping behavior for iOS
     4        https://bugs.webkit.org/show_bug.cgi?id=135769
     5
     6        Reviewed by Brent Fulgham.
     7
     8        Added support for snap points on iOS. This entails sending snap points from the web process to the UI process
     9        by encoding and decoding snap points and updating ScrollingTreeOverflowScrollingNodeIOS and WKWebView to support
     10        animation to snap points in the cases of mainframe and overflow scrolling, respectively.
     11
     12        There are no new tests yet -- we'll need to find a way to test this!
     13
     14        * WebCore.exp.in:
     15        * page/scrolling/AsyncScrollingCoordinator.cpp:
     16        (WebCore::setStateScrollingNodeSnapOffsetsAsFloat): Helper functions used to convert LayoutUnits to floats for snap offsets.
     17        (WebCore::AsyncScrollingCoordinator::frameViewLayoutUpdated): Update snap offsets for mainframe scrolling, as well as the state node.
     18        (WebCore::AsyncScrollingCoordinator::updateOverflowScrollingNode): Added snap offsets.
     19        * page/scrolling/AxisScrollSnapOffsets.h:
     20        (WebCore::closestSnapOffset): Computes the closest snap offset given a sorted vector of comparable types (e.g. float, LayoutUnit).
     21        * page/scrolling/ScrollingCoordinator.h:
     22        * page/scrolling/ScrollingStateScrollingNode.cpp:
     23        (WebCore::ScrollingStateScrollingNode::ScrollingStateScrollingNode):
     24        (WebCore::ScrollingStateScrollingNode::setHorizontalSnapOffsets):
     25        (WebCore::ScrollingStateScrollingNode::setVerticalSnapOffsets):
     26        * page/scrolling/ScrollingStateScrollingNode.h:
     27        (WebCore::ScrollingStateScrollingNode::horizontalSnapOffsets):
     28        (WebCore::ScrollingStateScrollingNode::verticalSnapOffsets):
     29        * page/scrolling/ScrollingTreeScrollingNode.cpp:
     30        (WebCore::ScrollingTreeScrollingNode::updateBeforeChildren):
     31        * page/scrolling/ScrollingTreeScrollingNode.h:
     32        (WebCore::ScrollingTreeScrollingNode::horizontalSnapOffsets):
     33        (WebCore::ScrollingTreeScrollingNode::verticalSnapOffsets):
     34        * rendering/RenderLayer.cpp:
     35        (WebCore::RenderLayer::updateScrollInfoAfterLayout): Update snap offsets for overflow scrolling.
     36        * rendering/RenderLayerCompositor.cpp:
     37        (WebCore::RenderLayerCompositor::updateScrollCoordinatedLayer): Updates the state node's snap offsets for overflow scrolling.
     38
    1392014-08-15  Dirk Schulze  <krit@webkit.org>
    240
  • trunk/Source/WebCore/WebCore.exp.in

    r172502 r172649  
    30123012#endif
    30133013
     3014#if ENABLE(CSS_SCROLL_SNAP)
     3015__ZN7WebCore27ScrollingStateScrollingNode22setVerticalSnapOffsetsERKN3WTF6VectorIfLm0ENS1_15CrashOnOverflowEEE
     3016__ZN7WebCore27ScrollingStateScrollingNode24setHorizontalSnapOffsetsERKN3WTF6VectorIfLm0ENS1_15CrashOnOverflowEEE
     3017#endif
     3018
    30143019#if ENABLE(DASHBOARD_SUPPORT)
    30153020__ZNK7WebCore8Document16annotatedRegionsEv
  • trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp

    r172365 r172649  
    6060}
    6161
     62static inline void setStateScrollingNodeSnapOffsetsAsFloat(ScrollingStateScrollingNode& node, ScrollEventAxis axis, const Vector<LayoutUnit>& snapOffsets, float deviceScaleFactor)
     63{
     64    // FIXME: Incorporate current page scale factor in snapping to device pixel. Perhaps we should just convert to float here and let UI process do the pixel snapping?
     65    Vector<float> snapOffsetsAsFloat;
     66    snapOffsetsAsFloat.reserveInitialCapacity(snapOffsets.size());
     67    for (size_t i = 0; i < snapOffsets.size(); ++i)
     68        snapOffsetsAsFloat.append(roundToDevicePixel(snapOffsets[i], deviceScaleFactor, false));
     69
     70    if (axis == ScrollEventAxis::Horizontal)
     71        node.setHorizontalSnapOffsets(snapOffsetsAsFloat);
     72    else
     73        node.setVerticalSnapOffsets(snapOffsetsAsFloat);
     74}
     75
    6276void AsyncScrollingCoordinator::frameViewLayoutUpdated(FrameView* frameView)
    6377{
     
    97111    node->setTotalContentsSize(frameView->totalContentsSize());
    98112    node->setReachableContentsSize(frameView->totalContentsSize());
     113
     114#if ENABLE(CSS_SCROLL_SNAP)
     115    frameView->updateSnapOffsets();
     116    if (const Vector<LayoutUnit>* horizontalSnapOffsets = frameView->horizontalSnapOffsets())
     117        setStateScrollingNodeSnapOffsetsAsFloat(*node, ScrollEventAxis::Horizontal, *horizontalSnapOffsets, frameView->frame().document()->deviceScaleFactor());
     118
     119    if (const Vector<LayoutUnit>* verticalSnapOffsets = frameView->verticalSnapOffsets())
     120        setStateScrollingNodeSnapOffsetsAsFloat(*node, ScrollEventAxis::Vertical, *verticalSnapOffsets, frameView->frame().document()->deviceScaleFactor());
     121#endif
    99122
    100123    ScrollableAreaParameters scrollParameters;
     
    400423        node->setReachableContentsSize(scrollingGeometry->reachableContentSize);
    401424        node->setScrollableAreaSize(scrollingGeometry->scrollableAreaSize);
     425#if ENABLE(CSS_SCROLL_SNAP)
     426        setStateScrollingNodeSnapOffsetsAsFloat(*node, ScrollEventAxis::Horizontal, scrollingGeometry->horizontalSnapOffsets, scrolledContentsLayer->deviceScaleFactor());
     427        setStateScrollingNodeSnapOffsetsAsFloat(*node, ScrollEventAxis::Vertical, scrollingGeometry->verticalSnapOffsets, scrolledContentsLayer->deviceScaleFactor());
     428#endif
    402429    }
    403430}
  • trunk/Source/WebCore/page/scrolling/AxisScrollSnapOffsets.cpp

    r172543 r172649  
    4444            LayoutUnit viewWidth = box->width();
    4545            LayoutUnit viewHeight = box->height();
    46             // FIXME: Check behavior with CSS rotations.
     46#if PLATFORM(IOS)
     47            // FIXME: Investigate why using localToContainerPoint gives the wrong offsets for iOS mainframe. Also, these offsets won't take transforms into account (make sure to test this!)
     48            float left = child->offsetLeft();
     49            float top = child->offsetTop();
     50#else
     51            // FIXME: Check that localToContainerPoint works with CSS rotations.
    4752            FloatPoint position = box->localToContainerPoint(FloatPoint(), parent.renderBox());
     53            float left = position.x();
     54            float top = position.y();
     55#endif
    4856            for (SnapCoordinate coordinate : box->style().scrollSnapCoordinates()) {
    49                 LayoutUnit lastPotentialSnapPositionX = LayoutUnit(position.x()) + valueForLength(coordinate.first, viewWidth);
     57                LayoutUnit lastPotentialSnapPositionX = LayoutUnit(left) + valueForLength(coordinate.first, viewWidth);
    5058                if (shouldAddHorizontalChildOffsets && lastPotentialSnapPositionX > 0)
    5159                    horizontalSnapOffsetSubsequence.append(lastPotentialSnapPositionX);
    5260
    53                 LayoutUnit lastPotentialSnapPositionY = LayoutUnit(position.y()) + valueForLength(coordinate.second, viewHeight);
     61                LayoutUnit lastPotentialSnapPositionY = LayoutUnit(top) + valueForLength(coordinate.second, viewHeight);
    5462                if (shouldAddVerticalChildOffsets && lastPotentialSnapPositionY > 0)
    5563                    verticalSnapOffsetSubsequence.append(lastPotentialSnapPositionY);
  • trunk/Source/WebCore/page/scrolling/AxisScrollSnapOffsets.h

    r172616 r172649  
    4242void updateSnapOffsetsForScrollableArea(ScrollableArea&, HTMLElement& scrollingElement, const RenderBox& scrollingElementBox, const RenderStyle& scrollingElementStyle);
    4343
    44 template <typename T>
    45 T closestSnapOffset(const Vector<T>& snapOffsets, T scrollDestination, float velocity)
     44// closestSnapOffset is a templated function that takes in a Vector representing snap offsets as LayoutTypes (e.g. LayoutUnit or float) and
     45// as well as a VelocityType indicating the velocity (e.g. float, CGFloat, etc.) This function is templated because the UI process will now
     46// use pixel snapped floats to represent snap offsets rather than LayoutUnits.
     47template <typename LayoutType, typename VelocityType>
     48LayoutType closestSnapOffset(const Vector<LayoutType>& snapOffsets, LayoutType scrollDestination, VelocityType velocity)
    4649{
    4750    ASSERT(snapOffsets.size());
     
    6669        }
    6770    }
    68     T lowerSnapPosition = snapOffsets[lowerIndex];
    69     T upperSnapPosition = snapOffsets[upperIndex];
     71    LayoutType lowerSnapPosition = snapOffsets[lowerIndex];
     72    LayoutType upperSnapPosition = snapOffsets[upperIndex];
    7073    // Nonzero velocity indicates a flick gesture. Even if another snap point is closer, snap to the one in the direction of the flick gesture.
    7174    if (velocity)
  • trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.h

    r170541 r172649  
    4444#endif
    4545
     46#if ENABLE(CSS_SCROLL_SNAP)
     47#include "AxisScrollSnapOffsets.h"
     48#endif
     49
    4650namespace WebCore {
    4751
     
    165169        FloatPoint scrollPosition;
    166170        IntPoint scrollOrigin;
     171#if ENABLE(CSS_SCROLL_SNAP)
     172        Vector<LayoutUnit> horizontalSnapOffsets;
     173        Vector<LayoutUnit> verticalSnapOffsets;
     174#endif
    167175    };
    168176
  • trunk/Source/WebCore/page/scrolling/ScrollingStateScrollingNode.cpp

    r170541 r172649  
    4949    , m_requestedScrollPosition(stateNode.requestedScrollPosition())
    5050    , m_scrollOrigin(stateNode.scrollOrigin())
     51#if ENABLE(CSS_SCROLL_SNAP)
     52    , m_horizontalSnapOffsets(stateNode.horizontalSnapOffsets())
     53    , m_verticalSnapOffsets(stateNode.verticalSnapOffsets())
     54#endif
    5155    , m_scrollableAreaParameters(stateNode.scrollableAreaParameters())
    5256    , m_requestedScrollPositionRepresentsProgrammaticScroll(stateNode.requestedScrollPositionRepresentsProgrammaticScroll())
     
    102106    setPropertyChanged(ScrollOrigin);
    103107}
     108
     109#if ENABLE(CSS_SCROLL_SNAP)
     110void ScrollingStateScrollingNode::setHorizontalSnapOffsets(const Vector<float>& snapOffsets)
     111{
     112    if (m_horizontalSnapOffsets == snapOffsets)
     113        return;
     114
     115    m_horizontalSnapOffsets = snapOffsets;
     116    setPropertyChanged(HorizontalSnapOffsets);
     117}
     118
     119void ScrollingStateScrollingNode::setVerticalSnapOffsets(const Vector<float>& snapOffsets)
     120{
     121    if (m_verticalSnapOffsets == snapOffsets)
     122        return;
     123
     124    m_verticalSnapOffsets = snapOffsets;
     125    setPropertyChanged(VerticalSnapOffsets);
     126}
     127#endif
    104128
    105129void ScrollingStateScrollingNode::setScrollableAreaParameters(const ScrollableAreaParameters& parameters)
  • trunk/Source/WebCore/page/scrolling/ScrollingStateScrollingNode.h

    r170541 r172649  
    4949        RequestedScrollPosition,
    5050        NumScrollingStateNodeBits,
     51#if ENABLE(CSS_SCROLL_SNAP)
     52        HorizontalSnapOffsets,
     53        VerticalSnapOffsets,
     54#endif
    5155    };
    5256
     
    6569    const IntPoint& scrollOrigin() const { return m_scrollOrigin; }
    6670    void setScrollOrigin(const IntPoint&);
     71
     72#if ENABLE(CSS_SCROLL_SNAP)
     73    const Vector<float>& horizontalSnapOffsets() const { return m_horizontalSnapOffsets; }
     74    void setHorizontalSnapOffsets(const Vector<float>&);
     75
     76    const Vector<float>& verticalSnapOffsets() const { return m_verticalSnapOffsets; }
     77    void setVerticalSnapOffsets(const Vector<float>&);
     78#endif
    6779
    6880    const ScrollableAreaParameters& scrollableAreaParameters() const { return m_scrollableAreaParameters; }
     
    8698    FloatPoint m_requestedScrollPosition;
    8799    IntPoint m_scrollOrigin;
     100#if ENABLE(CSS_SCROLL_SNAP)
     101    Vector<float> m_horizontalSnapOffsets;
     102    Vector<float> m_verticalSnapOffsets;
     103#endif
    88104    ScrollableAreaParameters m_scrollableAreaParameters;
    89105    bool m_requestedScrollPositionRepresentsProgrammaticScroll;
  • trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp

    r170568 r172649  
    6868        m_scrollOrigin = state.scrollOrigin();
    6969
     70#if ENABLE(CSS_SCROLL_SNAP)
     71    if (state.hasChangedProperty(ScrollingStateScrollingNode::HorizontalSnapOffsets))
     72        m_horizontalSnapOffsets = state.horizontalSnapOffsets();
     73
     74    if (state.hasChangedProperty(ScrollingStateScrollingNode::VerticalSnapOffsets))
     75        m_verticalSnapOffsets = state.verticalSnapOffsets();
     76#endif
     77
    7078    if (state.hasChangedProperty(ScrollingStateScrollingNode::ScrollableAreaParams))
    7179        m_scrollableAreaParameters = state.scrollableAreaParameters();
  • trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h

    r170568 r172649  
    5858    virtual FloatPoint scrollPosition() const = 0;
    5959
     60#if ENABLE(CSS_SCROLL_SNAP)
     61    const Vector<float>& horizontalSnapOffsets() const { return m_horizontalSnapOffsets; }
     62    const Vector<float>& verticalSnapOffsets() const { return m_verticalSnapOffsets; }
     63#endif
     64
    6065protected:
    6166    ScrollingTreeScrollingNode(ScrollingTree&, ScrollingNodeType, ScrollingNodeID);
     
    9398    FloatPoint m_lastCommittedScrollPosition;
    9499    IntPoint m_scrollOrigin;
    95    
     100#if ENABLE(CSS_SCROLL_SNAP)
     101    Vector<float> m_horizontalSnapOffsets;
     102    Vector<float> m_verticalSnapOffsets;
     103#endif
    96104    ScrollableAreaParameters m_scrollableAreaParameters;
    97105};
  • trunk/Source/WebCore/platform/mac/AxisScrollSnapAnimator.mm

    r172616 r172649  
    170170    projectedScrollDestination = std::min(std::max(projectedScrollDestination, m_snapOffsets->first()), m_snapOffsets->last());
    171171    m_initialOffset = offset;
    172     m_targetOffset = closestSnapOffset<LayoutUnit>(*m_snapOffsets, projectedScrollDestination, initialWheelDelta);
     172    m_targetOffset = closestSnapOffset<LayoutUnit, float>(*m_snapOffsets, projectedScrollDestination, initialWheelDelta);
    173173    if (m_initialOffset == m_targetOffset)
    174174        return;
  • trunk/Source/WebCore/rendering/RenderLayer.cpp

    r172543 r172649  
    33103310    if (compositor().updateLayerCompositingState(*this))
    33113311        compositor().setCompositingLayersNeedRebuild();
     3312
     3313#if ENABLE(CSS_SCROLL_SNAP)
     3314    // FIXME: Ensure that offsets are also updated in case of programmatic style changes.
     3315    // https://bugs.webkit.org/show_bug.cgi?id=135964
     3316    updateSnapOffsets();
     3317#endif
    33123318}
    33133319
  • trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp

    r172183 r172649  
    37713771            scrollingGeometry.contentSize = layer.contentsSize();
    37723772            scrollingGeometry.reachableContentSize = layer.scrollableContentsSize();
     3773#if ENABLE(CSS_SCROLL_SNAP)
     3774            if (const Vector<LayoutUnit>* offsets = layer.horizontalSnapOffsets())
     3775                scrollingGeometry.horizontalSnapOffsets = *offsets;
     3776            if (const Vector<LayoutUnit>* offsets = layer.verticalSnapOffsets())
     3777                scrollingGeometry.verticalSnapOffsets = *offsets;
     3778#endif
    37733779            scrollingCoordinator->updateOverflowScrollingNode(nodeID, backing->scrollingLayer(), backing->scrollingContentsLayer(), &scrollingGeometry);
    37743780        }
  • trunk/Source/WebKit2/ChangeLog

    r172646 r172649  
     12014-08-15  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        Implement snapping behavior for iOS
     4        https://bugs.webkit.org/show_bug.cgi?id=135769
     5
     6        Reviewed by Brent Fulgham.
     7
     8        Added support for snap points on iOS.
     9
     10        * Shared/Scrolling/RemoteScrollingCoordinatorTransaction.cpp:
     11        (ArgumentCoder<ScrollingStateScrollingNode>::encode): Added snap offset encoding.
     12        (ArgumentCoder<ScrollingStateScrollingNode>::decode): Added snap offset decoding.
     13        * UIProcess/API/Cocoa/WKWebView.mm:
     14        (-[WKWebView scrollViewWillEndDragging:withVelocity:targetContentOffset:]): For mainframe scrolling, retargets the scroll destination to the appropriate snap point.
     15        * UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h: Added methods to extract relevant information for WKWebView from snap offsets in mainframe scrolling.
     16        * UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm:
     17        (-[WKOverflowScrollViewDelegate scrollViewWillEndDragging:withVelocity:targetContentOffset:]): For overflow scrolling, retargets the scroll destination to the appropriate snap point.
     18        (WebKit::ScrollingTreeOverflowScrollingNodeIOS::updateAfterChildren): Sets the deceleration factor to FAST if snap points are active.
     19        * UIProcess/ios/RemoteScrollingCoordinatorProxyIOS.mm:
     20        (WebKit::RemoteScrollingCoordinatorProxy::adjustTargetContentOffsetForSnapping): Used by WKWebView for mainframe scrolling to retarget the scroll destination, if necessary.
     21        (WebKit::RemoteScrollingCoordinatorProxy::shouldSetScrollViewDecelerationRateFast): Used by WKWebView for mainframe scrolling to determine whether to set deceleration rate to the fast value.
     22        (WebKit::RemoteScrollingCoordinatorProxy::shouldSnapForMainFrameScrolling): Helper method.
     23        (WebKit::RemoteScrollingCoordinatorProxy::closestSnapOffsetForMainFrameScrolling): Helper method.
     24
    1252014-08-15  Gavin Barraclough  <barraclough@apple.com>
    226
  • trunk/Source/WebKit2/Shared/Scrolling/RemoteScrollingCoordinatorTransaction.cpp

    r171250 r172649  
    129129    SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::ScrollPosition, scrollPosition)
    130130    SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::ScrollOrigin, scrollOrigin)
     131#if ENABLE(CSS_SCROLL_SNAP)
     132    SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::HorizontalSnapOffsets, horizontalSnapOffsets)
     133    SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::VerticalSnapOffsets, verticalSnapOffsets)
     134#endif
    131135    SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::ScrollableAreaParams, scrollableAreaParameters)
    132136    SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::RequestedScrollPosition, requestedScrollPosition)
     
    194198    SCROLLING_NODE_DECODE(ScrollingStateScrollingNode::ScrollPosition, FloatPoint, setScrollPosition);
    195199    SCROLLING_NODE_DECODE(ScrollingStateScrollingNode::ScrollOrigin, IntPoint, setScrollOrigin);
     200#if ENABLE(CSS_SCROLL_SNAP)
     201    SCROLLING_NODE_DECODE(ScrollingStateScrollingNode::HorizontalSnapOffsets, Vector<float>, setHorizontalSnapOffsets);
     202    SCROLLING_NODE_DECODE(ScrollingStateScrollingNode::VerticalSnapOffsets, Vector<float>, setVerticalSnapOffsets);
     203#endif
    196204    SCROLLING_NODE_DECODE(ScrollingStateScrollingNode::ScrollableAreaParams, ScrollableAreaParameters, setScrollableAreaParameters);
    197205   
  • trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm

    r171709 r172649  
    8484#import "ProcessThrottler.h"
    8585#import "RemoteLayerTreeDrawingAreaProxy.h"
     86#import "RemoteScrollingCoordinatorProxy.h"
    8687#import "WKPDFView.h"
    8788#import "WKScrollView.h"
     
    12831284        [_contentView scrollViewWillStartPanOrPinchGesture];
    12841285    [_contentView willStartZoomOrScroll];
     1286#if ENABLE(CSS_SCROLL_SNAP) && ENABLE(ASYNC_SCROLLING)
     1287    // FIXME: We will want to detect whether snapping will occur before beginning to drag. See WebPageProxy::didCommitLayerTree.
     1288    WebKit::RemoteScrollingCoordinatorProxy* coordinator = _page->scrollingCoordinatorProxy();
     1289    scrollView.decelerationRate = (coordinator && coordinator->shouldSetScrollViewDecelerationRateFast()) ? UIScrollViewDecelerationRateFast : UIScrollViewDecelerationRateNormal;
     1290#endif
    12851291}
    12861292
     
    13001306    if ([scrollView isZooming])
    13011307        *targetContentOffset = [scrollView contentOffset];
     1308#if ENABLE(CSS_SCROLL_SNAP) && ENABLE(ASYNC_SCROLLING)
     1309    if (WebKit::RemoteScrollingCoordinatorProxy* coordinator = _page->scrollingCoordinatorProxy()) {
     1310        // FIXME: Here, I'm finding the maximum horizontal/vertical scroll offsets. There's probably a better way to do this.
     1311        CGSize maxScrollOffsets = CGSizeMake(scrollView.contentSize.width - scrollView.bounds.size.width, scrollView.contentSize.height - scrollView.bounds.size.height);
     1312        coordinator->adjustTargetContentOffsetForSnapping(maxScrollOffsets, velocity, targetContentOffset);
     1313    }
     1314#endif
    13021315}
    13031316
  • trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h

    r171560 r172649  
    8585    void scrollingTreeNodeWillStartScroll();
    8686    void scrollingTreeNodeDidEndScroll();
     87#if ENABLE(CSS_SCROLL_SNAP)
     88    void adjustTargetContentOffsetForSnapping(CGSize maxScrollDimensions, CGPoint velocity, CGPoint* targetContentOffset) const;
     89    bool shouldSetScrollViewDecelerationRateFast() const;
     90#endif
    8791#endif
    8892
    8993private:
    9094    void connectStateNodeLayers(WebCore::ScrollingStateTree&, const RemoteLayerTreeHost&);
     95#if ENABLE(CSS_SCROLL_SNAP)
     96    bool shouldSnapForMainFrameScrolling(WebCore::ScrollEventAxis) const;
     97    float closestSnapOffsetForMainFrameScrolling(WebCore::ScrollEventAxis, float scrollDestination, float velocity) const;
     98#endif
    9199
    92100    WebPageProxy& m_webPageProxy;
  • trunk/Source/WebKit2/UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm

    r172199 r172649  
    3838#import <wtf/TemporaryChange.h>
    3939
     40#if ENABLE(CSS_SCROLL_SNAP)
     41#import <WebCore/AxisScrollSnapOffsets.h>
     42#endif
     43
    4044using namespace WebCore;
    4145
     
    7377    _scrollingTreeNode->overflowScrollWillStart();
    7478}
     79
     80#if ENABLE(CSS_SCROLL_SNAP)
     81- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
     82{
     83    if (!_scrollingTreeNode->horizontalSnapOffsets().isEmpty())
     84        targetContentOffset->x = closestSnapOffset<float, CGFloat>(_scrollingTreeNode->horizontalSnapOffsets(), targetContentOffset->x, velocity.x);
     85    if (!_scrollingTreeNode->verticalSnapOffsets().isEmpty())
     86        targetContentOffset->y = closestSnapOffset<float, CGFloat>(_scrollingTreeNode->verticalSnapOffsets(), targetContentOffset->y, velocity.y);
     87}
     88#endif
    7589
    7690- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)willDecelerate
     
    189203            scrollView.contentInset = insets;
    190204        }
    191            
     205
     206#if ENABLE(CSS_SCROLL_SNAP)
     207        // FIXME: If only one axis snaps in 2D scrolling, the other axis will decelerate fast as well. Is this what we want?
     208        if (scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::HorizontalSnapOffsets) || scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::VerticalSnapOffsets))
     209            scrollView.decelerationRate = horizontalSnapOffsets().size() || verticalSnapOffsets().size() ? UIScrollViewDecelerationRateFast : UIScrollViewDecelerationRateNormal;
     210#endif
    192211        END_BLOCK_OBJC_EXCEPTIONS
    193212    }
  • trunk/Source/WebKit2/UIProcess/ios/RemoteScrollingCoordinatorProxyIOS.mm

    r171532 r172649  
    2424 */
    2525
    26 #include "config.h"
    27 #include "RemoteScrollingCoordinatorProxy.h"
     26#import "config.h"
     27#import "RemoteScrollingCoordinatorProxy.h"
    2828
    2929#if PLATFORM(IOS)
    3030#if ENABLE(ASYNC_SCROLLING)
    3131
    32 #include "LayerRepresentation.h"
    33 #include "RemoteLayerTreeHost.h"
    34 #include "WebPageProxy.h"
    35 #include <WebCore/ScrollingStateFrameScrollingNode.h>
    36 #include <WebCore/ScrollingStateOverflowScrollingNode.h>
    37 #include <WebCore/ScrollingStateTree.h>
    38 #include <UIKit/UIView.h>
     32#import "LayerRepresentation.h"
     33#import "RemoteLayerTreeHost.h"
     34#import "WebPageProxy.h"
     35#import <UIKit/UIView.h>
     36#import <WebCore/ScrollingStateFrameScrollingNode.h>
     37#import <WebCore/ScrollingStateOverflowScrollingNode.h>
     38#import <WebCore/ScrollingStateTree.h>
     39
     40#if ENABLE(CSS_SCROLL_SNAP)
     41#import <WebCore/AxisScrollSnapOffsets.h>
     42#import <WebCore/ScrollTypes.h>
     43#import <WebCore/ScrollingTreeFrameScrollingNode.h>
     44#endif
    3945
    4046using namespace WebCore;
     
    107113}
    108114
     115#if ENABLE(CSS_SCROLL_SNAP)
     116void RemoteScrollingCoordinatorProxy::adjustTargetContentOffsetForSnapping(CGSize maxScrollOffsets, CGPoint velocity, CGPoint* targetContentOffset) const
     117{
     118    // The bounds checking with maxScrollOffsets is to ensure that we won't interfere with rubber-banding when scrolling to the edge of the page.
     119    if (shouldSnapForMainFrameScrolling(WebCore::ScrollEventAxis::Horizontal) && targetContentOffset->x > 0 && targetContentOffset->x < maxScrollOffsets.width) {
     120        float potentialSnapPosition = closestSnapOffsetForMainFrameScrolling(WebCore::ScrollEventAxis::Horizontal, targetContentOffset->x, velocity.x);
     121        targetContentOffset->x = std::min<float>(maxScrollOffsets.width, potentialSnapPosition);
     122    }
     123    // FIXME: We need to account for how the top navigation bar changes in size.
     124    if (shouldSnapForMainFrameScrolling(WebCore::ScrollEventAxis::Vertical) && targetContentOffset->y > 0 && targetContentOffset->y < maxScrollOffsets.height) {
     125        float potentialSnapPosition = closestSnapOffsetForMainFrameScrolling(WebCore::ScrollEventAxis::Vertical, targetContentOffset->y, velocity.y);
     126        targetContentOffset->y = std::min<float>(maxScrollOffsets.height, potentialSnapPosition);
     127    }
     128}
     129
     130bool RemoteScrollingCoordinatorProxy::shouldSetScrollViewDecelerationRateFast() const
     131{
     132    return shouldSnapForMainFrameScrolling(ScrollEventAxis::Horizontal) || shouldSnapForMainFrameScrolling(ScrollEventAxis::Vertical);
     133}
     134
     135bool RemoteScrollingCoordinatorProxy::shouldSnapForMainFrameScrolling(ScrollEventAxis axis) const
     136{
     137    ScrollingTreeNode* root = m_scrollingTree->rootNode();
     138    if (root && root->isFrameScrollingNode()) {
     139        ScrollingTreeFrameScrollingNode* rootFrame = static_cast<ScrollingTreeFrameScrollingNode*>(root);
     140        const Vector<float>& snapOffsets = axis == ScrollEventAxis::Horizontal ? rootFrame->horizontalSnapOffsets() : rootFrame->verticalSnapOffsets();
     141        return snapOffsets.size() > 0;
     142    }
     143    return false;
     144}
     145
     146float RemoteScrollingCoordinatorProxy::closestSnapOffsetForMainFrameScrolling(ScrollEventAxis axis, float scrollDestination, float velocity) const
     147{
     148    ScrollingTreeNode* root = m_scrollingTree->rootNode();
     149    ASSERT(root && root->isFrameScrollingNode());
     150    ScrollingTreeFrameScrollingNode* rootFrame = static_cast<ScrollingTreeFrameScrollingNode*>(root);
     151    const Vector<float>& snapOffsets = axis == ScrollEventAxis::Horizontal ? rootFrame->horizontalSnapOffsets() : rootFrame->verticalSnapOffsets();
     152    return closestSnapOffset<float, float>(snapOffsets, scrollDestination, velocity);
     153}
     154#endif
     155
    109156} // namespace WebKit
    110157
Note: See TracChangeset for help on using the changeset viewer.