summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndras Becsi <andras.becsi@theqtcompany.com>2015-07-21 16:50:26 +0200
committerAndras Becsi <andras.becsi@theqtcompany.com>2015-08-12 17:22:02 +0200
commitf8116095536387c73cce3a0397e16662b42103e6 (patch)
tree26592871d76d5b552efb2647e4ac221607e7fadd /src
parent5b72783f06c50ffdfa4c6b5b808253245db89a1f (diff)
Add TouchTracker and hide the URL bar when scrolling
The tracker makes it possible to hide the URL bar when scrolling down the page and show it when scrolling up. The tracker installs an event filter on the RWHVDelegate by finding it when a touch event arrives.
Diffstat (limited to 'src')
-rw-r--r--src/main.cpp3
-rw-r--r--src/qml/BrowserWindow.qml51
-rw-r--r--src/qml/PageView.qml26
-rw-r--r--src/src.pro6
-rw-r--r--src/touchmockingapplication.cpp29
-rw-r--r--src/touchtracker.cpp124
-rw-r--r--src/touchtracker.h57
-rw-r--r--src/utils.h29
8 files changed, 290 insertions, 35 deletions
diff --git a/src/main.cpp b/src/main.cpp
index 339847b..f6645a2 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -43,6 +43,7 @@
#include "touchmockingapplication.h"
#include "utils.h"
+#include "touchtracker.h"
int main(int argc, char **argv)
{
@@ -67,6 +68,8 @@ int main(int argc, char **argv)
#endif
QtWebEngine::initialize();
+ qmlRegisterType<TouchTracker>("io.qt.browser", 1, 0, "TouchTracker");
+
BrowserWindow window;
QObject::connect(window.rootContext()->engine(), SIGNAL(quit()), &app, SLOT(quit()));
diff --git a/src/qml/BrowserWindow.qml b/src/qml/BrowserWindow.qml
index 6fedbc1..0de9d5a 100644
--- a/src/qml/BrowserWindow.qml
+++ b/src/qml/BrowserWindow.qml
@@ -63,6 +63,11 @@ Item {
property string uiSelectionColor: "#fad84a"
property int animationDuration: 200
+ property int velocityThreshold: 500
+ property int velocityY: 0
+ property real touchY: 0
+ property real touchReference: 0
+ property bool touchGesture: false
width: 1024
height: 600
@@ -128,7 +133,7 @@ Item {
anchors {
left: parent.left
right: parent.right
- top: parent.top
+ top: navigation.top
}
visible: opacity != 0.0
@@ -200,8 +205,50 @@ Item {
}
NavigationBar {
id: navigation
+
+ Behavior on y {
+ NumberAnimation { duration: animationDuration }
+ }
+
+ y: {
+ var diff = touchReference - touchY
+
+ if (velocityY > velocityThreshold) {
+ if (diff > 0)
+ return -toolBarHeight
+ else
+ return 0
+ }
+
+ if (!touchGesture || diff == 0) {
+ if (y < -toolBarHeight / 2)
+ return -toolBarHeight
+ else
+ return 0
+ }
+
+ if (diff > toolBarHeight)
+ return -toolBarHeight
+
+ if (diff > 0) {
+ if (y == -toolBarHeight)
+ return -toolBarHeight
+ return -diff
+ }
+
+ // diff < 0
+
+ if (y == 0)
+ return 0
+
+ diff = Math.abs(diff)
+ if (diff >= toolBarHeight)
+ return 0
+
+ return -toolBarHeight + diff
+ }
+
anchors {
- top: parent.top
left: parent.left
right: parent.right
}
diff --git a/src/qml/PageView.qml b/src/qml/PageView.qml
index a13e220..943ae01 100644
--- a/src/qml/PageView.qml
+++ b/src/qml/PageView.qml
@@ -35,7 +35,7 @@
**
****************************************************************************/
-import QtQuick 2.0
+import QtQuick 2.5
import QtWebEngine 1.3
import QtWebEngine.experimental 1.0
import QtQuick.Controls 1.5
@@ -43,6 +43,8 @@ import QtQuick.Controls.Styles 1.4
import QtQuick.Layouts 1.3
import QtGraphicalEffects 1.0
+import io.qt.browser 1.0
+
Rectangle {
id: root
@@ -124,7 +126,7 @@ Rectangle {
return
tabItem.image.url = webEngineView.url
- blur.grabToImage(function(result) {
+ webEngineView.grabToImage(function(result) {
tabItem.image.snapshot = result;
console.log("takeSnapshot("+result.url+")")
});
@@ -194,11 +196,23 @@ Rectangle {
radius: desaturate.desaturation * 25
}
- MouseArea {
- anchors.fill: parent
- enabled: !root.interactive
+ TouchTracker {
+ id: tracker
- onWheel: wheel.accepted = true
+ target: webEngineView
+ anchors.fill: parent
+ onTouchYChanged: browserWindow.touchY = tracker.touchY
+ onYVelocityChanged: browserWindow.velocityY = yVelocity
+ onTouchBegin: {
+ browserWindow.touchY = tracker.touchY
+ browserWindow.velocityY = yVelocity
+ browserWindow.touchReference = tracker.touchY
+ browserWindow.touchGesture = true
+ }
+ onTouchEnd: {
+ browserWindow.velocityY = yVelocity
+ browserWindow.touchGesture = false
+ }
}
Rectangle {
diff --git a/src/src.pro b/src/src.pro
index 30e6ce9..d97d37b 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -6,11 +6,13 @@ CONFIG -= app_bundle
SOURCES = main.cpp \
touchmockingapplication.cpp \
- browserwindow.cpp
+ browserwindow.cpp \
+ touchtracker.cpp
HEADERS = utils.h \
touchmockingapplication.h \
- browserwindow.h
+ browserwindow.h \
+ touchtracker.h
OTHER_FILES = \
qml/assets/UIButton.qml \
diff --git a/src/touchmockingapplication.cpp b/src/touchmockingapplication.cpp
index 4b8da4e..d57c570 100644
--- a/src/touchmockingapplication.cpp
+++ b/src/touchmockingapplication.cpp
@@ -44,6 +44,10 @@
#include <QMouseEvent>
#include <QTouchEvent>
+#include "utils.h"
+
+using namespace utils;
+
static inline QRectF touchRectForPosition(QPointF centerPoint)
{
QRectF touchRect(0, 0, 40, 40);
@@ -51,31 +55,6 @@ static inline QRectF touchRectForPosition(QPointF centerPoint)
return touchRect;
}
-static inline bool isTouchEvent(const QEvent* event)
-{
- switch (event->type()) {
- case QEvent::TouchBegin:
- case QEvent::TouchUpdate:
- case QEvent::TouchEnd:
- return true;
- default:
- return false;
- }
-}
-
-static inline bool isMouseEvent(const QEvent* event)
-{
- switch (event->type()) {
- case QEvent::MouseButtonPress:
- case QEvent::MouseMove:
- case QEvent::MouseButtonRelease:
- case QEvent::MouseButtonDblClick:
- return true;
- default:
- return false;
- }
-}
-
TouchMockingApplication::TouchMockingApplication(int& argc, char** argv)
: QGuiApplication(argc, argv)
, m_realTouchEventReceived(false)
diff --git a/src/touchtracker.cpp b/src/touchtracker.cpp
new file mode 100644
index 0000000..11cbb6e
--- /dev/null
+++ b/src/touchtracker.cpp
@@ -0,0 +1,124 @@
+#include "touchtracker.h"
+
+#include <QDateTime>
+
+#include "utils.h"
+
+using namespace utils;
+
+TouchTracker::TouchTracker(QQuickItem *parent)
+ : QQuickItem(parent)
+ , m_blockEvents(false)
+ , m_target(0)
+ , m_delegate(0)
+{
+ m_startPoint.ts = 0;
+ m_currentPoint.ts = 0;
+}
+
+QQuickItem *TouchTracker::target() const
+{
+ return m_target;
+}
+
+void TouchTracker::setTarget(QQuickItem * target)
+{
+ m_target = target;
+ emit targetChanged();
+}
+
+int TouchTracker::xVelocity() const
+{
+ qreal pos = qAbs(m_startPoint.x() - m_currentPoint.x());
+ qreal time = qAbs(m_startPoint.ts - m_currentPoint.ts);
+ return pos / time * 1000;
+}
+
+int TouchTracker::yVelocity() const
+{
+ qreal pos = qAbs(m_startPoint.y() - m_currentPoint.y());
+ qreal time = qAbs(m_startPoint.ts - m_currentPoint.ts);
+ return pos / time * 1000;
+}
+
+
+qreal TouchTracker::touchX() const
+{
+ return m_currentPoint.x();
+}
+
+qreal TouchTracker::touchY() const
+{
+ return m_currentPoint.y();
+}
+
+bool TouchTracker::blockEvents() const
+{
+ return m_blockEvents;
+}
+
+void TouchTracker::setBlockEvents(bool shouldBlock)
+{
+ if (m_blockEvents == shouldBlock)
+ return;
+ m_blockEvents = shouldBlock;
+ emit blockEventsChanged();
+}
+
+bool TouchTracker::eventFilter(QObject *obj, QEvent *event)
+{
+ if (obj != m_delegate)
+ return QQuickItem::eventFilter(obj, event);
+
+ if (event->type() == QEvent::Wheel)
+ return m_blockEvents;
+
+ if (!isTouchEvent(event))
+ return QQuickItem::eventFilter(obj, event);
+
+ const QTouchEvent *touch = static_cast<QTouchEvent*>(event);
+ const QList<QTouchEvent::TouchPoint> &points = touch->touchPoints();
+ m_currentPoint.pos = m_target->mapToScene(points.at(0).pos());
+ m_currentPoint.ts = QDateTime::currentMSecsSinceEpoch();
+
+ emit touchChanged();
+ emit velocityChanged();
+
+ if (event->type() == QEvent::TouchEnd)
+ emit touchEnd();
+
+ return m_blockEvents;
+}
+
+void TouchTracker::touchEvent(QTouchEvent * event)
+{
+ if (!m_target) {
+ if (!m_blockEvents)
+ QQuickItem::touchEvent(event);
+
+ return;
+ }
+
+ event->setAccepted(false);
+
+ const QList<QTouchEvent::TouchPoint> &points = event->touchPoints();
+ m_currentPoint.pos = m_target->mapToScene(points.at(0).pos());
+ m_currentPoint.ts = QDateTime::currentMSecsSinceEpoch();
+
+ if (event->type() == QEvent::TouchBegin) {
+ m_startPoint = m_currentPoint;
+ emit touchBegin();
+ }
+
+ emit touchChanged();
+
+ // We have to find the delegate to be able to filter
+ // events from the WebEngineView.
+ // This is a hack and should preferably be made easier
+ // with the API in some way.
+ QQuickItem *child = m_target->childAt(m_currentPoint.x(), m_currentPoint.y());
+ if (child && m_delegate != child) {
+ child->installEventFilter(this);
+ m_delegate = child;
+ }
+}
diff --git a/src/touchtracker.h b/src/touchtracker.h
new file mode 100644
index 0000000..9aa555a
--- /dev/null
+++ b/src/touchtracker.h
@@ -0,0 +1,57 @@
+#ifndef TOUCHTRACKER_H
+#define TOUCHTRACKER_H
+
+#include <QObject>
+#include <QQuickItem>
+
+class TouchTracker : public QQuickItem
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal touchX READ touchX NOTIFY touchChanged)
+ Q_PROPERTY(qreal touchY READ touchY NOTIFY touchChanged)
+ Q_PROPERTY(int xVelocity READ xVelocity NOTIFY velocityChanged)
+ Q_PROPERTY(int yVelocity READ yVelocity NOTIFY velocityChanged)
+ Q_PROPERTY(bool blockEvents READ blockEvents WRITE setBlockEvents NOTIFY blockEventsChanged)
+ Q_PROPERTY(QQuickItem* target READ target WRITE setTarget NOTIFY targetChanged)
+
+ struct PositionInfo
+ {
+ QPointF pos;
+ qint64 ts;
+ qreal x() const { return pos.x(); }
+ qreal y() const { return pos.y(); }
+ };
+
+public:
+ TouchTracker(QQuickItem *parent = 0);
+
+ qreal touchX() const;
+ qreal touchY() const;
+ int xVelocity() const;
+ int yVelocity() const;
+ QQuickItem* target() const;
+ bool blockEvents() const;
+ void setBlockEvents(bool shouldBlock);
+ void setTarget(QQuickItem * target);
+
+signals:
+ void touchChanged();
+ void blockEventsChanged();
+ void targetChanged();
+ void touchBegin();
+ void touchEnd();
+ void velocityChanged();
+
+protected:
+ bool eventFilter(QObject *obj, QEvent *event);
+ void touchEvent(QTouchEvent *event) override;
+
+private:
+ bool m_blockEvents;
+ PositionInfo m_startPoint;
+ PositionInfo m_currentPoint;
+ QQuickItem *m_target;
+ QQuickItem *m_delegate;
+};
+
+#endif // TOUCHTRACKER_H
diff --git a/src/utils.h b/src/utils.h
index 8ea1aea..45ba2ad 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -38,9 +38,38 @@
#ifndef UTILS_H
#define UTILS_H
+#include <QtCore/QEvent>
#include <QtCore/QFileInfo>
#include <QtCore/QUrl>
+namespace utils {
+inline bool isTouchEvent(const QEvent* event)
+{
+ switch (event->type()) {
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd:
+ return true;
+ default:
+ return false;
+ }
+}
+
+inline bool isMouseEvent(const QEvent* event)
+{
+ switch (event->type()) {
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseMove:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseButtonDblClick:
+ return true;
+ default:
+ return false;
+ }
+}
+
+}
+
class Utils : public QObject {
Q_OBJECT