Diff
Modified: trunk/Source/WebCore/ChangeLog (172648 => 172649)
--- trunk/Source/WebCore/ChangeLog 2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebCore/ChangeLog 2014-08-15 21:09:13 UTC (rev 172649)
@@ -1,3 +1,41 @@
+2014-08-15 Wenson Hsieh <[email protected]>
+
+ Implement snapping behavior for iOS
+ https://bugs.webkit.org/show_bug.cgi?id=135769
+
+ Reviewed by Brent Fulgham.
+
+ 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.
+
2014-08-15 Dirk Schulze <[email protected]>
Turn r/rx/ry to presentation attributes
Modified: trunk/Source/WebCore/WebCore.exp.in (172648 => 172649)
--- trunk/Source/WebCore/WebCore.exp.in 2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebCore/WebCore.exp.in 2014-08-15 21:09:13 UTC (rev 172649)
@@ -3011,6 +3011,11 @@
__ZN7WebCore16FilterOperationsaSERKS0_
#endif
+#if ENABLE(CSS_SCROLL_SNAP)
+__ZN7WebCore27ScrollingStateScrollingNode22setVerticalSnapOffsetsERKN3WTF6VectorIfLm0ENS1_15CrashOnOverflowEEE
+__ZN7WebCore27ScrollingStateScrollingNode24setHorizontalSnapOffsetsERKN3WTF6VectorIfLm0ENS1_15CrashOnOverflowEEE
+#endif
+
#if ENABLE(DASHBOARD_SUPPORT)
__ZNK7WebCore8Document16annotatedRegionsEv
#endif
Modified: trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp (172648 => 172649)
--- trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp 2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp 2014-08-15 21:09:13 UTC (rev 172649)
@@ -59,6 +59,20 @@
scheduleTreeStateCommit();
}
+static inline void setStateScrollingNodeSnapOffsetsAsFloat(ScrollingStateScrollingNode& node, ScrollEventAxis axis, const Vector<LayoutUnit>& snapOffsets, float deviceScaleFactor)
+{
+ // 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?
+ Vector<float> snapOffsetsAsFloat;
+ snapOffsetsAsFloat.reserveInitialCapacity(snapOffsets.size());
+ for (size_t i = 0; i < snapOffsets.size(); ++i)
+ snapOffsetsAsFloat.append(roundToDevicePixel(snapOffsets[i], deviceScaleFactor, false));
+
+ if (axis == ScrollEventAxis::Horizontal)
+ node.setHorizontalSnapOffsets(snapOffsetsAsFloat);
+ else
+ node.setVerticalSnapOffsets(snapOffsetsAsFloat);
+}
+
void AsyncScrollingCoordinator::frameViewLayoutUpdated(FrameView* frameView)
{
ASSERT(isMainThread());
@@ -97,6 +111,15 @@
node->setTotalContentsSize(frameView->totalContentsSize());
node->setReachableContentsSize(frameView->totalContentsSize());
+#if ENABLE(CSS_SCROLL_SNAP)
+ frameView->updateSnapOffsets();
+ if (const Vector<LayoutUnit>* horizontalSnapOffsets = frameView->horizontalSnapOffsets())
+ setStateScrollingNodeSnapOffsetsAsFloat(*node, ScrollEventAxis::Horizontal, *horizontalSnapOffsets, frameView->frame().document()->deviceScaleFactor());
+
+ if (const Vector<LayoutUnit>* verticalSnapOffsets = frameView->verticalSnapOffsets())
+ setStateScrollingNodeSnapOffsetsAsFloat(*node, ScrollEventAxis::Vertical, *verticalSnapOffsets, frameView->frame().document()->deviceScaleFactor());
+#endif
+
ScrollableAreaParameters scrollParameters;
scrollParameters.horizontalScrollElasticity = frameView->horizontalScrollElasticity();
scrollParameters.verticalScrollElasticity = frameView->verticalScrollElasticity();
@@ -399,6 +422,10 @@
node->setTotalContentsSize(scrollingGeometry->contentSize);
node->setReachableContentsSize(scrollingGeometry->reachableContentSize);
node->setScrollableAreaSize(scrollingGeometry->scrollableAreaSize);
+#if ENABLE(CSS_SCROLL_SNAP)
+ setStateScrollingNodeSnapOffsetsAsFloat(*node, ScrollEventAxis::Horizontal, scrollingGeometry->horizontalSnapOffsets, scrolledContentsLayer->deviceScaleFactor());
+ setStateScrollingNodeSnapOffsetsAsFloat(*node, ScrollEventAxis::Vertical, scrollingGeometry->verticalSnapOffsets, scrolledContentsLayer->deviceScaleFactor());
+#endif
}
}
Modified: trunk/Source/WebCore/page/scrolling/AxisScrollSnapOffsets.cpp (172648 => 172649)
--- trunk/Source/WebCore/page/scrolling/AxisScrollSnapOffsets.cpp 2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebCore/page/scrolling/AxisScrollSnapOffsets.cpp 2014-08-15 21:09:13 UTC (rev 172649)
@@ -43,14 +43,22 @@
if (RenderBox* box = child->renderBox()) {
LayoutUnit viewWidth = box->width();
LayoutUnit viewHeight = box->height();
- // FIXME: Check behavior with CSS rotations.
+#if PLATFORM(IOS)
+ // 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!)
+ float left = child->offsetLeft();
+ float top = child->offsetTop();
+#else
+ // FIXME: Check that localToContainerPoint works with CSS rotations.
FloatPoint position = box->localToContainerPoint(FloatPoint(), parent.renderBox());
+ float left = position.x();
+ float top = position.y();
+#endif
for (SnapCoordinate coordinate : box->style().scrollSnapCoordinates()) {
- LayoutUnit lastPotentialSnapPositionX = LayoutUnit(position.x()) + valueForLength(coordinate.first, viewWidth);
+ LayoutUnit lastPotentialSnapPositionX = LayoutUnit(left) + valueForLength(coordinate.first, viewWidth);
if (shouldAddHorizontalChildOffsets && lastPotentialSnapPositionX > 0)
horizontalSnapOffsetSubsequence.append(lastPotentialSnapPositionX);
- LayoutUnit lastPotentialSnapPositionY = LayoutUnit(position.y()) + valueForLength(coordinate.second, viewHeight);
+ LayoutUnit lastPotentialSnapPositionY = LayoutUnit(top) + valueForLength(coordinate.second, viewHeight);
if (shouldAddVerticalChildOffsets && lastPotentialSnapPositionY > 0)
verticalSnapOffsetSubsequence.append(lastPotentialSnapPositionY);
}
Modified: trunk/Source/WebCore/page/scrolling/AxisScrollSnapOffsets.h (172648 => 172649)
--- trunk/Source/WebCore/page/scrolling/AxisScrollSnapOffsets.h 2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebCore/page/scrolling/AxisScrollSnapOffsets.h 2014-08-15 21:09:13 UTC (rev 172649)
@@ -41,8 +41,11 @@
void updateSnapOffsetsForScrollableArea(ScrollableArea&, HTMLElement& scrollingElement, const RenderBox& scrollingElementBox, const RenderStyle& scrollingElementStyle);
-template <typename T>
-T closestSnapOffset(const Vector<T>& snapOffsets, T scrollDestination, float velocity)
+// closestSnapOffset is a templated function that takes in a Vector representing snap offsets as LayoutTypes (e.g. LayoutUnit or float) and
+// 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)
{
ASSERT(snapOffsets.size());
if (scrollDestination <= snapOffsets.first())
@@ -65,8 +68,8 @@
break;
}
}
- T lowerSnapPosition = snapOffsets[lowerIndex];
- T upperSnapPosition = snapOffsets[upperIndex];
+ 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)
return velocity < 0 ? lowerSnapPosition : upperSnapPosition;
Modified: trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.h (172648 => 172649)
--- trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.h 2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.h 2014-08-15 21:09:13 UTC (rev 172649)
@@ -43,6 +43,10 @@
#include <wtf/RetainPtr.h>
#endif
+#if ENABLE(CSS_SCROLL_SNAP)
+#include "AxisScrollSnapOffsets.h"
+#endif
+
namespace WebCore {
typedef unsigned SynchronousScrollingReasons;
@@ -164,6 +168,10 @@
FloatSize reachableContentSize; // Smaller than contentSize when overflow is hidden on one axis.
FloatPoint scrollPosition;
IntPoint scrollOrigin;
+#if ENABLE(CSS_SCROLL_SNAP)
+ Vector<LayoutUnit> horizontalSnapOffsets;
+ Vector<LayoutUnit> verticalSnapOffsets;
+#endif
};
virtual void updateFrameScrollingNode(ScrollingNodeID, GraphicsLayer* /*scrollLayer*/, GraphicsLayer* /*scrolledContentsLayer*/, GraphicsLayer* /*counterScrollingLayer*/, GraphicsLayer* /*insetClipLayer*/, const ScrollingGeometry* = nullptr) { }
Modified: trunk/Source/WebCore/page/scrolling/ScrollingStateScrollingNode.cpp (172648 => 172649)
--- trunk/Source/WebCore/page/scrolling/ScrollingStateScrollingNode.cpp 2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebCore/page/scrolling/ScrollingStateScrollingNode.cpp 2014-08-15 21:09:13 UTC (rev 172649)
@@ -48,6 +48,10 @@
, m_scrollPosition(stateNode.scrollPosition())
, m_requestedScrollPosition(stateNode.requestedScrollPosition())
, m_scrollOrigin(stateNode.scrollOrigin())
+#if ENABLE(CSS_SCROLL_SNAP)
+ , m_horizontalSnapOffsets(stateNode.horizontalSnapOffsets())
+ , m_verticalSnapOffsets(stateNode.verticalSnapOffsets())
+#endif
, m_scrollableAreaParameters(stateNode.scrollableAreaParameters())
, m_requestedScrollPositionRepresentsProgrammaticScroll(stateNode.requestedScrollPositionRepresentsProgrammaticScroll())
{
@@ -102,6 +106,26 @@
setPropertyChanged(ScrollOrigin);
}
+#if ENABLE(CSS_SCROLL_SNAP)
+void ScrollingStateScrollingNode::setHorizontalSnapOffsets(const Vector<float>& snapOffsets)
+{
+ if (m_horizontalSnapOffsets == snapOffsets)
+ return;
+
+ m_horizontalSnapOffsets = snapOffsets;
+ setPropertyChanged(HorizontalSnapOffsets);
+}
+
+void ScrollingStateScrollingNode::setVerticalSnapOffsets(const Vector<float>& snapOffsets)
+{
+ if (m_verticalSnapOffsets == snapOffsets)
+ return;
+
+ m_verticalSnapOffsets = snapOffsets;
+ setPropertyChanged(VerticalSnapOffsets);
+}
+#endif
+
void ScrollingStateScrollingNode::setScrollableAreaParameters(const ScrollableAreaParameters& parameters)
{
if (m_scrollableAreaParameters == parameters)
Modified: trunk/Source/WebCore/page/scrolling/ScrollingStateScrollingNode.h (172648 => 172649)
--- trunk/Source/WebCore/page/scrolling/ScrollingStateScrollingNode.h 2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebCore/page/scrolling/ScrollingStateScrollingNode.h 2014-08-15 21:09:13 UTC (rev 172649)
@@ -48,6 +48,10 @@
ScrollableAreaParams,
RequestedScrollPosition,
NumScrollingStateNodeBits,
+#if ENABLE(CSS_SCROLL_SNAP)
+ HorizontalSnapOffsets,
+ VerticalSnapOffsets,
+#endif
};
const FloatSize& scrollableAreaSize() const { return m_scrollableAreaSize; }
@@ -65,6 +69,14 @@
const IntPoint& scrollOrigin() const { return m_scrollOrigin; }
void setScrollOrigin(const IntPoint&);
+#if ENABLE(CSS_SCROLL_SNAP)
+ const Vector<float>& horizontalSnapOffsets() const { return m_horizontalSnapOffsets; }
+ void setHorizontalSnapOffsets(const Vector<float>&);
+
+ const Vector<float>& verticalSnapOffsets() const { return m_verticalSnapOffsets; }
+ void setVerticalSnapOffsets(const Vector<float>&);
+#endif
+
const ScrollableAreaParameters& scrollableAreaParameters() const { return m_scrollableAreaParameters; }
void setScrollableAreaParameters(const ScrollableAreaParameters& params);
@@ -85,6 +97,10 @@
FloatPoint m_scrollPosition;
FloatPoint m_requestedScrollPosition;
IntPoint m_scrollOrigin;
+#if ENABLE(CSS_SCROLL_SNAP)
+ Vector<float> m_horizontalSnapOffsets;
+ Vector<float> m_verticalSnapOffsets;
+#endif
ScrollableAreaParameters m_scrollableAreaParameters;
bool m_requestedScrollPositionRepresentsProgrammaticScroll;
};
Modified: trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp (172648 => 172649)
--- trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp 2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp 2014-08-15 21:09:13 UTC (rev 172649)
@@ -67,6 +67,14 @@
if (state.hasChangedProperty(ScrollingStateScrollingNode::ScrollOrigin))
m_scrollOrigin = state.scrollOrigin();
+#if ENABLE(CSS_SCROLL_SNAP)
+ if (state.hasChangedProperty(ScrollingStateScrollingNode::HorizontalSnapOffsets))
+ m_horizontalSnapOffsets = state.horizontalSnapOffsets();
+
+ if (state.hasChangedProperty(ScrollingStateScrollingNode::VerticalSnapOffsets))
+ m_verticalSnapOffsets = state.verticalSnapOffsets();
+#endif
+
if (state.hasChangedProperty(ScrollingStateScrollingNode::ScrollableAreaParams))
m_scrollableAreaParameters = state.scrollableAreaParameters();
}
Modified: trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h (172648 => 172649)
--- trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h 2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h 2014-08-15 21:09:13 UTC (rev 172649)
@@ -57,6 +57,11 @@
virtual FloatPoint scrollPosition() const = 0;
+#if ENABLE(CSS_SCROLL_SNAP)
+ const Vector<float>& horizontalSnapOffsets() const { return m_horizontalSnapOffsets; }
+ const Vector<float>& verticalSnapOffsets() const { return m_verticalSnapOffsets; }
+#endif
+
protected:
ScrollingTreeScrollingNode(ScrollingTree&, ScrollingNodeType, ScrollingNodeID);
@@ -92,7 +97,10 @@
FloatSize m_reachableContentsSize;
FloatPoint m_lastCommittedScrollPosition;
IntPoint m_scrollOrigin;
-
+#if ENABLE(CSS_SCROLL_SNAP)
+ Vector<float> m_horizontalSnapOffsets;
+ Vector<float> m_verticalSnapOffsets;
+#endif
ScrollableAreaParameters m_scrollableAreaParameters;
};
Modified: trunk/Source/WebCore/platform/mac/AxisScrollSnapAnimator.mm (172648 => 172649)
--- trunk/Source/WebCore/platform/mac/AxisScrollSnapAnimator.mm 2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebCore/platform/mac/AxisScrollSnapAnimator.mm 2014-08-15 21:09:13 UTC (rev 172649)
@@ -169,7 +169,7 @@
LayoutUnit projectedScrollDestination = newState == ScrollSnapState::Gliding ? m_beginTrackingWheelDeltaOffset + LayoutUnit(projectedInertialScrollDistance(initialWheelDelta)) : offset;
projectedScrollDestination = std::min(std::max(projectedScrollDestination, m_snapOffsets->first()), m_snapOffsets->last());
m_initialOffset = offset;
- m_targetOffset = closestSnapOffset<LayoutUnit>(*m_snapOffsets, projectedScrollDestination, initialWheelDelta);
+ m_targetOffset = closestSnapOffset<LayoutUnit, float>(*m_snapOffsets, projectedScrollDestination, initialWheelDelta);
if (m_initialOffset == m_targetOffset)
return;
Modified: trunk/Source/WebCore/rendering/RenderLayer.cpp (172648 => 172649)
--- trunk/Source/WebCore/rendering/RenderLayer.cpp 2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebCore/rendering/RenderLayer.cpp 2014-08-15 21:09:13 UTC (rev 172649)
@@ -3309,6 +3309,12 @@
// Composited scrolling may need to be enabled or disabled if the amount of overflow changed.
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();
+#endif
}
bool RenderLayer::overflowControlsIntersectRect(const IntRect& localRect) const
Modified: trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp (172648 => 172649)
--- trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp 2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp 2014-08-15 21:09:13 UTC (rev 172649)
@@ -3770,6 +3770,12 @@
scrollingGeometry.scrollableAreaSize = layer.visibleSize();
scrollingGeometry.contentSize = layer.contentsSize();
scrollingGeometry.reachableContentSize = layer.scrollableContentsSize();
+#if ENABLE(CSS_SCROLL_SNAP)
+ if (const Vector<LayoutUnit>* offsets = layer.horizontalSnapOffsets())
+ scrollingGeometry.horizontalSnapOffsets = *offsets;
+ if (const Vector<LayoutUnit>* offsets = layer.verticalSnapOffsets())
+ scrollingGeometry.verticalSnapOffsets = *offsets;
+#endif
scrollingCoordinator->updateOverflowScrollingNode(nodeID, backing->scrollingLayer(), backing->scrollingContentsLayer(), &scrollingGeometry);
}
}
Modified: trunk/Source/WebKit2/ChangeLog (172648 => 172649)
--- trunk/Source/WebKit2/ChangeLog 2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebKit2/ChangeLog 2014-08-15 21:09:13 UTC (rev 172649)
@@ -1,3 +1,27 @@
+2014-08-15 Wenson Hsieh <[email protected]>
+
+ Implement snapping behavior for iOS
+ https://bugs.webkit.org/show_bug.cgi?id=135769
+
+ Reviewed by Brent Fulgham.
+
+ 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.
+
2014-08-15 Gavin Barraclough <[email protected]>
Fix plugin visibility check.
Modified: trunk/Source/WebKit2/Shared/Scrolling/RemoteScrollingCoordinatorTransaction.cpp (172648 => 172649)
--- trunk/Source/WebKit2/Shared/Scrolling/RemoteScrollingCoordinatorTransaction.cpp 2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebKit2/Shared/Scrolling/RemoteScrollingCoordinatorTransaction.cpp 2014-08-15 21:09:13 UTC (rev 172649)
@@ -128,6 +128,10 @@
SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::ReachableContentsSize, reachableContentsSize)
SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::ScrollPosition, scrollPosition)
SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::ScrollOrigin, scrollOrigin)
+#if ENABLE(CSS_SCROLL_SNAP)
+ SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::HorizontalSnapOffsets, horizontalSnapOffsets)
+ SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::VerticalSnapOffsets, verticalSnapOffsets)
+#endif
SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::ScrollableAreaParams, scrollableAreaParameters)
SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::RequestedScrollPosition, requestedScrollPosition)
SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::RequestedScrollPosition, requestedScrollPositionRepresentsProgrammaticScroll)
@@ -193,6 +197,10 @@
SCROLLING_NODE_DECODE(ScrollingStateScrollingNode::ReachableContentsSize, FloatSize, setReachableContentsSize);
SCROLLING_NODE_DECODE(ScrollingStateScrollingNode::ScrollPosition, FloatPoint, setScrollPosition);
SCROLLING_NODE_DECODE(ScrollingStateScrollingNode::ScrollOrigin, IntPoint, setScrollOrigin);
+#if ENABLE(CSS_SCROLL_SNAP)
+ SCROLLING_NODE_DECODE(ScrollingStateScrollingNode::HorizontalSnapOffsets, Vector<float>, setHorizontalSnapOffsets);
+ SCROLLING_NODE_DECODE(ScrollingStateScrollingNode::VerticalSnapOffsets, Vector<float>, setVerticalSnapOffsets);
+#endif
SCROLLING_NODE_DECODE(ScrollingStateScrollingNode::ScrollableAreaParams, ScrollableAreaParameters, setScrollableAreaParameters);
if (node.hasChangedProperty(ScrollingStateScrollingNode::RequestedScrollPosition)) {
Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm (172648 => 172649)
--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm 2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm 2014-08-15 21:09:13 UTC (rev 172649)
@@ -83,6 +83,7 @@
#import "PrintInfo.h"
#import "ProcessThrottler.h"
#import "RemoteLayerTreeDrawingAreaProxy.h"
+#import "RemoteScrollingCoordinatorProxy.h"
#import "WKPDFView.h"
#import "WKScrollView.h"
#import "WKWebViewContentProviderRegistry.h"
@@ -1282,6 +1283,11 @@
if (scrollView.panGestureRecognizer.state == UIGestureRecognizerStateBegan)
[_contentView scrollViewWillStartPanOrPinchGesture];
[_contentView willStartZoomOrScroll];
+#if ENABLE(CSS_SCROLL_SNAP) && ENABLE(ASYNC_SCROLLING)
+ // FIXME: We will want to detect whether snapping will occur before beginning to drag. See WebPageProxy::didCommitLayerTree.
+ WebKit::RemoteScrollingCoordinatorProxy* coordinator = _page->scrollingCoordinatorProxy();
+ scrollView.decelerationRate = (coordinator && coordinator->shouldSetScrollViewDecelerationRateFast()) ? UIScrollViewDecelerationRateFast : UIScrollViewDecelerationRateNormal;
+#endif
}
- (void)_didFinishScrolling
@@ -1299,6 +1305,13 @@
// zooming. We'll animate to the right place once the zoom finishes.
if ([scrollView isZooming])
*targetContentOffset = [scrollView contentOffset];
+#if ENABLE(CSS_SCROLL_SNAP) && ENABLE(ASYNC_SCROLLING)
+ if (WebKit::RemoteScrollingCoordinatorProxy* coordinator = _page->scrollingCoordinatorProxy()) {
+ // FIXME: Here, I'm finding the maximum horizontal/vertical scroll offsets. There's probably a better way to do this.
+ CGSize maxScrollOffsets = CGSizeMake(scrollView.contentSize.width - scrollView.bounds.size.width, scrollView.contentSize.height - scrollView.bounds.size.height);
+ coordinator->adjustTargetContentOffsetForSnapping(maxScrollOffsets, velocity, targetContentOffset);
+ }
+#endif
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
Modified: trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h (172648 => 172649)
--- trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h 2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h 2014-08-15 21:09:13 UTC (rev 172649)
@@ -84,10 +84,18 @@
void scrollingTreeNodeWillStartPanGesture();
void scrollingTreeNodeWillStartScroll();
void scrollingTreeNodeDidEndScroll();
+#if ENABLE(CSS_SCROLL_SNAP)
+ void adjustTargetContentOffsetForSnapping(CGSize maxScrollDimensions, CGPoint velocity, CGPoint* targetContentOffset) const;
+ bool shouldSetScrollViewDecelerationRateFast() const;
#endif
+#endif
private:
void connectStateNodeLayers(WebCore::ScrollingStateTree&, const RemoteLayerTreeHost&);
+#if ENABLE(CSS_SCROLL_SNAP)
+ bool shouldSnapForMainFrameScrolling(WebCore::ScrollEventAxis) const;
+ float closestSnapOffsetForMainFrameScrolling(WebCore::ScrollEventAxis, float scrollDestination, float velocity) const;
+#endif
WebPageProxy& m_webPageProxy;
RefPtr<RemoteScrollingTree> m_scrollingTree;
Modified: trunk/Source/WebKit2/UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm (172648 => 172649)
--- trunk/Source/WebKit2/UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm 2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebKit2/UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm 2014-08-15 21:09:13 UTC (rev 172649)
@@ -37,6 +37,10 @@
#import <UIKit/UIScrollView.h>
#import <wtf/TemporaryChange.h>
+#if ENABLE(CSS_SCROLL_SNAP)
+#import <WebCore/AxisScrollSnapOffsets.h>
+#endif
+
using namespace WebCore;
@interface WKOverflowScrollViewDelegate : NSObject <UIScrollViewDelegate> {
@@ -73,6 +77,16 @@
_scrollingTreeNode->overflowScrollWillStart();
}
+#if ENABLE(CSS_SCROLL_SNAP)
+- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
+{
+ if (!_scrollingTreeNode->horizontalSnapOffsets().isEmpty())
+ targetContentOffset->x = closestSnapOffset<float, CGFloat>(_scrollingTreeNode->horizontalSnapOffsets(), targetContentOffset->x, velocity.x);
+ if (!_scrollingTreeNode->verticalSnapOffsets().isEmpty())
+ targetContentOffset->y = closestSnapOffset<float, CGFloat>(_scrollingTreeNode->verticalSnapOffsets(), targetContentOffset->y, velocity.y);
+}
+#endif
+
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)willDecelerate
{
if (_inUserInteraction && !willDecelerate) {
@@ -188,7 +202,12 @@
scrollView.contentInset = insets;
}
-
+
+#if ENABLE(CSS_SCROLL_SNAP)
+ // FIXME: If only one axis snaps in 2D scrolling, the other axis will decelerate fast as well. Is this what we want?
+ if (scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::HorizontalSnapOffsets) || scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::VerticalSnapOffsets))
+ scrollView.decelerationRate = horizontalSnapOffsets().size() || verticalSnapOffsets().size() ? UIScrollViewDecelerationRateFast : UIScrollViewDecelerationRateNormal;
+#endif
END_BLOCK_OBJC_EXCEPTIONS
}
}
Modified: trunk/Source/WebKit2/UIProcess/ios/RemoteScrollingCoordinatorProxyIOS.mm (172648 => 172649)
--- trunk/Source/WebKit2/UIProcess/ios/RemoteScrollingCoordinatorProxyIOS.mm 2014-08-15 21:04:31 UTC (rev 172648)
+++ trunk/Source/WebKit2/UIProcess/ios/RemoteScrollingCoordinatorProxyIOS.mm 2014-08-15 21:09:13 UTC (rev 172649)
@@ -23,20 +23,26 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "config.h"
-#include "RemoteScrollingCoordinatorProxy.h"
+#import "config.h"
+#import "RemoteScrollingCoordinatorProxy.h"
#if PLATFORM(IOS)
#if ENABLE(ASYNC_SCROLLING)
-#include "LayerRepresentation.h"
-#include "RemoteLayerTreeHost.h"
-#include "WebPageProxy.h"
-#include <WebCore/ScrollingStateFrameScrollingNode.h>
-#include <WebCore/ScrollingStateOverflowScrollingNode.h>
-#include <WebCore/ScrollingStateTree.h>
-#include <UIKit/UIView.h>
+#import "LayerRepresentation.h"
+#import "RemoteLayerTreeHost.h"
+#import "WebPageProxy.h"
+#import <UIKit/UIView.h>
+#import <WebCore/ScrollingStateFrameScrollingNode.h>
+#import <WebCore/ScrollingStateOverflowScrollingNode.h>
+#import <WebCore/ScrollingStateTree.h>
+#if ENABLE(CSS_SCROLL_SNAP)
+#import <WebCore/AxisScrollSnapOffsets.h>
+#import <WebCore/ScrollTypes.h>
+#import <WebCore/ScrollingTreeFrameScrollingNode.h>
+#endif
+
using namespace WebCore;
namespace WebKit {
@@ -106,6 +112,47 @@
m_webPageProxy.overflowScrollDidEndScroll();
}
+#if ENABLE(CSS_SCROLL_SNAP)
+void RemoteScrollingCoordinatorProxy::adjustTargetContentOffsetForSnapping(CGSize maxScrollOffsets, CGPoint velocity, CGPoint* targetContentOffset) const
+{
+ // The bounds checking with maxScrollOffsets is to ensure that we won't interfere with rubber-banding when scrolling to the edge of the page.
+ if (shouldSnapForMainFrameScrolling(WebCore::ScrollEventAxis::Horizontal) && targetContentOffset->x > 0 && targetContentOffset->x < maxScrollOffsets.width) {
+ float potentialSnapPosition = closestSnapOffsetForMainFrameScrolling(WebCore::ScrollEventAxis::Horizontal, targetContentOffset->x, velocity.x);
+ targetContentOffset->x = std::min<float>(maxScrollOffsets.width, potentialSnapPosition);
+ }
+ // FIXME: We need to account for how the top navigation bar changes in size.
+ if (shouldSnapForMainFrameScrolling(WebCore::ScrollEventAxis::Vertical) && targetContentOffset->y > 0 && targetContentOffset->y < maxScrollOffsets.height) {
+ float potentialSnapPosition = closestSnapOffsetForMainFrameScrolling(WebCore::ScrollEventAxis::Vertical, targetContentOffset->y, velocity.y);
+ targetContentOffset->y = std::min<float>(maxScrollOffsets.height, potentialSnapPosition);
+ }
+}
+
+bool RemoteScrollingCoordinatorProxy::shouldSetScrollViewDecelerationRateFast() const
+{
+ return shouldSnapForMainFrameScrolling(ScrollEventAxis::Horizontal) || shouldSnapForMainFrameScrolling(ScrollEventAxis::Vertical);
+}
+
+bool RemoteScrollingCoordinatorProxy::shouldSnapForMainFrameScrolling(ScrollEventAxis axis) const
+{
+ ScrollingTreeNode* root = m_scrollingTree->rootNode();
+ if (root && root->isFrameScrollingNode()) {
+ ScrollingTreeFrameScrollingNode* rootFrame = static_cast<ScrollingTreeFrameScrollingNode*>(root);
+ const Vector<float>& snapOffsets = axis == ScrollEventAxis::Horizontal ? rootFrame->horizontalSnapOffsets() : rootFrame->verticalSnapOffsets();
+ return snapOffsets.size() > 0;
+ }
+ return false;
+}
+
+float RemoteScrollingCoordinatorProxy::closestSnapOffsetForMainFrameScrolling(ScrollEventAxis axis, float scrollDestination, float velocity) const
+{
+ ScrollingTreeNode* root = m_scrollingTree->rootNode();
+ ASSERT(root && root->isFrameScrollingNode());
+ ScrollingTreeFrameScrollingNode* rootFrame = static_cast<ScrollingTreeFrameScrollingNode*>(root);
+ const Vector<float>& snapOffsets = axis == ScrollEventAxis::Horizontal ? rootFrame->horizontalSnapOffsets() : rootFrame->verticalSnapOffsets();
+ return closestSnapOffset<float, float>(snapOffsets, scrollDestination, velocity);
+}
+#endif
+
} // namespace WebKit