summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobert Griebl <rgriebl@trolltech.com>2010-04-21 19:48:00 +0200
committerRobert Griebl <rgriebl@trolltech.com>2010-04-21 19:48:00 +0200
commit8ce73323b52ac9b3d7a73e59080b879989c5b077 (patch)
tree0efb7fcfc37de68f6816071ec75b24fef13d6dd0
parente2caa922c952b7a7c7ba25dc29de8d33843db786 (diff)
forgot to add the webview scroller
-rw-r--r--testapp/qwebviewkineticscroller.cpp312
-rw-r--r--testapp/qwebviewkineticscroller.h89
2 files changed, 401 insertions, 0 deletions
diff --git a/testapp/qwebviewkineticscroller.cpp b/testapp/qwebviewkineticscroller.cpp
new file mode 100644
index 0000000..3d3790b
--- /dev/null
+++ b/testapp/qwebviewkineticscroller.cpp
@@ -0,0 +1,312 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qwebviewkineticscroller.h>
+#include <QApplication>
+#include <QGraphicsView>
+#include <QWebView>
+#include <QWebFrame>
+#include <QScrollBar>
+#include <QPointF>
+#include <QPointer>
+#include <QMouseEvent>
+#include <QTouchEvent>
+#if QT_VERSION < 0x040700
+# include <QTime>
+#else
+# include <QElapsedTimer>
+#endif
+
+#include <QtDebug>
+
+QT_BEGIN_NAMESPACE
+
+bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event);
+
+class QWebViewKineticScrollerPrivate
+{
+public:
+ QWebViewKineticScroller *q_ptr;
+
+ QWebView *web;
+ bool ignoreEvents;
+ bool touchActive;
+ bool pressed;
+ QPointF fractionalPosition;
+ QPointer<QWebFrame> scrollFrame;
+ Qt::ScrollBarPolicy oldHorizontalSBP;
+ Qt::ScrollBarPolicy oldVerticalSBP;
+
+#if QT_VERSION < 0x040700
+ QTime timer;
+#else
+ QElapsedTimer timer;
+#endif
+
+ QWebViewKineticScrollerPrivate()
+ : q_ptr(0)
+ , web(0)
+ , ignoreEvents(false)
+ , touchActive(false)
+ , pressed(false)
+ {}
+
+ void init()
+ {
+ timer.start();
+ }
+
+ void sendEvent(QWidget *w, QEvent *e)
+ {
+ ignoreEvents = true;
+ qt_sendSpontaneousEvent(w, e);
+ ignoreEvents = false;
+ }
+
+ QWebFrame *currentFrame() const;
+ QWebFrame *scrollingFrameAt(const QPointF &pos) const;
+};
+
+/*!
+ * The QWebViewKineticScroller class implements the QKineticScroller for the QWebView
+ */
+QWebViewKineticScroller::QWebViewKineticScroller()
+ : QObject()
+ , QKineticScroller()
+ , d_ptr(new QWebViewKineticScrollerPrivate())
+{
+ Q_D(QWebViewKineticScroller);
+ d->q_ptr = this;
+ d->init();
+}
+
+/*!
+ Destroys the scroller.
+*/
+QWebViewKineticScroller::~QWebViewKineticScroller()
+{ }
+
+void QWebViewKineticScroller::setWidget(QWebView *widget)
+{
+ Q_D(QWebViewKineticScroller);
+
+ if (d->web) {
+ d->web->removeEventFilter(this);
+ d->web->setAttribute(Qt::WA_AcceptTouchEvents, false);
+
+ QWebFrame *mainFrame = d->web->page()->mainFrame();
+ mainFrame->setScrollBarPolicy(Qt::Vertical, d->oldVerticalSBP);
+ mainFrame->setScrollBarPolicy(Qt::Horizontal, d->oldHorizontalSBP);
+ }
+
+ d->scrollFrame = 0;
+ reset();
+ d->web = widget;
+ d->fractionalPosition = QPointF();
+ setParent(d->web);
+
+ if (d->web) {
+ QWebFrame *mainFrame = d->web->page()->mainFrame();
+ d->oldVerticalSBP = mainFrame->scrollBarPolicy(Qt::Vertical);
+ d->oldHorizontalSBP = mainFrame->scrollBarPolicy(Qt::Horizontal);
+ mainFrame->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff);
+ mainFrame->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff);
+ d->web->setAttribute(Qt::WA_AcceptTouchEvents, true);
+ d->web->installEventFilter(this);
+ }
+}
+
+bool QWebViewKineticScroller::eventFilter(QObject *o, QEvent *e)
+{
+ Q_D(QWebViewKineticScroller);
+
+ qint64 timestamp = d->timer.elapsed();
+ bool res = false;
+
+ if (d->web && (o == d->web) && !d->ignoreEvents && d->web->isEnabled() && isEnabled()) {
+ switch (e->type()) {
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd: {
+ qWarning("TOUCH%s", e->type() == QEvent::TouchBegin ? "BEGIN" : (e->type() == QEvent::TouchEnd ? "END" : "UPDATE"));
+ Input type = (e->type() == QEvent::TouchBegin) ? InputPress :
+ ((e->type() == QEvent::TouchEnd) ? InputRelease : InputMove);
+ QTouchEvent *te = static_cast<QTouchEvent *>(e);
+ int idx = (te->deviceType() == QTouchEvent::TouchScreen) ? 0 : 1;
+
+ if (te->touchPoints().count() == (idx + 1)) {
+ QPointF p = te->touchPoints().at(idx).pos();
+ if (type == InputPress) {
+ // remember the frame where the button was pressed
+ QWebFrame *hitFrame = d->scrollingFrameAt(p);
+ if (hitFrame)
+ d->scrollFrame = hitFrame;
+ }
+
+ res = handleInput(type, p, timestamp);
+ if (type == InputPress) {
+ d->touchActive = true;
+ res = true; // we need to swallow this event, since WebKit would reject it otherwise
+ } else if (type == InputRelease) {
+ d->touchActive = false;
+ }
+ qWarning(" TOUCH%s (%d): %d", type == InputPress ? "BEGIN" : (type == InputRelease ? "END" : "UPDATE"), d->touchActive, res);
+ }
+ break;
+ }
+ case QEvent::Wheel:
+ // the two-finger gesture on the Mac is mapped to wheel events by default
+ qWarning("WHEEL");
+ res = d->touchActive;
+ break;
+
+ case QEvent::MouseButtonPress:
+ // re-install the event filter so that we get the mouse release before all other filters.
+ // this is an evil hack, but hard to work around without prioritized event filters.
+ d->web->removeEventFilter(this);
+ d->web->installEventFilter(this);
+ // fall through
+
+ case QEvent::MouseButtonDblClick:
+ case QEvent::MouseMove:
+ case QEvent::MouseButtonRelease:
+ if (!d->touchActive) {
+ Input type = (e->type() == QEvent::MouseButtonRelease) ? InputRelease :
+ ((e->type() == QEvent::MouseMove) ? InputMove : InputPress);
+ QPointF p = static_cast<QMouseEvent *>(e)->posF();
+
+ if (type == InputPress) {
+ // remember the frame where the button was pressed
+ QWebFrame *hitFrame = d->scrollingFrameAt(p);
+ if (hitFrame)
+ d->scrollFrame = hitFrame;
+ d->pressed = true;
+ } else if (type == InputRelease) {
+ d->pressed = false;
+ }
+
+ if (type != InputMove || d->pressed)
+ res = handleInput(type, p, timestamp);
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (res)
+ e->accept();
+ return res;
+}
+
+
+bool QWebViewKineticScroller::canStartScrollingAt(const QPointF & /*pos*/) const
+{
+ return true;
+}
+
+void QWebViewKineticScroller::cancelPress(const QPointF & /*pressPos*/)
+{
+}
+
+QWebFrame *QWebViewKineticScrollerPrivate::currentFrame() const
+{
+ if (web && scrollFrame)
+ return scrollFrame;
+ else if (web)
+ return web->page()->mainFrame();
+ else
+ return 0;
+}
+
+// returns the innermost frame at the given position that can be scrolled
+QWebFrame *QWebViewKineticScrollerPrivate::scrollingFrameAt(const QPointF &pos) const
+{
+ QWebFrame *hitFrame = 0;
+ if (web) {
+ QWebFrame *mainFrame = web->page()->mainFrame();
+ hitFrame = mainFrame->hitTestContent(pos.toPoint()).frame();
+ QSize range = hitFrame->contentsSize() - hitFrame->geometry().size();
+
+ while (hitFrame && range.width() <= 1 && range.height() <= 1)
+ hitFrame = hitFrame->parentFrame();
+ }
+ return hitFrame;
+}
+
+QSizeF QWebViewKineticScroller::viewportSize() const
+{
+ Q_D(const QWebViewKineticScroller);
+
+ return d->web ? d->web->page()->viewportSize() : QSize();
+}
+
+QPointF QWebViewKineticScroller::maximumContentPosition() const
+{
+ Q_D(const QWebViewKineticScroller);
+
+ QWebFrame *frame = d->currentFrame();
+ QSize s = frame ? frame->contentsSize() - frame->geometry().size() : QSize();
+ return QPointF(qMax(0, s.width()), qMax(0, s.height()));
+}
+
+QPointF QWebViewKineticScroller::contentPosition() const
+{
+ Q_D(const QWebViewKineticScroller);
+
+ QWebFrame *frame = d->currentFrame();
+ return frame ? QPointF(frame->scrollPosition()) + d->fractionalPosition : QPointF();
+}
+
+void QWebViewKineticScroller::setContentPosition(const QPointF &p, const QPointF & /*overshoot*/)
+{
+ Q_D(QWebViewKineticScroller);
+
+ QWebFrame *frame = d->currentFrame();
+ if (frame) {
+ QPoint pint(int(p.x()), int(p.y()));
+ frame->setScrollPosition(pint);
+ d->fractionalPosition = p - QPointF(pint);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/testapp/qwebviewkineticscroller.h b/testapp/qwebviewkineticscroller.h
new file mode 100644
index 0000000..1de369d
--- /dev/null
+++ b/testapp/qwebviewkineticscroller.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWEBVIEWKINETICSCROLLER_H
+#define QWEBVIEWKINETICSCROLLER_H
+
+#include <qkineticscroller.h>
+#include <QWebView>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QWebViewKineticScrollerPrivate;
+
+class Q_GUI_EXPORT QWebViewKineticScroller : public QObject, public QKineticScroller
+{
+ Q_OBJECT
+public:
+ QWebViewKineticScroller();
+ // QWebViewKineticScroller(QWebViewKineticScrollerPrivate &dd);
+ ~QWebViewKineticScroller();
+
+ void setWidget(QWebView *widget);
+
+ bool eventFilter(QObject *o, QEvent *e);
+
+protected:
+
+ virtual QSizeF viewportSize() const;
+ virtual QPointF maximumContentPosition() const;
+ virtual QPointF contentPosition() const;
+ virtual void setContentPosition(const QPointF &pos, const QPointF &overshootDelta);
+
+ virtual bool canStartScrollingAt(const QPointF &pos) const;
+ virtual void cancelPress(const QPointF &pressPos);
+
+ QScopedPointer<QWebViewKineticScrollerPrivate> d_ptr;
+
+private:
+ Q_DISABLE_COPY(QWebViewKineticScroller)
+ Q_DECLARE_PRIVATE(QWebViewKineticScroller)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QWEBVIEWSCROLLER_H