WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
Patch v9 (Resolves Bug 142205).
bug-142102-20150303104447.patch (text/plain), 78.29 KB, created by
Brent Fulgham
on 2015-03-03 10:45:04 PST
(
hide
)
Description:
Patch v9 (Resolves Bug 142205).
Filename:
MIME Type:
Creator:
Brent Fulgham
Created:
2015-03-03 10:45:04 PST
Size:
78.29 KB
patch
obsolete
>Index: Source/WebCore/ChangeLog >=================================================================== >--- Source/WebCore/ChangeLog (revision 180941) >+++ Source/WebCore/ChangeLog (working copy) >@@ -1,3 +1,87 @@ >+2015-03-03 Brent Fulgham <bfulgham@apple.com> >+ >+ Move scroll animating functions from ScrollAnimator to ScrollController >+ https://bugs.webkit.org/show_bug.cgi?id=142102 >+ <rdar://problem/20007161> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ No change in functionality. >+ >+ Do some refactoring of the various scrolling classes: >+ 1. Consolidate animation times to RunLoop::Timer instead of a combination of WebCore::Timer >+ and CFRunLoopTimers. Do this for Scroll Snap Point and Rubberband animations. >+ 2. Move ScrollController from platform/mac to platform/cocoa to enable sharing with iOS. >+ 3. Move code from ScrollAnimator{Mac} -> ScrollController. >+ 4. Rename scrollOffsetInAxis -> scrollOffsetOnAxis >+ 5. Rename immediateScrollInAxis -> immediateScrollOnAxis >+ >+ * WebCore.xcodeproj/project.pbxproj: Move ScrollController to 'platform/cocoa' >+ * page/mac/EventHandlerMac.mm: Make sure the scroll controller is notified of end-of-scroll >+ events, just as is done for the "event not handled" case in EventHandler.cpp. >+ (WebCore::EventHandler::platformCompleteWheelEvent): >+ * page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.h: Remove timer and some delegate >+ methods, now that ScrollController is controlling this state. >+ * page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm: >+ (WebCore::ScrollingTreeFrameScrollingNodeMac::~ScrollingTreeFrameScrollingNodeMac): We no longer >+ need to clean up the CFRunLoopTimer. >+ (WebCore::ScrollingTreeFrameScrollingNodeMac::stopSnapRubberbandTimer): Make sure scroll >+ state is updated after rubber band snap. >+ (WebCore::ScrollingTreeFrameScrollingNodeMac::scrollOffsetOnAxis): Add temporary stub needed >+ until Bug1973 is completed.). >+ (WebCore::ScrollingTreeFrameScrollingNodeMac::immediateScrollOnAxis): Ditto. >+ (WebCore::ScrollingTreeFrameScrollingNodeMac::startSnapRubberbandTimer): Deleted. >+ * platform/ScrollAnimator.cpp: >+ (WebCore::ScrollAnimator::ScrollAnimator): >+ (WebCore::ScrollAnimator::processWheelEventForScrollSnap): Just call the ScrollController method. >+ (WebCore::ScrollAnimator::handleWheelEvent): Ditto. >+ (WebCore::ScrollAnimator::updateScrollAnimatorsAndTimers): Ditto. >+ (WebCore::ScrollAnimator::scrollOffsetOnAxis): Renamed from scrollOffsetInAxis. >+ (WebCore::ScrollAnimator::immediateScrollOnAxis): Renamed from immediateScrollInAxis. >+ (WebCore::ScrollAnimator::scrollOffsetInAxis): Deleted. >+ (WebCore::ScrollAnimator::immediateScrollInAxis): Deleted. >+ (WebCore::ScrollAnimator::startScrollSnapTimer): Deleted. >+ (WebCore::ScrollAnimator::stopScrollSnapTimer): Deleted. >+ (WebCore::ScrollAnimator::horizontalScrollSnapTimerFired): Deleted. >+ (WebCore::ScrollAnimator::verticalScrollSnapTimerFired): Deleted. >+ * platform/ScrollAnimator.h: >+ * platform/cocoa/ScrollController.h: Copied from platform/mac/ScrollController.h. >+ (WebCore::ScrollControllerClient::startSnapRubberbandTimer): >+ (WebCore::ScrollControllerClient::stopSnapRubberbandTimer): >+ (WebCore::ScrollControllerClient::startScrollSnapTimer): >+ (WebCore::ScrollControllerClient::stopScrollSnapTimer): >+ * platform/cocoa/ScrollController.mm: Copied from platform/mac/ScrollController.mm. >+ (WebCore::ScrollController::ScrollController): Update to initialize new timers. >+ (WebCore::ScrollController::handleWheelEvent): Update to handle Scroll Snap Point events. >+ (WebCore::ScrollController::startSnapRubberbandTimer): Added. >+ (WebCore::ScrollController::stopSnapRubberbandTimer): Manage animation timers locally, do not >+ require client to maintain timers. >+ (WebCore::ScrollController::snapRubberBand): Ditto. >+ (WebCore::ScrollController::processWheelEventForScrollSnap): Added. (Moved from ScrollAnimatorMac) >+ (WebCore::ScrollController::updateScrollAnimatorsAndTimers): Ditto. Also updated to use RunLoop::Timer. >+ (WebCore::ScrollController::startScrollSnapTimer): Ditto. Also updated to use RunLoop::Timer. >+ (WebCore::ScrollController::stopScrollSnapTimer): Ditto. Also updated to use RunLoop::Timer. >+ (WebCore::ScrollController::horizontalScrollSnapTimerFired): Ditto. >+ (WebCore::ScrollController::verticalScrollSnapTimerFired): Ditto. >+ (WebCore::ScrollController::scrollOffsetOnAxis): Moved from ScrollAnimatorMac. >+ (WebCore::ScrollController::immediateScrollOnAxis): Ditto. >+ * platform/mac/AxisScrollSnapAnimator.h: Rename methods from 'InAxis' to 'OnAxis' >+ * platform/mac/AxisScrollSnapAnimator.mm: >+ (WebCore::AxisScrollSnapAnimator::handleWheelEvent): Update for 'InAxis' to 'OnAxis' renaming. >+ (WebCore::AxisScrollSnapAnimator::scrollSnapAnimationUpdate): Ditto. >+ (WebCore::AxisScrollSnapAnimator::beginScrollSnapAnimation): Ditto. >+ (WebCore::AxisScrollSnapAnimator::computeSnapDelta): Ditto. >+ (WebCore::AxisScrollSnapAnimator::computeGlideDelta): Ditto. >+ * platform/mac/ScrollAnimatorMac.h: >+ * platform/mac/ScrollAnimatorMac.mm: >+ (WebCore::ScrollAnimatorMac::ScrollAnimatorMac): Remove unused Rubberband timers (now that this is >+ controlled in the ScrollController) >+ (WebCore::ScrollAnimatorMac::startSnapRubberbandTimer): Deleted. >+ (WebCore::ScrollAnimatorMac::stopSnapRubberbandTimer): Deleted. >+ (WebCore::ScrollAnimatorMac::snapRubberBandTimerFired): Deleted. >+ * platform/mac/ScrollController.h: Removed. >+ * platform/mac/ScrollController.mm: Removed. >+ > 2015-03-03 Chris Dumez <cdumez@apple.com> > > Make AudioContext suspendable when it is not rendering >Index: Source/WebCore/WebCore.xcodeproj/project.pbxproj >=================================================================== >--- Source/WebCore/WebCore.xcodeproj/project.pbxproj (revision 180935) >+++ Source/WebCore/WebCore.xcodeproj/project.pbxproj (working copy) >@@ -16587,8 +16587,6 @@ > BC51156D12B1749C00C96754 /* ScrollAnimatorMac.mm */, > BC8B853C0E7C7F1100AB6984 /* ScrollbarThemeMac.h */, > BCEF869E0E844E9D00A85CD5 /* ScrollbarThemeMac.mm */, >- 1AA84F03143BA7BD0051D153 /* ScrollController.h */, >- 1AA84F02143BA7BD0051D153 /* ScrollController.mm */, > 9353676A09AED88B00D35CD6 /* ScrollViewMac.mm */, > 077AF14118F4B1BB0001ED61 /* SerializedPlatformRepresentationMac.h */, > 077AF14218F4B1BB0001ED61 /* SerializedPlatformRepresentationMac.mm */, >@@ -18698,6 +18696,8 @@ > 1A0409F21A43675C009E47F3 /* MachSendRight.cpp */, > 1A0409DB1A4360B5009E47F3 /* MachSendRight.h */, > ADB6B29718FB90240081963E /* MemoryPressureHandlerCocoa.mm */, >+ 1AA84F03143BA7BD0051D153 /* ScrollController.h */, >+ 1AA84F02143BA7BD0051D153 /* ScrollController.mm */, > 5D5975B119635F1100D00878 /* SystemVersion.h */, > 5D5975B219635F1100D00878 /* SystemVersion.mm */, > 7CC564B918BAC720001B9652 /* TelephoneNumberDetectorCocoa.cpp */, >Index: Source/WebCore/page/mac/EventHandlerMac.mm >=================================================================== >--- Source/WebCore/page/mac/EventHandlerMac.mm (revision 180935) >+++ Source/WebCore/page/mac/EventHandlerMac.mm (working copy) >@@ -961,6 +961,12 @@ bool EventHandler::platformCompleteWheel > > bool didHandleEvent = view ? view->wheelEvent(wheelEvent) : false; > m_isHandlingWheelEvent = false; >+ >+#if ENABLE(CSS_SCROLL_SNAP) >+ if (scrollableArea) >+ platformNotifySnapIfNecessary(wheelEvent, *scrollableArea); >+#endif >+ > return didHandleEvent; > } > >Index: Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.h >=================================================================== >--- Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.h (revision 180935) >+++ Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.h (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2012 Apple Inc. All rights reserved. >+ * Copyright (C) 2012, 2014-2015 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -51,39 +51,42 @@ private: > virtual void handleWheelEvent(const PlatformWheelEvent&) override; > > // ScrollController member functions. >- virtual bool allowsHorizontalStretching(const PlatformWheelEvent&) override; >- virtual bool allowsVerticalStretching(const PlatformWheelEvent&) override; >- virtual IntSize stretchAmount() override; >- virtual bool pinnedInDirection(const FloatSize&) override; >- virtual bool canScrollHorizontally() override; >- virtual bool canScrollVertically() override; >- virtual bool shouldRubberBandInDirection(ScrollDirection) override; >- virtual IntPoint absoluteScrollPosition() override; >- virtual void immediateScrollBy(const FloatSize&) override; >- virtual void immediateScrollByWithoutContentEdgeConstraints(const FloatSize&) override; >- virtual void startSnapRubberbandTimer() override; >- virtual void stopSnapRubberbandTimer() override; >- virtual void adjustScrollPositionToBoundsIfNecessary() override; >- >- virtual FloatPoint scrollPosition() const override; >- virtual void setScrollPosition(const FloatPoint&) override; >- virtual void setScrollPositionWithoutContentEdgeConstraints(const FloatPoint&) override; >+ bool allowsHorizontalStretching(const PlatformWheelEvent&) override; >+ bool allowsVerticalStretching(const PlatformWheelEvent&) override; >+ IntSize stretchAmount() override; >+ bool pinnedInDirection(const FloatSize&) override; >+ bool canScrollHorizontally() override; >+ bool canScrollVertically() override; >+ bool shouldRubberBandInDirection(ScrollDirection) override; >+ IntPoint absoluteScrollPosition() override; >+ void immediateScrollBy(const FloatSize&) override; >+ void immediateScrollByWithoutContentEdgeConstraints(const FloatSize&) override; >+ void stopSnapRubberbandTimer() override; >+ void adjustScrollPositionToBoundsIfNecessary() override; >+ >+ FloatPoint scrollPosition() const override; >+ void setScrollPosition(const FloatPoint&) override; >+ void setScrollPositionWithoutContentEdgeConstraints(const FloatPoint&) override; > >- virtual void updateLayersAfterViewportChange(const FloatRect& fixedPositionRect, double scale) override; >+ void updateLayersAfterViewportChange(const FloatRect& fixedPositionRect, double scale) override; > >- virtual void setScrollLayerPosition(const FloatPoint&) override; >+ void setScrollLayerPosition(const FloatPoint&) override; > >- virtual FloatPoint minimumScrollPosition() const override; >- virtual FloatPoint maximumScrollPosition() const override; >+ FloatPoint minimumScrollPosition() const override; >+ FloatPoint maximumScrollPosition() const override; > > void updateMainFramePinState(const FloatPoint& scrollPosition); > > bool isAlreadyPinnedInDirectionOfGesture(const PlatformWheelEvent&, ScrollEventAxis); > >+#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC) >+ LayoutUnit scrollOffsetOnAxis(ScrollEventAxis) override; >+ void immediateScrollOnAxis(ScrollEventAxis, float delta) override; >+#endif >+ > void logExposedUnfilledArea(); > > ScrollController m_scrollController; >- RetainPtr<CFRunLoopTimerRef> m_snapRubberbandTimer; > > RetainPtr<CALayer> m_scrollLayer; > RetainPtr<CALayer> m_scrolledContentsLayer; >Index: Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm >=================================================================== >--- Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm (revision 180935) >+++ Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2012, 2014 Apple Inc. All rights reserved. >+ * Copyright (C) 2012, 2014-2015 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -66,8 +66,6 @@ ScrollingTreeFrameScrollingNodeMac::Scro > > ScrollingTreeFrameScrollingNodeMac::~ScrollingTreeFrameScrollingNodeMac() > { >- if (m_snapRubberbandTimer) >- CFRunLoopTimerInvalidate(m_snapRubberbandTimer.get()); > } > > void ScrollingTreeFrameScrollingNodeMac::updateBeforeChildren(const ScrollingStateNode& stateNode) >@@ -296,30 +294,12 @@ void ScrollingTreeFrameScrollingNodeMac: > scrollByWithoutContentEdgeConstraints(offset); > } > >-void ScrollingTreeFrameScrollingNodeMac::startSnapRubberbandTimer() >-{ >- ASSERT(!m_snapRubberbandTimer); >- >- CFTimeInterval timerInterval = 1.0 / 60.0; >- >- m_snapRubberbandTimer = adoptCF(CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + timerInterval, timerInterval, 0, 0, ^(CFRunLoopTimerRef) { >- m_scrollController.snapRubberBandTimerFired(); >- })); >- CFRunLoopAddTimer(CFRunLoopGetCurrent(), m_snapRubberbandTimer.get(), kCFRunLoopDefaultMode); >-} >- > void ScrollingTreeFrameScrollingNodeMac::stopSnapRubberbandTimer() > { >- if (!m_snapRubberbandTimer) >- return; >- > scrollingTree().setMainFrameIsRubberBanding(false); > > // Since the rubberband timer has stopped, totalContentsSizeForRubberBand can be synchronized with totalContentsSize. > setTotalContentsSizeForRubberBand(totalContentsSize()); >- >- CFRunLoopTimerInvalidate(m_snapRubberbandTimer.get()); >- m_snapRubberbandTimer = nullptr; > } > > void ScrollingTreeFrameScrollingNodeMac::adjustScrollPositionToBoundsIfNecessary() >@@ -540,6 +520,19 @@ void logWheelEventHandlerCountChanged(un > WTFLogAlways("SCROLLING: Wheel event handler count changed. Time: %f Count: %u\n", WTF::monotonicallyIncreasingTime(), count); > } > >+#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC) >+LayoutUnit ScrollingTreeFrameScrollingNodeMac::scrollOffsetOnAxis(ScrollEventAxis) >+{ >+ // Temporary stub until http://webkit.org/b/141973. >+ return 0; >+} >+ >+void ScrollingTreeFrameScrollingNodeMac::immediateScrollOnAxis(ScrollEventAxis, float) >+{ >+ // Temporary stub until http://webkit.org/b/141973. >+} >+#endif >+ > } // namespace WebCore > > #endif // ENABLE(ASYNC_SCROLLING) && PLATFORM(MAC) >Index: Source/WebCore/platform/ScrollAnimator.cpp >=================================================================== >--- Source/WebCore/platform/ScrollAnimator.cpp (revision 180935) >+++ Source/WebCore/platform/ScrollAnimator.cpp (working copy) >@@ -49,6 +49,9 @@ std::unique_ptr<ScrollAnimator> ScrollAn > > ScrollAnimator::ScrollAnimator(ScrollableArea& scrollableArea) > : m_scrollableArea(scrollableArea) >+#if (ENABLE(CSS_SCROLL_SNAP) || ENABLE(RUBBER_BANDING)) && PLATFORM(MAC) >+ , m_scrollController(this) >+#endif > , m_currentPosX(0) > , m_currentPosY(0) > { >@@ -81,28 +84,17 @@ void ScrollAnimator::scrollToOffsetWitho > } > > #if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC) >-void ScrollAnimator::processWheelEventForScrollSnap(const PlatformWheelEvent& wheelEvent) >+bool ScrollAnimator::processWheelEventForScrollSnap(const PlatformWheelEvent& wheelEvent) > { >- if (m_verticalScrollSnapAnimator) >- m_verticalScrollSnapAnimator->handleWheelEvent(wheelEvent); >- if (m_horizontalScrollSnapAnimator) >- m_horizontalScrollSnapAnimator->handleWheelEvent(wheelEvent); >+ return m_scrollController.processWheelEventForScrollSnap(wheelEvent); > } > #endif > > bool ScrollAnimator::handleWheelEvent(const PlatformWheelEvent& e) > { > #if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC) >- if (m_verticalScrollSnapAnimator) { >- m_verticalScrollSnapAnimator->handleWheelEvent(e); >- if (m_verticalScrollSnapAnimator->shouldOverrideWheelEvent(e)) >- return false; >- } >- if (m_horizontalScrollSnapAnimator) { >- m_horizontalScrollSnapAnimator->handleWheelEvent(e); >- if (m_horizontalScrollSnapAnimator->shouldOverrideWheelEvent(e)) >- return false; >- } >+ if (!m_scrollController.processWheelEventForScrollSnap(e)) >+ return false; > #endif > #if PLATFORM(COCOA) > // Events in the PlatformWheelEventPhaseMayBegin phase have no deltas, and therefore never passes through the scroll handling logic below. >@@ -183,30 +175,15 @@ void ScrollAnimator::notifyPositionChang > #if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC) > void ScrollAnimator::updateScrollAnimatorsAndTimers() > { >- // FIXME: Currently, scroll snap animators are recreated even though the snap offsets alone can be updated. >- if (m_scrollableArea.horizontalSnapOffsets()) { >- m_horizontalScrollSnapAnimator = std::make_unique<AxisScrollSnapAnimator>(this, m_scrollableArea.horizontalSnapOffsets(), ScrollEventAxis::Horizontal); >- m_horizontalScrollSnapTimer = std::make_unique<Timer>(*this, &ScrollAnimator::horizontalScrollSnapTimerFired); >- } else if (m_horizontalScrollSnapAnimator) { >- m_horizontalScrollSnapAnimator = nullptr; >- m_horizontalScrollSnapTimer = nullptr; >- } >- if (m_scrollableArea.verticalSnapOffsets()) { >- m_verticalScrollSnapAnimator = std::make_unique<AxisScrollSnapAnimator>(this, m_scrollableArea.verticalSnapOffsets(), ScrollEventAxis::Vertical); >- m_verticalScrollSnapTimer = std::make_unique<Timer>(*this, &ScrollAnimator::verticalScrollSnapTimerFired); >- } else if (m_verticalScrollSnapAnimator) { >- m_verticalScrollSnapAnimator = nullptr; >- m_verticalScrollSnapTimer = nullptr; >- } >+ m_scrollController.updateScrollAnimatorsAndTimers(m_scrollableArea); > } > >-LayoutUnit ScrollAnimator::scrollOffsetInAxis(ScrollEventAxis axis) >+LayoutUnit ScrollAnimator::scrollOffsetOnAxis(ScrollEventAxis axis) > { >- FloatPoint currentPosition = this->currentPosition(); >- return axis == ScrollEventAxis::Horizontal ? currentPosition.x() : currentPosition.y(); >+ return axis == ScrollEventAxis::Horizontal ? m_currentPosX : m_currentPosY; > } > >-void ScrollAnimator::immediateScrollInAxis(ScrollEventAxis axis, float delta) >+void ScrollAnimator::immediateScrollOnAxis(ScrollEventAxis axis, float delta) > { > FloatPoint currentPosition = this->currentPosition(); > if (axis == ScrollEventAxis::Horizontal) >@@ -214,30 +191,6 @@ void ScrollAnimator::immediateScrollInAx > else > scrollToOffsetWithoutAnimation(FloatPoint(currentPosition.x(), currentPosition.y() + delta)); > } >- >-void ScrollAnimator::startScrollSnapTimer(ScrollEventAxis axis) >-{ >- Timer* scrollSnapTimer = axis == ScrollEventAxis::Horizontal ? m_horizontalScrollSnapTimer.get() : m_verticalScrollSnapTimer.get(); >- if (!scrollSnapTimer->isActive()) >- scrollSnapTimer->startRepeating(1.0 / 60.0); >-} >- >-void ScrollAnimator::stopScrollSnapTimer(ScrollEventAxis axis) >-{ >- Timer* scrollSnapTimer = axis == ScrollEventAxis::Horizontal ? m_horizontalScrollSnapTimer.get() : m_verticalScrollSnapTimer.get(); >- if (scrollSnapTimer->isActive()) >- scrollSnapTimer->stop(); >-} >- >-void ScrollAnimator::horizontalScrollSnapTimerFired() >-{ >- m_horizontalScrollSnapAnimator->scrollSnapAnimationUpdate(); >-} >- >-void ScrollAnimator::verticalScrollSnapTimerFired() >-{ >- m_verticalScrollSnapAnimator->scrollSnapAnimationUpdate(); >-} > #endif > > } // namespace WebCore >Index: Source/WebCore/platform/ScrollAnimator.h >=================================================================== >--- Source/WebCore/platform/ScrollAnimator.h (revision 180935) >+++ Source/WebCore/platform/ScrollAnimator.h (working copy) >@@ -33,14 +33,14 @@ > #define ScrollAnimator_h > > #include "FloatSize.h" >+#include "LayoutUnit.h" > #include "PlatformWheelEvent.h" > #include "ScrollTypes.h" > #include <wtf/FastMalloc.h> > #include <wtf/Forward.h> > >-#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC) >-#include "AxisScrollSnapAnimator.h" >-#include "Timer.h" >+#if (ENABLE(RUBBER_BANDING) || ENABLE(CSS_SCROLL_SNAP)) && PLATFORM(MAC) >+#include "ScrollController.h" > #endif > > namespace WebCore { >@@ -50,8 +50,8 @@ class PlatformTouchEvent; > class ScrollableArea; > class Scrollbar; > >-#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC) >-class ScrollAnimator : public AxisScrollSnapAnimatorClient { >+#if (ENABLE(CSS_SCROLL_SNAP) || ENABLE(RUBBER_BANDING)) && PLATFORM(MAC) >+class ScrollAnimator : private ScrollControllerClient { > #else > class ScrollAnimator { > #endif >@@ -118,33 +118,21 @@ public: > virtual bool isRubberBandInProgress() const { return false; } > > #if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC) >- void processWheelEventForScrollSnap(const PlatformWheelEvent&); >+ bool processWheelEventForScrollSnap(const PlatformWheelEvent&); > void updateScrollAnimatorsAndTimers(); >- virtual LayoutUnit scrollOffsetInAxis(ScrollEventAxis) override; >- virtual void immediateScrollInAxis(ScrollEventAxis, float delta) override; >- virtual void startScrollSnapTimer(ScrollEventAxis) override; >- virtual void stopScrollSnapTimer(ScrollEventAxis) override; >+ LayoutUnit scrollOffsetOnAxis(ScrollEventAxis) override; >+ void immediateScrollOnAxis(ScrollEventAxis, float delta) override; > #endif > > protected: > virtual void notifyPositionChanged(const FloatSize& delta); > >-#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC) >- // Trivial wrappers around the actual update loop in AxisScrollSnapAnimator, since WebCore Timer requires a Timer argument. >- void horizontalScrollSnapTimerFired(); >- void verticalScrollSnapTimerFired(); >-#endif >- > ScrollableArea& m_scrollableArea; >+#if (ENABLE(CSS_SCROLL_SNAP) || ENABLE(RUBBER_BANDING)) && PLATFORM(MAC) >+ ScrollController m_scrollController; >+#endif > float m_currentPosX; // We avoid using a FloatPoint in order to reduce > float m_currentPosY; // subclass code complexity. >-#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC) >- std::unique_ptr<AxisScrollSnapAnimator> m_horizontalScrollSnapAnimator; >- std::unique_ptr<Timer> m_horizontalScrollSnapTimer; >- // FIXME: Find a way to consolidate both timers into one variable. >- std::unique_ptr<AxisScrollSnapAnimator> m_verticalScrollSnapAnimator; >- std::unique_ptr<Timer> m_verticalScrollSnapTimer; >-#endif > }; > > } // namespace WebCore >Index: Source/WebCore/platform/cocoa/ScrollController.h >=================================================================== >--- Source/WebCore/platform/cocoa/ScrollController.h (revision 180935) (from Source/WebCore/platform/mac/ScrollController.h:180935) >+++ Source/WebCore/platform/cocoa/ScrollController.h (working copy) >@@ -0,0 +1,107 @@ >+/* >+ * Copyright (C) 2011 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >+ * THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#ifndef ScrollController_h >+#define ScrollController_h >+ >+#if ENABLE(RUBBER_BANDING) >+ >+#include "FloatPoint.h" >+#include "FloatSize.h" >+#include "ScrollTypes.h" >+#include <wtf/Noncopyable.h> >+ >+namespace WebCore { >+ >+class PlatformWheelEvent; >+ >+class ScrollControllerClient { >+protected: >+ virtual ~ScrollControllerClient() { } >+ >+public: >+ virtual bool allowsHorizontalStretching(const PlatformWheelEvent&) = 0; >+ virtual bool allowsVerticalStretching(const PlatformWheelEvent&) = 0; >+ virtual IntSize stretchAmount() = 0; >+ virtual bool pinnedInDirection(const FloatSize&) = 0; >+ virtual bool canScrollHorizontally() = 0; >+ virtual bool canScrollVertically() = 0; >+ virtual bool shouldRubberBandInDirection(ScrollDirection) = 0; >+ >+ // Return the absolute scroll position, not relative to the scroll origin. >+ virtual WebCore::IntPoint absoluteScrollPosition() = 0; >+ >+ virtual void immediateScrollBy(const FloatSize&) = 0; >+ virtual void immediateScrollByWithoutContentEdgeConstraints(const FloatSize&) = 0; >+ virtual void startSnapRubberbandTimer() = 0; >+ virtual void stopSnapRubberbandTimer() = 0; >+ >+ // If the current scroll position is within the overhang area, this function will cause >+ // the page to scroll to the nearest boundary point. >+ virtual void adjustScrollPositionToBoundsIfNecessary() = 0; >+}; >+ >+class ScrollController { >+ WTF_MAKE_NONCOPYABLE(ScrollController); >+ >+public: >+ explicit ScrollController(ScrollControllerClient*); >+ >+ bool handleWheelEvent(const PlatformWheelEvent&); >+ void snapRubberBandTimerFired(); >+ >+ bool isRubberBandInProgress() const; >+ >+private: >+ void stopSnapRubberbandTimer(); >+ void snapRubberBand(); >+ >+ bool shouldRubberBandInHorizontalDirection(const PlatformWheelEvent&); >+ >+ ScrollControllerClient* m_client; >+ >+ bool m_inScrollGesture; >+ bool m_momentumScrollInProgress; >+ bool m_ignoreMomentumScrolls; >+ >+ CFTimeInterval m_lastMomentumScrollTimestamp; >+ FloatSize m_overflowScrollDelta; >+ FloatSize m_stretchScrollForce; >+ FloatSize m_momentumVelocity; >+ >+ // Rubber band state. >+ CFTimeInterval m_startTime; >+ FloatSize m_startStretch; >+ FloatPoint m_origOrigin; >+ FloatSize m_origVelocity; >+ >+ bool m_snapRubberbandTimerIsActive; >+}; >+ >+} // namespace WebCore >+ >+#endif // ENABLE(RUBBER_BANDING) >+ >+#endif // ScrollController_h >Index: Source/WebCore/platform/cocoa/ScrollController.h >=================================================================== >--- Source/WebCore/platform/cocoa/ScrollController.h (working copy) >+++ Source/WebCore/platform/cocoa/ScrollController.h (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2011 Apple Inc. All rights reserved. >+ * Copyright (C) 2011, 2014-2015 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -32,10 +32,16 @@ > #include "FloatSize.h" > #include "ScrollTypes.h" > #include <wtf/Noncopyable.h> >+#include <wtf/RunLoop.h> >+ >+#if ENABLE(CSS_SCROLL_SNAP) >+#include "AxisScrollSnapAnimator.h" >+#endif > > namespace WebCore { > > class PlatformWheelEvent; >+class ScrollableArea; > > class ScrollControllerClient { > protected: >@@ -55,36 +61,74 @@ public: > > virtual void immediateScrollBy(const FloatSize&) = 0; > virtual void immediateScrollByWithoutContentEdgeConstraints(const FloatSize&) = 0; >- virtual void startSnapRubberbandTimer() = 0; >- virtual void stopSnapRubberbandTimer() = 0; >- >+ virtual void startSnapRubberbandTimer() >+ { >+ // Override to perform client-specific snap start logic >+ } >+ >+ virtual void stopSnapRubberbandTimer() >+ { >+ // Override to perform client-specific snap end logic >+ } >+ > // If the current scroll position is within the overhang area, this function will cause > // the page to scroll to the nearest boundary point. > virtual void adjustScrollPositionToBoundsIfNecessary() = 0; >+ >+#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC) >+ virtual LayoutUnit scrollOffsetOnAxis(ScrollEventAxis) = 0; >+ virtual void immediateScrollOnAxis(ScrollEventAxis, float delta) = 0; >+ virtual void startScrollSnapTimer(ScrollEventAxis) >+ { >+ // Override to perform client-specific scroll snap point start logic >+ } >+ >+ virtual void stopScrollSnapTimer(ScrollEventAxis) >+ { >+ // Override to perform client-specific scroll snap point end logic >+ >+ } >+#endif > }; > >+#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC) >+class ScrollController : public AxisScrollSnapAnimatorClient { >+#else > class ScrollController { >+#endif > WTF_MAKE_NONCOPYABLE(ScrollController); > > public: > explicit ScrollController(ScrollControllerClient*); > > bool handleWheelEvent(const PlatformWheelEvent&); >- void snapRubberBandTimerFired(); > > bool isRubberBandInProgress() const; > >+#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC) >+ bool processWheelEventForScrollSnap(const PlatformWheelEvent&); >+ void updateScrollAnimatorsAndTimers(const ScrollableArea&); >+#endif >+ > private: >+ void startSnapRubberbandTimer(); > void stopSnapRubberbandTimer(); > void snapRubberBand(); >+ void snapRubberBandTimerFired(); > > bool shouldRubberBandInHorizontalDirection(const PlatformWheelEvent&); > >- ScrollControllerClient* m_client; >+#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC) >+ void horizontalScrollSnapTimerFired(); >+ void verticalScrollSnapTimerFired(); >+ void startScrollSnapTimer(ScrollEventAxis) override; >+ void stopScrollSnapTimer(ScrollEventAxis) override; >+ >+ LayoutUnit scrollOffsetOnAxis(ScrollEventAxis) override; >+ void immediateScrollOnAxis(ScrollEventAxis, float delta) override; >+#endif > >- bool m_inScrollGesture; >- bool m_momentumScrollInProgress; >- bool m_ignoreMomentumScrolls; >+ ScrollControllerClient* m_client; > > CFTimeInterval m_lastMomentumScrollTimestamp; > FloatSize m_overflowScrollDelta; >@@ -96,7 +140,19 @@ private: > FloatSize m_startStretch; > FloatPoint m_origOrigin; > FloatSize m_origVelocity; >+ RunLoop::Timer<ScrollController> m_snapRubberbandTimer; > >+#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC) >+ // FIXME: Find a way to consolidate both timers into one variable. >+ std::unique_ptr<AxisScrollSnapAnimator> m_horizontalScrollSnapAnimator; >+ std::unique_ptr<AxisScrollSnapAnimator> m_verticalScrollSnapAnimator; >+ RunLoop::Timer<ScrollController> m_horizontalScrollSnapTimer; >+ RunLoop::Timer<ScrollController> m_verticalScrollSnapTimer; >+#endif >+ >+ bool m_inScrollGesture; >+ bool m_momentumScrollInProgress; >+ bool m_ignoreMomentumScrolls; > bool m_snapRubberbandTimerIsActive; > }; > >Index: Source/WebCore/platform/cocoa/ScrollController.mm >=================================================================== >--- Source/WebCore/platform/cocoa/ScrollController.mm (revision 180935) (from Source/WebCore/platform/mac/ScrollController.mm:180935) >+++ Source/WebCore/platform/cocoa/ScrollController.mm (working copy) >@@ -0,0 +1,406 @@ >+/* >+ * Copyright (C) 2011, 2014-2015 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >+ * THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#include "config.h" >+#include "ScrollController.h" >+ >+#include "PlatformWheelEvent.h" >+#include "WebCoreSystemInterface.h" >+#include <sys/sysctl.h> >+#include <sys/time.h> >+ >+#if ENABLE(RUBBER_BANDING) >+ >+static NSTimeInterval systemUptime() >+{ >+ if ([[NSProcessInfo processInfo] respondsToSelector:@selector(systemUptime)]) >+ return [[NSProcessInfo processInfo] systemUptime]; >+ >+ // Get how long system has been up. Found by looking getting "boottime" from the kernel. >+ static struct timeval boottime = {0, 0}; >+ if (!boottime.tv_sec) { >+ int mib[2] = {CTL_KERN, KERN_BOOTTIME}; >+ size_t size = sizeof(boottime); >+ if (-1 == sysctl(mib, 2, &boottime, &size, 0, 0)) >+ boottime.tv_sec = 0; >+ } >+ struct timeval now; >+ if (boottime.tv_sec && -1 != gettimeofday(&now, 0)) { >+ struct timeval uptime; >+ timersub(&now, &boottime, &uptime); >+ NSTimeInterval result = uptime.tv_sec + (uptime.tv_usec / 1E+6); >+ return result; >+ } >+ return 0; >+} >+ >+ >+namespace WebCore { >+ >+static const float scrollVelocityZeroingTimeout = 0.10f; >+static const float rubberbandDirectionLockStretchRatio = 1; >+static const float rubberbandMinimumRequiredDeltaBeforeStretch = 10; >+ >+static float elasticDeltaForTimeDelta(float initialPosition, float initialVelocity, float elapsedTime) >+{ >+ return wkNSElasticDeltaForTimeDelta(initialPosition, initialVelocity, elapsedTime); >+} >+ >+static float elasticDeltaForReboundDelta(float delta) >+{ >+ return wkNSElasticDeltaForReboundDelta(delta); >+} >+ >+static float reboundDeltaForElasticDelta(float delta) >+{ >+ return wkNSReboundDeltaForElasticDelta(delta); >+} >+ >+static float scrollWheelMultiplier() >+{ >+ static float multiplier = -1; >+ if (multiplier < 0) { >+ multiplier = [[NSUserDefaults standardUserDefaults] floatForKey:@"NSScrollWheelMultiplier"]; >+ if (multiplier <= 0) >+ multiplier = 1; >+ } >+ return multiplier; >+} >+ >+ScrollController::ScrollController(ScrollControllerClient* client) >+ : m_client(client) >+ , m_inScrollGesture(false) >+ , m_momentumScrollInProgress(false) >+ , m_ignoreMomentumScrolls(false) >+ , m_lastMomentumScrollTimestamp(0) >+ , m_startTime(0) >+ , m_snapRubberbandTimerIsActive(false) >+{ >+} >+ >+bool ScrollController::handleWheelEvent(const PlatformWheelEvent& wheelEvent) >+{ >+ if (wheelEvent.phase() == PlatformWheelEventPhaseBegan) { >+ // First, check if we should rubber-band at all. >+ if (m_client->pinnedInDirection(FloatSize(-wheelEvent.deltaX(), 0)) >+ && !shouldRubberBandInHorizontalDirection(wheelEvent)) >+ return false; >+ >+ m_inScrollGesture = true; >+ m_momentumScrollInProgress = false; >+ m_ignoreMomentumScrolls = false; >+ m_lastMomentumScrollTimestamp = 0; >+ m_momentumVelocity = FloatSize(); >+ >+ IntSize stretchAmount = m_client->stretchAmount(); >+ m_stretchScrollForce.setWidth(reboundDeltaForElasticDelta(stretchAmount.width())); >+ m_stretchScrollForce.setHeight(reboundDeltaForElasticDelta(stretchAmount.height())); >+ m_overflowScrollDelta = FloatSize(); >+ >+ stopSnapRubberbandTimer(); >+ >+ return true; >+ } >+ >+ if (wheelEvent.phase() == PlatformWheelEventPhaseEnded) { >+ snapRubberBand(); >+ return true; >+ } >+ >+ bool isMomentumScrollEvent = (wheelEvent.momentumPhase() != PlatformWheelEventPhaseNone); >+ if (m_ignoreMomentumScrolls && (isMomentumScrollEvent || m_snapRubberbandTimerIsActive)) { >+ if (wheelEvent.momentumPhase() == PlatformWheelEventPhaseEnded) { >+ m_ignoreMomentumScrolls = false; >+ return true; >+ } >+ return false; >+ } >+ >+ float deltaX = m_overflowScrollDelta.width(); >+ float deltaY = m_overflowScrollDelta.height(); >+ >+ // Reset overflow values because we may decide to remove delta at various points and put it into overflow. >+ m_overflowScrollDelta = FloatSize(); >+ >+ IntSize stretchAmount = m_client->stretchAmount(); >+ bool isVerticallyStretched = stretchAmount.height(); >+ bool isHorizontallyStretched = stretchAmount.width(); >+ >+ float eventCoalescedDeltaX; >+ float eventCoalescedDeltaY; >+ >+ if (isVerticallyStretched || isHorizontallyStretched) { >+ eventCoalescedDeltaX = -wheelEvent.unacceleratedScrollingDeltaX(); >+ eventCoalescedDeltaY = -wheelEvent.unacceleratedScrollingDeltaY(); >+ } else { >+ eventCoalescedDeltaX = -wheelEvent.deltaX(); >+ eventCoalescedDeltaY = -wheelEvent.deltaY(); >+ } >+ >+ deltaX += eventCoalescedDeltaX; >+ deltaY += eventCoalescedDeltaY; >+ >+ // Slightly prefer scrolling vertically by applying the = case to deltaY >+ if (fabsf(deltaY) >= fabsf(deltaX)) >+ deltaX = 0; >+ else >+ deltaY = 0; >+ >+ bool shouldStretch = false; >+ >+ PlatformWheelEventPhase momentumPhase = wheelEvent.momentumPhase(); >+ >+ // If we are starting momentum scrolling then do some setup. >+ if (!m_momentumScrollInProgress && (momentumPhase == PlatformWheelEventPhaseBegan || momentumPhase == PlatformWheelEventPhaseChanged)) >+ m_momentumScrollInProgress = true; >+ >+ CFTimeInterval timeDelta = wheelEvent.timestamp() - m_lastMomentumScrollTimestamp; >+ if (m_inScrollGesture || m_momentumScrollInProgress) { >+ if (m_lastMomentumScrollTimestamp && timeDelta > 0 && timeDelta < scrollVelocityZeroingTimeout) { >+ m_momentumVelocity.setWidth(eventCoalescedDeltaX / (float)timeDelta); >+ m_momentumVelocity.setHeight(eventCoalescedDeltaY / (float)timeDelta); >+ m_lastMomentumScrollTimestamp = wheelEvent.timestamp(); >+ } else { >+ m_lastMomentumScrollTimestamp = wheelEvent.timestamp(); >+ m_momentumVelocity = FloatSize(); >+ } >+ >+ if (isVerticallyStretched) { >+ if (!isHorizontallyStretched && m_client->pinnedInDirection(FloatSize(deltaX, 0))) { >+ // Stretching only in the vertical. >+ if (deltaY && (fabsf(deltaX / deltaY) < rubberbandDirectionLockStretchRatio)) >+ deltaX = 0; >+ else if (fabsf(deltaX) < rubberbandMinimumRequiredDeltaBeforeStretch) { >+ m_overflowScrollDelta.setWidth(m_overflowScrollDelta.width() + deltaX); >+ deltaX = 0; >+ } else >+ m_overflowScrollDelta.setWidth(m_overflowScrollDelta.width() + deltaX); >+ } >+ } else if (isHorizontallyStretched) { >+ // Stretching only in the horizontal. >+ if (m_client->pinnedInDirection(FloatSize(0, deltaY))) { >+ if (deltaX && (fabsf(deltaY / deltaX) < rubberbandDirectionLockStretchRatio)) >+ deltaY = 0; >+ else if (fabsf(deltaY) < rubberbandMinimumRequiredDeltaBeforeStretch) { >+ m_overflowScrollDelta.setHeight(m_overflowScrollDelta.height() + deltaY); >+ deltaY = 0; >+ } else >+ m_overflowScrollDelta.setHeight(m_overflowScrollDelta.height() + deltaY); >+ } >+ } else { >+ // Not stretching at all yet. >+ if (m_client->pinnedInDirection(FloatSize(deltaX, deltaY))) { >+ if (fabsf(deltaY) >= fabsf(deltaX)) { >+ if (fabsf(deltaX) < rubberbandMinimumRequiredDeltaBeforeStretch) { >+ m_overflowScrollDelta.setWidth(m_overflowScrollDelta.width() + deltaX); >+ deltaX = 0; >+ } else >+ m_overflowScrollDelta.setWidth(m_overflowScrollDelta.width() + deltaX); >+ } >+ shouldStretch = true; >+ } >+ } >+ } >+ >+ if (deltaX || deltaY) { >+ if (!(shouldStretch || isVerticallyStretched || isHorizontallyStretched)) { >+ if (deltaY) { >+ deltaY *= scrollWheelMultiplier(); >+ m_client->immediateScrollBy(FloatSize(0, deltaY)); >+ } >+ if (deltaX) { >+ deltaX *= scrollWheelMultiplier(); >+ m_client->immediateScrollBy(FloatSize(deltaX, 0)); >+ } >+ } else { >+ if (!m_client->allowsHorizontalStretching(wheelEvent)) { >+ deltaX = 0; >+ eventCoalescedDeltaX = 0; >+ } else if (deltaX && !isHorizontallyStretched && !m_client->pinnedInDirection(FloatSize(deltaX, 0))) { >+ deltaX *= scrollWheelMultiplier(); >+ >+ m_client->immediateScrollByWithoutContentEdgeConstraints(FloatSize(deltaX, 0)); >+ deltaX = 0; >+ } >+ >+ if (!m_client->allowsVerticalStretching(wheelEvent)) { >+ deltaY = 0; >+ eventCoalescedDeltaY = 0; >+ } else if (deltaY && !isVerticallyStretched && !m_client->pinnedInDirection(FloatSize(0, deltaY))) { >+ deltaY *= scrollWheelMultiplier(); >+ >+ m_client->immediateScrollByWithoutContentEdgeConstraints(FloatSize(0, deltaY)); >+ deltaY = 0; >+ } >+ >+ IntSize stretchAmount = m_client->stretchAmount(); >+ >+ if (m_momentumScrollInProgress) { >+ if ((m_client->pinnedInDirection(FloatSize(eventCoalescedDeltaX, eventCoalescedDeltaY)) || (fabsf(eventCoalescedDeltaX) + fabsf(eventCoalescedDeltaY) <= 0)) && m_lastMomentumScrollTimestamp) { >+ m_ignoreMomentumScrolls = true; >+ m_momentumScrollInProgress = false; >+ snapRubberBand(); >+ } >+ } >+ >+ m_stretchScrollForce.setWidth(m_stretchScrollForce.width() + deltaX); >+ m_stretchScrollForce.setHeight(m_stretchScrollForce.height() + deltaY); >+ >+ FloatSize dampedDelta(ceilf(elasticDeltaForReboundDelta(m_stretchScrollForce.width())), ceilf(elasticDeltaForReboundDelta(m_stretchScrollForce.height()))); >+ >+ m_client->immediateScrollByWithoutContentEdgeConstraints(dampedDelta - stretchAmount); >+ } >+ } >+ >+ if (m_momentumScrollInProgress && momentumPhase == PlatformWheelEventPhaseEnded) { >+ m_momentumScrollInProgress = false; >+ m_ignoreMomentumScrolls = false; >+ m_lastMomentumScrollTimestamp = 0; >+ } >+ >+ return true; >+} >+ >+static inline float roundTowardZero(float num) >+{ >+ return num > 0 ? ceilf(num - 0.5f) : floorf(num + 0.5f); >+} >+ >+static inline float roundToDevicePixelTowardZero(float num) >+{ >+ float roundedNum = roundf(num); >+ if (fabs(num - roundedNum) < 0.125) >+ num = roundedNum; >+ >+ return roundTowardZero(num); >+} >+ >+void ScrollController::snapRubberBandTimerFired() >+{ >+ if (!m_momentumScrollInProgress || m_ignoreMomentumScrolls) { >+ CFTimeInterval timeDelta = [NSDate timeIntervalSinceReferenceDate] - m_startTime; >+ >+ if (m_startStretch == FloatSize()) { >+ m_startStretch = m_client->stretchAmount(); >+ if (m_startStretch == FloatSize()) { >+ stopSnapRubberbandTimer(); >+ >+ m_stretchScrollForce = FloatSize(); >+ m_startTime = 0; >+ m_startStretch = FloatSize(); >+ m_origOrigin = FloatPoint(); >+ m_origVelocity = FloatSize(); >+ return; >+ } >+ >+ m_origOrigin = m_client->absoluteScrollPosition() - m_startStretch; >+ m_origVelocity = m_momentumVelocity; >+ >+ // Just like normal scrolling, prefer vertical rubberbanding >+ if (fabsf(m_origVelocity.height()) >= fabsf(m_origVelocity.width())) >+ m_origVelocity.setWidth(0); >+ >+ // Don't rubber-band horizontally if it's not possible to scroll horizontally >+ if (!m_client->canScrollHorizontally()) >+ m_origVelocity.setWidth(0); >+ >+ // Don't rubber-band vertically if it's not possible to scroll vertically >+ if (!m_client->canScrollVertically()) >+ m_origVelocity.setHeight(0); >+ } >+ >+ FloatPoint delta(roundToDevicePixelTowardZero(elasticDeltaForTimeDelta(m_startStretch.width(), -m_origVelocity.width(), (float)timeDelta)), >+ roundToDevicePixelTowardZero(elasticDeltaForTimeDelta(m_startStretch.height(), -m_origVelocity.height(), (float)timeDelta))); >+ >+ if (fabs(delta.x()) >= 1 || fabs(delta.y()) >= 1) { >+ m_client->immediateScrollByWithoutContentEdgeConstraints(FloatSize(delta.x(), delta.y()) - m_client->stretchAmount()); >+ >+ FloatSize newStretch = m_client->stretchAmount(); >+ >+ m_stretchScrollForce.setWidth(reboundDeltaForElasticDelta(newStretch.width())); >+ m_stretchScrollForce.setHeight(reboundDeltaForElasticDelta(newStretch.height())); >+ } else { >+ m_client->adjustScrollPositionToBoundsIfNecessary(); >+ >+ stopSnapRubberbandTimer(); >+ m_stretchScrollForce = FloatSize(); >+ m_startTime = 0; >+ m_startStretch = FloatSize(); >+ m_origOrigin = FloatPoint(); >+ m_origVelocity = FloatSize(); >+ } >+ } else { >+ m_startTime = [NSDate timeIntervalSinceReferenceDate]; >+ m_startStretch = FloatSize(); >+ } >+} >+ >+bool ScrollController::isRubberBandInProgress() const >+{ >+ if (!m_inScrollGesture && !m_momentumScrollInProgress && !m_snapRubberbandTimerIsActive) >+ return false; >+ >+ return !m_client->stretchAmount().isZero(); >+} >+ >+void ScrollController::stopSnapRubberbandTimer() >+{ >+ m_client->stopSnapRubberbandTimer(); >+ m_snapRubberbandTimerIsActive = false; >+} >+ >+void ScrollController::snapRubberBand() >+{ >+ CFTimeInterval timeDelta = systemUptime() - m_lastMomentumScrollTimestamp; >+ if (m_lastMomentumScrollTimestamp && timeDelta >= scrollVelocityZeroingTimeout) >+ m_momentumVelocity = FloatSize(); >+ >+ m_inScrollGesture = false; >+ >+ if (m_snapRubberbandTimerIsActive) >+ return; >+ >+ m_startTime = [NSDate timeIntervalSinceReferenceDate]; >+ m_startStretch = FloatSize(); >+ m_origOrigin = FloatPoint(); >+ m_origVelocity = FloatSize(); >+ >+ m_client->startSnapRubberbandTimer(); >+ m_snapRubberbandTimerIsActive = true; >+} >+ >+bool ScrollController::shouldRubberBandInHorizontalDirection(const PlatformWheelEvent& wheelEvent) >+{ >+ if (wheelEvent.deltaX() > 0) >+ return m_client->shouldRubberBandInDirection(ScrollLeft); >+ if (wheelEvent.deltaX() < 0) >+ return m_client->shouldRubberBandInDirection(ScrollRight); >+ >+ return true; >+} >+ >+} // namespace WebCore >+ >+#endif // ENABLE(RUBBER_BANDING) >Index: Source/WebCore/platform/cocoa/ScrollController.mm >=================================================================== >--- Source/WebCore/platform/cocoa/ScrollController.mm (working copy) >+++ Source/WebCore/platform/cocoa/ScrollController.mm (working copy) >@@ -31,6 +31,11 @@ > #include <sys/sysctl.h> > #include <sys/time.h> > >+#if ENABLE(CSS_SCROLL_SNAP) >+#include "AxisScrollSnapAnimator.h" >+#include "ScrollableArea.h" >+#endif >+ > #if ENABLE(RUBBER_BANDING) > > static NSTimeInterval systemUptime() >@@ -91,17 +96,26 @@ static float scrollWheelMultiplier() > > ScrollController::ScrollController(ScrollControllerClient* client) > : m_client(client) >+ , m_lastMomentumScrollTimestamp(0) >+ , m_startTime(0) >+ , m_snapRubberbandTimer(RunLoop::current(), this, &ScrollController::snapRubberBandTimerFired) >+#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC) >+ , m_horizontalScrollSnapTimer(RunLoop::current(), this, &ScrollController::horizontalScrollSnapTimerFired) >+ , m_verticalScrollSnapTimer(RunLoop::current(), this, &ScrollController::verticalScrollSnapTimerFired) >+#endif > , m_inScrollGesture(false) > , m_momentumScrollInProgress(false) > , m_ignoreMomentumScrolls(false) >- , m_lastMomentumScrollTimestamp(0) >- , m_startTime(0) > , m_snapRubberbandTimerIsActive(false) > { > } > > bool ScrollController::handleWheelEvent(const PlatformWheelEvent& wheelEvent) > { >+#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC) >+ if (!processWheelEventForScrollSnap(wheelEvent)) >+ return false; >+#endif > if (wheelEvent.phase() == PlatformWheelEventPhaseBegan) { > // First, check if we should rubber-band at all. > if (m_client->pinnedInDirection(FloatSize(-wheelEvent.deltaX(), 0)) >@@ -365,9 +379,16 @@ bool ScrollController::isRubberBandInPro > return !m_client->stretchAmount().isZero(); > } > >+void ScrollController::startSnapRubberbandTimer() >+{ >+ m_client->startSnapRubberbandTimer(); >+ m_snapRubberbandTimer.startRepeating(1.0 / 60.0); >+} >+ > void ScrollController::stopSnapRubberbandTimer() > { > m_client->stopSnapRubberbandTimer(); >+ m_snapRubberbandTimer.stop(); > m_snapRubberbandTimerIsActive = false; > } > >@@ -387,7 +408,7 @@ void ScrollController::snapRubberBand() > m_origOrigin = FloatPoint(); > m_origVelocity = FloatSize(); > >- m_client->startSnapRubberbandTimer(); >+ startSnapRubberbandTimer(); > m_snapRubberbandTimerIsActive = true; > } > >@@ -401,6 +422,73 @@ bool ScrollController::shouldRubberBandI > return true; > } > >+#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC) >+bool ScrollController::processWheelEventForScrollSnap(const PlatformWheelEvent& wheelEvent) >+{ >+ if (m_verticalScrollSnapAnimator) { >+ m_verticalScrollSnapAnimator->handleWheelEvent(wheelEvent); >+ if (m_verticalScrollSnapAnimator->shouldOverrideWheelEvent(wheelEvent)) >+ return false; >+ } >+ if (m_horizontalScrollSnapAnimator) { >+ m_horizontalScrollSnapAnimator->handleWheelEvent(wheelEvent); >+ if (m_horizontalScrollSnapAnimator->shouldOverrideWheelEvent(wheelEvent)) >+ return false; >+ } >+ >+ return true; >+} >+ >+void ScrollController::updateScrollAnimatorsAndTimers(const ScrollableArea& scrollableArea) >+{ >+ // FIXME: Currently, scroll snap animators are recreated even though the snap offsets alone can be updated. >+ if (scrollableArea.horizontalSnapOffsets()) >+ m_horizontalScrollSnapAnimator = std::make_unique<AxisScrollSnapAnimator>(this, scrollableArea.horizontalSnapOffsets(), ScrollEventAxis::Horizontal); >+ else if (m_horizontalScrollSnapAnimator) >+ m_horizontalScrollSnapAnimator = nullptr; >+ >+ if (scrollableArea.verticalSnapOffsets()) >+ m_verticalScrollSnapAnimator = std::make_unique<AxisScrollSnapAnimator>(this, scrollableArea.verticalSnapOffsets(), ScrollEventAxis::Vertical); >+ else if (m_verticalScrollSnapAnimator) >+ m_verticalScrollSnapAnimator = nullptr; >+} >+ >+void ScrollController::startScrollSnapTimer(ScrollEventAxis axis) >+{ >+ RunLoop::Timer<ScrollController>& scrollSnapTimer = axis == ScrollEventAxis::Horizontal ? m_horizontalScrollSnapTimer : m_verticalScrollSnapTimer; >+ if (!scrollSnapTimer.isActive()) >+ scrollSnapTimer.startRepeating(1.0 / 60.0); >+} >+ >+void ScrollController::stopScrollSnapTimer(ScrollEventAxis axis) >+{ >+ RunLoop::Timer<ScrollController>& scrollSnapTimer = axis == ScrollEventAxis::Horizontal ? m_horizontalScrollSnapTimer : m_verticalScrollSnapTimer; >+ scrollSnapTimer.stop(); >+} >+ >+void ScrollController::horizontalScrollSnapTimerFired() >+{ >+ if (m_horizontalScrollSnapAnimator) >+ m_horizontalScrollSnapAnimator->scrollSnapAnimationUpdate(); >+} >+ >+void ScrollController::verticalScrollSnapTimerFired() >+{ >+ if (m_verticalScrollSnapAnimator) >+ m_verticalScrollSnapAnimator->scrollSnapAnimationUpdate(); >+} >+ >+LayoutUnit ScrollController::scrollOffsetOnAxis(ScrollEventAxis axis) >+{ >+ return m_client->scrollOffsetOnAxis(axis); >+} >+ >+void ScrollController::immediateScrollOnAxis(ScrollEventAxis axis, float delta) >+{ >+ m_client->immediateScrollOnAxis(axis, delta); >+} >+#endif >+ > } // namespace WebCore > > #endif // ENABLE(RUBBER_BANDING) >Index: Source/WebCore/platform/mac/AxisScrollSnapAnimator.h >=================================================================== >--- Source/WebCore/platform/mac/AxisScrollSnapAnimator.h (revision 180935) >+++ Source/WebCore/platform/mac/AxisScrollSnapAnimator.h (working copy) >@@ -57,8 +57,8 @@ protected: > virtual ~AxisScrollSnapAnimatorClient() { } > > public: >- virtual LayoutUnit scrollOffsetInAxis(ScrollEventAxis) = 0; >- virtual void immediateScrollInAxis(ScrollEventAxis, float velocity) = 0; >+ virtual LayoutUnit scrollOffsetOnAxis(ScrollEventAxis) = 0; >+ virtual void immediateScrollOnAxis(ScrollEventAxis, float velocity) = 0; > virtual void startScrollSnapTimer(ScrollEventAxis) = 0; > virtual void stopScrollSnapTimer(ScrollEventAxis) = 0; > }; >Index: Source/WebCore/platform/mac/AxisScrollSnapAnimator.mm >=================================================================== >--- Source/WebCore/platform/mac/AxisScrollSnapAnimator.mm (revision 180935) >+++ Source/WebCore/platform/mac/AxisScrollSnapAnimator.mm (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2014 Apple Inc. All rights reserved. >+ * Copyright (C) 2014-2015 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -117,7 +117,7 @@ void AxisScrollSnapAnimator::handleWheel > // Begin tracking wheel deltas for glide prediction. > endScrollSnapAnimation(ScrollSnapState::UserInteraction); > pushInitialWheelDelta(wheelDelta); >- m_beginTrackingWheelDeltaOffset = m_client->scrollOffsetInAxis(m_axis); >+ m_beginTrackingWheelDeltaOffset = m_client->scrollOffsetOnAxis(m_axis); > break; > > case WheelEventStatus::InertialScrolling: >@@ -153,7 +153,7 @@ void AxisScrollSnapAnimator::scrollSnapA > ASSERT(m_currentState == ScrollSnapState::Gliding || m_currentState == ScrollSnapState::Snapping); > float delta = m_currentState == ScrollSnapState::Snapping ? computeSnapDelta() : computeGlideDelta(); > if (delta) >- m_client->immediateScrollInAxis(m_axis, delta); >+ m_client->immediateScrollOnAxis(m_axis, delta); > else > endScrollSnapAnimation(ScrollSnapState::DestinationReached); > } >@@ -161,7 +161,7 @@ void AxisScrollSnapAnimator::scrollSnapA > void AxisScrollSnapAnimator::beginScrollSnapAnimation(ScrollSnapState newState) > { > ASSERT(newState == ScrollSnapState::Gliding || newState == ScrollSnapState::Snapping); >- LayoutUnit offset = m_client->scrollOffsetInAxis(m_axis); >+ LayoutUnit offset = m_client->scrollOffsetOnAxis(m_axis); > float initialWheelDelta = newState == ScrollSnapState::Gliding ? averageInitialWheelDelta() : 0; > LayoutUnit projectedScrollDestination = newState == ScrollSnapState::Gliding ? m_beginTrackingWheelDeltaOffset + LayoutUnit(projectedInertialScrollDistance(initialWheelDelta)) : offset; > projectedScrollDestination = std::min(std::max(projectedScrollDestination, m_snapOffsets->first()), m_snapOffsets->last()); >@@ -203,7 +203,7 @@ void AxisScrollSnapAnimator::endScrollSn > // relationship of the distance traveled, clamped by arbitrary min and max values. > float AxisScrollSnapAnimator::computeSnapDelta() const > { >- LayoutUnit offset = m_client->scrollOffsetInAxis(m_axis); >+ LayoutUnit offset = m_client->scrollOffsetOnAxis(m_axis); > bool canComputeSnap = (m_initialOffset <= offset && offset < m_targetOffset) || (m_targetOffset < offset && offset <= m_initialOffset); > if (m_currentState != ScrollSnapState::Snapping || !canComputeSnap) > return 0; >@@ -237,7 +237,7 @@ float AxisScrollSnapAnimator::computeSna > // and VF. Thus, we can express our gliding equation all in terms of V0, VF and t. > float AxisScrollSnapAnimator::computeGlideDelta() const > { >- LayoutUnit offset = m_client->scrollOffsetInAxis(m_axis); >+ LayoutUnit offset = m_client->scrollOffsetOnAxis(m_axis); > bool canComputeGlide = (m_initialOffset <= offset && offset < m_targetOffset) || (m_targetOffset < offset && offset <= m_initialOffset); > if (m_currentState != ScrollSnapState::Gliding || !canComputeGlide) > return 0; >Index: Source/WebCore/platform/mac/ScrollAnimatorMac.h >=================================================================== >--- Source/WebCore/platform/mac/ScrollAnimatorMac.h (revision 180935) >+++ Source/WebCore/platform/mac/ScrollAnimatorMac.h (working copy) >@@ -32,7 +32,6 @@ > #include "FloatPoint.h" > #include "FloatSize.h" > #include "ScrollAnimator.h" >-#include "ScrollController.h" > #include "Timer.h" > #include <wtf/RetainPtr.h> > >@@ -42,15 +41,11 @@ OBJC_CLASS WebScrollbarPainterDelegate; > > typedef id ScrollbarPainterController; > >-#if !ENABLE(RUBBER_BANDING) >-class ScrollControllerClient { }; >-#endif >- > namespace WebCore { > > class Scrollbar; > >-class ScrollAnimatorMac : public ScrollAnimator, private ScrollControllerClient { >+class ScrollAnimatorMac : public ScrollAnimator { > > public: > ScrollAnimatorMac(ScrollableArea&); >@@ -150,17 +145,11 @@ private: > virtual WebCore::IntPoint absoluteScrollPosition() override; > virtual void immediateScrollByWithoutContentEdgeConstraints(const FloatSize&) override; > virtual void immediateScrollBy(const FloatSize&) override; >- virtual void startSnapRubberbandTimer() override; >- virtual void stopSnapRubberbandTimer() override; > virtual void adjustScrollPositionToBoundsIfNecessary() override; > > bool pinnedInDirection(float deltaX, float deltaY); >- void snapRubberBandTimerFired(); > > bool isAlreadyPinnedInDirectionOfGesture(const PlatformWheelEvent&, ScrollEventAxis); >- >- ScrollController m_scrollController; >- Timer m_snapRubberBandTimer; > #endif > > bool m_haveScrolledSincePageLoad; >Index: Source/WebCore/platform/mac/ScrollAnimatorMac.mm >=================================================================== >--- Source/WebCore/platform/mac/ScrollAnimatorMac.mm (revision 180935) >+++ Source/WebCore/platform/mac/ScrollAnimatorMac.mm (working copy) >@@ -643,10 +643,6 @@ ScrollAnimatorMac::ScrollAnimatorMac(Scr > : ScrollAnimator(scrollableArea) > , m_initialScrollbarPaintTimer(*this, &ScrollAnimatorMac::initialScrollbarPaintTimerFired) > , m_sendContentAreaScrolledTimer(*this, &ScrollAnimatorMac::sendContentAreaScrolledTimerFired) >-#if ENABLE(RUBBER_BANDING) >- , m_scrollController(this) >- , m_snapRubberBandTimer(*this, &ScrollAnimatorMac::snapRubberBandTimerFired) >-#endif > , m_haveScrolledSincePageLoad(false) > , m_needsScrollerStyleUpdate(false) > { >@@ -1270,21 +1266,6 @@ void ScrollAnimatorMac::immediateScrollB > m_currentPosY = newPos.y(); > notifyPositionChanged(adjustedDelta); > } >- >-void ScrollAnimatorMac::startSnapRubberbandTimer() >-{ >- m_snapRubberBandTimer.startRepeating(1.0 / 60.0); >-} >- >-void ScrollAnimatorMac::stopSnapRubberbandTimer() >-{ >- m_snapRubberBandTimer.stop(); >-} >- >-void ScrollAnimatorMac::snapRubberBandTimerFired() >-{ >- m_scrollController.snapRubberBandTimerFired(); >-} > #endif > > void ScrollAnimatorMac::updateScrollerStyle() >Index: Source/WebCore/platform/mac/ScrollController.h >=================================================================== >--- Source/WebCore/platform/mac/ScrollController.h (revision 180935) >+++ Source/WebCore/platform/mac/ScrollController.h (working copy) >@@ -1,107 +0,0 @@ >-/* >- * Copyright (C) 2011 Apple Inc. All rights reserved. >- * >- * Redistribution and use in source and binary forms, with or without >- * modification, are permitted provided that the following conditions >- * are met: >- * 1. Redistributions of source code must retain the above copyright >- * notice, this list of conditions and the following disclaimer. >- * 2. Redistributions in binary form must reproduce the above copyright >- * notice, this list of conditions and the following disclaimer in the >- * documentation and/or other materials provided with the distribution. >- * >- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >- * THE POSSIBILITY OF SUCH DAMAGE. >- */ >- >-#ifndef ScrollController_h >-#define ScrollController_h >- >-#if ENABLE(RUBBER_BANDING) >- >-#include "FloatPoint.h" >-#include "FloatSize.h" >-#include "ScrollTypes.h" >-#include <wtf/Noncopyable.h> >- >-namespace WebCore { >- >-class PlatformWheelEvent; >- >-class ScrollControllerClient { >-protected: >- virtual ~ScrollControllerClient() { } >- >-public: >- virtual bool allowsHorizontalStretching(const PlatformWheelEvent&) = 0; >- virtual bool allowsVerticalStretching(const PlatformWheelEvent&) = 0; >- virtual IntSize stretchAmount() = 0; >- virtual bool pinnedInDirection(const FloatSize&) = 0; >- virtual bool canScrollHorizontally() = 0; >- virtual bool canScrollVertically() = 0; >- virtual bool shouldRubberBandInDirection(ScrollDirection) = 0; >- >- // Return the absolute scroll position, not relative to the scroll origin. >- virtual WebCore::IntPoint absoluteScrollPosition() = 0; >- >- virtual void immediateScrollBy(const FloatSize&) = 0; >- virtual void immediateScrollByWithoutContentEdgeConstraints(const FloatSize&) = 0; >- virtual void startSnapRubberbandTimer() = 0; >- virtual void stopSnapRubberbandTimer() = 0; >- >- // If the current scroll position is within the overhang area, this function will cause >- // the page to scroll to the nearest boundary point. >- virtual void adjustScrollPositionToBoundsIfNecessary() = 0; >-}; >- >-class ScrollController { >- WTF_MAKE_NONCOPYABLE(ScrollController); >- >-public: >- explicit ScrollController(ScrollControllerClient*); >- >- bool handleWheelEvent(const PlatformWheelEvent&); >- void snapRubberBandTimerFired(); >- >- bool isRubberBandInProgress() const; >- >-private: >- void stopSnapRubberbandTimer(); >- void snapRubberBand(); >- >- bool shouldRubberBandInHorizontalDirection(const PlatformWheelEvent&); >- >- ScrollControllerClient* m_client; >- >- bool m_inScrollGesture; >- bool m_momentumScrollInProgress; >- bool m_ignoreMomentumScrolls; >- >- CFTimeInterval m_lastMomentumScrollTimestamp; >- FloatSize m_overflowScrollDelta; >- FloatSize m_stretchScrollForce; >- FloatSize m_momentumVelocity; >- >- // Rubber band state. >- CFTimeInterval m_startTime; >- FloatSize m_startStretch; >- FloatPoint m_origOrigin; >- FloatSize m_origVelocity; >- >- bool m_snapRubberbandTimerIsActive; >-}; >- >-} // namespace WebCore >- >-#endif // ENABLE(RUBBER_BANDING) >- >-#endif // ScrollController_h >Index: Source/WebCore/platform/mac/ScrollController.mm >=================================================================== >--- Source/WebCore/platform/mac/ScrollController.mm (revision 180935) >+++ Source/WebCore/platform/mac/ScrollController.mm (working copy) >@@ -1,406 +0,0 @@ >-/* >- * Copyright (C) 2011, 2014-2015 Apple Inc. All rights reserved. >- * >- * Redistribution and use in source and binary forms, with or without >- * modification, are permitted provided that the following conditions >- * are met: >- * 1. Redistributions of source code must retain the above copyright >- * notice, this list of conditions and the following disclaimer. >- * 2. Redistributions in binary form must reproduce the above copyright >- * notice, this list of conditions and the following disclaimer in the >- * documentation and/or other materials provided with the distribution. >- * >- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >- * THE POSSIBILITY OF SUCH DAMAGE. >- */ >- >-#include "config.h" >-#include "ScrollController.h" >- >-#include "PlatformWheelEvent.h" >-#include "WebCoreSystemInterface.h" >-#include <sys/sysctl.h> >-#include <sys/time.h> >- >-#if ENABLE(RUBBER_BANDING) >- >-static NSTimeInterval systemUptime() >-{ >- if ([[NSProcessInfo processInfo] respondsToSelector:@selector(systemUptime)]) >- return [[NSProcessInfo processInfo] systemUptime]; >- >- // Get how long system has been up. Found by looking getting "boottime" from the kernel. >- static struct timeval boottime = {0, 0}; >- if (!boottime.tv_sec) { >- int mib[2] = {CTL_KERN, KERN_BOOTTIME}; >- size_t size = sizeof(boottime); >- if (-1 == sysctl(mib, 2, &boottime, &size, 0, 0)) >- boottime.tv_sec = 0; >- } >- struct timeval now; >- if (boottime.tv_sec && -1 != gettimeofday(&now, 0)) { >- struct timeval uptime; >- timersub(&now, &boottime, &uptime); >- NSTimeInterval result = uptime.tv_sec + (uptime.tv_usec / 1E+6); >- return result; >- } >- return 0; >-} >- >- >-namespace WebCore { >- >-static const float scrollVelocityZeroingTimeout = 0.10f; >-static const float rubberbandDirectionLockStretchRatio = 1; >-static const float rubberbandMinimumRequiredDeltaBeforeStretch = 10; >- >-static float elasticDeltaForTimeDelta(float initialPosition, float initialVelocity, float elapsedTime) >-{ >- return wkNSElasticDeltaForTimeDelta(initialPosition, initialVelocity, elapsedTime); >-} >- >-static float elasticDeltaForReboundDelta(float delta) >-{ >- return wkNSElasticDeltaForReboundDelta(delta); >-} >- >-static float reboundDeltaForElasticDelta(float delta) >-{ >- return wkNSReboundDeltaForElasticDelta(delta); >-} >- >-static float scrollWheelMultiplier() >-{ >- static float multiplier = -1; >- if (multiplier < 0) { >- multiplier = [[NSUserDefaults standardUserDefaults] floatForKey:@"NSScrollWheelMultiplier"]; >- if (multiplier <= 0) >- multiplier = 1; >- } >- return multiplier; >-} >- >-ScrollController::ScrollController(ScrollControllerClient* client) >- : m_client(client) >- , m_inScrollGesture(false) >- , m_momentumScrollInProgress(false) >- , m_ignoreMomentumScrolls(false) >- , m_lastMomentumScrollTimestamp(0) >- , m_startTime(0) >- , m_snapRubberbandTimerIsActive(false) >-{ >-} >- >-bool ScrollController::handleWheelEvent(const PlatformWheelEvent& wheelEvent) >-{ >- if (wheelEvent.phase() == PlatformWheelEventPhaseBegan) { >- // First, check if we should rubber-band at all. >- if (m_client->pinnedInDirection(FloatSize(-wheelEvent.deltaX(), 0)) >- && !shouldRubberBandInHorizontalDirection(wheelEvent)) >- return false; >- >- m_inScrollGesture = true; >- m_momentumScrollInProgress = false; >- m_ignoreMomentumScrolls = false; >- m_lastMomentumScrollTimestamp = 0; >- m_momentumVelocity = FloatSize(); >- >- IntSize stretchAmount = m_client->stretchAmount(); >- m_stretchScrollForce.setWidth(reboundDeltaForElasticDelta(stretchAmount.width())); >- m_stretchScrollForce.setHeight(reboundDeltaForElasticDelta(stretchAmount.height())); >- m_overflowScrollDelta = FloatSize(); >- >- stopSnapRubberbandTimer(); >- >- return true; >- } >- >- if (wheelEvent.phase() == PlatformWheelEventPhaseEnded) { >- snapRubberBand(); >- return true; >- } >- >- bool isMomentumScrollEvent = (wheelEvent.momentumPhase() != PlatformWheelEventPhaseNone); >- if (m_ignoreMomentumScrolls && (isMomentumScrollEvent || m_snapRubberbandTimerIsActive)) { >- if (wheelEvent.momentumPhase() == PlatformWheelEventPhaseEnded) { >- m_ignoreMomentumScrolls = false; >- return true; >- } >- return false; >- } >- >- float deltaX = m_overflowScrollDelta.width(); >- float deltaY = m_overflowScrollDelta.height(); >- >- // Reset overflow values because we may decide to remove delta at various points and put it into overflow. >- m_overflowScrollDelta = FloatSize(); >- >- IntSize stretchAmount = m_client->stretchAmount(); >- bool isVerticallyStretched = stretchAmount.height(); >- bool isHorizontallyStretched = stretchAmount.width(); >- >- float eventCoalescedDeltaX; >- float eventCoalescedDeltaY; >- >- if (isVerticallyStretched || isHorizontallyStretched) { >- eventCoalescedDeltaX = -wheelEvent.unacceleratedScrollingDeltaX(); >- eventCoalescedDeltaY = -wheelEvent.unacceleratedScrollingDeltaY(); >- } else { >- eventCoalescedDeltaX = -wheelEvent.deltaX(); >- eventCoalescedDeltaY = -wheelEvent.deltaY(); >- } >- >- deltaX += eventCoalescedDeltaX; >- deltaY += eventCoalescedDeltaY; >- >- // Slightly prefer scrolling vertically by applying the = case to deltaY >- if (fabsf(deltaY) >= fabsf(deltaX)) >- deltaX = 0; >- else >- deltaY = 0; >- >- bool shouldStretch = false; >- >- PlatformWheelEventPhase momentumPhase = wheelEvent.momentumPhase(); >- >- // If we are starting momentum scrolling then do some setup. >- if (!m_momentumScrollInProgress && (momentumPhase == PlatformWheelEventPhaseBegan || momentumPhase == PlatformWheelEventPhaseChanged)) >- m_momentumScrollInProgress = true; >- >- CFTimeInterval timeDelta = wheelEvent.timestamp() - m_lastMomentumScrollTimestamp; >- if (m_inScrollGesture || m_momentumScrollInProgress) { >- if (m_lastMomentumScrollTimestamp && timeDelta > 0 && timeDelta < scrollVelocityZeroingTimeout) { >- m_momentumVelocity.setWidth(eventCoalescedDeltaX / (float)timeDelta); >- m_momentumVelocity.setHeight(eventCoalescedDeltaY / (float)timeDelta); >- m_lastMomentumScrollTimestamp = wheelEvent.timestamp(); >- } else { >- m_lastMomentumScrollTimestamp = wheelEvent.timestamp(); >- m_momentumVelocity = FloatSize(); >- } >- >- if (isVerticallyStretched) { >- if (!isHorizontallyStretched && m_client->pinnedInDirection(FloatSize(deltaX, 0))) { >- // Stretching only in the vertical. >- if (deltaY && (fabsf(deltaX / deltaY) < rubberbandDirectionLockStretchRatio)) >- deltaX = 0; >- else if (fabsf(deltaX) < rubberbandMinimumRequiredDeltaBeforeStretch) { >- m_overflowScrollDelta.setWidth(m_overflowScrollDelta.width() + deltaX); >- deltaX = 0; >- } else >- m_overflowScrollDelta.setWidth(m_overflowScrollDelta.width() + deltaX); >- } >- } else if (isHorizontallyStretched) { >- // Stretching only in the horizontal. >- if (m_client->pinnedInDirection(FloatSize(0, deltaY))) { >- if (deltaX && (fabsf(deltaY / deltaX) < rubberbandDirectionLockStretchRatio)) >- deltaY = 0; >- else if (fabsf(deltaY) < rubberbandMinimumRequiredDeltaBeforeStretch) { >- m_overflowScrollDelta.setHeight(m_overflowScrollDelta.height() + deltaY); >- deltaY = 0; >- } else >- m_overflowScrollDelta.setHeight(m_overflowScrollDelta.height() + deltaY); >- } >- } else { >- // Not stretching at all yet. >- if (m_client->pinnedInDirection(FloatSize(deltaX, deltaY))) { >- if (fabsf(deltaY) >= fabsf(deltaX)) { >- if (fabsf(deltaX) < rubberbandMinimumRequiredDeltaBeforeStretch) { >- m_overflowScrollDelta.setWidth(m_overflowScrollDelta.width() + deltaX); >- deltaX = 0; >- } else >- m_overflowScrollDelta.setWidth(m_overflowScrollDelta.width() + deltaX); >- } >- shouldStretch = true; >- } >- } >- } >- >- if (deltaX || deltaY) { >- if (!(shouldStretch || isVerticallyStretched || isHorizontallyStretched)) { >- if (deltaY) { >- deltaY *= scrollWheelMultiplier(); >- m_client->immediateScrollBy(FloatSize(0, deltaY)); >- } >- if (deltaX) { >- deltaX *= scrollWheelMultiplier(); >- m_client->immediateScrollBy(FloatSize(deltaX, 0)); >- } >- } else { >- if (!m_client->allowsHorizontalStretching(wheelEvent)) { >- deltaX = 0; >- eventCoalescedDeltaX = 0; >- } else if (deltaX && !isHorizontallyStretched && !m_client->pinnedInDirection(FloatSize(deltaX, 0))) { >- deltaX *= scrollWheelMultiplier(); >- >- m_client->immediateScrollByWithoutContentEdgeConstraints(FloatSize(deltaX, 0)); >- deltaX = 0; >- } >- >- if (!m_client->allowsVerticalStretching(wheelEvent)) { >- deltaY = 0; >- eventCoalescedDeltaY = 0; >- } else if (deltaY && !isVerticallyStretched && !m_client->pinnedInDirection(FloatSize(0, deltaY))) { >- deltaY *= scrollWheelMultiplier(); >- >- m_client->immediateScrollByWithoutContentEdgeConstraints(FloatSize(0, deltaY)); >- deltaY = 0; >- } >- >- IntSize stretchAmount = m_client->stretchAmount(); >- >- if (m_momentumScrollInProgress) { >- if ((m_client->pinnedInDirection(FloatSize(eventCoalescedDeltaX, eventCoalescedDeltaY)) || (fabsf(eventCoalescedDeltaX) + fabsf(eventCoalescedDeltaY) <= 0)) && m_lastMomentumScrollTimestamp) { >- m_ignoreMomentumScrolls = true; >- m_momentumScrollInProgress = false; >- snapRubberBand(); >- } >- } >- >- m_stretchScrollForce.setWidth(m_stretchScrollForce.width() + deltaX); >- m_stretchScrollForce.setHeight(m_stretchScrollForce.height() + deltaY); >- >- FloatSize dampedDelta(ceilf(elasticDeltaForReboundDelta(m_stretchScrollForce.width())), ceilf(elasticDeltaForReboundDelta(m_stretchScrollForce.height()))); >- >- m_client->immediateScrollByWithoutContentEdgeConstraints(dampedDelta - stretchAmount); >- } >- } >- >- if (m_momentumScrollInProgress && momentumPhase == PlatformWheelEventPhaseEnded) { >- m_momentumScrollInProgress = false; >- m_ignoreMomentumScrolls = false; >- m_lastMomentumScrollTimestamp = 0; >- } >- >- return true; >-} >- >-static inline float roundTowardZero(float num) >-{ >- return num > 0 ? ceilf(num - 0.5f) : floorf(num + 0.5f); >-} >- >-static inline float roundToDevicePixelTowardZero(float num) >-{ >- float roundedNum = roundf(num); >- if (fabs(num - roundedNum) < 0.125) >- num = roundedNum; >- >- return roundTowardZero(num); >-} >- >-void ScrollController::snapRubberBandTimerFired() >-{ >- if (!m_momentumScrollInProgress || m_ignoreMomentumScrolls) { >- CFTimeInterval timeDelta = [NSDate timeIntervalSinceReferenceDate] - m_startTime; >- >- if (m_startStretch == FloatSize()) { >- m_startStretch = m_client->stretchAmount(); >- if (m_startStretch == FloatSize()) { >- stopSnapRubberbandTimer(); >- >- m_stretchScrollForce = FloatSize(); >- m_startTime = 0; >- m_startStretch = FloatSize(); >- m_origOrigin = FloatPoint(); >- m_origVelocity = FloatSize(); >- return; >- } >- >- m_origOrigin = m_client->absoluteScrollPosition() - m_startStretch; >- m_origVelocity = m_momentumVelocity; >- >- // Just like normal scrolling, prefer vertical rubberbanding >- if (fabsf(m_origVelocity.height()) >= fabsf(m_origVelocity.width())) >- m_origVelocity.setWidth(0); >- >- // Don't rubber-band horizontally if it's not possible to scroll horizontally >- if (!m_client->canScrollHorizontally()) >- m_origVelocity.setWidth(0); >- >- // Don't rubber-band vertically if it's not possible to scroll vertically >- if (!m_client->canScrollVertically()) >- m_origVelocity.setHeight(0); >- } >- >- FloatPoint delta(roundToDevicePixelTowardZero(elasticDeltaForTimeDelta(m_startStretch.width(), -m_origVelocity.width(), (float)timeDelta)), >- roundToDevicePixelTowardZero(elasticDeltaForTimeDelta(m_startStretch.height(), -m_origVelocity.height(), (float)timeDelta))); >- >- if (fabs(delta.x()) >= 1 || fabs(delta.y()) >= 1) { >- m_client->immediateScrollByWithoutContentEdgeConstraints(FloatSize(delta.x(), delta.y()) - m_client->stretchAmount()); >- >- FloatSize newStretch = m_client->stretchAmount(); >- >- m_stretchScrollForce.setWidth(reboundDeltaForElasticDelta(newStretch.width())); >- m_stretchScrollForce.setHeight(reboundDeltaForElasticDelta(newStretch.height())); >- } else { >- m_client->adjustScrollPositionToBoundsIfNecessary(); >- >- stopSnapRubberbandTimer(); >- m_stretchScrollForce = FloatSize(); >- m_startTime = 0; >- m_startStretch = FloatSize(); >- m_origOrigin = FloatPoint(); >- m_origVelocity = FloatSize(); >- } >- } else { >- m_startTime = [NSDate timeIntervalSinceReferenceDate]; >- m_startStretch = FloatSize(); >- } >-} >- >-bool ScrollController::isRubberBandInProgress() const >-{ >- if (!m_inScrollGesture && !m_momentumScrollInProgress && !m_snapRubberbandTimerIsActive) >- return false; >- >- return !m_client->stretchAmount().isZero(); >-} >- >-void ScrollController::stopSnapRubberbandTimer() >-{ >- m_client->stopSnapRubberbandTimer(); >- m_snapRubberbandTimerIsActive = false; >-} >- >-void ScrollController::snapRubberBand() >-{ >- CFTimeInterval timeDelta = systemUptime() - m_lastMomentumScrollTimestamp; >- if (m_lastMomentumScrollTimestamp && timeDelta >= scrollVelocityZeroingTimeout) >- m_momentumVelocity = FloatSize(); >- >- m_inScrollGesture = false; >- >- if (m_snapRubberbandTimerIsActive) >- return; >- >- m_startTime = [NSDate timeIntervalSinceReferenceDate]; >- m_startStretch = FloatSize(); >- m_origOrigin = FloatPoint(); >- m_origVelocity = FloatSize(); >- >- m_client->startSnapRubberbandTimer(); >- m_snapRubberbandTimerIsActive = true; >-} >- >-bool ScrollController::shouldRubberBandInHorizontalDirection(const PlatformWheelEvent& wheelEvent) >-{ >- if (wheelEvent.deltaX() > 0) >- return m_client->shouldRubberBandInDirection(ScrollLeft); >- if (wheelEvent.deltaX() < 0) >- return m_client->shouldRubberBandInDirection(ScrollRight); >- >- return true; >-} >- >-} // namespace WebCore >- >-#endif // ENABLE(RUBBER_BANDING)
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 142102
:
247680
|
247682
|
247685
|
247689
|
247690
|
247691
|
247694
|
247696
|
247698
|
247769
|
247817