[SCM] WebKit Debian packaging branch, webkit-1.3, updated. upstream/1.3.7-4207-g178b198
weinig at apple.com
weinig at apple.com
Mon Feb 21 00:10:26 UTC 2011
The following commit has been merged in the webkit-1.3 branch:
commit cc0f1406b0ebbb0db7bbbfacd264a7f402f53aed
Author: weinig at apple.com <weinig at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date: Fri Jan 28 19:05:43 2011 +0000
Add basic rubber banding support
<rdar://problem/8219429>
https://bugs.webkit.org/show_bug.cgi?id=53277
Reviewed by Maciej Stachowiak.
Source/JavaScriptCore:
* wtf/Platform.h: Add ENABLE for rubber banding.
Source/WebCore:
* page/EventHandler.cpp:
(WebCore::EventHandler::handleGestureEvent):
Pass gesture events to the FrameView.
* platform/ScrollAnimator.cpp:
(WebCore::ScrollAnimator::handleGestureEvent):
* platform/ScrollAnimator.h:
Add stubbed out implementation.
* platform/ScrollView.cpp:
(WebCore::ScrollView::ScrollView):
(WebCore::ScrollView::overhangAmount):
(WebCore::ScrollView::wheelEvent):
* platform/ScrollView.h:
* platform/ScrollableArea.cpp:
(WebCore::ScrollableArea::ScrollableArea):
(WebCore::ScrollableArea::handleGestureEvent):
* platform/ScrollableArea.h:
(WebCore::ScrollableArea::constrainsScrollingToContentEdge):
(WebCore::ScrollableArea::setConstrainsScrollingToContentEdge):
Move constrains scrolling bit to ScrollableArea from ScrollView.
(WebCore::ScrollableArea::contentsSize):
(WebCore::ScrollableArea::overhangAmount):
Add additional virtual functions for information needed by the animator.
* platform/mac/ScrollAnimatorMac.h:
* platform/mac/ScrollAnimatorMac.mm:
(WebCore::ScrollAnimatorMac::ScrollAnimatorMac):
(WebCore::ScrollAnimatorMac::immediateScrollByDeltaX):
(WebCore::ScrollAnimatorMac::immediateScrollByDeltaY):
(WebCore::elasticDeltaForTimeDelta):
(WebCore::elasticDeltaForReboundDelta):
(WebCore::reboundDeltaForElasticDelta):
(WebCore::scrollWheelMultiplier):
(WebCore::ScrollAnimatorMac::handleWheelEvent):
(WebCore::ScrollAnimatorMac::handleGestureEvent):
(WebCore::ScrollAnimatorMac::pinnedInDirection):
(WebCore::ScrollAnimatorMac::allowsVerticalStretching):
(WebCore::ScrollAnimatorMac::allowsHorizontalStretching):
(WebCore::ScrollAnimatorMac::smoothScrollWithEvent):
(WebCore::ScrollAnimatorMac::beginScrollGesture):
(WebCore::ScrollAnimatorMac::endScrollGesture):
(WebCore::ScrollAnimatorMac::snapRubberBand):
(WebCore::roundTowardZero):
(WebCore::roundToDevicePixelTowardZero):
(WebCore::ScrollAnimatorMac::snapRubberBandTimerFired):
Implement basic rubber banding.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@76956 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index a7ab2d3..e2b6980 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,13 @@
+2011-01-28 Sam Weinig <sam at webkit.org>
+
+ Reviewed by Maciej Stachowiak.
+
+ Add basic rubber banding support
+ <rdar://problem/8219429>
+ https://bugs.webkit.org/show_bug.cgi?id=53277
+
+ * wtf/Platform.h: Add ENABLE for rubber banding.
+
2011-01-28 Sheriff Bot <webkit.review.bot at gmail.com>
Unreviewed, rolling out r76893.
diff --git a/Source/JavaScriptCore/wtf/Platform.h b/Source/JavaScriptCore/wtf/Platform.h
index b638a56..b340e11 100644
--- a/Source/JavaScriptCore/wtf/Platform.h
+++ b/Source/JavaScriptCore/wtf/Platform.h
@@ -605,6 +605,7 @@
#endif
#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
#define ENABLE_GESTURE_EVENTS 1
+#define ENABLE_RUBBER_BANDING 1
#endif
#if !defined(ENABLE_JAVA_BRIDGE)
#define ENABLE_JAVA_BRIDGE 1
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index e2af323..33c775a 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,60 @@
+2011-01-28 Sam Weinig <sam at webkit.org>
+
+ Reviewed by Maciej Stachowiak.
+
+ Add basic rubber banding support
+ <rdar://problem/8219429>
+ https://bugs.webkit.org/show_bug.cgi?id=53277
+
+ * page/EventHandler.cpp:
+ (WebCore::EventHandler::handleGestureEvent):
+ Pass gesture events to the FrameView.
+
+ * platform/ScrollAnimator.cpp:
+ (WebCore::ScrollAnimator::handleGestureEvent):
+ * platform/ScrollAnimator.h:
+ Add stubbed out implementation.
+
+ * platform/ScrollView.cpp:
+ (WebCore::ScrollView::ScrollView):
+ (WebCore::ScrollView::overhangAmount):
+ (WebCore::ScrollView::wheelEvent):
+ * platform/ScrollView.h:
+ * platform/ScrollableArea.cpp:
+ (WebCore::ScrollableArea::ScrollableArea):
+ (WebCore::ScrollableArea::handleGestureEvent):
+ * platform/ScrollableArea.h:
+ (WebCore::ScrollableArea::constrainsScrollingToContentEdge):
+ (WebCore::ScrollableArea::setConstrainsScrollingToContentEdge):
+ Move constrains scrolling bit to ScrollableArea from ScrollView.
+
+ (WebCore::ScrollableArea::contentsSize):
+ (WebCore::ScrollableArea::overhangAmount):
+ Add additional virtual functions for information needed by the animator.
+
+ * platform/mac/ScrollAnimatorMac.h:
+ * platform/mac/ScrollAnimatorMac.mm:
+ (WebCore::ScrollAnimatorMac::ScrollAnimatorMac):
+ (WebCore::ScrollAnimatorMac::immediateScrollByDeltaX):
+ (WebCore::ScrollAnimatorMac::immediateScrollByDeltaY):
+ (WebCore::elasticDeltaForTimeDelta):
+ (WebCore::elasticDeltaForReboundDelta):
+ (WebCore::reboundDeltaForElasticDelta):
+ (WebCore::scrollWheelMultiplier):
+ (WebCore::ScrollAnimatorMac::handleWheelEvent):
+ (WebCore::ScrollAnimatorMac::handleGestureEvent):
+ (WebCore::ScrollAnimatorMac::pinnedInDirection):
+ (WebCore::ScrollAnimatorMac::allowsVerticalStretching):
+ (WebCore::ScrollAnimatorMac::allowsHorizontalStretching):
+ (WebCore::ScrollAnimatorMac::smoothScrollWithEvent):
+ (WebCore::ScrollAnimatorMac::beginScrollGesture):
+ (WebCore::ScrollAnimatorMac::endScrollGesture):
+ (WebCore::ScrollAnimatorMac::snapRubberBand):
+ (WebCore::roundTowardZero):
+ (WebCore::roundToDevicePixelTowardZero):
+ (WebCore::ScrollAnimatorMac::snapRubberBandTimerFired):
+ Implement basic rubber banding.
+
2011-01-28 Dan Bernstein <mitz at apple.com>
Reviewed by Anders Carlsson.
diff --git a/Source/WebCore/page/EventHandler.cpp b/Source/WebCore/page/EventHandler.cpp
index b2988cb..ac7f60b 100644
--- a/Source/WebCore/page/EventHandler.cpp
+++ b/Source/WebCore/page/EventHandler.cpp
@@ -2040,9 +2040,18 @@ void EventHandler::defaultWheelEventHandler(Node* startNode, WheelEvent* wheelEv
}
#if ENABLE(GESTURE_EVENTS)
-bool EventHandler::handleGestureEvent(const PlatformGestureEvent&)
+bool EventHandler::handleGestureEvent(const PlatformGestureEvent& gestureEvent)
{
- // FIXME: Handle gesture events.
+ // FIXME: This should hit test and go to the correct subframe rather than
+ // always sending gestures to the main frame only. We should also ensure
+ // that if a frame gets a gesture begin gesture, it gets the corresponding
+ // end gesture as well.
+
+ FrameView* view = m_frame->view();
+ if (!view)
+ return false;
+
+ view->handleGestureEvent(gestureEvent);
return true;
}
#endif
diff --git a/Source/WebCore/platform/ScrollAnimator.cpp b/Source/WebCore/platform/ScrollAnimator.cpp
index faad79e..6fc78e7 100644
--- a/Source/WebCore/platform/ScrollAnimator.cpp
+++ b/Source/WebCore/platform/ScrollAnimator.cpp
@@ -113,6 +113,12 @@ void ScrollAnimator::handleWheelEvent(PlatformWheelEvent& e)
}
}
+#if ENABLE(GESTURE_EVENTS)
+void ScrollAnimator::handleGestureEvent(const PlatformGestureEvent&)
+{
+}
+#endif
+
FloatPoint ScrollAnimator::currentPosition() const
{
return FloatPoint(m_currentPosX, m_currentPosY);
diff --git a/Source/WebCore/platform/ScrollAnimator.h b/Source/WebCore/platform/ScrollAnimator.h
index a51abcb..679b13f 100644
--- a/Source/WebCore/platform/ScrollAnimator.h
+++ b/Source/WebCore/platform/ScrollAnimator.h
@@ -40,6 +40,10 @@ class FloatPoint;
class PlatformWheelEvent;
class ScrollableArea;
+#if ENABLE(GESTURE_EVENTS)
+class PlatformGestureEvent;
+#endif
+
class ScrollAnimator {
public:
static PassOwnPtr<ScrollAnimator> create(ScrollableArea*);
@@ -55,6 +59,9 @@ public:
virtual void scrollToOffsetWithoutAnimation(const FloatPoint&);
virtual void handleWheelEvent(PlatformWheelEvent&);
+#if ENABLE(GESTURE_EVENTS)
+ virtual void handleGestureEvent(const PlatformGestureEvent&);
+#endif
FloatPoint currentPosition() const;
diff --git a/Source/WebCore/platform/ScrollView.cpp b/Source/WebCore/platform/ScrollView.cpp
index 6d4f4ba..3fdca58 100644
--- a/Source/WebCore/platform/ScrollView.cpp
+++ b/Source/WebCore/platform/ScrollView.cpp
@@ -55,7 +55,6 @@ ScrollView::ScrollView()
, m_paintsEntireContents(false)
, m_clipsRepaints(true)
, m_delegatesScrolling(false)
- , m_constrainsScrollingToContentEdge(true)
{
platformInit();
}
@@ -399,6 +398,22 @@ bool ScrollView::logicalScroll(ScrollLogicalDirection direction, ScrollGranulari
return scroll(logicalToPhysical(direction, isVerticalDocument(), isFlippedDocument()), granularity);
}
+IntSize ScrollView::overhangAmount() const
+{
+ IntSize stretch;
+ if (scrollY() < 0)
+ stretch.setHeight(scrollY());
+ else if (scrollY() > contentsHeight() - visibleContentRect().height())
+ stretch.setHeight(scrollY() - (contentsHeight() - visibleContentRect().height()));
+
+ if (scrollX() < 0)
+ stretch.setWidth(scrollX());
+ else if (scrollX() > contentsWidth() - visibleContentRect().width())
+ stretch.setWidth(scrollX() - (contentsWidth() - visibleContentRect().width()));
+
+ return stretch;
+}
+
void ScrollView::windowResizerRectChanged()
{
if (platformWidget())
@@ -738,6 +753,16 @@ void ScrollView::wheelEvent(PlatformWheelEvent& e)
ScrollableArea::handleWheelEvent(e);
}
+#if ENABLE(GESTURE_EVENTS)
+void ScrollView::gestureEvent(const PlatformGestureEvent& gestureEvent)
+{
+ if (platformWidget())
+ return;
+
+ ScrollableArea::handleGestureEvent(gestureEvent);
+}
+#endif
+
void ScrollView::setFrameRect(const IntRect& newRect)
{
IntRect oldRect = frameRect();
diff --git a/Source/WebCore/platform/ScrollView.h b/Source/WebCore/platform/ScrollView.h
index 22872bd..cb7e647 100644
--- a/Source/WebCore/platform/ScrollView.h
+++ b/Source/WebCore/platform/ScrollView.h
@@ -51,7 +51,6 @@ class wxScrollWinEvent;
namespace WebCore {
class HostWindow;
-class PlatformWheelEvent;
class Scrollbar;
class ScrollView : public Widget, public ScrollableArea {
@@ -163,10 +162,6 @@ public:
int contentsHeight() const { return contentsSize().height(); }
virtual void setContentsSize(const IntSize&);
- // Functions for controlling if you can scroll past the end of the document.
- bool constrainsScrollingToContentEdge() const { return m_constrainsScrollingToContentEdge; }
- void setConstrainsScrollingToContentEdge(bool constrainsScrollingToContentEdge) { m_constrainsScrollingToContentEdge = constrainsScrollingToContentEdge; }
-
// Functions for querying the current scrolled position (both as a point, a size, or as individual X and Y values).
IntPoint scrollPosition() const { return visibleContentRect().location(); }
IntSize scrollOffset() const { return visibleContentRect().location() - IntPoint(); } // Gets the scrolled position as an IntSize. Convenient for adding to other sizes.
@@ -176,7 +171,9 @@ public:
IntPoint adjustScrollPositionWithinRange(const IntPoint&) const;
int scrollX() const { return scrollPosition().x(); }
int scrollY() const { return scrollPosition().y(); }
-
+
+ IntSize overhangAmount() const;
+
// Functions for scrolling the view.
void setScrollPosition(const IntPoint&);
void scrollBy(const IntSize& s) { return setScrollPosition(scrollPosition() + s); }
@@ -232,6 +229,9 @@ public:
// On Mac the underlying NSScrollView just does the scrolling, but on other platforms
// (like Windows), we need this function in order to do the scroll ourselves.
void wheelEvent(PlatformWheelEvent&);
+#if ENABLE(GESTURE_EVENTS)
+ void gestureEvent(const PlatformGestureEvent&);
+#endif
IntPoint convertChildToSelf(const Widget* child, const IntPoint& point) const
{
@@ -339,8 +339,6 @@ private:
bool m_clipsRepaints;
bool m_delegatesScrolling;
- bool m_constrainsScrollingToContentEdge;
-
// There are 8 possible combinations of writing mode and direction. Scroll origin will be non-zero in the x or y axis
// if there is any reversed direction or writing-mode. The combinations are:
// writing-mode / direction scrollOrigin.x() set scrollOrigin.y() set
diff --git a/Source/WebCore/platform/ScrollableArea.cpp b/Source/WebCore/platform/ScrollableArea.cpp
index f379f54..9c929ab 100644
--- a/Source/WebCore/platform/ScrollableArea.cpp
+++ b/Source/WebCore/platform/ScrollableArea.cpp
@@ -41,6 +41,7 @@ namespace WebCore {
ScrollableArea::ScrollableArea()
: m_scrollAnimator(ScrollAnimator::create(this))
+ , m_constrainsScrollingToContentEdge(true)
{
}
@@ -113,6 +114,13 @@ void ScrollableArea::handleWheelEvent(PlatformWheelEvent& wheelEvent)
m_scrollAnimator->handleWheelEvent(wheelEvent);
}
+#if ENABLE(GESTURE_EVENTS)
+void ScrollableArea::handleGestureEvent(const PlatformGestureEvent& gestureEvent)
+{
+ m_scrollAnimator->handleGestureEvent(gestureEvent);
+}
+#endif
+
void ScrollableArea::setScrollOffsetFromAnimation(const IntPoint& offset)
{
// Tell the derived class to scroll its contents.
diff --git a/Source/WebCore/platform/ScrollableArea.h b/Source/WebCore/platform/ScrollableArea.h
index a05fcf5..178cfc6 100644
--- a/Source/WebCore/platform/ScrollableArea.h
+++ b/Source/WebCore/platform/ScrollableArea.h
@@ -36,6 +36,10 @@ class FloatPoint;
class PlatformWheelEvent;
class ScrollAnimator;
+#if ENABLE(GESTURE_EVENTS)
+class PlatformGestureEvent;
+#endif
+
class ScrollableArea {
public:
ScrollableArea();
@@ -48,6 +52,13 @@ public:
void scrollToYOffsetWithoutAnimation(float x);
void handleWheelEvent(PlatformWheelEvent&);
+#if ENABLE(GESTURE_EVENTS)
+ void handleGestureEvent(const PlatformGestureEvent&);
+#endif
+
+ // Functions for controlling if you can scroll past the end of the document.
+ bool constrainsScrollingToContentEdge() const { return m_constrainsScrollingToContentEdge; }
+ void setConstrainsScrollingToContentEdge(bool constrainsScrollingToContentEdge) { m_constrainsScrollingToContentEdge = constrainsScrollingToContentEdge; }
virtual int scrollSize(ScrollbarOrientation) const = 0;
virtual int scrollPosition(Scrollbar*) const = 0;
@@ -92,12 +103,17 @@ public:
virtual int visibleHeight() const { ASSERT_NOT_REACHED(); return 0; }
virtual int visibleWidth() const { ASSERT_NOT_REACHED(); return 0; }
+ virtual IntSize contentsSize() const { ASSERT_NOT_REACHED(); return IntSize(); }
+
+ virtual IntSize overhangAmount() const { ASSERT_NOT_REACHED(); return IntSize(); }
+
private:
// NOTE: Only called from the ScrollAnimator.
friend class ScrollAnimator;
void setScrollOffsetFromAnimation(const IntPoint&);
OwnPtr<ScrollAnimator> m_scrollAnimator;
+ bool m_constrainsScrollingToContentEdge;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/mac/ScrollAnimatorMac.h b/Source/WebCore/platform/mac/ScrollAnimatorMac.h
index f05db40..e9cdc2f 100644
--- a/Source/WebCore/platform/mac/ScrollAnimatorMac.h
+++ b/Source/WebCore/platform/mac/ScrollAnimatorMac.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010, 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
@@ -28,7 +28,10 @@
#if ENABLE(SMOOTH_SCROLLING)
+#include "FloatPoint.h"
+#include "FloatSize.h"
#include "ScrollAnimator.h"
+#include "Timer.h"
#include <wtf/RetainPtr.h>
#ifdef __OBJC__
@@ -47,12 +50,46 @@ public:
virtual bool scroll(ScrollbarOrientation, ScrollGranularity, float step, float multiplier);
virtual void scrollToOffsetWithoutAnimation(const FloatPoint&);
- // Called by the ScrollAnimationHelperDelegate.
+#if ENABLE(RUBBER_BANDING)
+ virtual void handleWheelEvent(PlatformWheelEvent&);
+#if ENABLE(GESTURE_EVENTS)
+ virtual void handleGestureEvent(const PlatformGestureEvent&);
+#endif
+#endif
+
void immediateScrollToPoint(const FloatPoint& newPosition);
+ void immediateScrollByDeltaX(float deltaX);
+ void immediateScrollByDeltaY(float deltaY);
private:
RetainPtr<id> m_scrollAnimationHelper;
RetainPtr<ScrollAnimationHelperDelegate> m_scrollAnimationHelperDelegate;
+
+#if ENABLE(RUBBER_BANDING)
+ bool allowsVerticalStretching() const;
+ bool allowsHorizontalStretching() const;
+ bool pinnedInDirection(float deltaX, float deltaY);
+ void snapRubberBand();
+ void snapRubberBandTimerFired(Timer<ScrollAnimatorMac>*);
+ void smoothScrollWithEvent(PlatformWheelEvent&);
+ void beginScrollGesture();
+ void endScrollGesture();
+
+ bool m_inScrollGesture;
+ bool m_momentumScrollInProgress;
+ bool m_ignoreMomentumScrolls;
+ CFTimeInterval m_lastMomemtumScrollTimestamp;
+ FloatSize m_overflowScrollDelta;
+ FloatSize m_stretchScrollForce;
+ FloatSize m_momentumVelocity;
+
+ // Rubber band state.
+ CFTimeInterval m_startTime;
+ FloatSize m_startStretch;
+ FloatPoint m_origOrigin;
+ FloatSize m_origVelocity;
+ Timer<ScrollAnimatorMac> m_snapRubberBandTimer;
+#endif
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/mac/ScrollAnimatorMac.mm b/Source/WebCore/platform/mac/ScrollAnimatorMac.mm
index 59b333b..5ac36e7 100644
--- a/Source/WebCore/platform/mac/ScrollAnimatorMac.mm
+++ b/Source/WebCore/platform/mac/ScrollAnimatorMac.mm
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010, 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
@@ -30,6 +30,8 @@
#include "ScrollAnimatorMac.h"
#include "FloatPoint.h"
+#include "PlatformWheelEvent.h"
+#include "PlatformGestureEvent.h"
#include "ScrollableArea.h"
#include <wtf/PassOwnPtr.h>
@@ -122,6 +124,7 @@ static NSSize abs(NSSize size)
@end
+
namespace WebCore {
PassOwnPtr<ScrollAnimator> ScrollAnimator::create(ScrollableArea* scrollableArea)
@@ -131,6 +134,14 @@ PassOwnPtr<ScrollAnimator> ScrollAnimator::create(ScrollableArea* scrollableArea
ScrollAnimatorMac::ScrollAnimatorMac(ScrollableArea* scrollableArea)
: ScrollAnimator(scrollableArea)
+#if ENABLE(RUBBER_BANDING)
+ , m_inScrollGesture(false)
+ , m_momentumScrollInProgress(false)
+ , m_ignoreMomentumScrolls(false)
+ , m_lastMomemtumScrollTimestamp(0)
+ , m_startTime(0)
+ , m_snapRubberBandTimer(this, &ScrollAnimatorMac::snapRubberBandTimerFired)
+#endif
{
m_scrollAnimationHelperDelegate.adoptNS([[ScrollAnimationHelperDelegate alloc] initWithScrollAnimator:this]);
m_scrollAnimationHelper.adoptNS([[NSClassFromString(@"NSScrollAnimationHelper") alloc] initWithDelegate:m_scrollAnimationHelperDelegate.get()]);
@@ -177,6 +188,408 @@ void ScrollAnimatorMac::immediateScrollToPoint(const FloatPoint& newPosition)
notityPositionChanged();
}
+void ScrollAnimatorMac::immediateScrollByDeltaX(float deltaX)
+{
+ m_currentPosX += deltaX;
+ notityPositionChanged();
+}
+
+void ScrollAnimatorMac::immediateScrollByDeltaY(float deltaY)
+{
+ m_currentPosY += deltaY;
+ notityPositionChanged();
+}
+
+#if ENABLE(RUBBER_BANDING)
+
+static const double scrollVelocityZeroingTimeout = 0.10;
+static const double rubberbandStiffness = 20.0;
+static const double rubberbandDirectionLockStretchRatio = 1.0;
+static const double rubberbandMinimumRequiredDeltaBeforeStretch = 10.0;
+static const double rubberbandAmplitude = 0.31;
+static const double rubberbandPeriod = 1.6;
+
+static float elasticDeltaForTimeDelta(float initialPosition, float initialVelocity, float elapsedTime)
+{
+ float amplitude = rubberbandAmplitude;
+ float period = rubberbandPeriod;
+ float criticalDampeningFactor = exp((-elapsedTime * rubberbandStiffness) / period);
+
+ return (initialPosition + (-initialVelocity * elapsedTime * amplitude)) * criticalDampeningFactor;
+}
+
+static float elasticDeltaForReboundDelta(float delta)
+{
+ float stiffness = std::max(rubberbandStiffness, 1.0);
+ return delta / stiffness;
+}
+
+static float reboundDeltaForElasticDelta(float delta)
+{
+ return delta * rubberbandStiffness;
+}
+
+static float scrollWheelMultiplier()
+{
+ static float multiplier = -1.0;
+ if (multiplier < 0) {
+ multiplier = [[NSUserDefaults standardUserDefaults] floatForKey:@"NSScrollWheelMultiplier"];
+ if (multiplier <= 0)
+ multiplier = 1;
+ }
+ return multiplier;
+}
+
+void ScrollAnimatorMac::handleWheelEvent(PlatformWheelEvent& wheelEvent)
+{
+ if (!wheelEvent.hasPreciseScrollingDeltas()) {
+ ScrollAnimator::handleWheelEvent(wheelEvent);
+ return;
+ }
+
+ wheelEvent.accept();
+
+ bool isMometumScrollEvent = (wheelEvent.phase() != PlatformWheelEventPhaseNone);
+ if (m_ignoreMomentumScrolls && (isMometumScrollEvent || m_snapRubberBandTimer.isActive())) {
+ if (wheelEvent.phase() == PlatformWheelEventPhaseEnded)
+ m_ignoreMomentumScrolls = false;
+ return;
+ }
+
+ smoothScrollWithEvent(wheelEvent);
+}
+
+void ScrollAnimatorMac::handleGestureEvent(const PlatformGestureEvent& gestureEvent)
+{
+ if (gestureEvent.type() == PlatformGestureEvent::ScrollBeginType)
+ beginScrollGesture();
+ else
+ endScrollGesture();
+}
+
+bool ScrollAnimatorMac::pinnedInDirection(float deltaX, float deltaY)
+{
+ FloatSize limitDelta;
+ if (fabsf(deltaY) >= fabsf(deltaX)) {
+ if (deltaY < 0) {
+ // We are trying to scroll up. Make sure we are not pinned to the top
+ limitDelta.setHeight(m_scrollableArea->visibleContentRect().y());
+ } else {
+ // We are trying to scroll down. Make sure we are not pinned to the bottom
+ limitDelta.setHeight(m_scrollableArea->contentsSize().height() - m_scrollableArea->visibleContentRect().bottom());
+ }
+ } else if (deltaX != 0) {
+ if (deltaX < 0) {
+ // We are trying to scroll left. Make sure we are not pinned to the left
+ limitDelta.setWidth(m_scrollableArea->visibleContentRect().x());
+ } else {
+ // We are trying to scroll right. Make sure we are not pinned to the right
+ limitDelta.setWidth(m_scrollableArea->contentsSize().width() - m_scrollableArea->visibleContentRect().right());
+ }
+ }
+
+ if ((deltaX != 0 || deltaY != 0) && (limitDelta.width() < 1 && limitDelta.height() < 1))
+ return true;
+ return false;
+}
+
+bool ScrollAnimatorMac::allowsVerticalStretching() const
+{
+ Scrollbar* hScroller = m_scrollableArea->horizontalScrollbar();
+ Scrollbar* vScroller = m_scrollableArea->verticalScrollbar();
+ if (((vScroller && vScroller->enabled()) || (!hScroller || !hScroller->enabled())))
+ return true;
+
+ return false;
+}
+
+bool ScrollAnimatorMac::allowsHorizontalStretching() const
+{
+ Scrollbar* hScroller = m_scrollableArea->horizontalScrollbar();
+ Scrollbar* vScroller = m_scrollableArea->verticalScrollbar();
+ if (((hScroller && hScroller->enabled()) || (!vScroller || !vScroller->enabled())))
+ return true;
+
+ return false;
+}
+
+void ScrollAnimatorMac::smoothScrollWithEvent(PlatformWheelEvent& wheelEvent)
+{
+ 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();
+
+ float eventCoallescedDeltaX = -wheelEvent.deltaX();
+ float eventCoallescedDeltaY = -wheelEvent.deltaY();
+
+ deltaX += eventCoallescedDeltaX;
+ deltaY += eventCoallescedDeltaY;
+
+ // Slightly prefer scrolling vertically by applying the = case to deltaY
+ if (fabsf(deltaY) >= fabsf(deltaX))
+ deltaX = 0.0;
+ else
+ deltaY = 0.0;
+
+ bool isVerticallyStretched = false;
+ bool isHorizontallyStretched = false;
+ bool shouldStretch = false;
+
+ IntSize stretchAmount = m_scrollableArea->overhangAmount();
+
+ isHorizontallyStretched = (stretchAmount.width() == 0.0) ? false : true;
+ isVerticallyStretched = (stretchAmount.height() == 0.0) ? false : true;
+
+ PlatformWheelEventPhase phase = wheelEvent.phase();
+
+ // If we are starting momentum scrolling then do some setup.
+ if (!m_momentumScrollInProgress && (phase == PlatformWheelEventPhaseBegan || phase == PlatformWheelEventPhaseChanged))
+ m_momentumScrollInProgress = true;
+
+ CFTimeInterval timeDelta = wheelEvent.timestamp() - m_lastMomemtumScrollTimestamp;
+ if (m_inScrollGesture || m_momentumScrollInProgress) {
+ if (m_lastMomemtumScrollTimestamp && timeDelta > 0.0 && timeDelta < scrollVelocityZeroingTimeout) {
+ m_momentumVelocity.setWidth(eventCoallescedDeltaX / timeDelta);
+ m_momentumVelocity.setHeight(eventCoallescedDeltaY / timeDelta);
+ m_lastMomemtumScrollTimestamp = wheelEvent.timestamp();
+ } else {
+ m_lastMomemtumScrollTimestamp = wheelEvent.timestamp();
+ m_momentumVelocity = FloatSize();
+ }
+
+ if (isVerticallyStretched) {
+ if (!isHorizontallyStretched && pinnedInDirection(deltaX, 0)) {
+ // Stretching only in the vertical.
+ if (deltaY != 0.0 && (fabsf(deltaX / deltaY) < rubberbandDirectionLockStretchRatio))
+ deltaX = 0.0;
+ else if (fabsf(deltaX) < rubberbandMinimumRequiredDeltaBeforeStretch) {
+ m_overflowScrollDelta.setWidth(m_overflowScrollDelta.width() + deltaX);
+ deltaX = 0.0;
+ } else
+ m_overflowScrollDelta.setWidth(m_overflowScrollDelta.width() + deltaX);
+ }
+ } else if (isHorizontallyStretched) {
+ // Stretching only in the horizontal.
+ if (pinnedInDirection(0, deltaY)) {
+ if (deltaX != 0.0 && (fabsf(deltaY / deltaX) < rubberbandDirectionLockStretchRatio))
+ deltaY = 0.0;
+ else if (fabsf(deltaY) < rubberbandMinimumRequiredDeltaBeforeStretch) {
+ m_overflowScrollDelta.setHeight(m_overflowScrollDelta.height() + deltaY);
+ deltaY = 0.0;
+ } else
+ m_overflowScrollDelta.setHeight(m_overflowScrollDelta.height() + deltaY);
+ }
+ } else {
+ // Not stretching at all yet.
+ if (pinnedInDirection(deltaX, deltaY)) {
+ if (fabsf(deltaY) >= fabsf(deltaX)) {
+ if (fabsf(deltaX) < rubberbandMinimumRequiredDeltaBeforeStretch) {
+ m_overflowScrollDelta.setWidth(m_overflowScrollDelta.width() + deltaX);
+ deltaX = 0.0;
+ } else
+ m_overflowScrollDelta.setWidth(m_overflowScrollDelta.width() + deltaX);
+ }
+ shouldStretch = true;
+ }
+ }
+ }
+
+ if (deltaX != 0.0 || deltaY != 0.0) {
+ if (!(shouldStretch || isVerticallyStretched || isHorizontallyStretched)) {
+ if (deltaY != 0) {
+ deltaY *= scrollWheelMultiplier();
+ immediateScrollByDeltaY(deltaY);
+ }
+ if (deltaX != 0) {
+ deltaX *= scrollWheelMultiplier();
+ immediateScrollByDeltaX(deltaX);
+ }
+ } else {
+ if (!allowsHorizontalStretching()) {
+ deltaX = 0.0;
+ eventCoallescedDeltaX = 0.0;
+ } else if ((deltaX != 0) && !isHorizontallyStretched && !pinnedInDirection(deltaX, 0)) {
+ deltaX *= scrollWheelMultiplier();
+
+ m_scrollableArea->setConstrainsScrollingToContentEdge(false);
+ immediateScrollByDeltaX(deltaX);
+ m_scrollableArea->setConstrainsScrollingToContentEdge(true);
+
+ deltaX = 0.0;
+ }
+
+ if (!allowsVerticalStretching()) {
+ deltaY = 0.0;
+ eventCoallescedDeltaY = 0.0;
+ } else if ((deltaY != 0) && !isVerticallyStretched && !pinnedInDirection(0, deltaY)) {
+ deltaY *= scrollWheelMultiplier();
+
+ m_scrollableArea->setConstrainsScrollingToContentEdge(false);
+ immediateScrollByDeltaY(deltaY);
+ m_scrollableArea->setConstrainsScrollingToContentEdge(true);
+
+ deltaY = 0.0;
+ }
+
+ IntSize stretchAmount = m_scrollableArea->overhangAmount();
+
+ if (m_momentumScrollInProgress) {
+ if ((pinnedInDirection(eventCoallescedDeltaX, eventCoallescedDeltaY) || (fabsf(eventCoallescedDeltaX) + fabsf(eventCoallescedDeltaY) <= 0)) && m_lastMomemtumScrollTimestamp) {
+ m_ignoreMomentumScrolls = true;
+ m_momentumScrollInProgress = false;
+ snapRubberBand();
+ }
+ }
+
+ m_stretchScrollForce.setWidth(m_stretchScrollForce.width() + deltaX);
+ m_stretchScrollForce.setHeight(m_stretchScrollForce.height() + deltaY);
+
+ FloatSize dampedDelta(ceil(elasticDeltaForReboundDelta(m_stretchScrollForce.width())), ceil(elasticDeltaForReboundDelta(m_stretchScrollForce.height())));
+ FloatPoint origOrigin = m_scrollableArea->visibleContentRect().location() - stretchAmount;
+ FloatPoint newOrigin = origOrigin + dampedDelta;
+
+ if (origOrigin != newOrigin) {
+ m_scrollableArea->setConstrainsScrollingToContentEdge(false);
+ immediateScrollToPoint(newOrigin);
+ m_scrollableArea->setConstrainsScrollingToContentEdge(true);
+ }
+ }
+ }
+
+ if (m_momentumScrollInProgress && phase == PlatformWheelEventPhaseEnded) {
+ m_momentumScrollInProgress = false;
+ m_ignoreMomentumScrolls = false;
+ m_lastMomemtumScrollTimestamp = 0.0;
+ }
+}
+
+void ScrollAnimatorMac::beginScrollGesture()
+{
+ m_inScrollGesture = true;
+ m_momentumScrollInProgress = false;
+ m_ignoreMomentumScrolls = false;
+ m_lastMomemtumScrollTimestamp = 0.0;
+ m_momentumVelocity = FloatSize();
+
+ IntSize stretchAmount = m_scrollableArea->overhangAmount();
+ m_stretchScrollForce.setWidth(reboundDeltaForElasticDelta(stretchAmount.width()));
+ m_stretchScrollForce.setHeight(reboundDeltaForElasticDelta(stretchAmount.height()));
+
+ m_overflowScrollDelta = FloatSize();
+
+ if (m_snapRubberBandTimer.isActive())
+ m_snapRubberBandTimer.stop();
+}
+
+void ScrollAnimatorMac::endScrollGesture()
+{
+ snapRubberBand();
+}
+
+void ScrollAnimatorMac::snapRubberBand()
+{
+ CFTimeInterval timeDelta = [[NSProcessInfo processInfo] systemUptime] - m_lastMomemtumScrollTimestamp;
+ if (m_lastMomemtumScrollTimestamp && timeDelta >= scrollVelocityZeroingTimeout)
+ m_momentumVelocity = FloatSize();
+
+ m_inScrollGesture = false;
+
+ if (m_snapRubberBandTimer.isActive())
+ return;
+
+ m_startTime = [NSDate timeIntervalSinceReferenceDate];
+ m_startStretch = FloatSize();
+ m_origOrigin = FloatPoint();
+ m_origVelocity = FloatSize();
+
+ m_snapRubberBandTimer.startRepeating(1.0/60.0);
+}
+
+static inline double roundTowardZero(double num)
+{
+ return num > 0.0 ? ceil(num - 0.5) : floor(num + 0.5);
+}
+
+static inline double roundToDevicePixelTowardZero(double num)
+{
+ double roundedNum = round(num);
+ if (fabs(num - roundedNum) < 0.125) {
+ num = roundedNum;
+ }
+
+ return roundTowardZero(num);
+}
+
+void ScrollAnimatorMac::snapRubberBandTimerFired(Timer<ScrollAnimatorMac>*)
+{
+ if (!m_momentumScrollInProgress || m_ignoreMomentumScrolls) {
+ CFTimeInterval timeDelta = [NSDate timeIntervalSinceReferenceDate] - m_startTime;
+
+ if (m_startStretch == FloatSize()) {
+ m_startStretch = m_scrollableArea->overhangAmount();
+ if (m_startStretch == FloatSize()) {
+ m_snapRubberBandTimer.stop();
+ m_stretchScrollForce = FloatSize();
+ m_startTime = 0;
+ m_startStretch = FloatSize();
+ m_origOrigin = FloatPoint();
+ m_origVelocity = FloatSize();
+
+ return;
+ }
+
+ m_origOrigin = m_scrollableArea->visibleContentRect().location() - 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
+ Scrollbar* hScroller = m_scrollableArea->horizontalScrollbar();
+ if (!hScroller || !hScroller->enabled())
+ m_origVelocity.setWidth(0);
+
+ // Don't rubber-band vertically if it's not possible to scroll horizontally
+ Scrollbar* vScroller = m_scrollableArea->verticalScrollbar();
+ if (!vScroller || !vScroller->enabled())
+ m_origVelocity.setHeight(0);
+ }
+
+ FloatPoint delta(roundToDevicePixelTowardZero(elasticDeltaForTimeDelta(m_startStretch.width(), -m_origVelocity.width(), timeDelta)),
+ roundToDevicePixelTowardZero(elasticDeltaForTimeDelta(m_startStretch.height(), -m_origVelocity.height(), timeDelta)));
+
+ if (fabs(delta.x()) >= 1.0 || fabs(delta.y()) >= 1.0) {
+ FloatPoint newOrigin = m_origOrigin + delta;
+
+ m_scrollableArea->setConstrainsScrollingToContentEdge(false);
+ immediateScrollToPoint(newOrigin);
+ m_scrollableArea->setConstrainsScrollingToContentEdge(true);
+
+ FloatSize newStretch = m_scrollableArea->overhangAmount();
+
+ m_stretchScrollForce.setWidth(reboundDeltaForElasticDelta(newStretch.width()));
+ m_stretchScrollForce.setHeight(reboundDeltaForElasticDelta(newStretch.height()));
+ } else {
+ immediateScrollToPoint(m_origOrigin);
+
+ m_snapRubberBandTimer.stop();
+ m_stretchScrollForce = FloatSize();
+
+ m_startTime = 0;
+ m_startStretch = FloatSize();
+ m_origOrigin = FloatPoint();
+ m_origVelocity = FloatSize();
+ }
+ } else {
+ m_startTime = [NSDate timeIntervalSinceReferenceDate];
+ m_startStretch = FloatSize();
+ }
+}
+#endif
+
} // namespace WebCore
#endif // ENABLE(SMOOTH_SCROLLING)
--
WebKit Debian packaging
More information about the Pkg-webkit-commits
mailing list