WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
scrollend-programmatic-for-review
scrollend-programmatic-011.diff (text/plain), 51.25 KB, created by
cathiechen
on 2020-04-10 00:41:44 PDT
(
hide
)
Description:
scrollend-programmatic-for-review
Filename:
MIME Type:
Creator:
cathiechen
Created:
2020-04-10 00:41:44 PDT
Size:
51.25 KB
patch
obsolete
>diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index 215ece0b04..d47897411d 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,15 @@ >+2020-04-09 Cathie Chen <cathiechen@igalia.com> >+ >+ Add support for scrollend event of programmatic scrolling >+ https://bugs.webkit.org/show_bug.cgi?id=209134 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * platform/ios/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-for-scrollIntoView-expected.txt: Added. >+ Test fails on iOS because the FrameView scroll position is no clamped, see bug: 179735. >+ * platform/mac-wk1/TestExpectations: Test fails on mac-wk1 because the FrameView smooth scrolling is not functional. See bug: 191357. >+ * TestExpectations: Enable the test for programmatic scrolling scrollend event. >+ > 2020-04-09 Cathie Chen <cathiechen@igalia.com> > > Import test for programmatic scrolling scrollend event >diff --git a/LayoutTests/TestExpectations b/LayoutTests/TestExpectations >index 915051fc32..02b1dde7a3 100644 >--- a/LayoutTests/TestExpectations >+++ b/LayoutTests/TestExpectations >@@ -165,7 +165,15 @@ http/tests/in-app-browser-privacy/ [ Skip ] > fast/harness/uiscriptcontroller [ Skip ] > > # Only iOS has an implementation of UIScriptController::sendEventStream(). >-imported/w3c/web-platform-tests/dom/events/scrolling [ Skip ] >+imported/w3c/web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-document.html [ Skip ] >+imported/w3c/web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-element-with-overscroll-behavior.html [ Skip ] >+imported/w3c/web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-scrolled-element.html [ Skip ] >+imported/w3c/web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-window.html [ Skip ] >+imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-after-snap.html [ Skip ] >+imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-document.html [ Skip ] >+imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-element-with-overscroll-behavior.html [ Skip ] >+imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-scrolled-element.html [ Skip ] >+imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-window.html [ Skip ] > > # This test only makes sense on Mac > fast/attachment/attachment-subtitle-resize.html [ Skip ] >diff --git a/LayoutTests/imported/w3c/ChangeLog b/LayoutTests/imported/w3c/ChangeLog >index d1d2be30f9..9a192fb05e 100644 >--- a/LayoutTests/imported/w3c/ChangeLog >+++ b/LayoutTests/imported/w3c/ChangeLog >@@ -1,3 +1,15 @@ >+2020-04-09 Cathie Chen <cathiechen@igalia.com> >+ >+ Add support for scrollend event of programmatic scrolling >+ https://bugs.webkit.org/show_bug.cgi?id=209134 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * web-platform-tests/dom/events/scrolling/scrollend-event-fired-for-programmatic-scroll-expected.txt: >+ * web-platform-tests/dom/events/scrolling/scrollend-event-fired-for-programmatic-scroll.html: >+ * web-platform-tests/dom/events/scrolling/scrollend-event-fired-for-scrollIntoView-expected.txt: >+ * web-platform-tests/dom/events/scrolling/scrollend-event-fired-for-scrollIntoView.html: >+ > 2020-04-09 Cathie Chen <cathiechen@igalia.com> > > Import test for programmatic scrolling scrollend event >diff --git a/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-for-programmatic-scroll-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-for-programmatic-scroll-expected.txt >index 9541f96fc3..966c9f1abb 100644 >--- a/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-for-programmatic-scroll-expected.txt >+++ b/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-for-programmatic-scroll-expected.txt >@@ -1,4 +1,4 @@ > >-FAIL Tests scrollend event for calling scroll functions. promise_test: Unhandled rejection with value: "DIV.scrollTo did not receive scrollend event." >-FAIL Tests scrollend event for changing scroll attributes. promise_test: Unhandled rejection with value: "DIV.scrollTop did not receive scrollend event." >+PASS Tests scrollend event for calling scroll functions. >+PASS Tests scrollend event for changing scroll attributes. > >diff --git a/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-for-programmatic-scroll.html b/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-for-programmatic-scroll.html >index 79b5f5f018..26344881a2 100644 >--- a/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-for-programmatic-scroll.html >+++ b/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-for-programmatic-scroll.html >@@ -1,4 +1,4 @@ >-<!DOCTYPE HTML> >+<!DOCTYPE HTML><!-- webkit-test-runner [ experimental:OverscrollEventsEnabled=true experimental:CSSOMViewSmoothScrollingEnabled=true ] --> > <meta name="timeout" content="long"> > <script src="/resources/testharness.js"></script> > <script src="/resources/testharnessreport.js"></script> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-for-scrollIntoView-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-for-scrollIntoView-expected.txt >index 24c37eecb9..bec711fde3 100644 >--- a/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-for-scrollIntoView-expected.txt >+++ b/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-for-scrollIntoView-expected.txt >@@ -1,4 +1,4 @@ > >-FAIL Tests scrollend event for scrollIntoView. promise_test: Unhandled rejection with value: "DIV.scrollIntoView did not receive scrollend event." >-FAIL Tests scrollend event for nested scrollIntoView. promise_test: Unhandled rejection with value: "Nested scrollIntoView did not receive scrollend event." >+PASS Tests scrollend event for scrollIntoView. >+PASS Tests scrollend event for nested scrollIntoView. > >diff --git a/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-for-scrollIntoView.html b/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-for-scrollIntoView.html >index 63e1c3e22e..c3cde1155e 100644 >--- a/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-for-scrollIntoView.html >+++ b/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-for-scrollIntoView.html >@@ -1,4 +1,4 @@ >-<!DOCTYPE HTML> >+<!DOCTYPE HTML><!-- webkit-test-runner [ experimental:OverscrollEventsEnabled=true experimental:CSSOMViewSmoothScrollingEnabled=true ] --> > <meta name="timeout" content="long"> > <script src="/resources/testharness.js"></script> > <script src="/resources/testharnessreport.js"></script> >diff --git a/LayoutTests/platform/ios/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-for-scrollIntoView-expected.txt b/LayoutTests/platform/ios/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-for-scrollIntoView-expected.txt >new file mode 100644 >index 0000000000..4abaa6a231 >--- /dev/null >+++ b/LayoutTests/platform/ios/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-for-scrollIntoView-expected.txt >@@ -0,0 +1,4 @@ >+ >+FAIL Tests scrollend event for scrollIntoView. assert_equals: HTML.scrollIntoView scrollLeft expected 10000 but got 2200 >+PASS Tests scrollend event for nested scrollIntoView. >+ >diff --git a/LayoutTests/platform/mac-wk1/TestExpectations b/LayoutTests/platform/mac-wk1/TestExpectations >index 0e07479f7f..8551778f89 100644 >--- a/LayoutTests/platform/mac-wk1/TestExpectations >+++ b/LayoutTests/platform/mac-wk1/TestExpectations >@@ -755,6 +755,8 @@ webkit.org/b/191357 imported/w3c/web-platform-tests/css/cssom-view/scroll-behavi > webkit.org/b/191357 imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-main-frame-window.html [ Skip ] > webkit.org/b/191357 imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-subframe-root.html [ Skip ] > webkit.org/b/191357 imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-subframe-window.html [ Skip ] >+webkit.org/b/191357 imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-for-programmatic-scroll.html [ Skip ] >+webkit.org/b/191357 imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-for-scrollIntoView.html [ Skip ] > > webkit.org/b/189908 imported/w3c/web-platform-tests/resource-timing/resource_timing.worker.html [ Failure ] > >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 523a438d83..c6987460b3 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,91 @@ >+2020-04-09 Cathie Chen <cathiechen@igalia.com> >+ >+ Add support for scrollend event of programmatic scrolling >+ https://bugs.webkit.org/show_bug.cgi?id=209134 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Add support for scrollend event of programmatic scrolling. m_pendingScrollendEventTargetList in Document stores >+ the scrolled targets which need to dispatch scrollend events. FrameView and RenderLayer provide three ways to >+ add elements to the scrollend list. >+ 1. Instant scrolling including the scrolling position not changed animated scroll, the element would be added to >+ the list after scroll position changed. >+ 2. Animated scrolling, the element would be set as the m_scrollEndEventTarget of ScrollAnimation and add to the list >+ when animation stops. For scrollRectIntoView, in order to make sure scrollend event fired after all ancestor layers >+ finishing scrolling, add m_duringScrollRectIntoView to indicate if scrollRectIntoView finished. When ScrollAnimation >+ stops, it will try to find a duringScrollRectIntoView ancestor layer and pass the m_scrollEndEventTarget to its >+ ScrollAnimation. If no such layer found, add m_scrollEndEventTarget to the scrollend list. >+ 3. User asynchronous scrolling, the scroll position wouldn't change immediately. So saveScrollEndEventPosition >+ then checkScrollEndEventPosition if scroll position changed. The programmatic scrolling wouldn't trigger this way. >+ >+ Test: imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-for-programmatic-scroll.html >+ imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-for-scrollIntoView.html >+ >+ * dom/Document.cpp: >+ (WebCore::Document::commonTeardown): >+ (WebCore::Document::addPendingScrollEndEventTarget): Append the targets to m_pendingScrollEndEventTargetList. >+ (WebCore::Document::runScrollSteps): Dispatch scrollend event for each target. >+ * dom/Document.h: Add m_pendingScrollEndEventTargetList which keeps the scrollend event targets. >+ * dom/Element.cpp: >+ (WebCore::Element::setScrollLeft): Set RequestScrollEndEvent::Yes for FrameView element. >+ (WebCore::Element::setScrollTop): Ditto. >+ * page/DOMWindow.cpp: >+ (WebCore::DOMWindow::scrollTo const): Add document to the scrollend list for scrolling to (0, 0) optimization. >+ * page/FrameView.cpp: >+ (WebCore::FrameView::setScrollPosition): Add document to the scrollend list if it scrolled(instant scroll or smooth scroll >+ without changing the position, otherwise set document as the scrollEndTarget of scrollAniamtion.). >+ (WebCore::FrameView::saveScrollEndEventPosition): Save the scroll position that requires to fire an scrollend event. This is for asynchronous scroll. >+ (WebCore::FrameView::checkScrollEndEventPosition): Add document to the list if the scroll position equal to the preserved one. >+ (WebCore::FrameView::addPendingScrollEndEventTarget): Add Document to m_pendingScrollendEventTargetList in Document. >+ * page/FrameView.h: Add m_duringScrollRectIntoView to indicate FrameView is performing a animated scrollRectIntoView scroll. >+ * platform/ScrollAnimation.h: >+ (WebCore::ScrollAnimation::setScrollEndTarget): >+ * platform/ScrollAnimationSmooth.cpp: >+ (WebCore::ScrollAnimationSmooth::stop): Call notifyScrollEnd. >+ (WebCore::ScrollAnimationSmooth::notifyScrollEnd): setDuringScrollRectIntoView false. If there's m_scrollEndEventTarget, try to find an ancestor layer >+ duringScrollRectIntoView and set the target to it. Otherwise, add the target to the scrollend list. >+ (WebCore::ScrollAnimationSmooth::setScrollEndTarget): >+ (WebCore::ScrollAnimationSmooth::animationTimerFired): Call notifyScrollEnd if not continueAnimation. >+ * platform/ScrollAnimationSmooth.h: Add m_scrollEndEventTarget. >+ * platform/ScrollAnimator.cpp: >+ (WebCore::ScrollAnimator::setScrollEndTarget): Set m_scrollEndEventTarget to ScrollAnimationSmooth. >+ * platform/ScrollAnimator.h: >+ * platform/ScrollTypes.h: Add RequestScrollEndEvent. >+ * platform/ScrollView.cpp: >+ (WebCore::ScrollView::setContentsScrollPosition): Add RequestScrollEndEvent::Yes. >+ (WebCore::ScrollView::scrollTo): Call checkScrollEndEventPosition if the scroll position changed. >+ (WebCore::ScrollView::setScrollPosition): >+ * platform/ScrollView.h: >+ * platform/ScrollableArea.cpp: >+ (WebCore::ScrollableArea::setScrollEndTarget): >+ * platform/ScrollableArea.h: >+ (WebCore::ScrollableArea::saveScrollEndEventPosition): >+ (WebCore::ScrollableArea::checkScrollEndEventPosition): >+ (WebCore::ScrollableArea::addPendingScrollEndEventTarget): >+ (WebCore::ScrollableArea::duringScrollRectIntoView): >+ (WebCore::ScrollableArea::setDuringScrollRectIntoView): >+ (WebCore::ScrollableArea::findAncestorDuringScrollRectIntoView): >+ * rendering/RenderBox.cpp: >+ (WebCore::RenderBox::setScrollPosition): >+ * rendering/RenderLayer.cpp: >+ (WebCore::RenderLayer::scrollToXPosition): >+ (WebCore::RenderLayer::scrollToYPosition): >+ (WebCore::RenderLayer::setScrollPosition): Add element to the scrollend list if it scrolled(instant scroll or smooth scroll >+ without changing the position, otherwise set element as the scrollEndTarget of scrollAniamtion.). >+ (WebCore::RenderLayer::scrollToOffset): Call checkScrollEndEventPosition, if there is no scrolling. >+ (WebCore::RenderLayer::scrollTo): checkScrollEndEventPosition if scroll position changed. >+ (WebCore::RenderLayer::scrollRectToVisible): setDuringScrollRectIntoView(true) if it's performing a animated scrolling. >+ After parentLayer->scrollRectToVisible(), check if current layer is duringScrollRectIntoView, set the element as animation's scrollend Target. >+ Otherwise, find the duringScrollRectIntoView ancestor layer and pass the element to ancestor layer's scrollAnimation. >+ If no duringScrollRectIntoView layer found, add the element to the scrollend list. >+ (WebCore::RenderLayer::saveScrollEndEventPosition): >+ (WebCore::RenderLayer::checkScrollEndEventPosition): >+ (WebCore::RenderLayer::addPendingScrollEndEventTarget): >+ (WebCore::RenderLayer::findAncestorDuringScrollRectIntoView): Find the duringScrollRectIntoView ancestor layer, and check FrameView at the end. >+ * rendering/RenderLayer.h: >+ * rendering/RenderObject.cpp: >+ (WebCore::RenderObject::scrollRectToVisible): Add RequestScrollEndEvent::Yes. >+ > 2020-04-09 Cathie Chen <cathiechen@igalia.com> > > Add support for overscroll events parsing >diff --git a/Source/WebCore/dom/Document.cpp b/Source/WebCore/dom/Document.cpp >index cc8e8a3301..0093a85bd0 100644 >--- a/Source/WebCore/dom/Document.cpp >+++ b/Source/WebCore/dom/Document.cpp >@@ -799,6 +799,10 @@ void Document::commonTeardown() > > m_pendingScrollEventTargetList = nullptr; > >+#if ENABLE(OVERSCROLL_EVENTS) >+ m_pendingScrollEndEventTargetList = nullptr; >+#endif >+ > while (!m_timelines.computesEmpty()) > m_timelines.begin()->detachFromDocument(); > m_timeline = nullptr; >@@ -4067,6 +4071,26 @@ void Document::addPendingScrollEventTarget(ContainerNode& target) > targets.append(target); > } > >+#if ENABLE(OVERSCROLL_EVENTS) >+void Document::addPendingScrollEndEventTarget(ContainerNode& target) >+{ >+ if (!settings().overscrollEventsEnabled()) >+ return; >+ >+ if (!m_pendingScrollEndEventTargetList) >+ m_pendingScrollEndEventTargetList = makeUnique<PendingScrollEventTargetList>(); >+ >+ auto& targets = m_pendingScrollEndEventTargetList->targets; >+ if (targets.findMatching([&] (auto& entry) { return entry.ptr() == ⌖ }) != notFound) >+ return; >+ >+ if (targets.isEmpty()) >+ scheduleTimedRenderingUpdate(); >+ >+ targets.append(target); >+} >+#endif >+ > void Document::setNeedsVisualViewportScrollEvent() > { > if (!m_needsVisualViewportScrollEvent) >@@ -4092,6 +4116,18 @@ void Document::runScrollSteps() > if (auto* window = domWindow()) > window->visualViewport().dispatchEvent(Event::create(eventNames().scrollEvent, Event::CanBubble::No, Event::IsCancelable::No)); > } >+ >+#if ENABLE(OVERSCROLL_EVENTS) >+ // Deal with scrollend event. >+ if (m_pendingScrollEndEventTargetList && !m_pendingScrollEndEventTargetList->targets.isEmpty()) { >+ LOG_WITH_STREAM(Events, stream << "Document" << this << "sending scrollend events to pending scroll event targets"); >+ auto currentScrollEndTargets = WTFMove(m_pendingScrollEndEventTargetList->targets); >+ for (auto& target : currentScrollEndTargets) { >+ auto bubbles = target->isDocumentNode() ? Event::CanBubble::Yes : Event::CanBubble::No; >+ target->dispatchEvent(Event::create(eventNames().scrollendEvent, bubbles, Event::IsCancelable::No)); >+ } >+ } >+#endif > } > > void Document::addAudioProducer(MediaProducer& audioProducer) >diff --git a/Source/WebCore/dom/Document.h b/Source/WebCore/dom/Document.h >index 34fd00e15b..5d792079fc 100644 >--- a/Source/WebCore/dom/Document.h >+++ b/Source/WebCore/dom/Document.h >@@ -1365,6 +1365,9 @@ public: > void runResizeSteps(); > > void addPendingScrollEventTarget(ContainerNode&); >+#if ENABLE(OVERSCROLL_EVENTS) >+ void addPendingScrollEndEventTarget(ContainerNode&); >+#endif > void setNeedsVisualViewportScrollEvent(); > void runScrollSteps(); > >@@ -2051,6 +2054,9 @@ private: > > struct PendingScrollEventTargetList; > std::unique_ptr<PendingScrollEventTargetList> m_pendingScrollEventTargetList; >+#if ENABLE(OVERSCROLL_EVENTS) >+ std::unique_ptr<PendingScrollEventTargetList> m_pendingScrollEndEventTargetList; >+#endif > > #if ENABLE(MEDIA_STREAM) > HashSet<HTMLMediaElement*> m_mediaStreamStateChangeElements; >diff --git a/Source/WebCore/dom/Element.cpp b/Source/WebCore/dom/Element.cpp >index bc20435481..1ae3980f90 100644 >--- a/Source/WebCore/dom/Element.cpp >+++ b/Source/WebCore/dom/Element.cpp >@@ -1295,7 +1295,11 @@ void Element::setScrollLeft(int newLeft) > // See https://bugs.webkit.org/show_bug.cgi?id=205059 > AnimatedScroll animated = useSmoothScrolling(ScrollBehavior::Auto, document().documentElement()) ? AnimatedScroll::Yes : AnimatedScroll::No; > IntPoint position(static_cast<int>(newLeft * frame->pageZoomFactor() * frame->frameScaleFactor()), frame->view()->scrollY()); >+#if ENABLE(OVERSCROLL_EVENTS) >+ frame->view()->setScrollPosition(position, ScrollClamping::Clamped, animated, RequestScrollEndEvent::Yes); >+#else > frame->view()->setScrollPosition(position, ScrollClamping::Clamped, animated); >+#endif > } > return; > } >@@ -1319,7 +1323,11 @@ void Element::setScrollTop(int newTop) > // See https://bugs.webkit.org/show_bug.cgi?id=205059 > AnimatedScroll animated = useSmoothScrolling(ScrollBehavior::Auto, document().documentElement()) ? AnimatedScroll::Yes : AnimatedScroll::No; > IntPoint position(frame->view()->scrollX(), static_cast<int>(newTop * frame->pageZoomFactor() * frame->frameScaleFactor())); >+#if ENABLE(OVERSCROLL_EVENTS) >+ frame->view()->setScrollPosition(position, ScrollClamping::Clamped, animated, RequestScrollEndEvent::Yes); >+#else > frame->view()->setScrollPosition(position, ScrollClamping::Clamped, animated); >+#endif > } > return; > } >diff --git a/Source/WebCore/page/DOMWindow.cpp b/Source/WebCore/page/DOMWindow.cpp >index 09aab6b23d..62fde6e7c3 100644 >--- a/Source/WebCore/page/DOMWindow.cpp >+++ b/Source/WebCore/page/DOMWindow.cpp >@@ -1679,8 +1679,15 @@ void DOMWindow::scrollTo(const ScrollToOptions& options, ScrollClamping clamping > > // This is an optimization for the common case of scrolling to (0, 0) when the scroller is already at the origin. > // If an animated scroll is in progress, this optimization is skipped to ensure that the animated scroll is really stopped. >- if (view->currentScrollBehaviorStatus() == ScrollBehaviorStatus::NotInAnimation && !scrollToOptions.left.value() && !scrollToOptions.top.value() && view->contentsScrollPosition() == IntPoint(0, 0)) >+ if (view->currentScrollBehaviorStatus() == ScrollBehaviorStatus::NotInAnimation >+ && !scrollToOptions.left.value() >+ && !scrollToOptions.top.value() >+ && view->contentsScrollPosition() == IntPoint(0, 0)) { >+#if ENABLE(OVERSCROLL_EVENTS) >+ view->addPendingScrollEndEventTarget(); >+#endif > return; >+ } > > document()->updateLayoutIgnorePendingStylesheets(); > >diff --git a/Source/WebCore/page/FrameView.cpp b/Source/WebCore/page/FrameView.cpp >index d5464a37ec..141b82c95f 100644 >--- a/Source/WebCore/page/FrameView.cpp >+++ b/Source/WebCore/page/FrameView.cpp >@@ -2282,7 +2282,7 @@ void FrameView::scrollElementToRect(const Element& element, const IntRect& rect) > setScrollPosition(IntPoint(bounds.x() - centeringOffsetX - rect.x(), bounds.y() - centeringOffsetY - rect.y())); > } > >-void FrameView::setScrollPosition(const ScrollPosition& scrollPosition, ScrollClamping clamping, AnimatedScroll animated) >+void FrameView::setScrollPosition(const ScrollPosition& scrollPosition, ScrollClamping clamping, AnimatedScroll animated, RequestScrollEndEvent requestScrollEndEvent) > { > LOG_WITH_STREAM(Scrolling, stream << "FrameView::setScrollPosition " << scrollPosition << " , clearing anchor"); > >@@ -2295,10 +2295,21 @@ void FrameView::setScrollPosition(const ScrollPosition& scrollPosition, ScrollCl > Page* page = frame().page(); > if (page && page->isMonitoringWheelEvents()) > scrollAnimator().setWheelEventTestMonitor(page->wheelEventTestMonitor()); >+ >+ ScrollPosition newScrollPosition = (!delegatesScrolling() && clamping == ScrollClamping::Clamped) ? adjustScrollPositionWithinRange(scrollPosition) : scrollPosition; > if (animated == AnimatedScroll::Yes) >- scrollToOffsetWithAnimation(scrollOffsetFromPosition(scrollPosition), currentScrollType(), clamping); >+ scrollToOffsetWithAnimation(scrollOffsetFromPosition(newScrollPosition), currentScrollType(), clamping); > else >- ScrollView::setScrollPosition(scrollPosition, clamping); >+ ScrollView::setScrollPosition(newScrollPosition, clamping, animated, requestScrollEndEvent); >+ >+#if ENABLE(OVERSCROLL_EVENTS) >+ if (frame().settings().overscrollEventsEnabled() && requestScrollEndEvent == RequestScrollEndEvent::Yes) { >+ if (newScrollPosition == ScrollView::scrollPosition()) >+ addPendingScrollEndEventTarget(); >+ else if (animated == AnimatedScroll::Yes) >+ setScrollEndTarget(makeWeakPtr(frame().document())); >+ } >+#endif > > setCurrentScrollType(oldScrollType); > } >@@ -3735,6 +3746,32 @@ void FrameView::scrollToOffsetWithAnimation(const ScrollOffset& offset, ScrollTy > setCurrentScrollType(previousScrollType); > } > >+#if ENABLE(OVERSCROLL_EVENTS) >+void FrameView::saveScrollEndEventPosition(const ScrollPosition& position, ScrollClamping clamping) >+{ >+ if (!frame().settings().overscrollEventsEnabled()) >+ return; >+ >+ ScrollPosition clampedScrollPosition = clamping == ScrollClamping::Clamped ? adjustScrollPositionWithinRange(position) : position; >+ m_fireScrollEndEventAtPosition = clampedScrollPosition; >+} >+ >+void FrameView::checkScrollEndEventPosition(const ScrollPosition& position) >+{ >+ if (!m_fireScrollEndEventAtPosition || m_fireScrollEndEventAtPosition.value() != position) >+ return; >+ >+ addPendingScrollEndEventTarget(); >+ m_fireScrollEndEventAtPosition = WTF::nullopt; >+} >+ >+void FrameView::addPendingScrollEndEventTarget() >+{ >+ if (Document* document = frame().document()) >+ document->addPendingScrollEndEventTarget(*document); >+} >+#endif >+ > float FrameView::adjustScrollStepForFixedContent(float step, ScrollbarOrientation orientation, ScrollGranularity granularity) > { > if (granularity != ScrollByPage || orientation == HorizontalScrollbar) >diff --git a/Source/WebCore/page/FrameView.h b/Source/WebCore/page/FrameView.h >index 0a0d0a203a..be29a853e4 100644 >--- a/Source/WebCore/page/FrameView.h >+++ b/Source/WebCore/page/FrameView.h >@@ -230,7 +230,7 @@ public: > #if USE(COORDINATED_GRAPHICS) > WEBCORE_EXPORT void setFixedVisibleContentRect(const IntRect&) final; > #endif >- WEBCORE_EXPORT void setScrollPosition(const ScrollPosition&, ScrollClamping = ScrollClamping::Clamped, AnimatedScroll = AnimatedScroll::No) final; >+ WEBCORE_EXPORT void setScrollPosition(const ScrollPosition&, ScrollClamping = ScrollClamping::Clamped, AnimatedScroll = AnimatedScroll::No, RequestScrollEndEvent = RequestScrollEndEvent::No) final; > void restoreScrollbar(); > void scheduleScrollToFocusedElement(SelectionRevealMode); > void scrollToFocusedElementImmediatelyIfNeeded(); >@@ -667,6 +667,14 @@ public: > > String debugDescription() const final; > >+#if ENABLE(OVERSCROLL_EVENTS) >+ void saveScrollEndEventPosition(const ScrollPosition&, ScrollClamping = ScrollClamping::Clamped) final; >+ void checkScrollEndEventPosition(const ScrollPosition&) final; >+ void addPendingScrollEndEventTarget() final; >+ bool duringScrollRectIntoView() final { return m_duringScrollRectIntoView; } >+ void setDuringScrollRectIntoView(bool scrolling) final { m_duringScrollRectIntoView = scrolling; } >+#endif >+ > protected: > bool scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect) final; > void scrollContentsSlowPath(const IntRect& updateRect) final; >@@ -907,6 +915,10 @@ private: > > Pagination m_pagination; > >+#if ENABLE(OVERSCROLL_EVENTS) >+ Optional<ScrollPosition> m_fireScrollEndEventAtPosition; >+#endif >+ > enum class ViewportRendererType : uint8_t { None, Document, Body }; > ViewportRendererType m_viewportRendererType { ViewportRendererType::None }; > ScrollPinningBehavior m_scrollPinningBehavior { DoNotPin }; >@@ -952,6 +964,10 @@ private: > // True if autosize has been run since m_shouldAutoSize was set. > bool m_didRunAutosize { false }; > bool m_inUpdateEmbeddedObjects { false }; >+ >+#if ENABLE(OVERSCROLL_EVENTS) >+ bool m_duringScrollRectIntoView { false }; >+#endif > }; > > inline void FrameView::incrementVisuallyNonEmptyPixelCount(const IntSize& size) >diff --git a/Source/WebCore/platform/ScrollAnimation.h b/Source/WebCore/platform/ScrollAnimation.h >index 523a77f335..db53f1df7e 100644 >--- a/Source/WebCore/platform/ScrollAnimation.h >+++ b/Source/WebCore/platform/ScrollAnimation.h >@@ -26,6 +26,7 @@ > #ifndef ScrollAnimation_h > #define ScrollAnimation_h > >+#include "ContainerNode.h" > #include "ScrollTypes.h" > > namespace WebCore { >@@ -44,6 +45,9 @@ public: > virtual void updateVisibleLengths() { }; > virtual void setCurrentPosition(const FloatPoint&) { }; > virtual void serviceAnimation() { }; >+#if ENABLE(OVERSCROLL_EVENTS) >+ virtual void setScrollEndTarget(WeakPtr<ContainerNode>) { }; >+#endif > > protected: > ScrollAnimation(ScrollableArea& scrollableArea) >diff --git a/Source/WebCore/platform/ScrollAnimationSmooth.cpp b/Source/WebCore/platform/ScrollAnimationSmooth.cpp >index 2ca578a30f..44e88ab044 100644 >--- a/Source/WebCore/platform/ScrollAnimationSmooth.cpp >+++ b/Source/WebCore/platform/ScrollAnimationSmooth.cpp >@@ -28,7 +28,10 @@ > #include "config.h" > #include "ScrollAnimationSmooth.h" > >+#include "ContainerNode.h" >+#include "Document.h" > #include "FloatPoint.h" >+#include "RenderLayer.h" > #include "ScrollableArea.h" > > namespace WebCore { >@@ -80,10 +83,39 @@ void ScrollAnimationSmooth::scroll(const FloatPoint& position) > > void ScrollAnimationSmooth::stop() > { >+#if ENABLE(OVERSCROLL_EVENTS) >+ if (m_animationTimer.isActive()) >+ notifyScrollEnd(); >+#endif >+ > m_animationTimer.stop(); > m_scrollableArea.setScrollBehaviorStatus(ScrollBehaviorStatus::NotInAnimation); > } > >+#if ENABLE(OVERSCROLL_EVENTS) >+void ScrollAnimationSmooth::notifyScrollEnd() >+{ >+ if (!m_scrollEndEventTarget) { >+ m_scrollableArea.setDuringScrollRectIntoView(false); >+ return; >+ } >+ >+ auto* duringScrollingParentLayer = m_scrollableArea.duringScrollRectIntoView() ? m_scrollableArea.findAncestorDuringScrollRectIntoView() : nullptr; >+ if (duringScrollingParentLayer) >+ duringScrollingParentLayer->setScrollEndTarget(m_scrollEndEventTarget); >+ else >+ m_scrollEndEventTarget->document().addPendingScrollEndEventTarget(*m_scrollEndEventTarget); >+ >+ m_scrollableArea.setDuringScrollRectIntoView(false); >+ m_scrollEndEventTarget = nullptr; >+} >+ >+void ScrollAnimationSmooth::setScrollEndTarget(WeakPtr<ContainerNode> target) >+{ >+ m_scrollEndEventTarget = target; >+} >+#endif >+ > void ScrollAnimationSmooth::updateVisibleLengths() > { > m_horizontalData.visibleLength = m_scrollableArea.visibleWidth(); >@@ -410,8 +442,12 @@ void ScrollAnimationSmooth::animationTimerFired() > > if (continueAnimation) > startNextTimer(std::max(minimumTimerInterval, deltaToNextFrame)); >- else >+ else { > m_scrollableArea.setScrollBehaviorStatus(ScrollBehaviorStatus::NotInAnimation); >+#if ENABLE(OVERSCROLL_EVENTS) >+ notifyScrollEnd(); >+#endif >+ } > > m_notifyPositionChangedFunction(FloatPoint(m_horizontalData.currentPosition, m_verticalData.currentPosition)); > } >diff --git a/Source/WebCore/platform/ScrollAnimationSmooth.h b/Source/WebCore/platform/ScrollAnimationSmooth.h >index 8173fa7e20..184cfad1d1 100644 >--- a/Source/WebCore/platform/ScrollAnimationSmooth.h >+++ b/Source/WebCore/platform/ScrollAnimationSmooth.h >@@ -31,6 +31,7 @@ > > namespace WebCore { > >+class ContainerNode; > class FloatPoint; > class ScrollableArea; > enum class ScrollClamping : uint8_t; >@@ -48,10 +49,16 @@ public: > Bounce > }; > >+#if ENABLE(OVERSCROLL_EVENTS) >+ void setScrollEndTarget(WeakPtr<ContainerNode>) override; >+#endif > private: > bool scroll(ScrollbarOrientation, ScrollGranularity, float step, float multiplier) override; > void scroll(const FloatPoint&) override; > void stop() override; >+#if ENABLE(OVERSCROLL_EVENTS) >+ void notifyScrollEnd(); >+#endif > void updateVisibleLengths() override; > void setCurrentPosition(const FloatPoint&) override; > >@@ -104,6 +111,9 @@ private: > > MonotonicTime m_startTime; > Timer m_animationTimer; >+#if ENABLE(OVERSCROLL_EVENTS) >+ WeakPtr<ContainerNode> m_scrollEndEventTarget; >+#endif > }; > > } // namespace WebCore >diff --git a/Source/WebCore/platform/ScrollAnimator.cpp b/Source/WebCore/platform/ScrollAnimator.cpp >index 0fc729e912..d893008aa0 100644 >--- a/Source/WebCore/platform/ScrollAnimator.cpp >+++ b/Source/WebCore/platform/ScrollAnimator.cpp >@@ -287,5 +287,10 @@ void ScrollAnimator::didAddHorizontalScrollbar(Scrollbar*) > { > m_animationProgrammaticScroll->updateVisibleLengths(); > } >- >+#if ENABLE(OVERSCROLL_EVENTS) >+void ScrollAnimator::setScrollEndTarget(WeakPtr<ContainerNode> target) >+{ >+ m_animationProgrammaticScroll->setScrollEndTarget(target); >+} >+#endif > } // namespace WebCore >diff --git a/Source/WebCore/platform/ScrollAnimator.h b/Source/WebCore/platform/ScrollAnimator.h >index 9b7c09b690..eede798db5 100644 >--- a/Source/WebCore/platform/ScrollAnimator.h >+++ b/Source/WebCore/platform/ScrollAnimator.h >@@ -37,6 +37,7 @@ > #include "WheelEventTestMonitor.h" > #include <wtf/FastMalloc.h> > #include <wtf/Forward.h> >+#include <wtf/WeakPtr.h> > > #if ENABLE(RUBBER_BANDING) || ENABLE(CSS_SCROLL_SNAP) > #include "ScrollController.h" >@@ -44,6 +45,7 @@ > > namespace WebCore { > >+class ContainerNode; > class FloatPoint; > class PlatformTouchEvent; > class ScrollAnimation; >@@ -143,6 +145,10 @@ public: > FloatSize viewportSize() const override; > #endif > >+#if ENABLE(OVERSCROLL_EVENTS) >+ void setScrollEndTarget(WeakPtr<ContainerNode>); >+#endif >+ > protected: > virtual void notifyPositionChanged(const FloatSize& delta); > void updateActiveScrollSnapIndexForOffset(); >diff --git a/Source/WebCore/platform/ScrollTypes.h b/Source/WebCore/platform/ScrollTypes.h >index b975fb0430..562734547b 100644 >--- a/Source/WebCore/platform/ScrollTypes.h >+++ b/Source/WebCore/platform/ScrollTypes.h >@@ -65,6 +65,11 @@ enum class AnimatedScroll : uint8_t { > Yes > }; > >+enum class RequestScrollEndEvent : uint8_t { >+ No, >+ Yes >+}; >+ > inline ScrollDirection logicalToPhysical(ScrollLogicalDirection direction, bool isVertical, bool isFlipped) > { > switch (direction) { >diff --git a/Source/WebCore/platform/ScrollView.cpp b/Source/WebCore/platform/ScrollView.cpp >index 3aee3f948f..1ab20abc5b 100644 >--- a/Source/WebCore/platform/ScrollView.cpp >+++ b/Source/WebCore/platform/ScrollView.cpp >@@ -213,7 +213,11 @@ void ScrollView::setContentsScrollPosition(const IntPoint& position, ScrollClamp > if (platformWidget()) > setActualScrollPosition(position); > #endif >+#if ENABLE(OVERSCROLL_EVENTS) >+ setScrollPosition(position, clamping, animated, RequestScrollEndEvent::Yes); >+#else > setScrollPosition(position, clamping, animated); >+#endif > } > > FloatRect ScrollView::exposedContentRect() const >@@ -487,6 +491,10 @@ void ScrollView::scrollTo(const ScrollPosition& newPosition) > > m_scrollPosition = newPosition; > >+#if ENABLE(OVERSCROLL_EVENTS) >+ checkScrollEndEventPosition(m_scrollPosition); >+#endif >+ > if (scrollbarsSuppressed()) > return; > >@@ -514,7 +522,7 @@ void ScrollView::completeUpdatesAfterScrollTo(const IntSize& scrollDelta) > updateCompositingLayersAfterScrolling(); > } > >-void ScrollView::setScrollPosition(const ScrollPosition& scrollPosition, ScrollClamping clamping, AnimatedScroll/* animated*/) >+void ScrollView::setScrollPosition(const ScrollPosition& scrollPosition, ScrollClamping clamping, AnimatedScroll /* animated*/, RequestScrollEndEvent) > { > LOG_WITH_STREAM(Scrolling, stream << "ScrollView::setScrollPosition " << scrollPosition); > >diff --git a/Source/WebCore/platform/ScrollView.h b/Source/WebCore/platform/ScrollView.h >index e2ee613e61..e3c1d7d130 100644 >--- a/Source/WebCore/platform/ScrollView.h >+++ b/Source/WebCore/platform/ScrollView.h >@@ -262,7 +262,7 @@ public: > ScrollPosition cachedScrollPosition() const { return m_cachedScrollPosition; } > > // Functions for scrolling the view. >- virtual void setScrollPosition(const ScrollPosition&, ScrollClamping = ScrollClamping::Clamped, AnimatedScroll = AnimatedScroll::No); >+ virtual void setScrollPosition(const ScrollPosition&, ScrollClamping = ScrollClamping::Clamped, AnimatedScroll = AnimatedScroll::No, RequestScrollEndEvent = RequestScrollEndEvent::No); > > void scrollBy(const IntSize& s) { return setScrollPosition(scrollPosition() + s); } > >diff --git a/Source/WebCore/platform/ScrollableArea.cpp b/Source/WebCore/platform/ScrollableArea.cpp >index cdad3601d3..89d4d99e47 100644 >--- a/Source/WebCore/platform/ScrollableArea.cpp >+++ b/Source/WebCore/platform/ScrollableArea.cpp >@@ -32,6 +32,7 @@ > #include "config.h" > #include "ScrollableArea.h" > >+#include "ContainerNode.h" > #include "FloatPoint.h" > #include "GraphicsContext.h" > #include "GraphicsLayer.h" >@@ -775,4 +776,11 @@ TextStream& operator<<(TextStream& ts, const ScrollableArea& scrollableArea) > return ts; > } > >+#if ENABLE(OVERSCROLL_EVENTS) >+void ScrollableArea::setScrollEndTarget(WeakPtr<ContainerNode> target) >+{ >+ scrollAnimator().setScrollEndTarget(target); >+} >+#endif >+ > } // namespace WebCore >diff --git a/Source/WebCore/platform/ScrollableArea.h b/Source/WebCore/platform/ScrollableArea.h >index 45fac029bd..3b9a7779f3 100644 >--- a/Source/WebCore/platform/ScrollableArea.h >+++ b/Source/WebCore/platform/ScrollableArea.h >@@ -37,6 +37,7 @@ class TextStream; > > namespace WebCore { > >+class ContainerNode; > class FloatPoint; > class GraphicsContext; > class LayoutPoint; >@@ -352,6 +353,16 @@ public: > > virtual String debugDescription() const = 0; > >+#if ENABLE(OVERSCROLL_EVENTS) >+ virtual void saveScrollEndEventPosition(const ScrollPosition&, ScrollClamping = ScrollClamping::Clamped) { } >+ virtual void checkScrollEndEventPosition(const ScrollPosition&) { } >+ virtual void addPendingScrollEndEventTarget() { } >+ virtual bool duringScrollRectIntoView() { return false; } >+ virtual void setDuringScrollRectIntoView(bool) { } >+ virtual ScrollableArea* findAncestorDuringScrollRectIntoView() { return nullptr; } >+ void setScrollEndTarget(WeakPtr<ContainerNode>); >+#endif >+ > protected: > WEBCORE_EXPORT ScrollableArea(); > WEBCORE_EXPORT virtual ~ScrollableArea(); >diff --git a/Source/WebCore/rendering/RenderBox.cpp b/Source/WebCore/rendering/RenderBox.cpp >index c87fd0a57e..f81df6e60d 100644 >--- a/Source/WebCore/rendering/RenderBox.cpp >+++ b/Source/WebCore/rendering/RenderBox.cpp >@@ -602,7 +602,11 @@ void RenderBox::setScrollPosition(const ScrollPosition& position, ScrollType scr > if (!hasOverflowClip() || !layer()) > return; > setupWheelEventMonitor(*layer()); >+#if ENABLE(OVERSCROLL_EVENTS) >+ layer()->setScrollPosition(position, scrollType, clamping, animated, RequestScrollEndEvent::Yes); >+#else > layer()->setScrollPosition(position, scrollType, clamping, animated); >+#endif > } > > void RenderBox::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const >diff --git a/Source/WebCore/rendering/RenderLayer.cpp b/Source/WebCore/rendering/RenderLayer.cpp >index 790caee99e..0baad9a9b7 100644 >--- a/Source/WebCore/rendering/RenderLayer.cpp >+++ b/Source/WebCore/rendering/RenderLayer.cpp >@@ -2593,21 +2593,44 @@ void RenderLayer::applyPostLayoutScrollPositionIfNeeded() > void RenderLayer::scrollToXPosition(int x, ScrollType scrollType, ScrollClamping clamping, AnimatedScroll animated) > { > ScrollPosition position(x, m_scrollPosition.y()); >+#if ENABLE(OVERSCROLL_EVENTS) >+ setScrollPosition(position, scrollType, clamping, animated, RequestScrollEndEvent::Yes); >+#else > setScrollPosition(position, scrollType, clamping, animated); >+#endif > } > > void RenderLayer::scrollToYPosition(int y, ScrollType scrollType, ScrollClamping clamping, AnimatedScroll animated) > { > ScrollPosition position(m_scrollPosition.x(), y); >+#if ENABLE(OVERSCROLL_EVENTS) >+ setScrollPosition(position, scrollType, clamping, animated, RequestScrollEndEvent::Yes); >+#else > setScrollPosition(position, scrollType, clamping, animated); >+#endif > } > >-void RenderLayer::setScrollPosition(const ScrollPosition& position, ScrollType scrollType, ScrollClamping clamping, AnimatedScroll animated) >+void RenderLayer::setScrollPosition(const ScrollPosition& position, ScrollType scrollType, ScrollClamping clamping, AnimatedScroll animated, RequestScrollEndEvent requestScrollEndEvent) > { >+#if !ENABLE(OVERSCROLL_EVENTS) >+ UNUSED_PARAM(requestScrollEndEvent); >+#endif >+ >+ auto offset = scrollOffsetFromPosition(position); >+ ScrollOffset newScrollOffset = clamping == ScrollClamping::Clamped ? clampScrollOffset(offset) : offset; > if (animated == AnimatedScroll::Yes) >- scrollToOffsetWithAnimation(scrollOffsetFromPosition(position), scrollType, clamping); >+ scrollToOffsetWithAnimation(newScrollOffset, scrollType, clamping); > else >- scrollToOffset(scrollOffsetFromPosition(position), scrollType, clamping); >+ scrollToOffset(newScrollOffset, scrollType, clamping); >+ >+#if ENABLE(OVERSCROLL_EVENTS) >+ if (renderer().settings().overscrollEventsEnabled() && requestScrollEndEvent == RequestScrollEndEvent::Yes) { >+ if (newScrollOffset == scrollOffset()) >+ addPendingScrollEndEventTarget(); >+ else if (animated == AnimatedScroll::Yes) >+ setScrollEndTarget(makeWeakPtr(renderer().element())); >+ } >+#endif > } > > ScrollOffset RenderLayer::clampScrollOffset(const ScrollOffset& scrollOffset) const >@@ -2630,13 +2653,18 @@ void RenderLayer::scrollToOffset(const ScrollOffset& scrollOffset, ScrollType sc > scrollAnimator().cancelAnimations(); > > ScrollOffset clampedScrollOffset = clamping == ScrollClamping::Clamped ? clampScrollOffset(scrollOffset) : scrollOffset; >- if (clampedScrollOffset == this->scrollOffset()) >+ ScrollPosition clampedScrollPosition = scrollPositionFromOffset(clampedScrollOffset); >+ if (clampedScrollOffset == this->scrollOffset()) { >+#if ENABLE(OVERSCROLL_EVENTS) >+ checkScrollEndEventPosition(clampedScrollPosition); >+#endif > return; >+ } > > auto previousScrollType = currentScrollType(); > setCurrentScrollType(scrollType); > >- if (!requestScrollPositionUpdate(scrollPositionFromOffset(clampedScrollOffset), scrollType, clamping)) >+ if (!requestScrollPositionUpdate(clampedScrollPosition, scrollType, clamping)) > scrollToOffsetWithoutAnimation(clampedScrollOffset, clamping); > setScrollBehaviorStatus(ScrollBehaviorStatus::NotInAnimation); > >@@ -2760,6 +2788,10 @@ void RenderLayer::scrollTo(const ScrollPosition& position) > if (Element* element = renderer().element()) > element->document().addPendingScrollEventTarget(*element); > >+#if ENABLE(OVERSCROLL_EVENTS) >+ checkScrollEndEventPosition(m_scrollPosition); >+#endif >+ > if (scrollsOverflow()) > view.frameView().didChangeScrollOffset(); > >@@ -2805,10 +2837,14 @@ bool RenderLayer::allowsCurrentScroll() const > return box->hasHorizontalOverflow() || box->hasVerticalOverflow(); > } > >-void RenderLayer::scrollRectToVisible(const LayoutRect& absoluteRect, bool insideFixed, const ScrollRectToVisibleOptions& options) >+void RenderLayer::scrollRectToVisible(const LayoutRect& absoluteRect, bool insideFixed, const ScrollRectToVisibleOptions& options, RequestScrollEndEvent requestScrollEndEvent) > { > LOG_WITH_STREAM(Scrolling, stream << "Layer " << this << " scrollRectToVisible " << absoluteRect); > >+#if ENABLE(OVERSCROLL_EVENTS) >+ bool overscrollEventsEnabled = renderer().settings().overscrollEventsEnabled(); >+#endif >+ > LayoutRect newRect = absoluteRect; > FrameView& frameView = renderer().view().frameView(); > auto* parentLayer = enclosingContainingBlockLayer(*this, CrossFrameBoundaries::No); >@@ -2835,6 +2871,10 @@ void RenderLayer::scrollRectToVisible(const LayoutRect& absoluteRect, bool insid > if (autoscrollNotInProgress && useSmoothScrolling(options.behavior, box->element())) > animated = AnimatedScroll::Yes; > setScrollPosition(scrollPositionFromOffset(clampedScrollOffset), ScrollType::Programmatic, ScrollClamping::Clamped, animated); >+#if ENABLE(OVERSCROLL_EVENTS) >+ if (overscrollEventsEnabled && animated == AnimatedScroll::Yes && clampedScrollOffset != scrollOffset()) >+ setDuringScrollRectIntoView(true); >+#endif > IntSize scrollOffsetDifference = clampedScrollOffset - oldScrollOffset; > localExposeRect.move(-scrollOffsetDifference); > newRect = LayoutRect(box->localToAbsoluteQuad(FloatQuad(FloatRect(localExposeRect)), UseTransforms).boundingBox()); >@@ -2867,6 +2907,14 @@ void RenderLayer::scrollRectToVisible(const LayoutRect& absoluteRect, bool insid > animated = AnimatedScroll::Yes; > frameView.setScrollPosition(scrollPosition, ScrollClamping::Clamped, animated); > >+#if ENABLE(OVERSCROLL_EVENTS) >+ if (overscrollEventsEnabled && animated == AnimatedScroll::Yes && scrollPosition != frameView.scrollPosition()) { >+ frameView.setDuringScrollRectIntoView(true); >+ if (requestScrollEndEvent == RequestScrollEndEvent::Yes) >+ frameView.setScrollEndTarget(makeWeakPtr(frameView.frame().document())); >+ } >+#endif >+ > if (options.shouldAllowCrossOriginScrolling == ShouldAllowCrossOriginScrolling::Yes || frameView.safeToPropagateScrollToParent()) { > if (auto* enclosingLayer = ownerElement->renderer()->enclosingLayer()) > parentLayer = enclosingLayer->enclosingScrollableLayer(IncludeSelfOrNot::IncludeSelf, CrossFrameBoundaries::No); >@@ -2911,6 +2959,13 @@ void RenderLayer::scrollRectToVisible(const LayoutRect& absoluteRect, bool insid > if (autoscrollNotInProgress && useSmoothScrolling(options.behavior, renderer().document().documentElement())) > animated = AnimatedScroll::Yes; > frameView.setScrollPosition(clampedScrollPosition, ScrollClamping::Clamped, animated); >+#if ENABLE(OVERSCROLL_EVENTS) >+ if (overscrollEventsEnabled && animated == AnimatedScroll::Yes && clampedScrollPosition != frameView.scrollPosition()) { >+ frameView.setDuringScrollRectIntoView(true); >+ if (requestScrollEndEvent == RequestScrollEndEvent::Yes) >+ frameView.setScrollEndTarget(makeWeakPtr(frameView.frame().document())); >+ } >+#endif > } > > // This is the outermost view of a web page, so after scrolling this view we >@@ -2922,8 +2977,26 @@ void RenderLayer::scrollRectToVisible(const LayoutRect& absoluteRect, bool insid > } > } > >- if (parentLayer) >+ if (parentLayer) { > parentLayer->scrollRectToVisible(newRect, insideFixed, options); >+#if ENABLE(OVERSCROLL_EVENTS) >+ if (overscrollEventsEnabled && requestScrollEndEvent == RequestScrollEndEvent::Yes) { >+ ContainerNode* target = renderer().element(); >+ if (renderer().document().scrollingElement() == target) >+ target = &renderer().document(); >+ >+ if (duringScrollRectIntoView()) >+ setScrollEndTarget(makeWeakPtr(target)); >+ else { >+ auto* duringScrollingParentLayer = findAncestorDuringScrollRectIntoView(); >+ if (duringScrollingParentLayer) >+ duringScrollingParentLayer->setScrollEndTarget(makeWeakPtr(target)); >+ else >+ renderer().document().addPendingScrollEndEventTarget(*target); >+ } >+ } >+#endif >+ } > } > > void RenderLayer::updateCompositingLayersAfterScroll() >@@ -7056,6 +7129,49 @@ bool RenderLayer::invalidateEventRegion(EventRegionInvalidationReason reason) > #endif > } > >+#if ENABLE(OVERSCROLL_EVENTS) >+void RenderLayer::saveScrollEndEventPosition(const ScrollPosition& position, ScrollClamping clamping) >+{ >+ if (!renderer().settings().overscrollEventsEnabled()) >+ return; >+ >+ auto offset = scrollOffsetFromPosition(position); >+ ScrollOffset clampedScrollOffset = clamping == ScrollClamping::Clamped ? clampScrollOffset(offset) : offset; >+ m_fireScrollEndEventAtPosition = scrollPositionFromOffset(clampedScrollOffset); >+} >+ >+void RenderLayer::checkScrollEndEventPosition(const ScrollPosition& position) >+{ >+ if (!m_fireScrollEndEventAtPosition || m_fireScrollEndEventAtPosition.value() != position) >+ return; >+ >+ addPendingScrollEndEventTarget(); >+ >+ m_fireScrollEndEventAtPosition = WTF::nullopt; >+} >+ >+void RenderLayer::addPendingScrollEndEventTarget() >+{ >+ if (Element* element = renderer().element()) >+ element->document().addPendingScrollEndEventTarget(*element); >+} >+ >+ScrollableArea* RenderLayer::findAncestorDuringScrollRectIntoView() >+{ >+ auto* parentLayer = enclosingContainingBlockLayer(*this, CrossFrameBoundaries::No); >+ while (parentLayer) { >+ if (parentLayer->duringScrollRectIntoView()) >+ return parentLayer; >+ parentLayer = enclosingContainingBlockLayer(*parentLayer, CrossFrameBoundaries::No); >+ } >+ >+ FrameView& frameView = renderer().view().frameView(); >+ if (frameView.duringScrollRectIntoView()) >+ return &frameView; >+ return nullptr; >+} >+#endif >+ > TextStream& operator<<(WTF::TextStream& ts, ClipRectsType clipRectsType) > { > switch (clipRectsType) { >diff --git a/Source/WebCore/rendering/RenderLayer.h b/Source/WebCore/rendering/RenderLayer.h >index 7ef02970ab..3a053cb400 100644 >--- a/Source/WebCore/rendering/RenderLayer.h >+++ b/Source/WebCore/rendering/RenderLayer.h >@@ -452,7 +452,7 @@ public: > > void scrollToXPosition(int x, ScrollType, ScrollClamping = ScrollClamping::Clamped, AnimatedScroll = AnimatedScroll::No); > void scrollToYPosition(int y, ScrollType, ScrollClamping = ScrollClamping::Clamped, AnimatedScroll = AnimatedScroll::No); >- void setScrollPosition(const ScrollPosition&, ScrollType, ScrollClamping = ScrollClamping::Clamped, AnimatedScroll = AnimatedScroll::No); >+ void setScrollPosition(const ScrollPosition&, ScrollType, ScrollClamping = ScrollClamping::Clamped, AnimatedScroll = AnimatedScroll::No, RequestScrollEndEvent = RequestScrollEndEvent::No); > > // These are only used by marquee. > void scrollToXOffset(int x) { scrollToOffset(ScrollOffset(x, scrollOffset().y()), ScrollType::Programmatic, ScrollClamping::Unclamped); } >@@ -467,7 +467,7 @@ public: > void availableContentSizeChanged(AvailableSizeChangeReason) final; > > // "absoluteRect" is in scaled document coordinates. >- void scrollRectToVisible(const LayoutRect& absoluteRect, bool insideFixed, const ScrollRectToVisibleOptions&); >+ void scrollRectToVisible(const LayoutRect& absoluteRect, bool insideFixed, const ScrollRectToVisibleOptions&, RequestScrollEndEvent = RequestScrollEndEvent::No); > > bool scrollsOverflow() const; > bool hasScrollableHorizontalOverflow() const; >@@ -930,6 +930,15 @@ public: > > String debugDescription() const final; > >+#if ENABLE(OVERSCROLL_EVENTS) >+ void saveScrollEndEventPosition(const ScrollPosition&, ScrollClamping = ScrollClamping::Clamped) final; >+ void checkScrollEndEventPosition(const ScrollPosition&) final; >+ void addPendingScrollEndEventTarget() final; >+ bool duringScrollRectIntoView() final { return m_duringScrollRectIntoView; } >+ void setDuringScrollRectIntoView(bool scrolling) final { m_duringScrollRectIntoView = scrolling; } >+ ScrollableArea* findAncestorDuringScrollRectIntoView() final; >+#endif >+ > private: > > void setNextSibling(RenderLayer* next) { m_next = next; } >@@ -1286,6 +1295,10 @@ private: > bool m_layerListMutationAllowed : 1; > #endif > >+#if ENABLE(OVERSCROLL_EVENTS) >+ bool m_duringScrollRectIntoView : 1; >+#endif >+ > #if ENABLE(CSS_COMPOSITING) > unsigned m_blendMode : 5; // BlendMode > bool m_hasNotIsolatedCompositedBlendingDescendants : 1; >@@ -1361,6 +1374,10 @@ private: > > std::unique_ptr<RenderLayerFilters> m_filters; > std::unique_ptr<RenderLayerBacking> m_backing; >+ >+#if ENABLE(OVERSCROLL_EVENTS) >+ Optional<ScrollPosition> m_fireScrollEndEventAtPosition; >+#endif > > PaintFrequencyTracker m_paintFrequencyTracker; > }; >diff --git a/Source/WebCore/rendering/RenderObject.cpp b/Source/WebCore/rendering/RenderObject.cpp >index 8c144d651f..52c99c2684 100644 >--- a/Source/WebCore/rendering/RenderObject.cpp >+++ b/Source/WebCore/rendering/RenderObject.cpp >@@ -429,7 +429,11 @@ bool RenderObject::scrollRectToVisible(const LayoutRect& absoluteRect, bool insi > if (!enclosingLayer) > return false; > >+#if ENABLE(OVERSCROLL_EVENTS) >+ enclosingLayer->scrollRectToVisible(absoluteRect, insideFixed, options, RequestScrollEndEvent::Yes); >+#else > enclosingLayer->scrollRectToVisible(absoluteRect, insideFixed, options); >+#endif > return true; > } >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 209134
:
393744
|
393745
|
393746
|
393747
|
395799
|
395800
|
395801
|
395802
|
395805
|
395806
|
395939
|
395940
|
395943
|
395944
|
396058
|
396059
|
396062
|
399465
|
399466