diff -r 6aeb7a756187 -r 3c88a81ff781 ginebra2/ContentViews/ScrollableWebContentView.cpp --- 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 #include #include #include +#include #include #include +#include +#include +#include +#include "Gestures/GestureRecognizer.h" +#ifdef ORBIT_UI +#include +#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(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(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 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 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(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(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