Diff
Modified: trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNodeDelegate.cpp (221752 => 221753)
--- trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNodeDelegate.cpp 2017-09-07 20:12:57 UTC (rev 221752)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNodeDelegate.cpp 2017-09-07 20:21:12 UTC (rev 221753)
@@ -51,6 +51,21 @@
return m_scrollingNode.lastCommittedScrollPosition();
}
+const FloatSize& ScrollingTreeScrollingNodeDelegate::totalContentsSize()
+{
+ return m_scrollingNode.totalContentsSize();
+}
+
+const FloatSize& ScrollingTreeScrollingNodeDelegate::reachableContentsSize()
+{
+ return m_scrollingNode.reachableContentsSize();
+}
+
+const IntPoint& ScrollingTreeScrollingNodeDelegate::scrollOrigin() const
+{
+ return m_scrollingNode.scrollOrigin();
+}
+
} // namespace WebCore
#endif // PLATFORM(IOS) && ENABLE(ASYNC_SCROLLING)
Modified: trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNodeDelegate.h (221752 => 221753)
--- trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNodeDelegate.h 2017-09-07 20:12:57 UTC (rev 221752)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNodeDelegate.h 2017-09-07 20:21:12 UTC (rev 221753)
@@ -30,6 +30,8 @@
namespace WebCore {
class FloatPoint;
+class FloatSize;
+class IntPoint;
class ScrollingTreeScrollingNode;
class ScrollingTree;
@@ -43,6 +45,9 @@
protected:
WEBCORE_EXPORT ScrollingTree& scrollingTree() const;
WEBCORE_EXPORT FloatPoint lastCommittedScrollPosition() const;
+ WEBCORE_EXPORT const FloatSize& totalContentsSize();
+ WEBCORE_EXPORT const FloatSize& reachableContentsSize();
+ WEBCORE_EXPORT const IntPoint& scrollOrigin() const;
private:
ScrollingTreeScrollingNode& m_scrollingNode;
Modified: trunk/Source/WebKit/ChangeLog (221752 => 221753)
--- trunk/Source/WebKit/ChangeLog 2017-09-07 20:12:57 UTC (rev 221752)
+++ trunk/Source/WebKit/ChangeLog 2017-09-07 20:21:12 UTC (rev 221753)
@@ -1,3 +1,56 @@
+2017-09-07 Frederic Wang <[email protected]>
+
+ Move more code from ScrollingTreeScrollingNodeDelegateIOS to ScrollingTreeScrollingNodeDelegate
+ https://bugs.webkit.org/show_bug.cgi?id=174130
+
+ Reviewed by Simon Fraser.
+
+ * UIProcess/RemoteLayerTree/ios/ScrollingTreeOverflowScrollingNodeIOS.h: Remove some members,
+ headers and pre-declaration that are moved into the delegate.
+ (WebKit::ScrollingTreeOverflowScrollingNodeIOS::scrollLayer): Deleted.
+ * UIProcess/RemoteLayerTree/ios/ScrollingTreeOverflowScrollingNodeIOS.mm: Remove some headers and
+ WKOverflowScrollViewDelegate since they are moved into the delegate file. Also fix the
+ comment to closing the WebKit namespace.
+ (WebKit::ScrollingTreeOverflowScrollingNodeIOS::~ScrollingTreeOverflowScrollingNodeIOS):
+ Remove some code moved into the delegate and call the corresponding helper function to
+ preserve the current behavior.
+ (WebKit::ScrollingTreeOverflowScrollingNodeIOS::commitStateBeforeChildren): Ditto.
+ Note that it is only necessary to cast the parameter to a ScrollingStateTreeNode.
+ (WebKit::ScrollingTreeOverflowScrollingNodeIOS::commitStateAfterChildren): Ditto.
+ (WebKit::ScrollingTreeOverflowScrollingNodeIOS::updateLayersAfterAncestorChange): Ditto.
+ (WebKit::ScrollingTreeOverflowScrollingNodeIOS::scrollPosition): Ditto.
+ (WebKit::ScrollingTreeOverflowScrollingNodeIOS::setScrollLayerPosition): Ditto.
+ (-[WKOverflowScrollViewDelegate initWithScrollingTreeNodeDelegate:]): Deleted.
+ (-[WKOverflowScrollViewDelegate scrollViewDidScroll:]): Deleted.
+ (-[WKOverflowScrollViewDelegate scrollViewWillBeginDragging:]): Deleted.
+ (-[WKOverflowScrollViewDelegate scrollViewWillEndDragging:withVelocity:targetContentOffset:]): Deleted.
+ (-[WKOverflowScrollViewDelegate scrollViewDidEndDragging:willDecelerate:]): Deleted.
+ (-[WKOverflowScrollViewDelegate scrollViewDidEndDecelerating:]): Deleted.
+ * UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.h: Import headers and members
+ from ScrollingTreeOverflowScrollingNodeIOS. Define new helper functions for the code imported
+ from ScrollingTreeOverflowScrollingNodeIOS. Remove the friendship with
+ ScrollingTreeOverflowScrollingNodeIOS and only makes public the function used by that class.
+ (WebKit::ScrollingTreeScrollingNodeDelegateIOS::scrollLayer): This function is moved from
+ ScrollingTreeOverflowScrollingNodeIOS.
+ * UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.mm: Add headers,
+ WKOverflowScrollViewDelegate (renamed WKScrollingNodeScrollViewDelegate) and some helper code
+ imported from ScrollingTreeOverflowScrollingNodeIOS.
+ (-[WKScrollingNodeScrollViewDelegate scrollViewDidScroll:]): Moved from
+ ScrollingTreeOverflowScrollingNodeIOS.
+ (-[WKScrollingNodeScrollViewDelegate scrollViewWillBeginDragging:]): Ditto.
+ (-[WKScrollingNodeScrollViewDelegate scrollViewWillEndDragging:withVelocity:targetContentOffset:]): Ditto.
+ (-[WKScrollingNodeScrollViewDelegate scrollViewDidEndDragging:willDecelerate:]): Ditto.
+ (-[WKScrollingNodeScrollViewDelegate scrollViewDidEndDecelerating:]): Ditto.
+ (WebKit::ScrollingTreeScrollingNodeDelegateIOS::~ScrollingTreeScrollingNodeDelegateIOS):
+ Import code from ScrollingTreeOverflowScrollingNodeIOS.
+ (WebKit::ScrollingTreeScrollingNodeDelegateIOS::resetScrollViewDelegate): New helper function
+ importing code from ScrollingTreeOverflowScrollingNodeIOS.
+ (WebKit::ScrollingTreeScrollingNodeDelegateIOS::commitStateBeforeChildren): Ditto.
+ (WebKit::ScrollingTreeScrollingNodeDelegateIOS::commitStateAfterChildren): Ditto.
+ (WebKit::ScrollingTreeScrollingNodeDelegateIOS::updateLayersAfterAncestorChange): Ditto.
+ (WebKit::ScrollingTreeScrollingNodeDelegateIOS::scrollPosition): Ditto.
+ (WebKit::ScrollingTreeScrollingNodeDelegateIOS::setScrollLayerPosition): Ditto.
+
2017-09-07 Chris Dumez <[email protected]>
[WK2] Notify client when downloads are redirected
Modified: trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeOverflowScrollingNodeIOS.h (221752 => 221753)
--- trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeOverflowScrollingNodeIOS.h 2017-09-07 20:12:57 UTC (rev 221752)
+++ trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeOverflowScrollingNodeIOS.h 2017-09-07 20:21:12 UTC (rev 221753)
@@ -27,12 +27,8 @@
#if ENABLE(ASYNC_SCROLLING) && PLATFORM(IOS)
-#include <WebCore/ScrollingCoordinator.h>
#include <WebCore/ScrollingTreeOverflowScrollingNode.h>
-OBJC_CLASS CALayer;
-OBJC_CLASS WKOverflowScrollViewDelegate;
-
namespace WebKit {
class ScrollingTreeScrollingNodeDelegateIOS;
@@ -42,8 +38,6 @@
static Ref<ScrollingTreeOverflowScrollingNodeIOS> create(WebCore::ScrollingTree&, WebCore::ScrollingNodeID);
virtual ~ScrollingTreeOverflowScrollingNodeIOS();
- CALayer *scrollLayer() const { return m_scrollLayer.get(); }
-
private:
ScrollingTreeOverflowScrollingNodeIOS(WebCore::ScrollingTree&, WebCore::ScrollingNodeID);
@@ -61,10 +55,6 @@
void handleWheelEvent(const WebCore::PlatformWheelEvent&) override { }
- RetainPtr<CALayer> m_scrollLayer;
- RetainPtr<CALayer> m_scrolledContentsLayer;
-
- RetainPtr<WKOverflowScrollViewDelegate> m_scrollViewDelegate;
std::unique_ptr<ScrollingTreeScrollingNodeDelegateIOS> m_scrollingNodeDelegate;
};
Modified: trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeOverflowScrollingNodeIOS.mm (221752 => 221753)
--- trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeOverflowScrollingNodeIOS.mm 2017-09-07 20:12:57 UTC (rev 221752)
+++ trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeOverflowScrollingNodeIOS.mm 2017-09-07 20:21:12 UTC (rev 221753)
@@ -29,109 +29,12 @@
#if PLATFORM(IOS)
#if ENABLE(ASYNC_SCROLLING)
-#import <QuartzCore/QuartzCore.h>
-#import <UIKit/UIPanGestureRecognizer.h>
-#import <UIKit/UIScrollView.h>
+#import "ScrollingTreeScrollingNodeDelegateIOS.h"
+
#import <WebCore/ScrollingStateOverflowScrollingNode.h>
-#import <WebCore/ScrollingTree.h>
-#import <wtf/BlockObjCExceptions.h>
-#import <wtf/SetForScope.h>
-#if ENABLE(CSS_SCROLL_SNAP)
-#import <WebCore/AxisScrollSnapOffsets.h>
-#import <WebCore/ScrollSnapOffsetsInfo.h>
-#endif
-
-#import "ScrollingTreeScrollingNodeDelegateIOS.h"
-
using namespace WebCore;
-@interface WKOverflowScrollViewDelegate : NSObject <UIScrollViewDelegate> {
- WebKit::ScrollingTreeScrollingNodeDelegateIOS* _scrollingTreeNodeDelegate;
-}
-
-@property (nonatomic, getter=_isInUserInteraction) BOOL inUserInteraction;
-
-- (instancetype)initWithScrollingTreeNodeDelegate:(WebKit::ScrollingTreeScrollingNodeDelegateIOS*)delegate;
-
-@end
-
-@implementation WKOverflowScrollViewDelegate
-
-- (instancetype)initWithScrollingTreeNodeDelegate:(WebKit::ScrollingTreeScrollingNodeDelegateIOS*)delegate
-{
- if ((self = [super init]))
- _scrollingTreeNodeDelegate = delegate;
-
- return self;
-}
-
-- (void)scrollViewDidScroll:(UIScrollView *)scrollView
-{
- _scrollingTreeNodeDelegate->scrollViewDidScroll(scrollView.contentOffset, _inUserInteraction);
-}
-
-- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
-{
- _inUserInteraction = YES;
-
- if (scrollView.panGestureRecognizer.state == UIGestureRecognizerStateBegan)
- _scrollingTreeNodeDelegate->scrollViewWillStartPanGesture();
- _scrollingTreeNodeDelegate->scrollWillStart();
-}
-
-#if ENABLE(CSS_SCROLL_SNAP)
-- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
-{
- CGFloat horizontalTarget = targetContentOffset->x;
- CGFloat verticalTarget = targetContentOffset->y;
-
- unsigned originalHorizontalSnapPosition = _scrollingTreeNodeDelegate->scrollingNode().currentHorizontalSnapPointIndex();
- unsigned originalVerticalSnapPosition = _scrollingTreeNodeDelegate->scrollingNode().currentVerticalSnapPointIndex();
-
- if (!_scrollingTreeNodeDelegate->scrollingNode().horizontalSnapOffsets().isEmpty()) {
- unsigned index;
- float potentialSnapPosition = closestSnapOffset(_scrollingTreeNodeDelegate->scrollingNode().horizontalSnapOffsets(), _scrollingTreeNodeDelegate->scrollingNode().horizontalSnapOffsetRanges(), horizontalTarget, velocity.x, index);
- _scrollingTreeNodeDelegate->scrollingNode().setCurrentHorizontalSnapPointIndex(index);
- if (horizontalTarget >= 0 && horizontalTarget <= scrollView.contentSize.width)
- targetContentOffset->x = potentialSnapPosition;
- }
-
- if (!_scrollingTreeNodeDelegate->scrollingNode().verticalSnapOffsets().isEmpty()) {
- unsigned index;
- float potentialSnapPosition = closestSnapOffset(_scrollingTreeNodeDelegate->scrollingNode().verticalSnapOffsets(), _scrollingTreeNodeDelegate->scrollingNode().verticalSnapOffsetRanges(), verticalTarget, velocity.y, index);
- _scrollingTreeNodeDelegate->scrollingNode().setCurrentVerticalSnapPointIndex(index);
- if (verticalTarget >= 0 && verticalTarget <= scrollView.contentSize.height)
- targetContentOffset->y = potentialSnapPosition;
- }
-
- if (originalHorizontalSnapPosition != _scrollingTreeNodeDelegate->scrollingNode().currentHorizontalSnapPointIndex()
- || originalVerticalSnapPosition != _scrollingTreeNodeDelegate->scrollingNode().currentVerticalSnapPointIndex()) {
- _scrollingTreeNodeDelegate->currentSnapPointIndicesDidChange(_scrollingTreeNodeDelegate->scrollingNode().currentHorizontalSnapPointIndex(), _scrollingTreeNodeDelegate->scrollingNode().currentVerticalSnapPointIndex());
- }
-}
-#endif
-
-- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)willDecelerate
-{
- if (_inUserInteraction && !willDecelerate) {
- _inUserInteraction = NO;
- _scrollingTreeNodeDelegate->scrollViewDidScroll(scrollView.contentOffset, _inUserInteraction);
- _scrollingTreeNodeDelegate->scrollDidEnd();
- }
-}
-
-- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
-{
- if (_inUserInteraction) {
- _inUserInteraction = NO;
- _scrollingTreeNodeDelegate->scrollViewDidScroll(scrollView.contentOffset, _inUserInteraction);
- _scrollingTreeNodeDelegate->scrollDidEnd();
- }
-}
-
-@end
-
namespace WebKit {
Ref<ScrollingTreeOverflowScrollingNodeIOS> ScrollingTreeOverflowScrollingNodeIOS::create(WebCore::ScrollingTree& scrollingTree, WebCore::ScrollingNodeID nodeID)
@@ -147,125 +50,36 @@
ScrollingTreeOverflowScrollingNodeIOS::~ScrollingTreeOverflowScrollingNodeIOS()
{
- BEGIN_BLOCK_OBJC_EXCEPTIONS
- if (UIScrollView *scrollView = (UIScrollView *)[scrollLayer() delegate]) {
- ASSERT([scrollView isKindOfClass:[UIScrollView self]]);
- // The scrollView may have been adopted by another node, so only clear the delegate if it's ours.
- if (scrollView.delegate == m_scrollViewDelegate.get())
- scrollView.delegate = nil;
- }
- END_BLOCK_OBJC_EXCEPTIONS
-
- // WKOverflowScrollViewDelegate holds a pointer to ScrollingTreeScrollingNodeDelegateIOS, so we ensure it is destroyed first.
- m_scrollViewDelegate.clear();
- m_scrollingNodeDelegate.reset();
}
void ScrollingTreeOverflowScrollingNodeIOS::commitStateBeforeChildren(const WebCore::ScrollingStateNode& stateNode)
{
- if (stateNode.hasChangedProperty(ScrollingStateScrollingNode::ScrollLayer)) {
- BEGIN_BLOCK_OBJC_EXCEPTIONS
- if (UIScrollView *scrollView = (UIScrollView *)[scrollLayer() delegate]) {
- ASSERT([scrollView isKindOfClass:[UIScrollView self]]);
- scrollView.delegate = nil;
- }
- END_BLOCK_OBJC_EXCEPTIONS
- }
+ if (stateNode.hasChangedProperty(ScrollingStateScrollingNode::ScrollLayer))
+ m_scrollingNodeDelegate->resetScrollViewDelegate();
ScrollingTreeOverflowScrollingNode::commitStateBeforeChildren(stateNode);
-
- const auto& scrollingStateNode = downcast<ScrollingStateOverflowScrollingNode>(stateNode);
- if (scrollingStateNode.hasChangedProperty(ScrollingStateNode::ScrollLayer))
- m_scrollLayer = scrollingStateNode.layer();
-
- if (scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::ScrolledContentsLayer))
- m_scrolledContentsLayer = scrollingStateNode.scrolledContentsLayer();
+ m_scrollingNodeDelegate->commitStateBeforeChildren(downcast<ScrollingStateScrollingNode>(stateNode));
}
void ScrollingTreeOverflowScrollingNodeIOS::commitStateAfterChildren(const ScrollingStateNode& stateNode)
{
ScrollingTreeOverflowScrollingNode::commitStateAfterChildren(stateNode);
-
- SetForScope<bool> updatingChange(m_scrollingNodeDelegate->m_updatingFromStateNode, true);
-
- const auto& scrollingStateNode = downcast<ScrollingStateOverflowScrollingNode>(stateNode);
-
- if (scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::ScrollLayer)
- || scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::TotalContentsSize)
- || scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::ReachableContentsSize)
- || scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::ScrollPosition)
- || scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::ScrollOrigin)) {
- BEGIN_BLOCK_OBJC_EXCEPTIONS
- UIScrollView *scrollView = (UIScrollView *)[scrollLayer() delegate];
- ASSERT([scrollView isKindOfClass:[UIScrollView self]]);
-
- if (scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::ScrollLayer)) {
- if (!m_scrollViewDelegate)
- m_scrollViewDelegate = adoptNS([[WKOverflowScrollViewDelegate alloc] initWithScrollingTreeNodeDelegate:m_scrollingNodeDelegate.get()]);
-
- scrollView.scrollsToTop = NO;
- scrollView.delegate = m_scrollViewDelegate.get();
- }
-
- bool recomputeInsets = scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::TotalContentsSize);
- if (scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::ReachableContentsSize)) {
- scrollView.contentSize = scrollingStateNode.reachableContentsSize();
- recomputeInsets = true;
- }
-
- if ((scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::ScrollPosition)
- || scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::ScrollOrigin))
- && ![m_scrollViewDelegate _isInUserInteraction]) {
- scrollView.contentOffset = scrollingStateNode.scrollPosition() + scrollOrigin();
- recomputeInsets = true;
- }
-
- if (recomputeInsets) {
- UIEdgeInsets insets = UIEdgeInsetsMake(0, 0, 0, 0);
- // With RTL or bottom-to-top scrolling (non-zero origin), we need extra space on the left or top.
- if (scrollOrigin().x())
- insets.left = reachableContentsSize().width() - totalContentsSize().width();
-
- if (scrollOrigin().y())
- insets.top = reachableContentsSize().height() - totalContentsSize().height();
-
- 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
- }
+ m_scrollingNodeDelegate->commitStateAfterChildren(downcast<ScrollingStateScrollingNode>(stateNode));
}
void ScrollingTreeOverflowScrollingNodeIOS::updateLayersAfterAncestorChange(const ScrollingTreeNode& changedNode, const FloatRect& fixedPositionRect, const FloatSize& cumulativeDelta)
{
- if (!m_children)
- return;
-
- FloatSize scrollDelta = lastCommittedScrollPosition() - scrollPosition();
-
- for (auto& child : *m_children)
- child->updateLayersAfterAncestorChange(changedNode, fixedPositionRect, cumulativeDelta + scrollDelta);
+ m_scrollingNodeDelegate->updateLayersAfterAncestorChange(changedNode, fixedPositionRect, cumulativeDelta);
}
FloatPoint ScrollingTreeOverflowScrollingNodeIOS::scrollPosition() const
{
- BEGIN_BLOCK_OBJC_EXCEPTIONS
- UIScrollView *scrollView = (UIScrollView *)[scrollLayer() delegate];
- ASSERT([scrollView isKindOfClass:[UIScrollView self]]);
- return [scrollView contentOffset];
- END_BLOCK_OBJC_EXCEPTIONS
+ return m_scrollingNodeDelegate->scrollPosition();
}
void ScrollingTreeOverflowScrollingNodeIOS::setScrollLayerPosition(const FloatPoint& scrollPosition, const FloatRect&)
{
- [m_scrollLayer setPosition:CGPointMake(-scrollPosition.x() + scrollOrigin().x(), -scrollPosition.y() + scrollOrigin().y())];
-
- m_scrollingNodeDelegate->updateChildNodesAfterScroll(scrollPosition);
+ m_scrollingNodeDelegate->setScrollLayerPosition(scrollPosition);
}
void ScrollingTreeOverflowScrollingNodeIOS::updateLayersAfterDelegatedScroll(const FloatPoint& scrollPosition)
@@ -273,7 +87,7 @@
m_scrollingNodeDelegate->updateChildNodesAfterScroll(scrollPosition);
}
-} // namespace WebCore
+} // namespace WebKit
#endif // ENABLE(ASYNC_SCROLLING)
#endif // PLATFORM(IOS)
Modified: trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.h (221752 => 221753)
--- trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.h 2017-09-07 20:12:57 UTC (rev 221752)
+++ trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.h 2017-09-07 20:21:12 UTC (rev 221753)
@@ -27,11 +27,19 @@
#if PLATFORM(IOS) && ENABLE(ASYNC_SCROLLING)
+#include <UIKit/UIScrollView.h>
+#include <WebCore/ScrollingCoordinator.h>
+#include <WebCore/ScrollingTreeScrollingNode.h>
#include <WebCore/ScrollingTreeScrollingNodeDelegate.h>
+OBJC_CLASS CALayer;
+OBJC_CLASS WKScrollingNodeScrollViewDelegate;
+
namespace WebCore {
class FloatPoint;
+class FloatRect;
+class FloatSize;
class ScrollingTreeScrollingNode;
}
@@ -38,11 +46,7 @@
namespace WebKit {
-class ScrollingTreeOverflowScrollingNodeIOS;
-
class ScrollingTreeScrollingNodeDelegateIOS : public WebCore::ScrollingTreeScrollingNodeDelegate {
- friend class ScrollingTreeOverflowScrollingNodeIOS;
-
public:
explicit ScrollingTreeScrollingNodeDelegateIOS(WebCore::ScrollingTreeScrollingNode&);
~ScrollingTreeScrollingNodeDelegateIOS() final;
@@ -52,13 +56,33 @@
void scrollViewWillStartPanGesture() const;
void scrollViewDidScroll(const WebCore::FloatPoint& scrollPosition, bool inUserInteraction) const;
void currentSnapPointIndicesDidChange(unsigned horizontal, unsigned vertical) const;
+ CALayer *scrollLayer() const { return m_scrollLayer.get(); }
-private:
+ void resetScrollViewDelegate();
+ void commitStateBeforeChildren(const WebCore::ScrollingStateScrollingNode&);
+ void commitStateAfterChildren(const WebCore::ScrollingStateScrollingNode&);
+ void updateLayersAfterAncestorChange(const WebCore::ScrollingTreeNode& changedNode, const WebCore::FloatRect& fixedPositionRect, const WebCore::FloatSize& cumulativeDelta);
+ WebCore::FloatPoint scrollPosition() const;
+ void setScrollLayerPosition(const WebCore::FloatPoint&);
void updateChildNodesAfterScroll(const WebCore::FloatPoint& scrollPosition);
- bool m_updatingFromStateNode;
+private:
+ RetainPtr<CALayer> m_scrollLayer;
+ RetainPtr<CALayer> m_scrolledContentsLayer;
+ RetainPtr<WKScrollingNodeScrollViewDelegate> m_scrollViewDelegate;
+ bool m_updatingFromStateNode { false };
};
} // namespace WebKit
+@interface WKScrollingNodeScrollViewDelegate : NSObject <UIScrollViewDelegate> {
+ WebKit::ScrollingTreeScrollingNodeDelegateIOS* _scrollingTreeNodeDelegate;
+}
+
+@property (nonatomic, getter=_isInUserInteraction) BOOL inUserInteraction;
+
+- (instancetype)initWithScrollingTreeNodeDelegate:(WebKit::ScrollingTreeScrollingNodeDelegateIOS*)delegate;
+
+@end
+
#endif // PLATFORM(IOS) && ENABLE(ASYNC_SCROLLING)
Modified: trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.mm (221752 => 221753)
--- trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.mm 2017-09-07 20:12:57 UTC (rev 221752)
+++ trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.mm 2017-09-07 20:21:12 UTC (rev 221753)
@@ -28,12 +28,99 @@
#if PLATFORM(IOS) && ENABLE(ASYNC_SCROLLING)
+#import <QuartzCore/QuartzCore.h>
+#import <UIKit/UIPanGestureRecognizer.h>
+#import <UIKit/UIScrollView.h>
+#import <WebCore/ScrollingStateOverflowScrollingNode.h>
#import <WebCore/ScrollingTree.h>
#import <WebCore/ScrollingTreeFrameScrollingNode.h>
#import <WebCore/ScrollingTreeScrollingNode.h>
+#import <wtf/BlockObjCExceptions.h>
+#import <wtf/SetForScope.h>
+#if ENABLE(CSS_SCROLL_SNAP)
+#import <WebCore/AxisScrollSnapOffsets.h>
+#import <WebCore/ScrollSnapOffsetsInfo.h>
+#endif
+
using namespace WebCore;
+@implementation WKScrollingNodeScrollViewDelegate
+
+- (instancetype)initWithScrollingTreeNodeDelegate:(WebKit::ScrollingTreeScrollingNodeDelegateIOS*)delegate
+{
+ if ((self = [super init]))
+ _scrollingTreeNodeDelegate = delegate;
+
+ return self;
+}
+
+- (void)scrollViewDidScroll:(UIScrollView *)scrollView
+{
+ _scrollingTreeNodeDelegate->scrollViewDidScroll(scrollView.contentOffset, _inUserInteraction);
+}
+
+- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
+{
+ _inUserInteraction = YES;
+
+ if (scrollView.panGestureRecognizer.state == UIGestureRecognizerStateBegan)
+ _scrollingTreeNodeDelegate->scrollViewWillStartPanGesture();
+ _scrollingTreeNodeDelegate->scrollWillStart();
+}
+
+#if ENABLE(CSS_SCROLL_SNAP)
+- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
+{
+ CGFloat horizontalTarget = targetContentOffset->x;
+ CGFloat verticalTarget = targetContentOffset->y;
+
+ unsigned originalHorizontalSnapPosition = _scrollingTreeNodeDelegate->scrollingNode().currentHorizontalSnapPointIndex();
+ unsigned originalVerticalSnapPosition = _scrollingTreeNodeDelegate->scrollingNode().currentVerticalSnapPointIndex();
+
+ if (!_scrollingTreeNodeDelegate->scrollingNode().horizontalSnapOffsets().isEmpty()) {
+ unsigned index;
+ float potentialSnapPosition = closestSnapOffset(_scrollingTreeNodeDelegate->scrollingNode().horizontalSnapOffsets(), _scrollingTreeNodeDelegate->scrollingNode().horizontalSnapOffsetRanges(), horizontalTarget, velocity.x, index);
+ _scrollingTreeNodeDelegate->scrollingNode().setCurrentHorizontalSnapPointIndex(index);
+ if (horizontalTarget >= 0 && horizontalTarget <= scrollView.contentSize.width)
+ targetContentOffset->x = potentialSnapPosition;
+ }
+
+ if (!_scrollingTreeNodeDelegate->scrollingNode().verticalSnapOffsets().isEmpty()) {
+ unsigned index;
+ float potentialSnapPosition = closestSnapOffset(_scrollingTreeNodeDelegate->scrollingNode().verticalSnapOffsets(), _scrollingTreeNodeDelegate->scrollingNode().verticalSnapOffsetRanges(), verticalTarget, velocity.y, index);
+ _scrollingTreeNodeDelegate->scrollingNode().setCurrentVerticalSnapPointIndex(index);
+ if (verticalTarget >= 0 && verticalTarget <= scrollView.contentSize.height)
+ targetContentOffset->y = potentialSnapPosition;
+ }
+
+ if (originalHorizontalSnapPosition != _scrollingTreeNodeDelegate->scrollingNode().currentHorizontalSnapPointIndex()
+ || originalVerticalSnapPosition != _scrollingTreeNodeDelegate->scrollingNode().currentVerticalSnapPointIndex()) {
+ _scrollingTreeNodeDelegate->currentSnapPointIndicesDidChange(_scrollingTreeNodeDelegate->scrollingNode().currentHorizontalSnapPointIndex(), _scrollingTreeNodeDelegate->scrollingNode().currentVerticalSnapPointIndex());
+ }
+}
+#endif
+
+- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)willDecelerate
+{
+ if (_inUserInteraction && !willDecelerate) {
+ _inUserInteraction = NO;
+ _scrollingTreeNodeDelegate->scrollViewDidScroll(scrollView.contentOffset, _inUserInteraction);
+ _scrollingTreeNodeDelegate->scrollDidEnd();
+ }
+}
+
+- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
+{
+ if (_inUserInteraction) {
+ _inUserInteraction = NO;
+ _scrollingTreeNodeDelegate->scrollViewDidScroll(scrollView.contentOffset, _inUserInteraction);
+ _scrollingTreeNodeDelegate->scrollDidEnd();
+ }
+}
+
+@end
+
namespace WebKit {
ScrollingTreeScrollingNodeDelegateIOS::ScrollingTreeScrollingNodeDelegateIOS(ScrollingTreeScrollingNode& scrollingNode)
@@ -44,8 +131,115 @@
ScrollingTreeScrollingNodeDelegateIOS::~ScrollingTreeScrollingNodeDelegateIOS()
{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ if (UIScrollView *scrollView = (UIScrollView *)[scrollLayer() delegate]) {
+ ASSERT([scrollView isKindOfClass:[UIScrollView self]]);
+ // The scrollView may have been adopted by another node, so only clear the delegate if it's ours.
+ if (scrollView.delegate == m_scrollViewDelegate.get())
+ scrollView.delegate = nil;
+ }
+ END_BLOCK_OBJC_EXCEPTIONS
}
+void ScrollingTreeScrollingNodeDelegateIOS::resetScrollViewDelegate()
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ if (UIScrollView *scrollView = (UIScrollView *)[scrollLayer() delegate]) {
+ ASSERT([scrollView isKindOfClass:[UIScrollView self]]);
+ scrollView.delegate = nil;
+ }
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+void ScrollingTreeScrollingNodeDelegateIOS::commitStateBeforeChildren(const ScrollingStateScrollingNode& scrollingStateNode)
+{
+ if (scrollingStateNode.hasChangedProperty(ScrollingStateNode::ScrollLayer))
+ m_scrollLayer = scrollingStateNode.layer();
+
+ if (scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::ScrolledContentsLayer))
+ m_scrolledContentsLayer = scrollingStateNode.scrolledContentsLayer();
+}
+
+void ScrollingTreeScrollingNodeDelegateIOS::commitStateAfterChildren(const ScrollingStateScrollingNode& scrollingStateNode)
+{
+ SetForScope<bool> updatingChange(m_updatingFromStateNode, true);
+ if (scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::ScrollLayer)
+ || scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::TotalContentsSize)
+ || scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::ReachableContentsSize)
+ || scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::ScrollPosition)
+ || scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::ScrollOrigin)) {
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ UIScrollView *scrollView = (UIScrollView *)[scrollLayer() delegate];
+ ASSERT([scrollView isKindOfClass:[UIScrollView self]]);
+
+ if (scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::ScrollLayer)) {
+ if (!m_scrollViewDelegate)
+ m_scrollViewDelegate = adoptNS([[WKScrollingNodeScrollViewDelegate alloc] initWithScrollingTreeNodeDelegate:this]);
+
+ scrollView.scrollsToTop = NO;
+ scrollView.delegate = m_scrollViewDelegate.get();
+ }
+
+ bool recomputeInsets = scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::TotalContentsSize);
+ if (scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::ReachableContentsSize)) {
+ scrollView.contentSize = scrollingStateNode.reachableContentsSize();
+ recomputeInsets = true;
+ }
+
+ if ((scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::ScrollPosition)
+ || scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::ScrollOrigin))
+ && ![m_scrollViewDelegate _isInUserInteraction]) {
+ scrollView.contentOffset = scrollingStateNode.scrollPosition() + scrollOrigin();
+ recomputeInsets = true;
+ }
+
+ if (recomputeInsets) {
+ UIEdgeInsets insets = UIEdgeInsetsMake(0, 0, 0, 0);
+ // With RTL or bottom-to-top scrolling (non-zero origin), we need extra space on the left or top.
+ if (scrollOrigin().x())
+ insets.left = reachableContentsSize().width() - totalContentsSize().width();
+
+ if (scrollOrigin().y())
+ insets.top = reachableContentsSize().height() - totalContentsSize().height();
+
+ 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 = scrollingNode().horizontalSnapOffsets().size() || scrollingNode().verticalSnapOffsets().size() ? UIScrollViewDecelerationRateFast : UIScrollViewDecelerationRateNormal;
+#endif
+ END_BLOCK_OBJC_EXCEPTIONS
+ }
+}
+
+void ScrollingTreeScrollingNodeDelegateIOS::updateLayersAfterAncestorChange(const ScrollingTreeNode& changedNode, const FloatRect& fixedPositionRect, const FloatSize& cumulativeDelta)
+{
+ if (!scrollingNode().children())
+ return;
+
+ FloatSize scrollDelta = lastCommittedScrollPosition() - scrollingNode().scrollPosition();
+
+ for (auto& child : *scrollingNode().children())
+ child->updateLayersAfterAncestorChange(changedNode, fixedPositionRect, cumulativeDelta + scrollDelta);
+}
+
+FloatPoint ScrollingTreeScrollingNodeDelegateIOS::scrollPosition() const
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ UIScrollView *scrollView = (UIScrollView *)[scrollLayer() delegate];
+ ASSERT([scrollView isKindOfClass:[UIScrollView self]]);
+ return [scrollView contentOffset];
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+void ScrollingTreeScrollingNodeDelegateIOS::setScrollLayerPosition(const FloatPoint& scrollPosition)
+{
+ [m_scrollLayer setPosition:CGPointMake(scrollPosition.x() + scrollOrigin().x(), scrollPosition.y() + scrollOrigin().y())];
+ updateChildNodesAfterScroll(scrollPosition);
+}
+
void ScrollingTreeScrollingNodeDelegateIOS::updateChildNodesAfterScroll(const FloatPoint& scrollPosition)
{
if (!scrollingNode().children())