--- 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