[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