ginebra2/ContentViews/ScrollableWebContentView.cpp
changeset 16 3c88a81ff781
parent 9 b39122337a00
--- a/ginebra2/ContentViews/ScrollableWebContentView.cpp	Thu Sep 23 15:32:11 2010 -0400
+++ b/ginebra2/ContentViews/ScrollableWebContentView.cpp	Fri Oct 15 17:30:59 2010 -0400
@@ -20,63 +20,133 @@
 */
 
 #include "ScrollableWebContentView.h"
-
-#include "Gestures/GestureRecognizer.h"
 #include "Kinetics/KineticScroller.h"
 #include "ScrollableViewBase.h"
 #include "ViewportMetaDataParser.h"
-#include "WebContentAnimationItem.h"
+#include "WebView.h"
+#include "qstmgestureevent.h"
+#include "qstmfilelogger.h"
+#include "bedrockprovisioning.h"
+#include "ScrollHelper.h"
 
 #include <QApplication>
 #include <QGraphicsScene>
 #include <QGraphicsSceneMouseEvent>
 #include <QGraphicsWebView>
+#include <QStyleOptionGraphicsItem>
 #include <QWebElement>
 #include <QWebHitTestResult>
+#include <QWebPage>
+#include <QWebHistory>
+#include <QInputContext>
 
+#include "Gestures/GestureRecognizer.h"
+#ifdef ORBIT_UI
+#include <hbinputmethod.h>
+#endif // ORBIT_UI
+
+namespace GVA {
 //Kinetic scroll constants
 static const int ScrollsPerSecond = 30;
 static const int MinimumScrollVelocity = 10;
 static const qreal AxisLockThreshold = .8;
 
-
 //Zooming constants
-static const int ZoomAnimationDuration = 300;   //ms. Zooming transition duration
+const int ZoomAnimationDuration = 600;   //ms. Zooming transition duration
+const int MaxZoomAnimationDuration = 2000;   //ms. Zooming transition duration
 static const qreal ZoomStep = .5;               //Incremental zoom step
-const int TileUpdateEnableDelay = 500;         //Wait duration before tiling updates are enabled.
+#ifdef Q_WS_MAEMO_5
+const int TileUpdateEnableDelay = 10;         //Wait duration before tiling updates are enabled.
+#else
+const int TileUpdateEnableDelay = 150;         //Wait duration before tiling updates are enabled.
+#endif
+static const int MinDoubleClickZoomTargetWidth = 100;     //Target block width for applying double tap zoom
+static const int ZoomCommitDuration = 60;                //Timeout before commiting zoom
+static const qreal ZoomableContentMinWidth = 300.;
 
-namespace GVA {
+static const qreal InvalidCoord = 1e10;
+static const int TouchDownTimeout = 200;
+static const int HoverTimeout = 100;
 
-ScrollableWebContentView::ScrollableWebContentView(WebContentAnimationItem* webAnimationItem, QGraphicsItem* parent)
+#undef USE_KINETIC_SCROLLER
+using namespace qstmGesture;
+
+ScrollableWebContentView::ScrollableWebContentView(WebView* scrolledWidget, QGraphicsItem* parent)
     : ScrollableViewBase(parent)
     , m_gestureRecognizer(this)
+    , m_isInputOn(false)
+    , m_ignoreNextRelease(false)
 {
     m_viewportMetaData = new ViewportMetaData();
 
+    scrolledWidget->installEventFilter(this);
+    
     //Kinetic scroller settings
     //Sets the number of scrolls (frames) per second to sps.
     m_kineticScroller->setScrollsPerSecond(ScrollsPerSecond);
     //For elastic scroll in page edges
     m_kineticScroller->setOvershootPolicy(KineticScroller::OvershootWhenScrollable);
 
+    setWidget(scrolledWidget);
+
+    m_tileUpdateEnableTimer.setSingleShot(true);
+    connect(&m_tileUpdateEnableTimer, SIGNAL(timeout()), this, SLOT(enableContentUpdates()));
+    m_zoomCommitTimer.setSingleShot(true);
+    connect(&m_zoomCommitTimer, SIGNAL(timeout()),this,SLOT(commitZoom()));
+
+    //Setup zooming animator
+    m_zoomAnimator = new QPropertyAnimation(this, "viewableRect");
+    //m_zoomAnimator->setDuration(ZoomAnimationDuration);
+    connect(m_zoomAnimator, SIGNAL(stateChanged(QAbstractAnimation::State,QAbstractAnimation::State)), 
+            this, SLOT(zoomAnimationStateChanged(QAbstractAnimation::State,QAbstractAnimation::State)));
+    
+    m_isSuperPage = false;
+    m_gesturesEnabled = true;
+    m_isLoading = false;
+    m_touchDownTimer = UiTimer::New();
+    m_touchDownTimer->setTimerCallback((char*)"touchDownCallback");
+    
+    m_hoverTimer = UiTimer::New();
+    m_hoverTimer->setTimerCallback((char*)"hoverCallback");
+        
+    m_touchDownTimer->setPriority(150);
+    m_pinchFinishTime = QTime::currentTime();
+    // ScrollHelper
+    m_scrollHelper = new ScrollHelper(this);
+    initScrollHelper();
+        
     //Gesture settings
     //For detecting scroll direction
     m_gestureRecognizer.setAxisLockThreshold(AxisLockThreshold);
     //To enable touch and drag scrolling
     m_gestureRecognizer.setMinimumVelocity(MinimumScrollVelocity);
 
-    setWidget(webAnimationItem);
-    //FIX ME : Revisit this code. Duplicate info sharing!
-    webAnimationItem->setViewportMetaData(m_viewportMetaData);
+    grabGesture(QStm_Gesture::assignedType());
+    connect(this, SIGNAL(viewScrolled(QPoint&, QPoint&)), scrolledWidget, SLOT(viewScrolled(QPoint&, QPoint&)));
+    installEventFilter(this);
+}
 
+void ScrollableWebContentView::initScrollHelper()
+{
+    qreal decel = BedrockSettings->value("KineticDeceleration").toDouble();
+    m_scrollHelper->setDeceleration(decel);
 
-    m_tileUpdateEnableTimer.setSingleShot(true);
-    connect(&m_tileUpdateEnableTimer, SIGNAL(timeout()), webAnimationItem, SLOT(enableContentUpdates()));
+    qreal maxFlickKoef = BedrockSettings->value("MaxFlickInViewportUnits").toDouble();
+    qreal minFlickKoef = BedrockSettings->value("MinFlickInViewportUnits").toDouble();
+    qreal midFlickKoef = BedrockSettings->value("MidFlickInViewportUnits").toDouble();
+    m_scrollHelper->setFlickLimits(minFlickKoef, midFlickKoef, maxFlickKoef);
 
-    //Setup zooming animator
-    m_zoomAnimator = new QPropertyAnimation(webAnimationItem, "geometry");
-    m_zoomAnimator->setDuration(ZoomAnimationDuration);
-    connect(m_zoomAnimator, SIGNAL(stateChanged(QAbstractAnimation::State,QAbstractAnimation::State)), this, SLOT(zoomAnimationStateChanged(QAbstractAnimation::State,QAbstractAnimation::State)));
+    qreal maxFlickSpeed = BedrockSettings->value("MaxFlickSpeed").toDouble();
+    qreal minFlickSpeed = BedrockSettings->value("MinFlickSpeed").toDouble();
+    qreal midFlickSpeed = BedrockSettings->value("MidFlickSpeed").toDouble();
+    m_scrollHelper->setFlickSpeedLimits(minFlickSpeed, midFlickSpeed, maxFlickSpeed);
+
+    int maxFlickDuration = BedrockSettings->value("MaxFlickDuration").toInt();
+    int minFlickDuration = BedrockSettings->value("MinFlickDuration").toInt();
+    int midFlickDuration = BedrockSettings->value("MidFlickDuration").toInt();
+    m_scrollHelper->setFlickDurationLimits(minFlickDuration, midFlickDuration, maxFlickDuration);
+    
+    connect(m_scrollHelper, SIGNAL(scrollFinished()), this, SLOT(stopScrolling()));
     
     m_gesturesEnabled = true;
 }
@@ -84,116 +154,277 @@
 ScrollableWebContentView::~ScrollableWebContentView()
 {
     delete m_viewportMetaData;
-    delete m_kineticScroller;
-
     if(m_zoomAnimator) {
         m_zoomAnimator->stop();
         delete m_zoomAnimator;
     }
+    
+    m_touchDownTimer->stop();
+    delete m_touchDownTimer;
+    
+    m_hoverTimer->stop();
+    delete m_hoverTimer;
+
 }
 
-WebContentAnimationItem* ScrollableWebContentView::viewportWidget() const
-{
-    return qobject_cast<WebContentAnimationItem*>(scrollWidget());
-}
-
-void ScrollableWebContentView::zoomToScreenCenter(bool zoomIn)
+void ScrollableWebContentView::stepZoom(bool zoomIn)
 {
     //If viewport metadata has user scalable false.
     //Do not zoom.
     if (!m_viewportMetaData->m_userScalable)
         return;
 
+    if (isZooming()) {
+        stopZoomAnimation();
+        return;
+    }
+    
     qreal scale = 1;
     scale += ZoomStep;
 
     if (!zoomIn)
         scale = 1/scale;
 
-    qreal curScale =  viewportWidget()->zoomScale();
+    qreal curScale =  scrollWidget()->scale();
+    qreal destScale = curScale * scale;
 
-    if (zoomIn && (curScale * scale > m_viewportMetaData->m_maximumScale))
-        scale = m_viewportMetaData->m_maximumScale / curScale;
-    else if (!zoomIn && (curScale * scale < m_viewportMetaData->m_minimumScale))
-        scale = m_viewportMetaData->m_minimumScale / curScale;
+    if (zoomIn && (destScale > m_viewportMetaData->m_maximumScale))
+        destScale = m_viewportMetaData->m_maximumScale;
+    else if (!zoomIn && (destScale < m_viewportMetaData->m_minimumScale))
+        destScale = m_viewportMetaData->m_minimumScale;
 
-    if(scale == 1.)
+    if(destScale == curScale)
         return;
 
     //Screen center
-    QPointF scrCenter(size().width()/2, size().height()/2);
-    //Map screen center to document
-    QPointF docPoint(viewportWidget()->mapFromScene(scrCenter));
-    //Maintain that spot in the same point on the viewport
-    QPointF docPointInScr(viewportWidget()->mapToParent(docPoint));
-    startZoomAnimToItemHotspot(docPoint, docPointInScr, scale);
+    //QPointF zoomHotSpot(size().width()/2, size().height()/2); //center zoom looks ugly in some cases
+    QPointF zoomHotSpot(0, 0);
+    
+    startZoomAnimationToHotSpot(zoomHotSpot, destScale);
+}
+
+
+int ScrollableWebContentView::zoomAnimationTime(bool zoomIn, qreal targetScale)
+{
+    qreal curScale = zoomScale(); 
+    qreal scaleRatio = zoomIn ? (targetScale / curScale) :
+                            1.2 * (curScale / targetScale);
+    qreal fullScaleRatio = (m_viewportMetaData->m_maximumScale / m_viewportMetaData->m_minimumScale);
+    return MaxZoomAnimationDuration * scaleRatio / fullScaleRatio;
+}
+
+void ScrollableWebContentView::toggleZoom(bool zoomIn)
+{
+    m_scrollHelper->stopScrollNoSignal();
+    if (isZooming()) {
+        stopZoomAnimation();
+        commitZoom();
+        return;
+    }
+    qreal scale = zoomIn ? m_viewportMetaData->m_maximumScale : m_viewportMetaData->m_minimumScale;
+    int t = zoomAnimationTime(zoomIn, scale);
+    QPointF zoomHotSpot(0, 0);
+    startZoomAnimationToHotSpot(zoomHotSpot, scale, t);
+}
+
+QRectF ScrollableWebContentView::viewportRectInPageCoord(const QPointF& viewportHotSpot, 
+                                                         const qreal destScale)
+{
+    QSizeF vpSize = size();
+    QSizeF contentSize = webView()->size();
+    QSizeF scaleVpSize(vpSize.width() / destScale, vpSize.height() / destScale);
+    QPointF contentHotSpot = webView()->mapFromParent(viewportHotSpot);
+    QPointF scaledHotSpot = viewportHotSpot / destScale; 
+    QRectF destViewRect( contentHotSpot - scaledHotSpot, scaleVpSize);
+    return destViewRect;
 }
 
-ZoomMetaData ScrollableWebContentView::currentPageInfo()
+void ScrollableWebContentView::startZoomAnimationToHotSpot(const QPointF& viewportHotSpot, 
+                                                           const qreal destScale, int animTime)
 {
-    ZoomMetaData data;
+    QRectF destViewRect = viewportRectInPageCoord(viewportHotSpot, destScale);
+    startZoomAnimation(destViewRect, animTime);
+}
 
-    data.initialScale = m_viewportMetaData->m_initialScale;
-    data.minScale = m_viewportMetaData->m_minimumScale;
-    data.maxScale = m_viewportMetaData->m_maximumScale;
-    data.userScalable = m_viewportMetaData->m_userScalable;
-    data.m_specifiedWidth = m_viewportMetaData->m_specifiedData.m_width;
-    data.m_specifiedHeight= m_viewportMetaData->m_specifiedData.m_height;
-
-    data.rect = viewportWidget()->geometry();
-    data.scale = viewportWidget()->zoomScale();
-    data.webViewSize = viewportWidget()->webView()->geometry();
-    data.viewportSize = size();
-
-    return data;
+void ScrollableWebContentView::zoomToHotSpot(const QPointF& viewportHotSpot, const qreal destScale)
+{
+    QRectF destViewRect = viewportRectInPageCoord(viewportHotSpot, destScale);
+    destViewRect = validateViewportRect(destViewRect);
+    setViewableRect(destViewRect);
 }
 
-void ScrollableWebContentView::setCurrentPageInfo(ZoomMetaData data)
+WebPageData ScrollableWebContentView::pageDataFromViewportInfo()
 {
+    if(!m_viewportMetaData->m_isValid) return WebPageData();
+
+    // No viewport data saving or restoring for superpages
+    if(isSuperPage()) return WebPageData();
+
+    // invalidate viewport meta data after saving to history
+    // cannot do it earlier because loadStarted event comes earlier than save to history
+    if(m_isLoading)
+        m_viewportMetaData->m_isValid = false;
+
+    bool fitToScreen = qFuzzyCompare(m_viewportMetaData->m_width / webView()->size().width(), zoomScale());
+
+    return WebPageData(m_viewportMetaData->m_maximumScale, m_viewportMetaData->m_minimumScale,
+                       m_viewportMetaData->m_userScalable, m_viewportMetaData->m_initialScale,
+                       geometry(), webView()->geometry(), scrollWidget()->scale(), size(),
+                       m_viewportMetaData->m_specifiedData.m_width, m_viewportMetaData->m_specifiedData.m_height,
+                       fitToScreen);
+}
+
+QSizeF ScrollableWebContentView::parentSize() const
+{
+    return static_cast<QGraphicsWidget*>(parentItem())->size();
+}
+
+void ScrollableWebContentView::setPageDataToViewportInfo(const WebPageData& data)
+{
+    if(!data.isValid()) return;
+
+    // No viewport data saving or restoring for superpages
+    if(isSuperPage()) return;
+
     m_viewportMetaData->m_initialScale = data.initialScale;
     m_viewportMetaData->m_minimumScale = data.minScale;
     m_viewportMetaData->m_maximumScale = data.maxScale;
     m_viewportMetaData->m_userScalable = data.userScalable;
-    m_viewportMetaData->m_specifiedData.m_width = data.m_specifiedWidth;
-    m_viewportMetaData->m_specifiedData.m_height = data.m_specifiedHeight;
+    m_viewportMetaData->m_specifiedData.m_width = data.specifiedWidth;
+    m_viewportMetaData->m_specifiedData.m_height = data.specifiedHeight;
     m_viewportMetaData->m_isValid = true;
+    m_viewportMetaData->m_width = data.viewportSize.width();
+    m_viewportMetaData->m_height = data.viewportSize.height();
 
-    m_viewportMetaData->m_width = data.webViewSize.width();
-    m_viewportMetaData->m_height = data.webViewSize.height();
+
+    if(m_viewportMetaData->m_width < 0 ||
+       m_viewportMetaData->m_width < 0) {
+        m_viewportMetaData->m_isValid = false;
+        reset();
+        return;
+    }
+
+    QSizeF newSize = parentSize();
+    if(newSize.isEmpty())
+        newSize = data.viewportSize;
+
+    disableContentUpdates();
+    //    updateViewportMetaDataFromPageTag();
+
+
+    QSizeF vpSz(m_viewportMetaData->m_width, m_viewportMetaData->m_height);
+    if(vpSz.isEmpty())
+        vpSz = newSize;
+
+    // sometimes on load from history webpage doesn't resize webView
+    // set correct size of webView here
+    webView()->setGeometry(QRectF( QPointF(0, 0),
+                                   QSizeF(webView()->page()->mainFrame()->contentsSize())));
+
+    qreal sc = data.scale; //qBound(m_viewportMetaData->m_minimumScale,data.scale,m_viewportMetaData->m_maximumScale);
+    webView()->setScale(sc);
 
-    viewportWidget()->webView()->setGeometry(data.webViewSize);
-    viewportWidget()->setZoomScale(data.scale, true);
-    viewportWidget()->setGeometry(data.rect);
+//    qreal fitToScreenScale = data.viewportSize.width() / webView()->size().width();
+//    bool isFitToScreen = qFuzzyCompare(zoomScale(), fitToScreenScale);
+    adjustViewportSize(data.viewportSize, newSize);
+    m_viewportMetaData->adjustZoomValues(webView()->size());
+    if(data.fitToScreen && newSize.width() != vpSz.width()) {
+        qreal fitToScreenScale = size().width() / webView()->size().width();
+        fitToScreenScale = qBound(m_viewportMetaData->m_minimumScale,
+                                  fitToScreenScale,m_viewportMetaData->m_minimumScale);
+        webView()->setScale(fitToScreenScale);
+    }
+//    else
+//       updatePreferredContentSize();
+
+    if (newSize.width() != m_viewportMetaData->m_width ||
+        newSize.height() != m_viewportMetaData->m_height) {
+        //setGeometry(0, 0, m_viewportMetaData->m_width, m_viewportMetaData->m_height);
+        m_scrollHelper->setViewportSize(size());
+    }
+
 
-    if (data.viewportSize.width() != size().width())
-        adjustViewportSize(data.viewportSize, size());
+    if (data.webViewRect.isValid()) {
+        QPointF webViewPos = data.webViewRect.topLeft();
+        qreal newSc = webView()->scale(); // might be adjust by fitToScreen
+        webViewPos = webViewPos / sc * newSc; // recalc pos if scale changed by fitToScreen
+        QSizeF ss = webView()->size() * newSc;
+        if(!ss.isEmpty()) {
+            webViewPos.setX(qBound((qreal)m_viewportMetaData->m_width - (qreal)ss.width(), (qreal)webViewPos.x(), (qreal)0.0));
+            webViewPos.setY(qBound((qreal)m_viewportMetaData->m_height - (qreal)ss.height(), (qreal)webViewPos.y(), (qreal)0.0));
+            if(ss.width() < m_viewportMetaData->m_width) webViewPos.setX(0);
+            if(ss.height() < m_viewportMetaData->m_height) webViewPos.setY(0);
+        }
+        setScrollWidgetPos(webViewPos);
+    }
+    enableContentUpdates();
+//    updatePreferredContentSize();
+    
+
+    // emit scrolled event to hide/show url bar
+
+    QPoint p(0, 0);
+    if(!m_isLoading) {
+        p = scrollPosition();
+    }
+    QPoint d(0, 0);
+    emit viewScrolled(p, d);
+
 }
 
-ZoomMetaData ScrollableWebContentView::defaultZoomData()
+WebPageData ScrollableWebContentView::defaultZoomData()
 {
-    ZoomMetaData data;
+    WebPageData data;
 
+    data.magic = 0;
     data.initialScale = m_viewportMetaData->m_initialScale;
     data.minScale = m_viewportMetaData->m_minimumScale;
     data.maxScale = m_viewportMetaData->m_maximumScale;
     data.userScalable = m_viewportMetaData->m_userScalable;
 
     data.scale = 1.0;
-    data.rect = QRectF();
-    data.webViewSize = QRectF();
-    data.viewportSize = QSizeF();
+    data.rect = rect();
+    data.webViewRect = webView()->rect();
+    data.viewportSize = QSizeF(m_viewportMetaData->m_width, m_viewportMetaData->m_height);
 
     return data;
 }
 
 void ScrollableWebContentView::updatePreferredContentSize()
 {
-    viewportWidget()->updatePreferredContentSize(QSize(m_viewportMetaData->m_width
-                                                       , m_viewportMetaData->m_height));
+#ifdef VIEWPORT_ALWAYS_ALLOW_ZOOMING
+    // Don't call updatePreferredContentSize() if we've over-ridden user-scalable because it
+    // resets the content size and zoom factor.
+    if(m_viewportMetaData->m_userScalableOverRidden)
+        return;
+#endif
+    QSize s = m_viewportMetaData->getSpecifiedSize();
+/*    if (!isSuperPage()) {
+        prefferedHeight = qMax(m_viewportMetaData->m_width, m_viewportMetaData->m_height);
+        prefferedWidth = m_viewportMetaData->m_width;        
+        if(m_viewportMetaData->m_width * 1.5 < prefferedHeight) {
+            // If the screen sides ratio is less than 3:2, than vertical width is
+            // too narrow for normal page layout, but setting preffered width to the biggest side
+            // makes page too scaled. Because of this set the page to the average of 2 viewport sides.
+            prefferedWidth = (m_viewportMetaData->m_width + prefferedHeight) / 2;
+        }
+    }
+
+//    if(m_viewportMetaData->m_specifiedData.)
+*/
+    webView()->page()->setPreferredContentsSize(s);
+}
+                                                                                                                                                                                                                                                                
+void ScrollableWebContentView::setPage(QWebPage* page)
+{
+    m_isSuperPage = false;
+    m_gesturesEnabled = true;
+    webView()->setPage(page);
 }
 
 void ScrollableWebContentView::setSuperPage()
 {
+    m_isSuperPage = true;
     m_viewportMetaData->m_initialScale = 1.;
     m_viewportMetaData->m_minimumScale = 1.;
     m_viewportMetaData->m_maximumScale = 1.;
@@ -201,17 +432,41 @@
     m_viewportMetaData->m_specifiedData.m_height = "device-height";
     m_viewportMetaData->m_userScalable = false;
 
-    QSize contentSize = viewportWidget()->contentsSize();
-    QRect webViewRect(0, 0, size().width(), contentSize.height());
-    viewportWidget()->webView()->setGeometry(webViewRect);
-    viewportWidget()->setZoomScale(1., true);
-    viewportWidget()->setGeometry(webViewRect);
+    disableContentUpdates();
+    webView()->setScale(1.);
+    //QSize contentSize = (webView()->size() * zoomScale()).toSize();
+    //QRect webViewRect(0, 0, size().width(), contentSize.height());
+    //webView()->setGeometry(webViewRect);
+    setScrollWidgetPos(QPointF(0, 0));
 
     m_viewportMetaData->m_width = size().width();
     m_viewportMetaData->m_height = size().height();
     m_viewportMetaData->m_isValid = true;
+    enableContentUpdates();
+#ifdef VIEWPORT_ALWAYS_ALLOW_ZOOMING
+    updatePreferredContentSize();
+    //viewportWidget()->updatePreferredContentSize(QSize(m_viewportMetaData->m_width
+     //                                                  , m_viewportMetaData->m_height));
+#else
+    updatePreferredContentSize();
+#endif
+}
 
-    updatePreferredContentSize();
+void ScrollableWebContentView::updateViewportMetaDataFromPageTag()
+{
+    QWebPage* page = webView()->page();
+    if (!page)
+        return;
+
+    QWebFrame* frame = page->mainFrame();
+    QMap<QString, QString> metaData = frame->metaData();
+    QString viewportTag = metaData.value("viewport");
+
+    QRect clientRect = geometry().toAlignedRect();
+    ViewportMetaDataParser parser(clientRect);
+    parser.parse(viewportTag, *m_viewportMetaData);
+
+    m_viewportMetaData->adjustZoomValues(webView()->size());
 }
 
 void ScrollableWebContentView::reset()
@@ -222,65 +477,902 @@
     // page->mainFrame() to get the metaData so that we use the meta data of the corresponding
     // frame
 
-    QWebPage* page = viewportWidget()->webView()->page();
+    QWebPage* page = webView()->page();
     if (!page)
         return;
+//    if(m_viewportMetaData->m_isValid) return;
 
     //Initialize viewport metadata
     m_viewportMetaData->reset();
 
-    QWebFrame* frame = page->mainFrame();
-    QMap<QString, QString> metaData = frame->metaData();
-    QString viewportTag = metaData.value("viewport");
+    disableContentUpdates();
+
+    webView()->setScale(1);
+
+    // sometimes on load from history webpage doesn't resize webView
+    // set correct size of webView here
+    webView()->setGeometry(QRectF( QPointF(0, 0),
+                                   QSizeF(webView()->page()->mainFrame()->contentsSize())));
+
+    updateViewportMetaDataFromPageTag();
+
+    //setViewportWidgetGeometry(QRectF(QPointF(),
+    //                                 QSize(m_viewportMetaData->m_width, m_viewportMetaData->m_height)));
 
-    QRect clientRect = geometry().toAlignedRect();
-    ViewportMetaDataParser parser(clientRect);
-    *m_viewportMetaData = parser.parse(viewportTag);
+    static const QPoint nullP(0,0);
+    setScrollPosition(nullP,nullP);
+
+    QSizeF sz(m_viewportMetaData->m_width, m_viewportMetaData->m_height);
+    adjustViewportSize(sz, size());
 
-    updatePreferredContentSize();
-    setViewportWidgetGeometry(QRectF(QPointF(),
-                                     QSize(m_viewportMetaData->m_width, m_viewportMetaData->m_height)
-                                     * m_viewportMetaData->m_initialScale));
+    qreal initScale = m_viewportMetaData->m_initialScale > 0 ? m_viewportMetaData->m_initialScale :
+                      m_viewportMetaData->m_width / webView()->size().width();
+    // m_viewportMetaData->m_initialScale = m_viewportMetaData->m_width / webView()->size().width();
+    webView()->setScale(initScale);
+
+    enableContentUpdates();
+
+    m_scrollHelper->setViewportSize(size());
+
+    // Update corrected viewport data back to webpage metadata
+    emit viewPortChanged();
 }
 
 void ScrollableWebContentView::contentsSizeChanged(const QSize& newContentSize)
 {
-    QRect clientRect = geometry().toAlignedRect();
-    m_viewportMetaData->updateViewportData(newContentSize, clientRect);
-    viewportWidget()->resize(QSize(m_viewportMetaData->m_width, m_viewportMetaData->m_height)
-                             * m_viewportMetaData->m_initialScale);
+    m_viewportMetaData->adjustZoomValues(newContentSize);
+    qreal sc = zoomScale();
+    sc = qBound(m_viewportMetaData->m_minimumScale, sc, m_viewportMetaData->m_maximumScale);
+    if(!qFuzzyCompare(sc, zoomScale()))
+        webView()->setScale(sc);
+    emit viewPortChanged();
+}
+
+void ScrollableWebContentView::pageLoadStarted()
+{
+    m_isLoading = true;
+//    m_viewportMetaData->m_isValid = false;
+}
+
+void ScrollableWebContentView::pageLoadProgress(int progress)
+{
 }
 
 void ScrollableWebContentView::pageLoadFinished(bool ok)
 {
     Q_UNUSED(ok);
-    QSize contentSize = viewportWidget()->contentsSize();
-    QRect clientRect = geometry().toAlignedRect();
-    m_viewportMetaData->updateViewportData(contentSize, clientRect);
+    m_isLoading = false;
+    if(!m_viewportMetaData->m_isValid)
+        m_viewportMetadataResetTimer.singleShot(0,this,SLOT(reset()));
+    else {
+        QSize contentSize = scrollWidget()->size().toSize();
+        m_viewportMetaData->adjustZoomValues(contentSize);
+    }
+
+    // report scroll position to hide url bar if necessary
+    QPoint p = scrollPosition();
+    QPoint d(0, 0);
+    emit viewScrolled(p, d);
+    
+    webView()->update(); // invalidate the view to force tiles update
+}
+
+
+void ScrollableWebContentView::zoomAtPoint(QPointF touchPoint)
+{
+    QRectF target;
+
+    //Get the focusable element rect from current touch position
+    if(isZoomedIn()) {
+        startZoomAnimationToHotSpot(touchPoint,size().width() / webView()->size().width());
+        return;
+    }
+
+    //Pass all events to recognizer
+    QRectF zoomRect = findZoomableRectForPoint(touchPoint);
+
+    if (!zoomRect.isValid()) {
+        //FIX ME: Add an event ignore animation
+        return;
+    }
+
+    startZoomAnimation(zoomRect);
+}
+
+
+void ScrollableWebContentView::setViewportWidgetGeometry(const QRectF& r)
+{
+    if(r != geometry()) {
+        setGeometry(r);
+        emit viewPortChanged();
+    }
+}
+
+
+bool ScrollableWebContentView::isZoomedIn() const
+{
+    qreal vpWidth = size().width();
+    qreal scaledContentWidth = scrollWidget()->size().width() * zoomScale(); 
+    qreal diff = scaledContentWidth - vpWidth; 
+    return  diff > 0.01f;
+}
+
+void ScrollableWebContentView::stateChanged(KineticScrollable::State oldState,
+                                            KineticScrollable::State newState)
+{
+    ScrollableViewBase::stateChanged(oldState, newState);
+
+    switch(newState) {
+        case KineticScrollable::Pushing :
+        case KineticScrollable::AutoScrolling :
+            m_tileUpdateEnableTimer.stop();
+            //disableContentUpdates();
+        break;
+        case KineticScrollable::Inactive :
+            m_tileUpdateEnableTimer.start(TileUpdateEnableDelay);
+        break;
+    }
+}
+
+QRectF ScrollableWebContentView::validateViewportRect(const QRectF& rect)
+{
+    QRectF ret(rect);
+
+    if(ret.right() > webView()->size().width())
+        ret.moveLeft(webView()->size().width() - ret.width());
+    if(ret.bottom() > webView()->size().height())
+        ret.moveTop(webView()->size().height() - ret.height());
+    if(ret.x() < 0) ret.moveLeft(0);
+    if(ret.y() < 0) ret.moveTop(0);
+//    if(ret.width() > webView()->size().width()) ret.setWidth(webView()->size().width());
+    if(ret.width() > webView()->size().width())
+        ret.moveLeft(0); // do not center! ret.moveLeft(webView()->size().width() / 2 - ret.width() / 2);
+    if(ret.height() > webView()->size().height())
+        ret.moveTop(0); // do not center! ret.moveTop(webView()->size().height() / 2 - ret.height() / 2);
+
+    return ret;
+}
+
+QRectF ScrollableWebContentView::viewableRect()
+{
+    return webView()->mapRectFromParent(geometry());
+}
+
+void ScrollableWebContentView::setViewableRect(const QRectF& rect)
+{
+    qreal scale = size().width() / rect.width(); 
+    qstmDebug() << "setViewableRect: rect: " << rect << ", scale: " << scale << "\n";
+    setZoomScale(scale, false);
+    m_isScrolling = true;
+    scrollPageTo(rect.topLeft());
+    m_isScrolling = false;
+}
+
+void ScrollableWebContentView::startZoomAnimation(const QRectF& destViewRect, int animTime)
+{
+    if (webView()->geometry().isValid()) {
+        m_zoomAnimator->setDuration(animTime);
+        m_zoomAnimator->setStartValue(webView()->mapRectFromParent(geometry()));
+        m_animationEndRect = validateViewportRect(destViewRect);
+        m_zoomAnimator->setEndValue(m_animationEndRect);
+        m_zoomAnimator->start();
+    }
+}
+
+void ScrollableWebContentView::stopZoomAnimation()
+{
+    m_zoomAnimator->stop();
+}
+
+void ScrollableWebContentView::zoomAnimationStateChanged(QAbstractAnimation::State newState,QAbstractAnimation::State)
+{
+    switch (newState) {
+    case QAbstractAnimation::Stopped:
+        commitZoom();
+        break;
+    case QAbstractAnimation::Running:
+        disableContentUpdates();
+        break;
+    default:
+        break;
+    }
+}
+
+void ScrollableWebContentView::resizeEvent(QGraphicsSceneResizeEvent* event)
+{
+    //Ignore resize when chrome is being still setup
+    if (event->oldSize().width()) {
+
+        qreal fitToScreenScale = event->oldSize().width() / webView()->size().width();
+        bool isFitToScreen = qFuzzyCompare(zoomScale(), fitToScreenScale);
+        QGraphicsWidget::resizeEvent(event);
+        adjustViewportSize(event->oldSize(), event->newSize());
+        if (isFitToScreen && !isSuperPage()) {
+            QPointF docViewTopLeft(webView()->mapFromParent(QPointF(0,0)));
+            fitToScreenScale = size().width() / webView()->size().width();
+            zoomToHotSpot(docViewTopLeft, fitToScreenScale);
+            m_zoomCommitTimer.start(ZoomCommitDuration);
+        } else {
+            QRectF viewRect = mapRectToItem(webView(), QRectF(QPointF(0,0), size()));
+            QRectF validRect = validateViewportRect(viewRect);
+            if(validRect != viewRect)
+                setViewableRect(validRect);
+        }
+        m_scrollHelper->setViewportSize(size());
+    }
+
+#ifdef OWN_BACKING_STORE
+    webView()->viewportUpdated();
+#endif // OWN_BACKING_STORE
+}
+
+bool  ScrollableWebContentView::isChangedToPortrait(QSizeF oldSize, QSizeF newSize)
+{
+    return (oldSize.width() > oldSize.height()) && 
+           (newSize.width() < newSize.height());
+}
+
+bool  ScrollableWebContentView::isChangedToLandscape(QSizeF oldSize, QSizeF newSize)
+{
+    return (oldSize.width() < oldSize.height()) && 
+           (newSize.width() > newSize.height());
+    emit mouseEvent(QEvent::GraphicsSceneMouseRelease);
+}
+
+bool ScrollableWebContentView::isOrientationChanged(QSizeF oldSize, QSizeF newSize)
+{
+    return isChangedToPortrait(oldSize, newSize) || 
+           isChangedToLandscape(oldSize, newSize);
+}
+
+
+void ScrollableWebContentView::adjustViewportSize(QSizeF oldSize, QSizeF newSize)
+{
+    if(newSize.isNull()) return;
+
+    if (isOrientationChanged(oldSize, newSize)) {
+        m_viewportMetaData->orientationChanged(oldSize);
+    }
+    m_viewportMetaData->adjustViewportData(newSize);
+    updatePreferredContentSize();
+    return;    
+}
+
+void ScrollableWebContentView::sendEventToWebKit(QEvent::Type type, const QPointF& scenePos, bool select)
+{
+    QGraphicsSceneMouseEvent event(type);
+    qstmSetGraphicsSceneMouseEvent(scenePos, webView(), event, select);
+    webView()->page()->event(&event);
+}
+
+void ScrollableWebContentView::disableContentUpdates()
+{
+    if (m_zoomCommitTimer.isActive()) {
+        m_zoomCommitTimer.stop();
+    }
+    webView()->setTiledBackingStoreFrozen(true);
+}
+
+void ScrollableWebContentView::enableContentUpdates()
+{
+    webView()->setTiledBackingStoreFrozen(false);
+}
+
+void ScrollableWebContentView::commitZoom()
+{         
+    m_zoomCommitTimer.stop();
+    notifyZoomActions(zoomScale());
+    enableContentUpdates();
+    emit scaleChanged(zoomScale());
+}
+
+WebView* ScrollableWebContentView::webView() const
+{
+    return static_cast<WebView*>(scrollWidget());
+}
+
+void ScrollableWebContentView::setZoomScale(qreal value, bool immediateCommit)
+{
+    value = qBound(m_viewportMetaData->m_minimumScale, value, m_viewportMetaData->m_maximumScale);
+    qreal curZoomScale = zoomScale();
+
+    if (qFuzzyCompare(value, curZoomScale)) {
+        notifyZoomActions(curZoomScale);
+        return;
+    }
+
+    if (!immediateCommit)
+        disableContentUpdates();
+
+    webView()->setScale(value);
+
+    if (immediateCommit)
+        commitZoom();
+//    else
+//        m_zoomCommitTimer.start(ZoomCommitDuration);
+}
+
+qreal ScrollableWebContentView::zoomScale() const
+{
+    if (!webView())
+        return 1.;
+
+    return webView()->scale();
+}
+
+QRectF ScrollableWebContentView::findZoomableRectForPoint(const QPointF& point)
+{
+    QPointF zoomPoint = webView()->mapFromParent(point);
+
+    QWebHitTestResult hitResult = webView()->page()->mainFrame()->hitTestContent(zoomPoint.toPoint());
+    QWebElement targetElement = hitResult.enclosingBlockElement();
+
+    while (!targetElement.isNull() && targetElement.geometry().width() < MinDoubleClickZoomTargetWidth)
+        targetElement = targetElement.parent();
+
+    if (!targetElement.isNull()) {
+        QRectF elementRect = targetElement.geometry();
+        qreal overMinWidth = elementRect.width() - ZoomableContentMinWidth;
+        if (overMinWidth < 0)
+            elementRect.adjust(overMinWidth / 2, 0, -overMinWidth / 2, 0);
+        qreal destScale = size().width() / elementRect.width();
+        QPointF rectPoint(elementRect.x(),zoomPoint.y() - point.y() / destScale);
+        return QRectF(rectPoint, elementRect.size());
+    }
+    return QRectF();
+}
+
+void ScrollableWebContentView::notifyZoomActions(qreal newScale)
+{
+    bool enableZoomIn = false;
+    bool enableZoomOut = false;
+
+    if (m_viewportMetaData->m_userScalable) {
+
+        if (newScale > m_viewportMetaData->m_minimumScale)
+            enableZoomOut = true;
+        else
+            enableZoomOut = false;
+
+        if (newScale < m_viewportMetaData->m_maximumScale)
+            enableZoomIn = true;
+        else
+            enableZoomIn = false;
+    }
+
+    emit updateZoomActions(enableZoomIn, enableZoomOut);
+}
+
+
+
+bool ScrollableWebContentView::eventFilter(QObject* o, QEvent* e)
+{
+    if (o != scrollWidget()) return false;
+    bool ret = false;
+
+    if (m_gesturesEnabled) {
+            ret = QStm_GestureEventFilter::instance()->eventFilter(o, e);
+        }
+
+    // Superpages should never receive contextmenu events
+    if (isSuperPage() && (e->type() == QEvent::GraphicsSceneContextMenu || e->type() == QEvent::ContextMenu))
+        ret = true;
+    
+    return ret;
+}
+
+bool ScrollableWebContentView::event(QEvent * e) 
+{
+    if (e->type() == QEvent::Gesture && m_gesturesEnabled) {
+          QStm_Gesture* gesture = getQStmGesture(e);
+          if (gesture) {
+              bool ret = handleQStmGesture(gesture);
+              if (gesture->getGestureStmType() == QStmTouchGestureType)
+                  e->accept();
+              return ret;
+          }
+    }
+    return QGraphicsWidget::event(e);
+}
+
+
+
+bool  ScrollableWebContentView::handleQStmGesture(QStm_Gesture* gesture)
+{
+#ifdef OWN_BACKING_STORE
+    // Signal tiling to minimize tile update activity while user does something
+    webView()->userActivity();
+#endif
+    QStm_GestureType type = gesture->getGestureStmType();
+    bool ret = false;
+    switch (type) {
+        case QStmTapGestureType:
+        {
+            ret = doTap(gesture);
+            break;
+        }
+
+        case QStmMaybeTapGestureType:
+        {
+            ret = doMaybeTap(gesture);
+            break;
+        }
 
-    viewportWidget()->resize(QSize(m_viewportMetaData->m_width, m_viewportMetaData->m_height)
-                             * m_viewportMetaData->m_initialScale);
-    viewportWidget()->setZoomScale(m_viewportMetaData->m_initialScale, true);
+        case QStmReleaseGestureType:
+        {
+            ret = doRelease(gesture);
+            break;
+        }
+        case QStmLeftRightGestureType:
+        {
+            ret = doLeftRight(gesture);
+            break;
+        }
+        case QStmUpDownGestureType:
+        {
+            ret = doUpDown(gesture);
+            break;
+        }
+        case QStmPanGestureType:
+        {
+            ret = doPan(gesture);
+            break;
+        }
+        case QStmFlickGestureType:
+        {
+            ret = doFlick(gesture);
+            break;
+        }
+        case QStmDoubleTapGestureType:
+        {
+            ret = doDoubleTap(gesture);
+            break;
+        }
+        case QStmTouchGestureType:
+        {
+            ret = doTouch(gesture);
+            break;
+        }
+        case QStmPinchGestureType:
+        {
+            ret = doPinch(gesture);  
+            break;
+        }
+        case QStmLongPressGestureType:
+        {
+            ret = doLongPress(gesture);
+            break;
+        }
+        
+        default: 
+        {
+            ret = true;
+        }
+    }
+    
+    return ret;
+}
+
+QWebHitTestResult  ScrollableWebContentView::hitTest(const QPointF& scenePos)
+{
+    QPointF contextPt = webView()->mapFromScene(scenePos);
+    QWebPage* page = webView()->page();
+    return page->currentFrame()->hitTestContent(contextPt.toPoint()); 
+}
+
+
+
+bool ScrollableWebContentView::toggleVkb()
+{
+    bool inputEnabled = false;
+    QInputContext *ic = qApp->inputContext();
+    if (m_hitTest.isContentEditable()) {
+        QEvent sipe(QEvent::RequestSoftwareInputPanel);
+        ic->filterEvent(&sipe);
+        inputEnabled = true;
+    }
+    else {
+        QEvent sipe(QEvent::CloseSoftwareInputPanel);
+        ic->filterEvent(&sipe);
+
+    }
+    m_isInputOn = inputEnabled;
+    return inputEnabled;
+}
+
+bool  ScrollableWebContentView::toggleInputMethod(bool on)
+{
+    QGraphicsView* gv = qstmGetGraphicsView(webView());
+    bool oldInputEnabled = false;
+    if (gv != NULL) {
+        gv->testAttribute(Qt::WA_InputMethodEnabled);
+        gv->setAttribute(Qt::WA_InputMethodEnabled, on);
+    }
+    m_isInputOn = on;
+    return oldInputEnabled;
+}
+
+bool  ScrollableWebContentView::inputMethodEnabled()
+{
+#ifdef ORBIT_UI
+    HbInputMethod* im = HbInputMethod::activeInputMethod();
+    
+    QGraphicsView* gv = qstmGetGraphicsView(webView());
+    bool enabled = false;
+    if (gv) {
+        enabled = gv->testAttribute(Qt::WA_InputMethodEnabled);
+    }
+    return enabled; 
+#else
+    return false;
+#endif // ORBIT_UI
+}
+
+bool  ScrollableWebContentView::doLongPress(QStm_Gesture* gesture)
+{
+    bool willHandle = m_gesturesEnabled && !isSuperPage();
+    if (willHandle) {
+//        QWebPage* page = webView()->page();
+        QPoint gpos = gesture->position();
+        QPointF pos = qstmMapToScene(gpos, this);
+//        QPointF contextPt = webView()->mapFromScene(pos);
+        //QWebHitTestResult result = page->currentFrame()->hitTestContent(contextPt.toPoint());
+    //Notify context menu observers
+        emit contextEventObject(&m_hitTest, pos);
+        m_ignoreNextRelease = true;
+    }
+    return willHandle;
+}
+
+
+
+bool ScrollableWebContentView::doTouch(QStm_Gesture* gesture)
+{
+    bool willHandle = m_gesturesEnabled;
+    m_scrollHelper->stopScrollNoSignal();
+    m_touchDownPos = gesture->scenePosition(this);
+    if (!isSuperPage()) {
+        m_hitTest = hitTest(m_touchDownPos);
+        //toggleInputMethod(false);
+        qreal scale = zoomScale();
+
+        m_hoverTimer->stop();
+        m_hoverTimer->setSingleShot(true);
+        
+        m_touchDownTimer->stop();
+        m_touchDownTimer->setSingleShot(true);
+                
+        m_touchDownTimer->start(TouchDownTimeout, this);
+        m_hoverTimer->start(HoverTimeout, this);
+    }
+    else {
+        sendEventToWebKit(QEvent::GraphicsSceneMousePress, m_touchDownPos);
+    }
+    return willHandle;
+}
+
+void ScrollableWebContentView::touchDownCallback()
+{
+    m_touchDownTimer->stop();
+    if (m_gesturesEnabled) {
+        sendEventToWebKit(QEvent::GraphicsSceneMousePress, m_touchDownPos);
+    }
+}
+
+void ScrollableWebContentView::hoverCallback()
+{
+    m_hoverTimer->stop();
+    if (m_gesturesEnabled && !isSuperPage()) {
+        sendEventToWebKit(QEvent::GraphicsSceneMouseMove, m_touchDownPos);
+    }
+}
+
+
+bool ScrollableWebContentView::doTap(QStm_Gesture* gesture)
+{
+    bool willHandle = m_gesturesEnabled;
+    if (willHandle && !isSuperPage()) {
+        QPointF pos = gesture->scenePosition(this);
+        bool hasInputMethod = toggleVkb();
+        sendEventToWebKit(QEvent::GraphicsSceneMouseRelease, pos);
+        emit contentViewMouseEvent(QEvent::GraphicsSceneMouseRelease);
+    }
+    return willHandle;
+}
+
+bool ScrollableWebContentView::doMaybeTap(QStm_Gesture* gesture)
+{
+    bool willHandle = m_gesturesEnabled;
+    if (willHandle && isSuperPage()) {
+        QPointF pos = gesture->scenePosition(this);
+        sendEventToWebKit(QEvent::GraphicsSceneMouseRelease, pos);
+    }
+    return willHandle;
+}
+
+#ifdef USE_KINETIC_SCROLLER
+bool ScrollableWebContentView::doPan(QStm_Gesture* gesture)
+{
+    if (m_touchDownTimer->isActive()) {
+        m_touchDownTimer->stop();
+    }
+    
+    QStm_GestureType type = gesture->getGestureStmType();
+    bool willHandle = m_gesturesEnabled;
+    
+    if (willHandle) {
+        QPoint scrollPos = ScrollableViewBase::scrollPosition();
+        QPoint delta = gesture->getLengthAndDirection();
+        delta.ry() = -delta.y();
+        m_kineticScroller->doPan(delta);
+    }
+    return willHandle;
+}
+#else
+
+
+bool ScrollableWebContentView::doLeftRight(QStm_Gesture* gesture)
+{
+    bool ret = true;
+    if (m_hitTest.isContentEditable() && m_isInputOn) {
+        QPointF pos = gesture->scenePosition(this);
+        sendEventToWebKit(QEvent::GraphicsSceneMouseMove, pos, true);
+    }
+    else {
+        ret = doPan(gesture);
+    }
+    return ret;
 }
 
+
+bool ScrollableWebContentView::doUpDown(QStm_Gesture* gesture)
+{
+    bool ret = true;
+    if (m_hitTest.isContentEditable() && m_isInputOn) {
+        QPointF pos = gesture->scenePosition(this);
+        sendEventToWebKit(QEvent::GraphicsSceneMouseMove, pos, true);
+    }
+    else {
+        ret = doPan(gesture);
+    }
+    return ret;
+}
+
+
+
+bool ScrollableWebContentView::doPan(QStm_Gesture* gesture)
+{
+    bool willHandle = m_gesturesEnabled;
+    if (m_hitTest.isContentEditable() && m_isInputOn) {
+        QPointF pos = gesture->scenePosition(this);
+        sendEventToWebKit(QEvent::GraphicsSceneMouseMove, pos, true);
+    }
+    else {
+        dehighlightWebElement();
+        if (willHandle) {
+            if (gesture->gestureState() != Qt::GestureFinished) {
+                QPointF delta = gesture->sceneLengthAndDirection(this);
+
+                if (isSuperPage()) {
+                    delta.rx() = 0.0;
+                }
+                else {
+                    //delta.rx() = -delta.x();
+                }
+            
+                //disableContentUpdates();
+                qstmDebug() << "doPan: gesture timestamp: " << gesture->timestamp().toString("hh:mm:ss.zzz") <<
+                        ", delta: " << delta << "\n";
+
+                m_scrollHelper->scroll(delta);
+            }
+        }
+    }
+    return willHandle;
+}
+#endif //USE_KINETIC_SCROLLER
+
+
+bool ScrollableWebContentView::doRelease(QStm_Gesture* gesture)
+{
+    bool willHandle = m_gesturesEnabled;
+    if (willHandle) {
+        if (m_ignoreNextRelease) {
+            m_ignoreNextRelease = false;
+        }
+        else if (m_scrollHelper->isScrolling()) {
+            m_scrollHelper->panFromOvershoot();
+//            enableContentUpdates();
+        }
+        else {
+            /*
+             * on tap we send mouseRelease
+             * assumption here is that we can get
+             * either tap or release gesture but not both.
+             */
+            doTap(gesture);
+        }
+    }
+    return willHandle;
+}
+
+#ifdef USE_KINETIC_SCROLLER
+bool ScrollableWebContentView::doFlick(QStm_Gesture* gesture)
+{
+    int direction = gesture->getDirection();
+    QStm_GestureType type = gesture->getGestureStmType();
+    bool willHandle = m_gesturesEnabled;
+    if (willHandle ) {          
+        m_kineticScroller->doFlick(90 * gesture->getSpeedVec());
+    }
+}
+
+#else
+bool ScrollableWebContentView::doFlick(QStm_Gesture* gesture)
+{    
+    bool willHandle = m_gesturesEnabled;
+    int afterPinch = m_pinchFinishTime.elapsed();
+    if (willHandle && afterPinch > 100 && m_scrollHelper->isScrolling()) {
+        dehighlightWebElement();
+        int direction = gesture->sceneDirection(this);
+        QPointF v = gesture->sceneSpeedVec(this);
+        QPointF vOrig = v;
+        qstmDebug() << "doFlick: timestamp: " << gesture->timestamp().toString("hh:mm:ss.zzz") <<
+                ", v: " << v << "\n";
+        if (v.x() != 0.0 || v.y() != 0.0) {
+            if (direction == EEast || direction == EWest) {
+                v.ry() = 0.0;
+            }
+            if (direction == ENorth || direction == ESouth) {
+                v.rx() = 0.0;
+            }
+            m_scrollHelper->kineticScroll(v);
+            //enableContentUpdates();
+            //m_tileUpdateEnableTimer.start(TileUpdateEnableDelay);
+        }
+        else if (afterPinch <= 500) {
+            qstmDebug() << "doFlick: Flick is too soon after pinch\n";
+        }
+    }
+    return willHandle;
+}
+#endif //USE_KINETIC_SCROLLER
+
+bool ScrollableWebContentView::doDoubleTap(QStm_Gesture* gesture)
+{
+    if (!m_gesturesEnabled || !m_viewportMetaData->m_userScalable) {
+        m_touchDownTimer->stop();
+        m_hoverTimer->stop();
+        return m_gesturesEnabled;    
+    }
+    dehighlightWebElement();
+    QPointF pos = gesture->scenePosition(this);
+    pos = mapFromScene(pos);
+    qstmDebug() << "doDoubleTap: zoom at pos: " << pos << "\n";
+    zoomAtPoint(pos);
+    
+    return m_gesturesEnabled;
+}
+
+#define square(x) (x)*(x)
+
+qreal ScrollableWebContentView::calcScale(int origDistance, QPointF p1, QPointF p2)
+{
+    qreal d1f = origDistance;
+    qreal dist = calcDistance(p1, p2);
+    return (dist/ d1f);
+}
+
+qreal ScrollableWebContentView::calcDistance(QPointF pt1, QPointF pt2)
+{
+    return (sqrt((double)square(pt2.x() - pt1.x()) + square(pt2.y() - pt1.y())));
+}
+
+QPointF ScrollableWebContentView::calcCenter(QPointF pt1, QPointF pt2)
+{
+    return((pt1 + pt2) / 2);
+}
+
+bool ScrollableWebContentView::doPinch(QStm_Gesture* gesture)
+{
+    m_scrollHelper->stopScrollNoSignal();
+    dehighlightWebElement();
+    m_pinchFinishTime.restart();
+    if (!m_gesturesEnabled || !m_viewportMetaData->m_userScalable)
+        return m_gesturesEnabled;
+
+    // Normally, "details" contains the distance between the two touched points
+    // It's null when the pinch starts (which in effect is zero)
+    // When we start pinch, we don't zoom because there is no delta
+    QPointF p1 = gesture->scenePosition(this);
+    QPointF p2 = gesture->scenePosition2(this);
+    if (gesture->gestureState() == Qt::GestureFinished) {
+        commitZoom();        
+        return m_gesturesEnabled;
+    }
+
+    if (!gesture->getDetails()) {
+        m_pinchStartDistance = calcDistance(p1, p2);
+        m_pinchStartScale = zoomScale();
+    }
+    else {
+        qreal scale = calcScale(m_pinchStartDistance, p1, p2);
+        qreal newScale = qBound(m_viewportMetaData->m_minimumScale, 
+                                scale * m_pinchStartScale,
+                                m_viewportMetaData->m_maximumScale);
+        // Don't allow zooming beyond the min/max but still call the zoom animation (coz the hotspot could be moving and we want to pan with it)
+        //zoomToHotSpot(calcCenter(p1, p2), newScale);
+        if (!qFuzzyCompare(zoomScale(), newScale)) {
+            startZoomAnimationToHotSpot(calcCenter(p1, p2), newScale, ZoomAnimationDuration);
+        }
+    }
+    return m_gesturesEnabled;
+}
+
+bool ScrollableWebContentView::isZooming()
+{
+    return m_zoomAnimator->state() == QAbstractAnimation::Running;     
+}
+
+void ScrollableWebContentView::setGesturesEnabled(bool value) 
+{ 
+    if (!value && m_touchDownTimer->isActive()) {
+        m_touchDownTimer->stop();
+    }
+
+    m_gesturesEnabled = value;
+}
+
+bool ScrollableWebContentView::gesturesEnabled() 
+{ 
+    return m_gesturesEnabled; 
+}
+
+
+void ScrollableWebContentView::dehighlightWebElement()
+{
+    m_touchDownTimer->stop();
+    m_hoverTimer->stop();
+    
+    QSizeF contentSize = webView()->size();
+    QPointF dummyPosF(-contentSize.width() - 2.0, -contentSize.height( ) - 2.0);
+    QPoint dummyPos(-1, -1);
+    QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
+    event.setScenePos(dummyPos);
+    event.setPos(dummyPos);
+    event.setButton(Qt::LeftButton);
+
+    bool hasInputMethod = toggleInputMethod(false);
+    webView()->page()->event(&event);
+    toggleInputMethod(hasInputMethod);
+    //sendEventToWebKit(QEvent::GraphicsSceneMouseRelease, dummyPos);    
+}
+
+
+void ScrollableWebContentView::stopScrolling()
+{
+    m_isScrolling = false;
+    //enableContentUpdates();
+}
+
+
+
 bool ScrollableWebContentView::sceneEventFilter(QGraphicsItem* item, QEvent* event)
 {
     Q_UNUSED(item);
 
     bool handled = false;
-    
-    if (!isVisible() || !m_gesturesEnabled) {
-        if (event->type() == QEvent::GraphicsSceneContextMenu)
-            return true;
-        else
-            return handled;
-    }
+#ifdef USE_KINETIC_SCROLLER    
+    if (!isVisible())
+        return handled;
 
     //Pass all events to recognizer
     handled  = m_gestureRecognizer.mouseEventFilter(static_cast<QGraphicsSceneMouseEvent *>(event));
+#endif
     return handled;
 }
 
+
 void ScrollableWebContentView::handleGesture(GestureEvent* gestureEvent)
 {
     switch (gestureEvent->type()) {
@@ -317,12 +1409,9 @@
 
 void ScrollableWebContentView::handleRelease(GestureEvent* gestureEvent)
 {
-    //FIX ME:
-    emit mouseEvent(QEvent::GraphicsSceneMousePress);
     //Cache release event to send on release
     QPointF pos = gestureEvent->position();
     sendEventToWebKit(QEvent::GraphicsSceneMouseRelease, pos);
-    emit mouseEvent(QEvent::GraphicsSceneMouseRelease);
 }
 
 void ScrollableWebContentView::handleDoubleTap(GestureEvent* gestureEvent)
@@ -331,35 +1420,29 @@
         return;
 
     QRectF target;
-    WebContentAnimationItem* webViewProxy = viewportWidget();
-
-    // Contentview center is the focus hotspot
-    QPointF viewTargetHotspot(size().width() / 2, size().height() / 2);
 
     //Get the focussable element rect from current touch position
-    QPointF touchPoint = webViewProxy->mapFromScene(gestureEvent->position());
-    QRectF zoomRect = webViewProxy->findZoomableRectForPoint(touchPoint);
+    QPointF touchPoint = mapFromScene(gestureEvent->position());
+
+    if(isZoomedIn()) {
+        startZoomAnimationToHotSpot(touchPoint,size().width() / webView()->size().width());
+            return;
+    }
+
+    QRectF zoomRect = findZoomableRectForPoint(touchPoint);
 
     if (!zoomRect.isValid()) {
         //FIX ME: Add an event ignore animation
         return;
     }
 
-    // target is the center of the identified rect x-wise
-    // y-wise it's the place user touched
-    QPointF hotspot(zoomRect.center().x(), touchPoint.y());
-    qreal scale = size().width() / zoomRect.size().width();
-    startZoomAnimToItemHotspot(hotspot, viewTargetHotspot, scale, zoomRect);
+    startZoomAnimation(zoomRect);
 }
 
 void ScrollableWebContentView::handlePan(GestureEvent* gestureEvent)
 {
     QPoint scrollPos = ScrollableViewBase::scrollPosition();
     m_kineticScroller->doPan(gestureEvent->delta());
-    QPoint delta;
-    delta.setX(-gestureEvent->delta().x());
-    delta.setY(-gestureEvent->delta().y());
-    emit viewScrolled(scrollPos, delta);
 }
 
 void ScrollableWebContentView::handleFlick(GestureEvent* gestureEvent)
@@ -370,158 +1453,21 @@
 
 void ScrollableWebContentView::handleLongTap(GestureEvent* gestureEvent)
 {
-    QWebPage* page = viewportWidget()->webView()->page();
-    QPointF contextPt = viewportWidget()->webView()->mapFromScene(gestureEvent->position());
+    QWebPage* page = webView()->page();
+    QPointF contextPt = webView()->mapFromScene(gestureEvent->position());
     QWebHitTestResult result = page->currentFrame()->hitTestContent(contextPt.toPoint());
-
+    
     //Notify context menu observers
-    emit contextEventObject(&result);
-}
-
-void ScrollableWebContentView::setViewportWidgetGeometry(const QRectF& r)
-{
-    ScrollableViewBase::setScrollWidgetGeometry(r);
-}
-
-void ScrollableWebContentView::startZoomAnimToItemHotspot(const QPointF& hotspot, const QPointF& viewTargetHotspot, qreal scale,  QRectF target)
-{
-    WebContentAnimationItem* animWidget = viewportWidget();
-
-    QPointF newHotspot = hotspot * scale;
-    QPointF newViewportOrigon = newHotspot - viewTargetHotspot;
-    QRectF zoomedRect(-newViewportOrigon, animWidget->size() * scale);
-
-    QRectF temp = adjustScrollWidgetRect(zoomedRect);
-    qreal diff = qAbs(scrollWidget()->geometry().y() - temp.y());
-
-    //FIX ME : Seperate the logic for centerzoom and block-focus zoom
-    if (qFuzzyCompare(scrollWidget()->geometry().topLeft().x(), temp.topLeft().x())
-        && qFuzzyCompare(scrollWidget()->geometry().width(), temp.width())
-        && qFuzzyCompare(scrollWidget()->geometry().height(), temp.height())
-        && !target.isEmpty() && (diff <= target.height())) {
-
-            scale = size().width() / animWidget->size().width();
-            newHotspot = QPointF(0, -animWidget->pos().y()) * scale;
-            newViewportOrigon = newHotspot - viewTargetHotspot;
-            zoomedRect = QRectF(-newViewportOrigon, animWidget->size() * scale);
-    }
-
-    startZoomAnimation(zoomedRect);
-}
-
-bool ScrollableWebContentView::isZoomedIn() const
-{
-    return size().width() < viewportWidget()->size().width();
-}
-
-void ScrollableWebContentView::stateChanged(KineticScrollable::State oldState
-                                            , KineticScrollable::State newState)
-{
-    ScrollableViewBase::stateChanged(oldState, newState);
-
-    if (newState == KineticScrollable::Pushing) {
-        m_tileUpdateEnableTimer.stop();
-        viewportWidget()->disableContentUpdates();
-    }
-    else if (newState == KineticScrollable::AutoScrolling) {
-        m_tileUpdateEnableTimer.stop();
-        viewportWidget()->disableContentUpdates();
-    }
-    else if (newState == KineticScrollable::Inactive) {
-        m_tileUpdateEnableTimer.start(TileUpdateEnableDelay);
-    }
-}
-
-void ScrollableWebContentView::startZoomAnimation(const QRectF& destRect)
-{
-    QAbstractAnimation::State animState = m_zoomAnimator->state();
-    if (animState == QAbstractAnimation::Running)
-        return;
-
-    m_zoomAnimator->setStartValue(scrollWidget()->geometry());
-    m_animationEndRect = adjustScrollWidgetRect(destRect);
-    m_zoomAnimator->setEndValue(m_animationEndRect);
-    m_zoomAnimator->start();
+    emit contextEventObject(&result, gestureEvent->position());
 }
 
-void ScrollableWebContentView::stopZoomAnimation()
-{
-    m_animationEndRect = QRectF();
-    m_zoomAnimator->stop();
-}
-
-void ScrollableWebContentView::updateZoomEndRect()
-{
-    if (m_animationEndRect.isValid())
-        scrollWidget()->setGeometry(m_animationEndRect);
-}
-
-void ScrollableWebContentView::zoomAnimationStateChanged(QAbstractAnimation::State newState,QAbstractAnimation::State)
+void ScrollableWebContentView::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
 {
-    switch (newState) {
-    case QAbstractAnimation::Stopped:
-        updateZoomEndRect();
-        break;
-    default:
-        break;
-    }
-}
 
-void ScrollableWebContentView::resizeEvent(QGraphicsSceneResizeEvent* event)
-{
-    QGraphicsWidget::resizeEvent(event);
+    QRectF fillRect = option ? option->exposedRect : QRectF(QPoint(0, 0), size());
 
-    //Ignore resize when chrome is being still setup
-    if (!event->oldSize().width())
-        return;
-
-    adjustViewportSize(event->oldSize(), event->newSize());
+    painter->fillRect(fillRect, Qt::white);
 }
 
-void ScrollableWebContentView::adjustViewportSize(QSizeF oldSize, QSizeF newSize)
-{
-    //FIX ME : Check this
-    if (m_viewportMetaData->m_isValid) {
-
-        QRect clientRect = geometry().toAlignedRect();
-        if (m_viewportMetaData->isLayoutNeeded())  {
-            m_viewportMetaData->orientationChanged(clientRect);
-            updatePreferredContentSize();
-            return;
-        } else
-            m_viewportMetaData->updateViewportData(viewportWidget()->contentsSize(), clientRect);
-    }
-
-    qreal scale = newSize.width() / oldSize.width();
-    QPointF middleLeft(0, oldSize.height()/2);
-    QPointF docPoint(viewportWidget()->mapFromScene(middleLeft));
-
-    QPointF resizedMiddleLeft(0, newSize.height()/2);
-    QPointF resizedDocPoint(viewportWidget()->mapFromScene(resizedMiddleLeft));
-    QPointF docPointInScr(viewportWidget()->mapToParent(resizedDocPoint));
-
-    //FIX ME : Should be handled with only following function call
-    //Since its not working, work-around is added. Plz fix it
-    //startZoomAnimToItemHotspot(docPoint, docPointInScr, scale);
-
-    QPointF newHotspot = docPoint * scale;
-    QPointF newViewportOrigon = newHotspot - docPointInScr;
-    QRectF zoomedRect(-newViewportOrigon,  viewportWidget()->size() * scale);
-    QRectF adjustRect = adjustScrollWidgetRect(zoomedRect);
-
-    setScrollWidgetGeometry(zoomedRect);
-}
-
-void ScrollableWebContentView::sendEventToWebKit(QEvent::Type type, QPointF& scenPos)
-{
-    //Setup event and send it to webkit
-    QGraphicsSceneMouseEvent event(type);
-    event.setScenePos(scenPos);
-    event.setPos(viewportWidget()->webView()->mapFromScene(event.scenePos()));
-    event.setButton(Qt::LeftButton);
-    event.setButtons(Qt::LeftButton);
-    event.setModifiers(Qt::NoModifier);
-    viewportWidget()->webView()->page()->event(&event);
-}
 
 } //namespace GVA