Title: [184139] trunk/Source
Revision
184139
Author
[email protected]
Date
2015-05-11 18:12:01 -0700 (Mon, 11 May 2015)

Log Message

Scroll snap logic should be triggered when resizing the WebView
https://bugs.webkit.org/show_bug.cgi?id=142590
<rdar://problem/20125088>

Reviewed by Simon Fraser.

Source/WebCore:

Tests coming in a second patch.

Resizing of the main frame or overflow regions was properly recalculating the scroll snap points,
but there was no code to honor these values when window resizing was occurring. The correction was
handled in two ways:
1. Scrolling thread operations that moved to new snap points needed to notify the main thread that
   it had shifted to a new snap point, so that the resize code (which happens on the main thread)
   could ensure that we stayed clamped to the correct 'tile' in the snap region.
2. Main thread (overflow) resizes were likewise missing code to honor the current snap position
   after resizing calculations were complete.

This change also required the addition of two indices to the scrollable area to track which scroll
snap point was currently being used. We don't bother with a 'none' case because you cannot have a
'none' state when you have an active set of scroll snap points, and we do not execute this code
if the scroll snap points are null.

The FrameView code was computing updated snap offsets after it had dispatched frame view layout
information to the scrolling thread, which was wrong. This was also corrected.

I think it might be possible to track all of this state inside the ScrollController, but the current
scroll snap architecture destroys and recreates the state each time a new set of interactions starts.
This should be fixed in the future, which would allow us to remove some of this local state.

* page/FrameView.cpp:
(WebCore::FrameView::performPostLayoutTasks): Make sure 'updateSnapOffsets' is called prior to
calling 'frameViewLayoutUpdated' so the scrolling thread gets correct updated points. Add a new
call to 'scrollToNearestActiveSnapPoint', which will keep us on our current snap point during
resize (if appropriate).
* page/scrolling/AsyncScrollingCoordinator.cpp:
(WebCore::AsyncScrollingCoordinator::updateScrollSnapOffsetIndices): Added. This finds and notifies
the correct scroll region when a new snap position (index) has been selected by user interaction on
the scrolling thread.
(WebCore::AsyncScrollingCoordinator::deferTestsForReason): Added an assertion for 'isMainThread'.
(WebCore::AsyncScrollingCoordinator::removeTestDeferralForReason): Ditto.
* page/scrolling/AsyncScrollingCoordinator.h:
* page/scrolling/AxisScrollSnapOffsets.h:
(WebCore::closestSnapOffset): Modified to also return the selected snap point index so we can track
it to handle resize operations.
* page/scrolling/ScrollingTree.h:
(WebCore::ScrollingTree::updateScrollSnapOffsetIndices):
* page/scrolling/ThreadedScrollingTree.cpp:
(WebCore::ThreadedScrollingTree::updateScrollSnapOffsetIndices): Added method to dispatch the active
horizontal and vertical scroll snap indices back to the main thread.
* page/scrolling/ThreadedScrollingTree.h:
* page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm:
(WebCore::ScrollingTreeFrameScrollingNodeMac::handleWheelEvent): After the scroll controller processes
the current event, notify the main thread of any change in the active scroll snap index.
* platform/ScrollAnimator.cpp:
(WebCore::ScrollAnimator::activeScrollSnapOffsetIndexDidChange): Added method to allow ScrollAnimator
clients to find out about the current scroll snap state, which is only known by the ScrollController.
(WebCore::ScrollAnimator::activeScrollSnapOffsetIndexForAxis): Ditto.
* platform/ScrollAnimator.h:
* platform/ScrollView.cpp:
(WebCore::ScrollView::scrollToNearestActiveSnapPoint): Added method that allows us to set scroll position
to one of our active scroll snap offsets.
* platform/ScrollView.h:
* platform/ScrollableArea.cpp:
(WebCore::ScrollableArea::handleWheelEvent): If the active scroll snap offset has changed, make sure we
keep track of the new values for potential resize operations.
(WebCore::ScrollableArea::clearHorizontalSnapOffsets): Make sure to also clear out the current snap index.
(WebCore::ScrollableArea::clearVerticalSnapOffsets): Ditto.
(WebCore::ScrollableArea::nearestActiveSnapPoint): New method that returns an updated IntPoint reflecting
the proper scroll position based on the active scroll snap offset.
* platform/ScrollableArea.h:
(WebCore::ScrollableArea::currentHorizontalSnapPointIndex): Added.
(WebCore::ScrollableArea::setCurrentHorizontalSnapPointIndex): Added.
(WebCore::ScrollableArea::currentVerticalSnapPointIndex): Added.
(WebCore::ScrollableArea::setCurrentVerticalSnapPointIndex): Added.
(WebCore::ScrollableArea::scrollToNearestActiveSnapPoint): Added.
* platform/cocoa/ScrollController.h:
(WebCore::ScrollControllerClient::activeScrollOffsetIndex): Added new method for clients to implement.
(WebCore::ScrollController::activeScrollSnapOffsetIndexDidChange): Added.
(WebCore::ScrollController::setScrollSnapOffsetIndexDidChange): Added.
* platform/cocoa/ScrollController.mm:
(WebCore::ScrollController::activeScrollSnapOffsetIndexForAxis): Helper method to return current active
index (if applicable).
(WebCore::ScrollController::setActiveScrollSnapOffsetIndexForAxis): Helper function to safely set
the current active index.
(WebCore::ScrollController::beginScrollSnapAnimation): Updated to keep track of the new active scroll snap
index, as well as whether the current animation actually changed the active snap point offset.
* platform/cocoa/ScrollSnapAnimatorState.h: Revise to use modern C++ initializers, and to track a new index
that represents the current scroll snap offset.
* platform/cocoa/ScrollSnapAnimatorState.mm:
(WebCore::ScrollSnapAnimatorState::ScrollSnapAnimatorState): Update for modern C++ syntax.
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::scrollToNearestActiveSnapPoint): New method to set scroll position to be one of our
active scroll snap points.
(WebCore::RenderLayer::updateScrollInfoAfterLayout): Add a new call to 'scrollToNearestActiveSnapPoint' so that
we stay on the current scroll snap offset during resizing.
* rendering/RenderLayer.h:

Source/WebKit2:

* UIProcess/ios/RemoteScrollingCoordinatorProxyIOS.mm:
(RemoteScrollingCoordinatorProxy::closestSnapOffsetForMainFrameScrolling): Modify use of 'closestSnapOffset' to satisfy the additional
argument I added. This is currently not used for anything on iOS.
* UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm: Ditto.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (184138 => 184139)


--- trunk/Source/WebCore/ChangeLog	2015-05-12 01:06:59 UTC (rev 184138)
+++ trunk/Source/WebCore/ChangeLog	2015-05-12 01:12:01 UTC (rev 184139)
@@ -1,3 +1,102 @@
+2015-05-11  Brent Fulgham  <[email protected]>
+
+        Scroll snap logic should be triggered when resizing the WebView
+        https://bugs.webkit.org/show_bug.cgi?id=142590
+        <rdar://problem/20125088>
+
+        Reviewed by Simon Fraser.
+
+        Tests coming in a second patch.
+
+        Resizing of the main frame or overflow regions was properly recalculating the scroll snap points,
+        but there was no code to honor these values when window resizing was occurring. The correction was
+        handled in two ways:
+        1. Scrolling thread operations that moved to new snap points needed to notify the main thread that
+           it had shifted to a new snap point, so that the resize code (which happens on the main thread)
+           could ensure that we stayed clamped to the correct 'tile' in the snap region.
+        2. Main thread (overflow) resizes were likewise missing code to honor the current snap position
+           after resizing calculations were complete.
+
+        This change also required the addition of two indices to the scrollable area to track which scroll
+        snap point was currently being used. We don't bother with a 'none' case because you cannot have a
+        'none' state when you have an active set of scroll snap points, and we do not execute this code
+        if the scroll snap points are null.
+
+        The FrameView code was computing updated snap offsets after it had dispatched frame view layout
+        information to the scrolling thread, which was wrong. This was also corrected.
+
+        I think it might be possible to track all of this state inside the ScrollController, but the current
+        scroll snap architecture destroys and recreates the state each time a new set of interactions starts.
+        This should be fixed in the future, which would allow us to remove some of this local state.
+
+        * page/FrameView.cpp:
+        (WebCore::FrameView::performPostLayoutTasks): Make sure 'updateSnapOffsets' is called prior to
+        calling 'frameViewLayoutUpdated' so the scrolling thread gets correct updated points. Add a new
+        call to 'scrollToNearestActiveSnapPoint', which will keep us on our current snap point during
+        resize (if appropriate).
+        * page/scrolling/AsyncScrollingCoordinator.cpp:
+        (WebCore::AsyncScrollingCoordinator::updateScrollSnapOffsetIndices): Added. This finds and notifies
+        the correct scroll region when a new snap position (index) has been selected by user interaction on
+        the scrolling thread.
+        (WebCore::AsyncScrollingCoordinator::deferTestsForReason): Added an assertion for 'isMainThread'.
+        (WebCore::AsyncScrollingCoordinator::removeTestDeferralForReason): Ditto.
+        * page/scrolling/AsyncScrollingCoordinator.h:
+        * page/scrolling/AxisScrollSnapOffsets.h:
+        (WebCore::closestSnapOffset): Modified to also return the selected snap point index so we can track
+        it to handle resize operations.
+        * page/scrolling/ScrollingTree.h:
+        (WebCore::ScrollingTree::updateScrollSnapOffsetIndices):
+        * page/scrolling/ThreadedScrollingTree.cpp:
+        (WebCore::ThreadedScrollingTree::updateScrollSnapOffsetIndices): Added method to dispatch the active
+        horizontal and vertical scroll snap indices back to the main thread.
+        * page/scrolling/ThreadedScrollingTree.h:
+        * page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm:
+        (WebCore::ScrollingTreeFrameScrollingNodeMac::handleWheelEvent): After the scroll controller processes
+        the current event, notify the main thread of any change in the active scroll snap index.
+        * platform/ScrollAnimator.cpp:
+        (WebCore::ScrollAnimator::activeScrollSnapOffsetIndexDidChange): Added method to allow ScrollAnimator
+        clients to find out about the current scroll snap state, which is only known by the ScrollController.
+        (WebCore::ScrollAnimator::activeScrollSnapOffsetIndexForAxis): Ditto.
+        * platform/ScrollAnimator.h:
+        * platform/ScrollView.cpp:
+        (WebCore::ScrollView::scrollToNearestActiveSnapPoint): Added method that allows us to set scroll position
+        to one of our active scroll snap offsets.
+        * platform/ScrollView.h:
+        * platform/ScrollableArea.cpp:
+        (WebCore::ScrollableArea::handleWheelEvent): If the active scroll snap offset has changed, make sure we
+        keep track of the new values for potential resize operations.
+        (WebCore::ScrollableArea::clearHorizontalSnapOffsets): Make sure to also clear out the current snap index.
+        (WebCore::ScrollableArea::clearVerticalSnapOffsets): Ditto.
+        (WebCore::ScrollableArea::nearestActiveSnapPoint): New method that returns an updated IntPoint reflecting
+        the proper scroll position based on the active scroll snap offset.
+        * platform/ScrollableArea.h:
+        (WebCore::ScrollableArea::currentHorizontalSnapPointIndex): Added.
+        (WebCore::ScrollableArea::setCurrentHorizontalSnapPointIndex): Added.
+        (WebCore::ScrollableArea::currentVerticalSnapPointIndex): Added.
+        (WebCore::ScrollableArea::setCurrentVerticalSnapPointIndex): Added.
+        (WebCore::ScrollableArea::scrollToNearestActiveSnapPoint): Added.
+        * platform/cocoa/ScrollController.h:
+        (WebCore::ScrollControllerClient::activeScrollOffsetIndex): Added new method for clients to implement.
+        (WebCore::ScrollController::activeScrollSnapOffsetIndexDidChange): Added.
+        (WebCore::ScrollController::setScrollSnapOffsetIndexDidChange): Added.
+        * platform/cocoa/ScrollController.mm:
+        (WebCore::ScrollController::activeScrollSnapOffsetIndexForAxis): Helper method to return current active
+        index (if applicable).
+        (WebCore::ScrollController::setActiveScrollSnapOffsetIndexForAxis): Helper function to safely set
+        the current active index.
+        (WebCore::ScrollController::beginScrollSnapAnimation): Updated to keep track of the new active scroll snap
+        index, as well as whether the current animation actually changed the active snap point offset.
+        * platform/cocoa/ScrollSnapAnimatorState.h: Revise to use modern C++ initializers, and to track a new index
+        that represents the current scroll snap offset.
+        * platform/cocoa/ScrollSnapAnimatorState.mm:
+        (WebCore::ScrollSnapAnimatorState::ScrollSnapAnimatorState): Update for modern C++ syntax.
+        * rendering/RenderLayer.cpp:
+        (WebCore::RenderLayer::scrollToNearestActiveSnapPoint): New method to set scroll position to be one of our
+        active scroll snap points.
+        (WebCore::RenderLayer::updateScrollInfoAfterLayout): Add a new call to 'scrollToNearestActiveSnapPoint' so that
+        we stay on the current scroll snap offset during resizing.
+        * rendering/RenderLayer.h:
+
 2015-05-11  Myles C. Maxfield  <[email protected]>
 
         Addressing post-review comments after r184037.

Modified: trunk/Source/WebCore/page/FrameView.cpp (184138 => 184139)


--- trunk/Source/WebCore/page/FrameView.cpp	2015-05-12 01:06:59 UTC (rev 184138)
+++ trunk/Source/WebCore/page/FrameView.cpp	2015-05-12 01:12:01 UTC (rev 184139)
@@ -2974,7 +2974,11 @@
     frame().loader().client().dispatchDidLayout();
 
     updateWidgetPositions();
-    
+
+#if ENABLE(CSS_SCROLL_SNAP)
+    updateSnapOffsets();
+#endif
+
     // layout() protects FrameView, but it still can get destroyed when updateEmbeddedObjects()
     // is called through the post layout timer.
     Ref<FrameView> protect(*this);
@@ -2996,15 +3000,7 @@
     sendResizeEventIfNeeded();
     viewportContentsChanged();
 
-#if ENABLE(CSS_SCROLL_SNAP)
-    if (!frame().isMainFrame()) {
-        updateSnapOffsets();
-#if PLATFORM(MAC)
-        if (ScrollAnimator* scrollAnimator = existingScrollAnimator())
-            return scrollAnimator->updateScrollAnimatorsAndTimers();
-#endif
-    }
-#endif
+    updateScrollSnapState();
 }
 
 IntSize FrameView::sizeForResizeEvent() const

Modified: trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp (184138 => 184139)


--- trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp	2015-05-12 01:06:59 UTC (rev 184138)
+++ trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp	2015-05-12 01:12:01 UTC (rev 184139)
@@ -562,8 +562,33 @@
 }
 
 #if PLATFORM(COCOA)
+void AsyncScrollingCoordinator::setActiveScrollSnapIndices(ScrollingNodeID scrollingNodeID, unsigned horizontalIndex, unsigned verticalIndex)
+{
+    ASSERT(isMainThread());
+    
+    if (!m_page)
+        return;
+    
+    FrameView* frameView = frameViewForScrollingNode(scrollingNodeID);
+    if (!frameView)
+        return;
+    
+    if (scrollingNodeID == frameView->scrollLayerID()) {
+        frameView->setCurrentHorizontalSnapPointIndex(horizontalIndex);
+        frameView->setCurrentVerticalSnapPointIndex(verticalIndex);
+        return;
+    }
+    
+    // Overflow-scroll area.
+    if (ScrollableArea* scrollableArea = frameView->scrollableAreaForScrollLayerID(scrollingNodeID)) {
+        scrollableArea->setCurrentHorizontalSnapPointIndex(horizontalIndex);
+        scrollableArea->setCurrentVerticalSnapPointIndex(verticalIndex);
+    }
+}
+
 void AsyncScrollingCoordinator::deferTestsForReason(WheelEventTestTrigger::ScrollableAreaIdentifier identifier, WheelEventTestTrigger::DeferTestTriggerReason reason) const
 {
+    ASSERT(isMainThread());
     if (!m_page || !m_page->expectsWheelEventTriggers())
         return;
 
@@ -575,6 +600,7 @@
 
 void AsyncScrollingCoordinator::removeTestDeferralForReason(WheelEventTestTrigger::ScrollableAreaIdentifier identifier, WheelEventTestTrigger::DeferTestTriggerReason reason) const
 {
+    ASSERT(isMainThread());
     if (!m_page || !m_page->expectsWheelEventTriggers())
         return;
 

Modified: trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.h (184138 => 184139)


--- trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.h	2015-05-12 01:06:59 UTC (rev 184138)
+++ trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.h	2015-05-12 01:12:01 UTC (rev 184139)
@@ -57,6 +57,7 @@
     WEBCORE_EXPORT void scheduleUpdateScrollPositionAfterAsyncScroll(ScrollingNodeID, const FloatPoint&, bool programmaticScroll, SetOrSyncScrollingLayerPosition);
 
 #if PLATFORM(COCOA)
+    void setActiveScrollSnapIndices(ScrollingNodeID, unsigned horizontalIndex, unsigned verticalIndex);
     void deferTestsForReason(WheelEventTestTrigger::ScrollableAreaIdentifier, WheelEventTestTrigger::DeferTestTriggerReason) const;
     void removeTestDeferralForReason(WheelEventTestTrigger::ScrollableAreaIdentifier, WheelEventTestTrigger::DeferTestTriggerReason) const;
 #endif

Modified: trunk/Source/WebCore/page/scrolling/AxisScrollSnapOffsets.h (184138 => 184139)


--- trunk/Source/WebCore/page/scrolling/AxisScrollSnapOffsets.h	2015-05-12 01:06:59 UTC (rev 184138)
+++ trunk/Source/WebCore/page/scrolling/AxisScrollSnapOffsets.h	2015-05-12 01:12:01 UTC (rev 184139)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014-2015 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -44,12 +44,14 @@
 // as well as a VelocityType indicating the velocity (e.g. float, CGFloat, etc.) This function is templated because the UI process will now
 // use pixel snapped floats to represent snap offsets rather than LayoutUnits.
 template <typename LayoutType, typename VelocityType>
-LayoutType closestSnapOffset(const Vector<LayoutType>& snapOffsets, LayoutType scrollDestination, VelocityType velocity)
+LayoutType closestSnapOffset(const Vector<LayoutType>& snapOffsets, LayoutType scrollDestination, VelocityType velocity, unsigned& activeSnapIndex)
 {
     ASSERT(snapOffsets.size());
+    activeSnapIndex = 0;
     if (scrollDestination <= snapOffsets.first())
         return snapOffsets.first();
 
+    activeSnapIndex = snapOffsets.size() - 1;
     if (scrollDestination >= snapOffsets.last())
         return snapOffsets.last();
 
@@ -70,10 +72,13 @@
     LayoutType lowerSnapPosition = snapOffsets[lowerIndex];
     LayoutType upperSnapPosition = snapOffsets[upperIndex];
     // Nonzero velocity indicates a flick gesture. Even if another snap point is closer, snap to the one in the direction of the flick gesture.
-    if (velocity)
+    if (velocity) {
+        activeSnapIndex = (velocity < 0) ? lowerIndex : upperIndex;
         return velocity < 0 ? lowerSnapPosition : upperSnapPosition;
+    }
 
     bool isCloserToLowerSnapPosition = scrollDestination - lowerSnapPosition <= upperSnapPosition - scrollDestination;
+    activeSnapIndex = isCloserToLowerSnapPosition ? lowerIndex : upperIndex;
     return isCloserToLowerSnapPosition ? lowerSnapPosition : upperSnapPosition;
 }
 

Modified: trunk/Source/WebCore/page/scrolling/ScrollingTree.h (184138 => 184139)


--- trunk/Source/WebCore/page/scrolling/ScrollingTree.h	2015-05-12 01:06:59 UTC (rev 184138)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTree.h	2015-05-12 01:12:01 UTC (rev 184139)
@@ -100,6 +100,7 @@
     
 #if PLATFORM(MAC)
     virtual void handleWheelEventPhase(PlatformWheelEventPhase) = 0;
+    virtual void setActiveScrollSnapIndices(ScrollingNodeID, unsigned /*horizontalIndex*/, unsigned /*verticalIndex*/) { }
     virtual void deferTestsForReason(WheelEventTestTrigger::ScrollableAreaIdentifier, WheelEventTestTrigger::DeferTestTriggerReason) { }
     virtual void removeTestDeferralForReason(WheelEventTestTrigger::ScrollableAreaIdentifier, WheelEventTestTrigger::DeferTestTriggerReason) { }
 #endif

Modified: trunk/Source/WebCore/page/scrolling/ThreadedScrollingTree.cpp (184138 => 184139)


--- trunk/Source/WebCore/page/scrolling/ThreadedScrollingTree.cpp	2015-05-12 01:06:59 UTC (rev 184138)
+++ trunk/Source/WebCore/page/scrolling/ThreadedScrollingTree.cpp	2015-05-12 01:12:01 UTC (rev 184139)
@@ -123,6 +123,17 @@
     });
 }
 
+void ThreadedScrollingTree::setActiveScrollSnapIndices(ScrollingNodeID nodeID, unsigned horizontalIndex, unsigned verticalIndex)
+{
+    if (!m_scrollingCoordinator)
+        return;
+    
+    RefPtr<AsyncScrollingCoordinator> scrollingCoordinator = m_scrollingCoordinator;
+    RunLoop::main().dispatch([scrollingCoordinator, nodeID, horizontalIndex, verticalIndex] {
+        scrollingCoordinator->setActiveScrollSnapIndices(nodeID, horizontalIndex, verticalIndex);
+    });
+}
+
 void ThreadedScrollingTree::deferTestsForReason(WheelEventTestTrigger::ScrollableAreaIdentifier identifier, WheelEventTestTrigger::DeferTestTriggerReason reason)
 {
     if (!m_scrollingCoordinator)

Modified: trunk/Source/WebCore/page/scrolling/ThreadedScrollingTree.h (184138 => 184139)


--- trunk/Source/WebCore/page/scrolling/ThreadedScrollingTree.h	2015-05-12 01:06:59 UTC (rev 184138)
+++ trunk/Source/WebCore/page/scrolling/ThreadedScrollingTree.h	2015-05-12 01:12:01 UTC (rev 184139)
@@ -62,6 +62,7 @@
     virtual void scrollingTreeNodeDidScroll(ScrollingNodeID, const FloatPoint& scrollPosition, SetOrSyncScrollingLayerPosition = SyncScrollingLayerPosition) override;
 #if PLATFORM(MAC)
     void handleWheelEventPhase(PlatformWheelEventPhase) override;
+    void setActiveScrollSnapIndices(ScrollingNodeID, unsigned horizontalIndex, unsigned verticalIndex) override;
     void deferTestsForReason(WheelEventTestTrigger::ScrollableAreaIdentifier, WheelEventTestTrigger::DeferTestTriggerReason) override;
     void removeTestDeferralForReason(WheelEventTestTrigger::ScrollableAreaIdentifier, WheelEventTestTrigger::DeferTestTriggerReason) override;
 #endif

Modified: trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm (184138 => 184139)


--- trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm	2015-05-12 01:06:59 UTC (rev 184138)
+++ trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm	2015-05-12 01:12:01 UTC (rev 184139)
@@ -184,6 +184,10 @@
 #endif
 
     m_scrollController.handleWheelEvent(wheelEvent);
+#if ENABLE(CSS_SCROLL_SNAP)
+    if (m_scrollController.activeScrollSnapIndexDidChange())
+        scrollingTree().setActiveScrollSnapIndices(scrollingNodeID(), m_scrollController.activeScrollSnapIndexForAxis(ScrollEventAxis::Horizontal), m_scrollController.activeScrollSnapIndexForAxis(ScrollEventAxis::Vertical));
+#endif
     scrollingTree().setOrClearLatchedNode(wheelEvent, scrollingNodeID());
     scrollingTree().handleWheelEventPhase(wheelEvent.phase());
 }

Modified: trunk/Source/WebCore/platform/ScrollAnimator.cpp (184138 => 184139)


--- trunk/Source/WebCore/platform/ScrollAnimator.cpp	2015-05-12 01:06:59 UTC (rev 184138)
+++ trunk/Source/WebCore/platform/ScrollAnimator.cpp	2015-05-12 01:12:01 UTC (rev 184139)
@@ -87,6 +87,16 @@
 {
     return m_scrollController.processWheelEventForScrollSnap(wheelEvent);
 }
+
+bool ScrollAnimator::activeScrollSnapIndexDidChange() const
+{
+    return m_scrollController.activeScrollSnapIndexDidChange();
+}
+
+unsigned ScrollAnimator::activeScrollSnapIndexForAxis(ScrollEventAxis axis) const
+{
+    return m_scrollController.activeScrollSnapIndexForAxis(axis);
+}
 #endif
 
 bool ScrollAnimator::handleWheelEvent(const PlatformWheelEvent& e)

Modified: trunk/Source/WebCore/platform/ScrollAnimator.h (184138 => 184139)


--- trunk/Source/WebCore/platform/ScrollAnimator.h	2015-05-12 01:06:59 UTC (rev 184138)
+++ trunk/Source/WebCore/platform/ScrollAnimator.h	2015-05-12 01:12:01 UTC (rev 184139)
@@ -130,6 +130,8 @@
     void updateScrollAnimatorsAndTimers();
     LayoutUnit scrollOffsetOnAxis(ScrollEventAxis) const override;
     void immediateScrollOnAxis(ScrollEventAxis, float delta) override;
+    bool activeScrollSnapIndexDidChange() const;
+    unsigned activeScrollSnapIndexForAxis(ScrollEventAxis) const;
 #endif
 
 protected:

Modified: trunk/Source/WebCore/platform/ScrollableArea.cpp (184138 => 184139)


--- trunk/Source/WebCore/platform/ScrollableArea.cpp	2015-05-12 01:06:59 UTC (rev 184138)
+++ trunk/Source/WebCore/platform/ScrollableArea.cpp	2015-05-12 01:12:01 UTC (rev 184139)
@@ -46,6 +46,7 @@
     virtual ~SameSizeAsScrollableArea();
 #if ENABLE(CSS_SCROLL_SNAP)
     void* pointers[3];
+    unsigned currentIndices[2];
 #else
     void* pointer;
 #endif
@@ -188,7 +189,14 @@
     if (!isScrollableOrRubberbandable())
         return false;
 
-    return scrollAnimator().handleWheelEvent(wheelEvent);
+    bool handledEvent = scrollAnimator().handleWheelEvent(wheelEvent);
+#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC)
+    if (scrollAnimator().activeScrollSnapIndexDidChange()) {
+        setCurrentHorizontalSnapPointIndex(scrollAnimator().activeScrollSnapIndexForAxis(ScrollEventAxis::Horizontal));
+        setCurrentVerticalSnapPointIndex(scrollAnimator().activeScrollSnapIndexForAxis(ScrollEventAxis::Vertical));
+    }
+#endif
+    return handledEvent;
 }
 
 #if ENABLE(TOUCH_EVENTS)
@@ -409,14 +417,64 @@
 void ScrollableArea::clearHorizontalSnapOffsets()
 {
     m_horizontalSnapOffsets = nullptr;
+    m_currentHorizontalSnapPointIndex = 0;
 }
 
 void ScrollableArea::clearVerticalSnapOffsets()
 {
     m_verticalSnapOffsets = nullptr;
+    m_currentVerticalSnapPointIndex = 0;
 }
+
+IntPoint ScrollableArea::nearestActiveSnapPoint(const IntPoint& currentPosition)
+{
+    if (!horizontalSnapOffsets() && !verticalSnapOffsets())
+        return currentPosition;
+    
+    if (!existingScrollAnimator())
+        return currentPosition;
+    
+    IntPoint correctedPosition = currentPosition;
+    
+    if (horizontalSnapOffsets()) {
+        const auto& horizontal = *horizontalSnapOffsets();
+        
+        size_t activeIndex = currentHorizontalSnapPointIndex();
+        if (activeIndex < horizontal.size())
+            correctedPosition.setX(horizontal[activeIndex].toInt());
+    }
+    
+    if (verticalSnapOffsets()) {
+        const auto& vertical = *verticalSnapOffsets();
+        
+        size_t activeIndex = currentVerticalSnapPointIndex();
+        if (activeIndex < vertical.size())
+            correctedPosition.setY(vertical[activeIndex].toInt());
+    }
+
+    return correctedPosition;
+}
+
+void ScrollableArea::updateScrollSnapState()
+{
+#if PLATFORM(MAC)
+    if (ScrollAnimator* scrollAnimator = existingScrollAnimator())
+        scrollAnimator->updateScrollAnimatorsAndTimers();
 #endif
 
+    IntPoint currentPosition = scrollPosition();
+    IntPoint correctedPosition = nearestActiveSnapPoint(currentPosition);
+    
+    if (correctedPosition != currentPosition)
+        scrollToOffsetWithoutAnimation(correctedPosition);
+}
+#else
+void ScrollableArea::updateScrollSnapState()
+{
+}
+#endif
+
+
 void ScrollableArea::serviceScrollAnimations()
 {
     if (ScrollAnimator* scrollAnimator = existingScrollAnimator())

Modified: trunk/Source/WebCore/platform/ScrollableArea.h (184138 => 184139)


--- trunk/Source/WebCore/platform/ScrollableArea.h	2015-05-12 01:06:59 UTC (rev 184138)
+++ trunk/Source/WebCore/platform/ScrollableArea.h	2015-05-12 01:12:01 UTC (rev 184139)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008, 2011, 2014 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008, 2011, 2014-2015 Apple Inc. All Rights Reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -66,8 +66,15 @@
     void setVerticalSnapOffsets(std::unique_ptr<Vector<LayoutUnit>>);
     void clearHorizontalSnapOffsets();
     void clearVerticalSnapOffsets();
+    unsigned currentHorizontalSnapPointIndex() const { return m_currentHorizontalSnapPointIndex; }
+    void setCurrentHorizontalSnapPointIndex(unsigned index) { m_currentHorizontalSnapPointIndex = index; }
+    unsigned currentVerticalSnapPointIndex() const { return m_currentVerticalSnapPointIndex; }
+    void setCurrentVerticalSnapPointIndex(unsigned index) { m_currentVerticalSnapPointIndex = index; }
+    IntPoint nearestActiveSnapPoint(const IntPoint&);
 #endif
 
+    void updateScrollSnapState();
+
 #if ENABLE(TOUCH_EVENTS)
     virtual bool isTouchScrollable() const { return false; }
     virtual bool handleTouchEvent(const PlatformTouchEvent&);
@@ -305,6 +312,8 @@
 #if ENABLE(CSS_SCROLL_SNAP)
     std::unique_ptr<Vector<LayoutUnit>> m_horizontalSnapOffsets;
     std::unique_ptr<Vector<LayoutUnit>> m_verticalSnapOffsets;
+    unsigned m_currentHorizontalSnapPointIndex { 0 };
+    unsigned m_currentVerticalSnapPointIndex { 0 };
 #endif
 
     // There are 8 possible combinations of writing mode and direction. Scroll origin will be non-zero in the x or y axis

Modified: trunk/Source/WebCore/platform/cocoa/ScrollController.h (184138 => 184139)


--- trunk/Source/WebCore/platform/cocoa/ScrollController.h	2015-05-12 01:06:59 UTC (rev 184138)
+++ trunk/Source/WebCore/platform/cocoa/ScrollController.h	2015-05-12 01:12:01 UTC (rev 184139)
@@ -97,6 +97,11 @@
     {
         return 1.0f;
     }
+
+    virtual unsigned activeScrollOffsetIndex(ScrollEventAxis) const
+    {
+        return 0;
+    }
 #endif
 };
 
@@ -114,6 +119,10 @@
     bool processWheelEventForScrollSnap(const PlatformWheelEvent&);
     void updateScrollAnimatorsAndTimers(const ScrollableArea&);
     void updateScrollSnapPoints(ScrollEventAxis, const Vector<LayoutUnit>&);
+    unsigned activeScrollSnapIndexForAxis(ScrollEventAxis) const;
+    void setActiveScrollSnapIndexForAxis(ScrollEventAxis, unsigned);
+    bool activeScrollSnapIndexDidChange() const { return m_activeScrollSnapIndexDidChange; }
+    void setScrollSnapIndexDidChange(bool state) { m_activeScrollSnapIndexDidChange = state; }
 #endif
 
 private:
@@ -172,6 +181,7 @@
     bool m_momentumScrollInProgress { false };
     bool m_ignoreMomentumScrolls { false };
     bool m_snapRubberbandTimerIsActive { false };
+    bool m_activeScrollSnapIndexDidChange { false };
 };
     
 } // namespace WebCore

Modified: trunk/Source/WebCore/platform/cocoa/ScrollController.mm (184138 => 184139)


--- trunk/Source/WebCore/platform/cocoa/ScrollController.mm	2015-05-12 01:06:59 UTC (rev 184138)
+++ trunk/Source/WebCore/platform/cocoa/ScrollController.mm	2015-05-12 01:12:01 UTC (rev 184139)
@@ -685,6 +685,26 @@
     snapState.m_glidePhaseShift = acos((snapState.m_glideInitialWheelDelta - targetFinalWheelDelta) / (snapState.m_glideInitialWheelDelta + targetFinalWheelDelta));
 }
 
+unsigned ScrollController::activeScrollSnapIndexForAxis(ScrollEventAxis axis) const
+{
+    if ((axis == ScrollEventAxis::Horizontal) && !m_horizontalScrollSnapState)
+        return 0;
+    if ((axis == ScrollEventAxis::Vertical) && !m_verticalScrollSnapState)
+        return 0;
+    
+    const ScrollSnapAnimatorState& snapState = scrollSnapPointState(axis);
+    return snapState.m_activeSnapIndex;
+}
+
+void ScrollController::setActiveScrollSnapIndexForAxis(ScrollEventAxis axis, unsigned index)
+{
+    auto* snapState = (axis == ScrollEventAxis::Horizontal) ? m_horizontalScrollSnapState.get() : m_verticalScrollSnapState.get();
+    if (!snapState)
+        return;
+
+    snapState->m_activeSnapIndex = index;
+}
+
 void ScrollController::beginScrollSnapAnimation(ScrollEventAxis axis, ScrollSnapState newState)
 {
     ASSERT(newState == ScrollSnapState::Gliding || newState == ScrollSnapState::Snapping);
@@ -701,10 +721,12 @@
     
     projectedScrollDestination = std::min(std::max(LayoutUnit(projectedScrollDestination / scaleFactor), snapState.m_snapOffsets.first()), snapState.m_snapOffsets.last());
     snapState.m_initialOffset = offset;
-    snapState.m_targetOffset = scaleFactor * closestSnapOffset<LayoutUnit, float>(snapState.m_snapOffsets, projectedScrollDestination, initialWheelDelta);
+    m_activeScrollSnapIndexDidChange = false;
+    snapState.m_targetOffset = scaleFactor * closestSnapOffset<LayoutUnit, float>(snapState.m_snapOffsets, projectedScrollDestination, initialWheelDelta, snapState.m_activeSnapIndex);
     if (snapState.m_initialOffset == snapState.m_targetOffset)
         return;
     
+    m_activeScrollSnapIndexDidChange = true;
     snapState.m_currentState = newState;
     if (newState == ScrollSnapState::Gliding) {
         snapState.m_shouldOverrideWheelEvent = true;

Modified: trunk/Source/WebCore/platform/cocoa/ScrollSnapAnimatorState.h (184138 => 184139)


--- trunk/Source/WebCore/platform/cocoa/ScrollSnapAnimatorState.h	2015-05-12 01:06:59 UTC (rev 184138)
+++ trunk/Source/WebCore/platform/cocoa/ScrollSnapAnimatorState.h	2015-05-12 01:12:01 UTC (rev 184139)
@@ -59,12 +59,13 @@
     LayoutUnit m_targetOffset;
     // Used to track gliding behavior.
     LayoutUnit m_beginTrackingWheelDeltaOffset;
-    int m_numWheelDeltasTracked;
+    int m_numWheelDeltasTracked { 0 };
+    unsigned m_activeSnapIndex { 0 };
     float m_wheelDeltaWindow[wheelDeltaWindowSize];
-    float m_glideMagnitude;
-    float m_glidePhaseShift;
-    float m_glideInitialWheelDelta;
-    bool m_shouldOverrideWheelEvent;
+    float m_glideMagnitude { 0 };
+    float m_glidePhaseShift { 0 };
+    float m_glideInitialWheelDelta { 0 };
+    bool m_shouldOverrideWheelEvent { false };
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/platform/cocoa/ScrollSnapAnimatorState.mm (184138 => 184139)


--- trunk/Source/WebCore/platform/cocoa/ScrollSnapAnimatorState.mm	2015-05-12 01:06:59 UTC (rev 184138)
+++ trunk/Source/WebCore/platform/cocoa/ScrollSnapAnimatorState.mm	2015-05-12 01:12:01 UTC (rev 184139)
@@ -37,11 +37,6 @@
     , m_initialOffset(0)
     , m_targetOffset(0)
     , m_beginTrackingWheelDeltaOffset(0)
-    , m_numWheelDeltasTracked(0)
-    , m_glideMagnitude(0)
-    , m_glidePhaseShift(0)
-    , m_glideInitialWheelDelta(0)
-    , m_shouldOverrideWheelEvent(false)
 {
 }
 

Modified: trunk/Source/WebCore/rendering/RenderLayer.cpp (184138 => 184139)


--- trunk/Source/WebCore/rendering/RenderLayer.cpp	2015-05-12 01:06:59 UTC (rev 184138)
+++ trunk/Source/WebCore/rendering/RenderLayer.cpp	2015-05-12 01:12:01 UTC (rev 184139)
@@ -3461,6 +3461,12 @@
 
     computeScrollDimensions();
 
+#if ENABLE(CSS_SCROLL_SNAP)
+    // FIXME: Ensure that offsets are also updated in case of programmatic style changes.
+    // https://bugs.webkit.org/show_bug.cgi?id=135964
+    updateSnapOffsets();
+#endif
+
     if (box->style().overflowX() != OMARQUEE && !isRubberBandInProgress()) {
         // Layout may cause us to be at an invalid scroll position. In this case we need
         // to pull our scroll offsets back to the max (or push them up to the min).
@@ -3488,15 +3494,7 @@
     if (compositor().updateLayerCompositingState(*this))
         compositor().setCompositingLayersNeedRebuild();
 
-#if ENABLE(CSS_SCROLL_SNAP)
-    // FIXME: Ensure that offsets are also updated in case of programmatic style changes.
-    // https://bugs.webkit.org/show_bug.cgi?id=135964
-    updateSnapOffsets();
-#if PLATFORM(MAC)
-    if (ScrollAnimator* scrollAnimator = existingScrollAnimator())
-        return scrollAnimator->updateScrollAnimatorsAndTimers();
-#endif
-#endif
+    updateScrollSnapState();
 }
 
 bool RenderLayer::overflowControlsIntersectRect(const IntRect& localRect) const

Modified: trunk/Source/WebKit2/ChangeLog (184138 => 184139)


--- trunk/Source/WebKit2/ChangeLog	2015-05-12 01:06:59 UTC (rev 184138)
+++ trunk/Source/WebKit2/ChangeLog	2015-05-12 01:12:01 UTC (rev 184139)
@@ -1,3 +1,16 @@
+2015-05-11  Brent Fulgham  <[email protected]>
+
+        Scroll snap logic should be triggered when resizing the WebView
+        https://bugs.webkit.org/show_bug.cgi?id=142590
+        <rdar://problem/20125088>
+
+        Reviewed by Simon Fraser.
+
+        * UIProcess/ios/RemoteScrollingCoordinatorProxyIOS.mm:
+        (RemoteScrollingCoordinatorProxy::closestSnapOffsetForMainFrameScrolling): Modify use of 'closestSnapOffset' to satisfy the additional
+        argument I added. This is currently not used for anything on iOS.
+        * UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm: Ditto.
+
 2015-05-11  Andreas Kling  <[email protected]>
 
         Force a rebuild of JSNPObject.cpp on bots.

Modified: trunk/Source/WebKit2/UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm (184138 => 184139)


--- trunk/Source/WebKit2/UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm	2015-05-12 01:06:59 UTC (rev 184138)
+++ trunk/Source/WebKit2/UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm	2015-05-12 01:12:01 UTC (rev 184139)
@@ -80,10 +80,11 @@
 #if ENABLE(CSS_SCROLL_SNAP)
 - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
 {
+    unsigned ignore;
     if (!_scrollingTreeNode->horizontalSnapOffsets().isEmpty())
-        targetContentOffset->x = closestSnapOffset<float, CGFloat>(_scrollingTreeNode->horizontalSnapOffsets(), targetContentOffset->x, velocity.x);
+        targetContentOffset->x = closestSnapOffset<float, CGFloat>(_scrollingTreeNode->horizontalSnapOffsets(), targetContentOffset->x, velocity.x, ignore);
     if (!_scrollingTreeNode->verticalSnapOffsets().isEmpty())
-        targetContentOffset->y = closestSnapOffset<float, CGFloat>(_scrollingTreeNode->verticalSnapOffsets(), targetContentOffset->y, velocity.y);
+        targetContentOffset->y = closestSnapOffset<float, CGFloat>(_scrollingTreeNode->verticalSnapOffsets(), targetContentOffset->y, velocity.y, ignore);
 }
 #endif
 

Modified: trunk/Source/WebKit2/UIProcess/ios/RemoteScrollingCoordinatorProxyIOS.mm (184138 => 184139)


--- trunk/Source/WebKit2/UIProcess/ios/RemoteScrollingCoordinatorProxyIOS.mm	2015-05-12 01:06:59 UTC (rev 184138)
+++ trunk/Source/WebKit2/UIProcess/ios/RemoteScrollingCoordinatorProxyIOS.mm	2015-05-12 01:12:01 UTC (rev 184139)
@@ -150,8 +150,9 @@
     ScrollingTreeFrameScrollingNode* rootFrame = static_cast<ScrollingTreeFrameScrollingNode*>(root);
     const Vector<float>& snapOffsets = axis == ScrollEventAxis::Horizontal ? rootFrame->horizontalSnapOffsets() : rootFrame->verticalSnapOffsets();
 
+    unsigned ignore = 0;
     float scaledScrollDestination = scrollDestination / m_webPageProxy.displayedContentScale();
-    float rawClosestSnapOffset = closestSnapOffset<float, float>(snapOffsets, scaledScrollDestination, velocity);
+    float rawClosestSnapOffset = closestSnapOffset<float, float>(snapOffsets, scaledScrollDestination, velocity, ignore);
     return rawClosestSnapOffset * m_webPageProxy.displayedContentScale();
 }
 #endif
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to