webengine/osswebengine/WebKit/s60/webview/WebPageScrollHandler.cpp
changeset 0 dd21522fd290
child 1 7c90e6132015
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/webengine/osswebengine/WebKit/s60/webview/WebPageScrollHandler.cpp	Mon Mar 30 12:54:55 2009 +0300
@@ -0,0 +1,684 @@
+/*
+* Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:   Implementation of drag scrolling
+*
+*/
+
+
+// INCLUDE FILES
+#include <Browser_platform_variant.hrh>
+#include <../bidi.h>
+#include "WebPageScrollHandler.h"
+#include "BrCtl.h"
+#include "WebFrame.h"
+#include "WebFrameView.h"
+#include "WebView.h"
+#include <AknUtils.h>
+#include "Page.h"
+#include "Frame.h"
+#include "WebCoreFrameBridge.h"
+#include "FrameView.h"
+#include "FocusController.h"
+#include "PlatformScrollbar.h"
+#include "WebScrollbarDrawer.h"
+#include "RenderObject.h"
+#include "WebScrollingDeceleratorGH.h"
+
+#include "WebKitLogger.h"
+using namespace WebCore;
+using namespace RT_GestureHelper;
+// constants
+const int KPageOverviewScrollPeriodic = 20 * 1000; // Update frequently for faster, smoother scrolling
+const int KMicroInterval = 300000;
+const int KPageOverviewScrollStart = 1000;
+const int KCancelDecelerationTimeout = 200000; //Decelerate only if flicked KCancelDecelerationTimeout microsec after last drag event.
+
+const int KScrollIntervalTimeout = 40000; // scroll timer interval in microseconds
+const int KAngularDeviationThreshold = 160; // % deviation ignored from minor axis of motion(120 means 20 %)
+const int KScrollThresholdPixels = 10; // scrolls only if delta is above this threshold
+const int KScrollDirectionBoundary = 30; // Bound around focal point within which scrolling locks in X or Y states
+const float KTanOfThresholdAngle = 0.46; // tan of 25 degree
+
+int handleScrollTimerEventCallback( TAny* ptr);
+
+// ============================= LOCAL FUNCTIONS ===============================
+int WebPageScrollHandler::pageOverviewScrollCallback( TAny* aPtr )
+{
+#ifdef BRDO_USE_GESTURE_HELPER
+    static_cast<WebPageScrollHandler*>(aPtr)->scrollPageOverviewGH();
+#else
+    static_cast<WebPageScrollHandler*>(aPtr)->handlePageOverviewScrollCallback();
+#endif //BRDO_USE_GESTURE_HELPER
+    return KErrNone;
+}
+    
+int handleScrollTimerEventCallback( TAny* ptr)
+{
+    WebPageScrollHandler* scrollHandler = static_cast<WebPageScrollHandler*>(ptr);
+    scrollHandler->scrollContent();
+    return EFalse;    
+}      
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// ScrollableView::contentPos
+// 
+// -----------------------------------------------------------------------------
+//
+TPoint ScrollableView::contentPos()
+{
+    WebFrameView* fv = activeFrameView();
+    if (fv) return fv->contentPos();
+    return TPoint (0,0);
+}
+
+WebFrameView* ScrollableView::activeFrameView()
+{
+    if (m_scrollingElement) {
+        return kit(m_scrollingElement->document()->frame())->frameView();
+    }
+    else {
+        return m_frameView;
+    }
+}
+
+
+// -----------------------------------------------------------------------------
+// WebPageScrollHandler::NewL
+// The two-phase Symbian constructor
+// -----------------------------------------------------------------------------
+//
+WebPageScrollHandler* WebPageScrollHandler::NewL(WebView& webView)
+    {
+    WebPageScrollHandler* self = new (ELeave) WebPageScrollHandler( webView );
+    CleanupStack::PushL(self);
+    self->constructL();
+    CleanupStack::Pop(); //self
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// WebPageScrollHandler::WebPageScrollHandler
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+WebPageScrollHandler::WebPageScrollHandler(WebView& webView)
+: m_webView( &webView ), m_decel(0), m_decelGH(NULL)
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// WebPageScrollHandler::constructL
+// The constructor that can contain code that might leave.
+// -----------------------------------------------------------------------------
+//
+void WebPageScrollHandler::constructL()
+    {
+        m_scrollTimer = CPeriodic::NewL(CActive::EPriorityUserInput - 1);
+        m_pageOverviewScrollPeriodic = CPeriodic::NewL(CActive::EPriorityUserInput - 1);
+        m_lastPosition = TPoint(0, 0);
+        
+        if(AknLayoutUtils::PenEnabled()) {
+            m_touchScrolling = true;
+            m_scrollDirectionState = ScrollDirectionUnassigned;
+            m_scrollbarDrawer = WebScrollbarDrawer::NewL();
+#ifndef BRDO_USE_GESTURE_HELPER            
+            m_decel = WebScrollingDecelerator::NewL(*m_webView);
+#else            
+	        m_decelGH = WebScrollingDeceleratorGH::NewL(*m_webView);
+#endif	    
+        }
+        else  {
+            m_touchScrolling = false;            
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// Destructor
+// -----------------------------------------------------------------------------
+WebPageScrollHandler::~WebPageScrollHandler()
+{    
+    
+    if (m_scrollTimer) {
+        m_scrollTimer->Cancel();
+        delete m_scrollTimer;    
+    }
+
+    if (m_pageOverviewScrollPeriodic) {
+        m_pageOverviewScrollPeriodic->Cancel();
+        delete m_pageOverviewScrollPeriodic;
+    }
+
+    delete m_decel;
+    delete m_decelGH;
+    delete m_scrollbarDrawer;
+}
+    
+void WebPageScrollHandler::handlePageOverviewScrollingL(const TPointerEvent& pointerEvent)
+{
+    switch (pointerEvent.iType){
+        case TPointerEvent::EButton1Down:            
+            m_webView->setViewIsScrolling(false);
+            m_lastPointerEvent.iPosition.SetXY(0,0);
+            m_lastDragEvent = pointerEvent;
+            break;
+
+        case TPointerEvent::EDrag:
+            if (!m_webView->viewIsScrolling()){
+                m_webView->setViewIsScrolling(true);
+                m_pageOverviewScrollPeriodic->Start( 0, KPageOverviewScrollPeriodic, TCallBack(&pageOverviewScrollCallback, this));
+            }
+            break;
+
+        case TPointerEvent::EButton1Up:
+            if (m_pageOverviewScrollPeriodic->IsActive()){ 
+                m_pageOverviewScrollPeriodic->Cancel();
+            }
+            m_webView->closePageView();
+            m_webView->setViewIsScrolling(false);
+            break;
+
+        default:
+            break;
+   }
+  
+   // Scroll here only for EButton1Up and EButton1Down if needed
+   if(pointerEvent.iType != TPointerEvent::EDrag && m_lastPointerEvent.iPosition != pointerEvent.iPosition){
+       scrollPageOverview( pointerEvent );
+   }
+   m_lastPointerEvent = pointerEvent; 
+}
+
+void WebPageScrollHandler::handlePageOverviewScrollCallback()
+{
+    int absX = Abs( m_lastDragEvent.iPosition.iX - m_lastPointerEvent.iPosition.iX);
+    int absY = Abs( m_lastDragEvent.iPosition.iY - m_lastPointerEvent.iPosition.iY);
+
+   // Scrolling for EDrag events
+
+    if( absX > 3 ||  absY > 3){
+        scrollPageOverview( m_lastPointerEvent );
+        m_lastDragEvent = m_lastPointerEvent;
+    }
+}
+
+
+void WebPageScrollHandler::scrollPageOverview(const TPointerEvent& pointerEvent)
+{
+
+    TRect indicatorRect = m_webView->pageScaler()->IndicatorRect();
+    TInt zoomLevel = m_webView->pageScaler()->ZoomOutLevel();
+    TPoint currentPosition = m_webView->mainFrame()->frameView()->contentPos();
+    TInt xInDoc = ((pointerEvent.iPosition.iX - indicatorRect.iTl.iX  - indicatorRect.Width() / 2) * zoomLevel ) / 100 + currentPosition.iX;
+    TInt yInDoc = ((pointerEvent.iPosition.iY - indicatorRect.iTl.iY  - indicatorRect.Height() / 2) * zoomLevel ) / 100 + currentPosition.iY;
+           
+    m_webView->mainFrame()->frameView()->scrollTo(TPoint(xInDoc, yInDoc));    
+
+}
+
+void WebPageScrollHandler::updateScrolling(const TPointerEvent& pointerEvent)
+{
+    switch (pointerEvent.iType)
+    {
+        case TPointerEvent::EButton1Down:
+        {        
+            m_lastMoveEventTime = 0; 
+            m_lastPosition = pointerEvent.iPosition;
+            m_currentPosition = pointerEvent.iPosition;
+            m_webView->setViewIsScrolling(false);         
+            // stop deceleration scrolling cycle            
+            if (m_decel) {
+                m_decel->stopDecelL();    
+            }
+            m_scrollableView.m_scrollingElement = NULL;
+            m_scrollableView.m_frameView = NULL;
+            break;
+        }
+        case TPointerEvent::EButton1Up:
+        {
+            m_scrollTimer->Cancel();
+            if (m_scrollableView.m_scrollingElement) {
+                if (m_scrollableView.m_scrollingElement) {
+                    m_scrollableView.m_scrollingElement->deref();
+                    m_scrollableView.m_scrollingElement = NULL;
+                }
+            }
+            else {
+                if (m_lastMoveEventTime != 0)
+                {           
+                    // Start deceleration only if the delta since last drag event is less than threshold
+                    TTime now;
+                    now.HomeTime();             
+                    TTimeIntervalMicroSeconds ms = now.MicroSecondsFrom(m_lastMoveEventTime);
+                    if (ms < KCancelDecelerationTimeout) {
+                        m_decel->startDecelL();    
+                    }
+                }            
+                if (m_webView->viewIsScrolling()) {
+                    Frame* frame = m_webView->page()->focusController()->focusedOrMainFrame();
+                    frame->bridge()->sendScrollEvent();                            
+                }
+            }
+            m_scrollbarDrawer->fadeScrollbar();
+            m_scrollDirectionState = ScrollDirectionUnassigned;
+            m_lastMoveEventTime = 0;
+            break;
+        }
+    }
+}
+
+void WebPageScrollHandler::setupScrolling(const TPoint& aNewPosition)
+{   
+    if (m_lastPosition == TPoint(0, 0)) {
+        m_lastPosition = aNewPosition;
+    }
+    if(m_lastPosition == aNewPosition)
+        return; // no displacement -- means no need for scrolling    
+
+    //Ignore move events until they jump the threshold (avoids jittery finger effect) 
+    TInt absX = Abs( aNewPosition.iX - m_lastPosition.iX);
+    TInt absY = Abs( aNewPosition.iY - m_lastPosition.iY);
+    if( absX < KScrollThresholdPixels &&  absY < KScrollThresholdPixels)
+        return;
+            
+    if (calculateScrollableFrameView(aNewPosition))  {
+
+        // normalize current position to minimize cumulative rounding error 
+        m_currentNormalizedPosition.iX = m_scrollableView.contentPos().iX * 100;
+        m_currentNormalizedPosition.iY = m_scrollableView.contentPos().iY * 100;
+        // do the scrolling in a time out
+        m_scrollTimer->Cancel();                   
+        m_scrollTimer->Start( 0, KScrollIntervalTimeout, TCallBack(&handleScrollTimerEventCallback,this));
+        m_webView->setViewIsScrolling(true);
+        m_webView->toggleRepaintTimer(false);
+    }
+
+
+}    
+
+void WebPageScrollHandler::scrollContent()
+{
+    TPoint scrollDelta = m_lastPosition - m_currentPosition;
+ 
+    if(!m_scrollableView.activeFrameView())
+            return;
+        
+    int absX = Abs(scrollDelta.iX);
+    int absY = Abs(scrollDelta.iY);
+                                       
+    if(absX || absY) //move only if necessary
+    {      
+        // calculate which direction we are trying to scroll
+        if(m_scrollDirectionState == ScrollDirectionUnassigned) {
+            m_focalPoint = m_currentPosition;
+            calculateScrollDirection(absX, absY);
+        }   
+        
+        switch (m_scrollDirectionState)
+        {           
+            case ScrollDirectionX: //scroll in X dir
+            {
+                scrollDelta.iY = 0;
+                scrollDelta.iX *= 100;
+                //Fallback to XY state if the current position is out of bounds                
+                TPoint boundaryCheckpoint = m_focalPoint - m_currentPosition;                                
+                if(Abs(boundaryCheckpoint.iY) > KScrollDirectionBoundary)
+                    m_scrollDirectionState = ScrollDirectionXY;
+                break;
+            }
+            case ScrollDirectionY: //scroll in Y dir
+            {                
+                scrollDelta.iX = 0;
+                scrollDelta.iY *= 100;
+                //Fallback to XY state if the current position is out of bounds                
+                TPoint boundaryCheckpoint = m_focalPoint - m_currentPosition;                                
+                if(Abs(boundaryCheckpoint.iX) > KScrollDirectionBoundary)
+                    m_scrollDirectionState = ScrollDirectionXY;
+                break;
+            }
+            case ScrollDirectionXY: //scroll in XY
+            {
+                scrollDelta.iX *= 100;
+                scrollDelta.iY *= 100;
+                m_scrollDirectionState = ScrollDirectionUnassigned;
+                break;
+            }
+        }        
+        if (m_scrollableView.m_scrollingElement) {
+            bool shouldScrollVertically = false;
+            bool shouldScrollHorizontally = false;
+            //WebFrameView* mfv = m_webView->mainFrame()->frameView();
+            WebFrame* frame = kit(m_scrollableView.m_scrollingElement->document()->frame());
+            IntPoint currPoint = frame->frameView()->viewCoordsInFrameCoords(m_currentPosition);
+            RenderObject* render = m_scrollableView.m_scrollingElement->renderer();
+            __ASSERT_DEBUG(render->isScrollable(), User::Panic(_L(""), KErrGeneral));
+            if (scrollDelta.iY)
+                shouldScrollVertically = !render->scroll(ScrollDown, ScrollByPixel, frame->frameView()->toDocCoords(scrollDelta).iY / 100);
+            if (scrollDelta.iX)
+                shouldScrollHorizontally = !render->scroll(ScrollRight, ScrollByPixel, frame->frameView()->toDocCoords(scrollDelta).iX / 100);
+            TPoint scrollPos = frame->frameView()->contentPos();
+            TPoint newscrollDelta = frame->frameView()->toDocCoords(scrollDelta);
+            m_currentNormalizedPosition +=  newscrollDelta;     
+
+            if (shouldScrollHorizontally) {
+                scrollPos.iX = m_currentNormalizedPosition.iX/100;
+            }
+            if (shouldScrollVertically) {
+                scrollPos.iY = m_currentNormalizedPosition.iY/100;
+            }
+            frame->frameView()->scrollTo(scrollPos);
+            m_lastPosition = m_currentPosition;
+            m_currentNormalizedPosition.iX = frame->frameView()->contentPos().iX * 100;
+            m_currentNormalizedPosition.iY = frame->frameView()->contentPos().iY * 100;
+            if (shouldScrollVertically || shouldScrollHorizontally)
+                updateScrollbars(scrollPos, newscrollDelta);
+            currPoint = frame->frameView()->viewCoordsInFrameCoords(m_currentPosition);
+            if (shouldScrollHorizontally || shouldScrollVertically) {
+                core(frame)->sendScrollEvent();
+                m_webView->DrawNow();
+            }
+        }
+        else {
+            TPoint scrollPos;
+            TPoint newscrollDelta = m_scrollableView.m_frameView->toDocCoords(scrollDelta);
+            m_currentNormalizedPosition +=  newscrollDelta;  
+            scrollPos.iX = m_currentNormalizedPosition.iX/100;
+            scrollPos.iY = m_currentNormalizedPosition.iY/100;
+            TPoint cpos = m_scrollableView.m_frameView->contentPos();
+           
+            if(!m_scrollableView.m_frameView->needScroll(scrollPos)) {
+                m_scrollDirectionState = ScrollDirectionUnassigned;
+                m_lastPosition = m_currentPosition;
+                m_currentNormalizedPosition.iX = m_scrollableView.contentPos().iX * 100;
+                m_currentNormalizedPosition.iY = m_scrollableView.contentPos().iY * 100;
+            }
+            else {
+                m_scrollableView.m_frameView->scrollTo(scrollPos);
+                m_lastPosition = m_currentPosition;
+#ifndef BRDO_USE_GESTURE_HELPER                
+                m_decel->updatePos();
+#endif                
+            // update scroll bars
+                updateScrollbars(scrollPos, newscrollDelta);
+            }
+        }
+    }
+} 
+
+bool WebPageScrollHandler::calculateScrollableFrameView(const TPoint& aNewPosition)
+{
+    if (calculateScrollableElement(aNewPosition)) return true;
+    
+    //First figure out the direction we are scrolling    
+    bool x_r = false;
+    bool x_l = false;
+    bool y_t = false;
+    bool y_b = false;
+
+    //find the x direction
+    int x_delta = aNewPosition.iX - m_lastPosition.iX;
+    if (x_delta > 0) {
+        x_l = true;                
+    } else if (x_delta < 0){
+        x_r = true;
+    }
+
+    //find the y direction
+    int y_delta = aNewPosition.iY - m_lastPosition.iY;
+    if (y_delta > 0) {
+        y_t = true;                
+    } else if (y_delta < 0){
+        y_b = true;
+    }
+        
+    m_scrollableView.m_frameView = NULL;
+        
+    //find the frame that can scroll if we can't scroll check the parents        
+    WebFrame* frame = m_webView->mainFrame()->frameAtPoint(aNewPosition);
+    for (; frame; frame = frame->parentFrame())  {
+    
+        // Dont scroll a frameset
+        if (frame->parentFrame() && frame->parentFrame()->isFrameSet()) 
+            continue;     
+        
+        TPoint contentpos = frame->frameView()->contentPos();
+        TSize contentsize = frame->frameView()->contentSize();        
+        TRect framerect = frame->frameView()->rect();        
+        
+        //if the content width is > frameview width
+        if (contentsize.iWidth > framerect.Width() && frame->frameView()->hScrollbar()->isEnabled()) {
+            //IF we are trying to scroll to the right we need 
+            //to see if the content position < content size - frameview size        
+            //ELSE if we are trying to the left we need 
+            //to see if the content position > 0 
+            if (x_r) {        
+                if (contentpos.iX < (contentsize.iWidth - framerect.Width())) {
+                    m_scrollableView.m_frameView = frame->frameView();
+                    return true;                
+                }
+
+            } else if (x_l) {
+                if (contentpos.iX > 0) {
+                    m_scrollableView.m_frameView = frame->frameView();
+                    return true;                
+                }            
+            }
+        }
+        
+        //if the content height is > frameview height
+        if (contentsize.iHeight > framerect.Height() && frame->frameView()->vScrollbar()->isEnabled()) {
+            //IF we are trying to scroll down we need 
+            //to see if the content position < content size - frameview size        
+            //ELSE if we are trying to scroll up we need 
+            //to see if the content position > 0 
+            if (y_b) {        
+                if (contentpos.iY < (contentsize.iHeight - framerect.Height())) {
+                    m_scrollableView.m_frameView = frame->frameView();
+                    return true;                
+                }
+
+            } else if (y_t) {
+                if (contentpos.iY > 0) {
+                    m_scrollableView.m_frameView = frame->frameView();
+                    return true;                
+                }            
+            }
+        }
+    }
+    
+    //could not find a scrollable frame        
+    m_scrollableView.m_frameView  = m_webView->mainFrame()->frameView();
+    return true;
+   
+}
+
+void WebPageScrollHandler::calculateScrollDirection(int absX, int absY)
+{
+     //assign scroll direction state according to scroll angle
+    if((absX * KAngularDeviationThreshold) < (absY * 100))
+        m_scrollDirectionState = ScrollDirectionY;
+    else if((absY * KAngularDeviationThreshold) < (absX * 100))
+        m_scrollDirectionState = ScrollDirectionX;
+    else
+        m_scrollDirectionState = ScrollDirectionXY;    
+}
+
+void WebPageScrollHandler::updateScrollbars(const TPoint& scrollPos, TPoint& newscrollDelta)
+{
+    WebFrameView* fv = m_scrollableView.activeFrameView();
+    if (fv) {
+        
+        if (fv->vScrollbar()) {
+            fv->vScrollbar()->setValue(scrollPos.iY);
+        }
+
+        if (fv->hScrollbar()) {
+            fv->hScrollbar()->setValue(scrollPos.iX);
+        }
+        
+        if ((fv->frame() == m_webView->mainFrame())) {
+          m_scrollbarDrawer->drawScrollbar(m_webView, newscrollDelta);
+        }
+    }
+}
+         
+
+bool WebPageScrollHandler::calculateScrollableElement(const TPoint& aNewPosition)
+{
+    WebFrame* frame = m_webView->mainFrame()->frameAtPoint(aNewPosition);
+    if( !frame ) return false;
+    TPoint pt = frame->frameView()->viewCoordsInFrameCoords(aNewPosition);
+    Element* e = core(frame)->document()->elementFromPoint(pt.iX, pt.iY);
+    Element* currElement = NULL;
+    if(!e) return NULL;
+    RenderObject* render = e->renderer();
+    if (render && render->isScrollable()) {
+        RenderLayer* layer = render->enclosingLayer();
+        Element* parent = e;
+        currElement = e;
+        while (!currElement->isControl() && parent && parent->renderer() && parent->renderer()->enclosingLayer() == layer) {
+            currElement = parent;
+            Node* pn = parent;
+            do {
+                pn = pn->parent();
+            } while (pn && !pn->isElementNode());
+            parent = static_cast<Element*>(pn);
+        }
+        if (currElement) {
+            currElement->ref();
+            m_scrollableView.m_scrollingElement = currElement; 
+            m_scrollableView.m_frameView = NULL;
+            return true;
+        }
+    }
+    return false;
+}
+
+
+void WebPageScrollHandler::scrollPageOverviewGH()
+{
+
+    TRect indicatorRect = m_webView->pageScaler()->IndicatorRect();
+    TInt zoomLevel = m_webView->pageScaler()->ZoomOutLevel();
+    TPoint currentPosition = m_webView->mainFrame()->frameView()->contentPos();
+    TInt xInDoc = ((m_currentPosition.iX - indicatorRect.iTl.iX  - indicatorRect.Width() / 2) * zoomLevel ) / 100 + currentPosition.iX;
+    TInt yInDoc = ((m_currentPosition.iY - indicatorRect.iTl.iY  - indicatorRect.Height() / 2) * zoomLevel ) / 100 + currentPosition.iY;
+           
+    m_webView->mainFrame()->frameView()->scrollTo(TPoint(xInDoc, yInDoc));    
+
+}
+
+
+void WebPageScrollHandler::handleScrollingGH(const MGestureEvent& aEvent)
+{   
+    TPoint newPos = aEvent.CurrentPos();
+    m_currentPosition = newPos;
+    if (m_webView->inPageViewMode()) {
+        if (!m_pageOverviewScrollPeriodic->IsActive()){
+            m_pageOverviewScrollPeriodic->Start( 0, KPageOverviewScrollPeriodic, 
+                                                TCallBack(&pageOverviewScrollCallback, this));
+            m_webView->setViewIsScrolling(true);
+            m_webView->toggleRepaintTimer(false);
+        }
+    }
+    else if (!m_webView->viewIsScrolling()) {
+        setupScrolling(newPos);    
+    }
+}
+
+
+void WebPageScrollHandler::handleTouchDownGH(const MGestureEvent& aEvent)
+{
+    TPoint newPos = aEvent.CurrentPos();
+    m_lastMoveEventTime = 0; 
+    m_lastPosition = newPos;
+    m_currentPosition = newPos;
+    m_webView->setViewIsScrolling(false);      
+    m_webView->toggleRepaintTimer(true);
+            
+    if (m_decelGH) {
+        m_decelGH->cancelDecel();
+    }
+    m_scrollableView.m_scrollingElement = NULL;
+    m_scrollableView.m_frameView = NULL;
+}
+
+
+void WebPageScrollHandler::handleTouchUpGH(const MGestureEvent& aEvent)
+{
+    bool decelDoesScrollbars = false;
+    TPoint newPos = aEvent.CurrentPos();
+
+    if (m_webView->inPageViewMode()) {
+        if (m_pageOverviewScrollPeriodic->IsActive()){ 
+            m_pageOverviewScrollPeriodic->Cancel();
+        }
+        m_webView->closePageView();
+        scrollPageOverviewGH();
+        m_webView->setViewIsScrolling(false);
+        m_webView->toggleRepaintTimer(true);
+    }
+    else {
+        m_scrollTimer->Cancel();
+        m_lastPosition = TPoint(0, 0);
+        if (m_scrollableView.m_scrollingElement) {
+            if (m_scrollableView.m_scrollingElement) {
+                m_scrollableView.m_scrollingElement->deref();
+                m_scrollableView.m_scrollingElement = NULL;
+            }
+        }
+        else {
+            decelDoesScrollbars = startDeceleration(aEvent);
+                    
+            if (m_webView->viewIsScrolling()) {
+                Frame* frame = m_webView->page()->focusController()->focusedOrMainFrame();
+                frame->bridge()->sendScrollEvent();                            
+            }
+        }
+    
+        if (!decelDoesScrollbars) {
+            m_scrollbarDrawer->fadeScrollbar();
+            m_webView->setViewIsScrolling(false);
+            m_webView->toggleRepaintTimer(true);
+        }
+        m_scrollDirectionState = ScrollDirectionUnassigned;
+        m_lastMoveEventTime = 0;
+    }
+}
+
+
+bool WebPageScrollHandler::startDeceleration(const MGestureEvent& aEvent)
+{
+    bool started = false;
+    TRealPoint gstSpeed = aEvent.Speed();
+    if (Abs(gstSpeed.iX / gstSpeed.iY) <= KTanOfThresholdAngle) {
+       gstSpeed.iX = 0;
+    }
+    
+    if (Abs(gstSpeed.iY / gstSpeed.iX) <= KTanOfThresholdAngle) { 
+       gstSpeed.iY = 0;
+    }
+    
+    if ((Abs(gstSpeed.iX) > 0) || (Abs(gstSpeed.iY) > 0)) {
+       m_decelGH->startDecel(gstSpeed, m_scrollbarDrawer); 
+       started = true;
+    }
+    
+    
+    return started;
+}
+
+//  End of File