aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@digia.com>2013-05-08 15:21:59 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-03-10 15:01:14 +0100
commitfe2de633f9b9454ec8a9c2a5874ad85f49d8d54d (patch)
treed15cc7bb53673f8b9b6af8a0c4648f8b29bb80b4
parent2df6031b5935fafcada04bc15b281c63bdbfabf9 (diff)
MultiPointTouchArea: handles mouse too, unless mouseEnabled is false
A new boolean property mouseEnabled is introduced (true by default). If set to true, then it will handle any non-synthetic mouse event as if it were a touch point. If set to false, the area becomes transparent for real mouse events so that a MultiPointTouchArea can be stacked on top of a MouseArea in order to separate handling of touch and mouse. In either case it continues to absorb and ignore synthesized mouse events (including touch-to-mouse synthesis in QQuickWindow). [ChangeLog][QtQuick][MultiPointTouchArea]handles mouse as a touchpoint; added mouseEnabled property to permit transparent pass-through to mouse-sensitive items Change-Id: I4af94d838f0060154494589c0f15c6858ee89ddb Task-number: QTBUG-31047 Reviewed-by: Frederik Gladhorn <frederik.gladhorn@digia.com>
-rw-r--r--src/quick/items/qquickmultipointtoucharea.cpp156
-rw-r--r--src/quick/items/qquickmultipointtoucharea_p.h10
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/data/dualGestures.qml94
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/data/inMouseArea.qml30
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/data/mouse.qml29
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp285
6 files changed, 594 insertions, 10 deletions
diff --git a/src/quick/items/qquickmultipointtoucharea.cpp b/src/quick/items/qquickmultipointtoucharea.cpp
index 973f6efdcc..6a5ba931c7 100644
--- a/src/quick/items/qquickmultipointtoucharea.cpp
+++ b/src/quick/items/qquickmultipointtoucharea.cpp
@@ -236,7 +236,14 @@ void QQuickTouchPoint::setSceneY(qreal sceneY)
A MultiPointTouchArea is an invisible item that is used to track multiple touch points.
The \l Item::enabled property is used to enable and disable touch handling. When disabled,
- the touch area becomes transparent to mouse/touch events.
+ the touch area becomes transparent to mouse and touch events.
+
+ By default, the mouse will be handled the same way as a single touch point,
+ and items under the touch area will not receive mouse events because the
+ touch area is handling them. But if the \l mouseEnabled property is set to
+ false, it becomes transparent to mouse events so that another
+ mouse-sensitive Item (such as a MouseArea) can be used to handle mouse
+ interaction separately.
MultiPointTouchArea can be used in two ways:
@@ -313,6 +320,10 @@ void QQuickTouchPoint::setSceneY(qreal sceneY)
This property holds a set of user-defined touch point objects that can be bound to.
+ If mouseEnabled is true (the default) and the left mouse button is pressed
+ while the mouse is over the touch area, the current mouse position will be
+ one of these touch points.
+
In the following example, we have two small rectangles that follow our touch points.
\snippet qml/multipointtoucharea/multipointtoucharea.qml 0
@@ -326,7 +337,9 @@ QQuickMultiPointTouchArea::QQuickMultiPointTouchArea(QQuickItem *parent)
: QQuickItem(parent),
_minimumTouchPoints(0),
_maximumTouchPoints(INT_MAX),
- _stealMouse(false)
+ _mouseTouchPoint(Q_NULLPTR),
+ _stealMouse(false),
+ _mouseEnabled(true)
{
setAcceptedMouseButtons(Qt::LeftButton);
setFiltersChildMouseEvents(true);
@@ -358,6 +371,11 @@ QQuickMultiPointTouchArea::~QQuickMultiPointTouchArea()
one handling two finger touches, and another handling three finger touches.
By default, all touch points within the touch area are handled.
+
+ If mouseEnabled is true, the mouse acts as a touch point, so it is also
+ subject to these constraints: for example if maximumTouchPoints is two, you
+ can use the mouse as one touch point and a finger as another touch point
+ for a total of two.
*/
int QQuickMultiPointTouchArea::minimumTouchPoints() const
@@ -386,6 +404,25 @@ void QQuickMultiPointTouchArea::setMaximumTouchPoints(int num)
emit maximumTouchPointsChanged();
}
+/*!
+ \qmlproperty bool QtQuick::MultiPointTouchArea::mouseEnabled
+
+ This property controls whether the MultiPointTouchArea will handle mouse
+ events too. If it is true (the default), the touch area will treat the
+ mouse the same as a single touch point; if it is false, the touch area will
+ ignore mouse events and allow them to "pass through" so that they can be
+ handled by other items underneath.
+*/
+void QQuickMultiPointTouchArea::setMouseEnabled(bool arg)
+{
+ if (_mouseEnabled != arg) {
+ _mouseEnabled = arg;
+ if (_mouseTouchPoint && !arg)
+ _mouseTouchPoint = Q_NULLPTR;
+ emit mouseEnabledChanged();
+ }
+}
+
void QQuickMultiPointTouchArea::touchEvent(QTouchEvent *event)
{
switch (event->type()) {
@@ -434,10 +471,46 @@ void QQuickMultiPointTouchArea::updateTouchData(QEvent *event)
bool ended = false;
bool moved = false;
bool started = false;
+ bool isMouseEvent = false;
clearTouchLists();
- QTouchEvent *e = static_cast<QTouchEvent*>(event);
- QList<QTouchEvent::TouchPoint> touchPoints = e->touchPoints();
+ QList<QTouchEvent::TouchPoint> touchPoints;
+
+ switch (event->type()) {
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd:
+ touchPoints = static_cast<QTouchEvent*>(event)->touchPoints();
+ break;
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseMove:
+ case QEvent::MouseButtonRelease: {
+ QMouseEvent *me = static_cast<QMouseEvent*>(event);
+ _mouseQpaTouchPoint.setPos(me->localPos());
+ _mouseQpaTouchPoint.setScenePos(me->windowPos());
+ _mouseQpaTouchPoint.setScreenPos(me->screenPos());
+ if (event->type() == QEvent::MouseMove)
+ _mouseQpaTouchPoint.setState(Qt::TouchPointMoved);
+ else if (event->type() == QEvent::MouseButtonRelease)
+ _mouseQpaTouchPoint.setState(Qt::TouchPointReleased);
+ else { // QEvent::MouseButtonPress
+ _mouseQpaTouchPoint.setState(Qt::TouchPointPressed);
+ _pressedTouchPoints.append(_mouseTouchPoint);
+ }
+ touchPoints << _mouseQpaTouchPoint;
+ isMouseEvent = true;
+ break;
+ }
+ default:
+ qWarning("updateTouchData: unhandled event type %d", event->type());
+ break;
+ }
+
+ if (!isMouseEvent && _mouseTouchPoint) {
+ QQuickWindow *c = window();
+ if (c && c->mouseGrabberItem() == this)
+ touchPoints << _mouseQpaTouchPoint;
+ }
int numTouchPoints = touchPoints.count();
//always remove released touches, and make sure we handle all releases before adds.
foreach (const QTouchEvent::TouchPoint &p, touchPoints) {
@@ -517,10 +590,12 @@ void QQuickMultiPointTouchArea::clearTouchLists()
{
foreach (QObject *obj, _releasedTouchPoints) {
QQuickTouchPoint *dtp = static_cast<QQuickTouchPoint*>(obj);
- if (!dtp->isQmlDefined())
+ if (!dtp->isQmlDefined()) {
+ _touchPoints.remove(dtp->pointId());
delete dtp;
- else
+ } else {
dtp->setInUse(false);
+ }
}
_releasedTouchPoints.clear();
_pressedTouchPoints.clear();
@@ -547,6 +622,25 @@ void QQuickMultiPointTouchArea::addTouchPoint(const QTouchEvent::TouchPoint *p)
_pressedTouchPoints.append(dtp);
}
+void QQuickMultiPointTouchArea::addTouchPoint(const QMouseEvent *e)
+{
+ QQuickTouchPoint *dtp = 0;
+ foreach (QQuickTouchPoint *tp, _touchPrototypes)
+ if (!tp->inUse()) {
+ tp->setInUse(true);
+ dtp = tp;
+ break;
+ }
+
+ if (dtp == 0)
+ dtp = new QQuickTouchPoint(false);
+ updateTouchPoint(dtp, e);
+ dtp->setPressed(true);
+ _touchPoints.insert(-1, dtp);
+ _pressedTouchPoints.append(dtp);
+ _mouseTouchPoint = dtp;
+}
+
#ifdef Q_OS_OSX
void QQuickMultiPointTouchArea::hoverEnterEvent(QHoverEvent *event)
{
@@ -597,9 +691,23 @@ void QQuickMultiPointTouchArea::updateTouchPoint(QQuickTouchPoint *dtp, const QT
dtp->setSceneY(p->scenePos().y());
}
+void QQuickMultiPointTouchArea::updateTouchPoint(QQuickTouchPoint *dtp, const QMouseEvent *e)
+{
+ dtp->setPreviousX(dtp->x());
+ dtp->setPreviousY(dtp->y());
+ dtp->setX(e->localPos().x());
+ dtp->setY(e->localPos().y());
+ if (e->type() == QEvent::MouseButtonPress) {
+ dtp->setStartX(e->localPos().x());
+ dtp->setStartY(e->localPos().y());
+ }
+ dtp->setSceneX(e->windowPos().x());
+ dtp->setSceneY(e->windowPos().y());
+}
+
void QQuickMultiPointTouchArea::mousePressEvent(QMouseEvent *event)
{
- if (!isEnabled()) {
+ if (!isEnabled() || !_mouseEnabled || event->button() != Qt::LeftButton) {
QQuickItem::mousePressEvent(event);
return;
}
@@ -607,25 +715,53 @@ void QQuickMultiPointTouchArea::mousePressEvent(QMouseEvent *event)
_stealMouse = false;
setKeepMouseGrab(false);
event->setAccepted(true);
+ _mousePos = event->localPos();
+
+ if (event->source() != Qt::MouseEventNotSynthesized)
+ return;
+
+ if (_touchPoints.count() >= _minimumTouchPoints - 1 && _touchPoints.count() < _maximumTouchPoints) {
+ addTouchPoint(event);
+ updateTouchData(event);
+ emit pressed(_pressedTouchPoints);
+ }
}
void QQuickMultiPointTouchArea::mouseMoveEvent(QMouseEvent *event)
{
- if (!isEnabled()) {
+ if (!isEnabled() || !_mouseEnabled) {
QQuickItem::mouseMoveEvent(event);
return;
}
- //do nothing
+ if (event->source() != Qt::MouseEventNotSynthesized)
+ return;
+
+ _movedTouchPoints.clear();
+ updateTouchData(event);
}
void QQuickMultiPointTouchArea::mouseReleaseEvent(QMouseEvent *event)
{
_stealMouse = false;
- if (!isEnabled()) {
+ if (!isEnabled() || !_mouseEnabled) {
QQuickItem::mouseReleaseEvent(event);
return;
}
+
+ if (event->source() != Qt::MouseEventNotSynthesized)
+ return;
+
+ if (_mouseTouchPoint) {
+ updateTouchData(event);
+ _mouseTouchPoint->setPressed(false);
+ _mouseTouchPoint->setInUse(false);
+ _releasedTouchPoints.append(_mouseTouchPoint);
+ emit released(_releasedTouchPoints);
+ _releasedTouchPoints.removeAll(_mouseTouchPoint);
+ _mouseTouchPoint = Q_NULLPTR;
+ }
+
QQuickWindow *c = window();
if (c && c->mouseGrabberItem() == this)
ungrabMouse();
diff --git a/src/quick/items/qquickmultipointtoucharea_p.h b/src/quick/items/qquickmultipointtoucharea_p.h
index 83cc407401..9dbca2be54 100644
--- a/src/quick/items/qquickmultipointtoucharea_p.h
+++ b/src/quick/items/qquickmultipointtoucharea_p.h
@@ -191,6 +191,7 @@ class Q_AUTOTEST_EXPORT QQuickMultiPointTouchArea : public QQuickItem
Q_PROPERTY(QQmlListProperty<QQuickTouchPoint> touchPoints READ touchPoints)
Q_PROPERTY(int minimumTouchPoints READ minimumTouchPoints WRITE setMinimumTouchPoints NOTIFY minimumTouchPointsChanged)
Q_PROPERTY(int maximumTouchPoints READ maximumTouchPoints WRITE setMaximumTouchPoints NOTIFY maximumTouchPointsChanged)
+ Q_PROPERTY(bool mouseEnabled READ mouseEnabled WRITE setMouseEnabled NOTIFY mouseEnabledChanged)
public:
QQuickMultiPointTouchArea(QQuickItem *parent=0);
@@ -200,6 +201,8 @@ public:
void setMinimumTouchPoints(int num);
int maximumTouchPoints() const;
void setMaximumTouchPoints(int num);
+ bool mouseEnabled() const { return _mouseEnabled; }
+ void setMouseEnabled(bool arg);
QQmlListProperty<QQuickTouchPoint> touchPoints() {
return QQmlListProperty<QQuickTouchPoint>(this, 0, QQuickMultiPointTouchArea::touchPoint_append, QQuickMultiPointTouchArea::touchPoint_count, QQuickMultiPointTouchArea::touchPoint_at, 0);
@@ -229,6 +232,7 @@ Q_SIGNALS:
void touchUpdated(const QList<QObject*> &touchPoints);
void minimumTouchPointsChanged();
void maximumTouchPointsChanged();
+ void mouseEnabledChanged();
protected:
void touchEvent(QTouchEvent *);
@@ -241,9 +245,11 @@ protected:
void addTouchPrototype(QQuickTouchPoint* prototype);
void addTouchPoint(const QTouchEvent::TouchPoint *p);
+ void addTouchPoint(const QMouseEvent *e);
void clearTouchLists();
void updateTouchPoint(QQuickTouchPoint*, const QTouchEvent::TouchPoint*);
+ void updateTouchPoint(QQuickTouchPoint *dtp, const QMouseEvent *e);
void updateTouchData(QEvent*);
bool sendMouseEvent(QMouseEvent *event);
@@ -265,7 +271,11 @@ private:
QList<QObject*> _movedTouchPoints;
int _minimumTouchPoints;
int _maximumTouchPoints;
+ QQuickTouchPoint *_mouseTouchPoint; // exists when mouse button is down and _mouseEnabled is true; null otherwise
+ QTouchEvent::TouchPoint _mouseQpaTouchPoint; // synthetic QPA touch point to hold state and position of the mouse
+ QPointF _mousePos;
bool _stealMouse;
+ bool _mouseEnabled;
};
QT_END_NAMESPACE
diff --git a/tests/auto/quick/qquickmultipointtoucharea/data/dualGestures.qml b/tests/auto/quick/qquickmultipointtoucharea/data/dualGestures.qml
new file mode 100644
index 0000000000..dfb667df30
--- /dev/null
+++ b/tests/auto/quick/qquickmultipointtoucharea/data/dualGestures.qml
@@ -0,0 +1,94 @@
+/* From the docs about minimumTouchPoints/maximumTouchPoints:
+ "...allow you to, for example, have nested MultiPointTouchAreas,
+ one handling two finger touches, and another handling three finger touches."
+ But in this test they are side-by-side: the left one handles any number
+ of touches up to 2, and the right one requires 3.
+*/
+import QtQuick 2.0
+
+Row {
+ width: 640
+ height: 480
+
+ Rectangle {
+ color: "black"
+ border.color: "white"
+ height: parent.height
+ width: parent.width / 2
+ MultiPointTouchArea {
+ objectName: "dualTouchArea"
+ anchors.fill: parent
+ maximumTouchPoints: 2
+ touchPoints: [
+ TouchPoint { id: touch1 },
+ TouchPoint { id: touch2 }
+ ]
+ Rectangle {
+ objectName: "touch1rect"
+ color: "red"
+ width: 30
+ height: width
+ radius: width / 2
+ x: touch1.x
+ y: touch1.y
+ border.color: touch1.pressed ? "white" : "transparent"
+ }
+ Rectangle {
+ objectName: "touch2rect"
+ color: "yellow"
+ width: 30
+ height: width
+ radius: width / 2
+ x: touch2.x
+ y: touch2.y
+ border.color: touch2.pressed ? "white" : "transparent"
+ }
+ }
+ }
+
+
+ Rectangle {
+ color: "black"
+ border.color: "white"
+ height: parent.height
+ width: parent.width / 2
+ MultiPointTouchArea {
+ objectName: "tripleTouchArea"
+ anchors.fill: parent
+ minimumTouchPoints: 3
+ maximumTouchPoints: 3
+ touchPoints: [
+ TouchPoint { id: touch3 },
+ TouchPoint { id: touch4 },
+ TouchPoint { id: touch5 }
+ ]
+ Rectangle {
+ objectName: "touch3rect"
+ color: "green"
+ width: 30
+ height: width
+ x: touch3.x
+ y: touch3.y
+ border.color: touch3.pressed ? "white" : "transparent"
+ }
+ Rectangle {
+ objectName: "touch4rect"
+ color: "blue"
+ width: 30
+ height: width
+ x: touch4.x
+ y: touch4.y
+ border.color: touch4.pressed ? "white" : "transparent"
+ }
+ Rectangle {
+ objectName: "touch5rect"
+ color: "violet"
+ width: 30
+ height: width
+ x: touch5.x
+ y: touch5.y
+ border.color: touch5.pressed ? "white" : "transparent"
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickmultipointtoucharea/data/inMouseArea.qml b/tests/auto/quick/qquickmultipointtoucharea/data/inMouseArea.qml
new file mode 100644
index 0000000000..9c5d758e13
--- /dev/null
+++ b/tests/auto/quick/qquickmultipointtoucharea/data/inMouseArea.qml
@@ -0,0 +1,30 @@
+import QtQuick 2.2
+
+MouseArea {
+ id: root
+ width: 240
+ height: 320
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
+
+ Rectangle {
+ anchors.fill: parent
+ color: "black"
+ border.width: 5
+ border.color: parent.pressed ? "red" : "blue"
+
+ Rectangle {
+ anchors.fill: parent
+ anchors.margins: 25
+ color: mpta.pressed ? "orange" : "cyan"
+
+ MultiPointTouchArea {
+ id: mpta
+ objectName: "mpta"
+ property bool pressed: false
+ anchors.fill: parent
+ onPressed: pressed = true
+ onReleased: pressed = false
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickmultipointtoucharea/data/mouse.qml b/tests/auto/quick/qquickmultipointtoucharea/data/mouse.qml
new file mode 100644
index 0000000000..0abcc76f7c
--- /dev/null
+++ b/tests/auto/quick/qquickmultipointtoucharea/data/mouse.qml
@@ -0,0 +1,29 @@
+import QtQuick 2.0
+
+MultiPointTouchArea {
+ width: 240
+ height: 320
+
+ property int touchCount: 0
+ property int cancelCount: 0
+
+ minimumTouchPoints: 1
+ maximumTouchPoints: 4
+ touchPoints: [
+ TouchPoint { id: p1; objectName: "point1" },
+ TouchPoint { objectName: "point2" }
+ ]
+
+ onPressed: { touchCount = touchPoints.length }
+ onTouchUpdated: { touchCount = touchPoints.length }
+ onCanceled: { cancelCount = touchPoints.length }
+
+ Rectangle {
+ color: "red"
+ height: 30
+ width: 30
+ x: p1.x
+ y: p1.y
+ }
+
+}
diff --git a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
index 2bddac4ef3..1d4932c432 100644
--- a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
+++ b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
@@ -43,6 +43,7 @@
#include <QtTest/QSignalSpy>
#include <private/qquickmultipointtoucharea_p.h>
#include <private/qquickflickable_p.h>
+#include <private/qquickmousearea_p.h>
#include <qpa/qwindowsysteminterface.h>
#include <QtQuick/qquickview.h>
#include <QtGui/QScreen>
@@ -72,9 +73,13 @@ private slots:
void nested();
void inFlickable();
void inFlickable2();
+ void inMouseArea();
+ void mouseAsTouchpoint();
void invisible();
void transformedTouchArea_data();
void transformedTouchArea();
+ void mouseInteraction();
+ void mouseInteraction_data();
private:
QQuickView *createAndShowView(const QString &file);
@@ -550,6 +555,9 @@ void tst_QQuickMultiPointTouchArea::inFlickable()
QQuickFlickable *flickable = qobject_cast<QQuickFlickable *>(window->rootObject());
QVERIFY(flickable != 0);
+ QQuickMultiPointTouchArea *mpta = window->rootObject()->findChild<QQuickMultiPointTouchArea*>();
+ QVERIFY(mpta != 0);
+
QQuickTouchPoint *point11 = window->rootObject()->findChild<QQuickTouchPoint*>("point1");
QQuickTouchPoint *point12 = window->rootObject()->findChild<QQuickTouchPoint*>("point2");
@@ -625,6 +633,8 @@ void tst_QQuickMultiPointTouchArea::inFlickable()
p1 = QPoint(20,100);
p2 = QPoint(40,100);
QTest::touchEvent(window.data(), device).press(0, p1).press(1, p2);
+ // ensure that mouse events do not fall through to the Flickable
+ mpta->setMaximumTouchPoints(3);
QTest::mousePress(window.data(), Qt::LeftButton, 0, p1);
QCOMPARE(point11->pressed(), true);
@@ -744,6 +754,239 @@ void tst_QQuickMultiPointTouchArea::inFlickable2()
QTRY_VERIFY(!flickable->isMoving());
}
+// QTBUG-31047
+void tst_QQuickMultiPointTouchArea::inMouseArea()
+{
+ QScopedPointer<QQuickView> window(createAndShowView("inMouseArea.qml"));
+ QVERIFY(window->rootObject() != 0);
+
+ QQuickMouseArea *mouseArea = qobject_cast<QQuickMouseArea *>(window->rootObject());
+ QVERIFY(mouseArea != 0);
+
+ QQuickMultiPointTouchArea *mpta = window->rootObject()->findChild<QQuickMultiPointTouchArea*>("mpta");
+ QVERIFY(mpta != 0);
+
+ QPoint innerPoint(40,100);
+ QPoint outerPoint(10,100);
+
+ QTest::touchEvent(window.data(), device).press(0, innerPoint);
+ QVERIFY(mpta->property("pressed").toBool());
+ QTest::touchEvent(window.data(), device).release(0, innerPoint);
+ QVERIFY(!mpta->property("pressed").toBool());
+
+ QTest::mousePress(window.data(), Qt::LeftButton, 0, outerPoint);
+ QVERIFY(mouseArea->property("pressed").toBool());
+ QTest::mouseRelease(window.data(), Qt::LeftButton, 0, outerPoint);
+ QVERIFY(!mouseArea->property("pressed").toBool());
+
+ QTest::mousePress(window.data(), Qt::LeftButton, 0, innerPoint);
+ QVERIFY(mpta->property("pressed").toBool());
+ QVERIFY(!mouseArea->property("pressed").toBool());
+ QTest::mouseRelease(window.data(), Qt::LeftButton, 0, innerPoint);
+ QVERIFY(!mpta->property("pressed").toBool());
+ QVERIFY(!mouseArea->property("pressed").toBool());
+
+ QTest::touchEvent(window.data(), device).press(0, innerPoint);
+ QVERIFY(mpta->property("pressed").toBool());
+ QTest::touchEvent(window.data(), device).release(0, innerPoint);
+ QVERIFY(!mpta->property("pressed").toBool());
+
+ QTest::touchEvent(window.data(), device).press(0, outerPoint);
+ QVERIFY(mouseArea->property("pressed").toBool());
+ QVERIFY(!mpta->property("pressed").toBool());
+ QTest::touchEvent(window.data(), device).release(0, outerPoint);
+ QVERIFY(!mouseArea->property("pressed").toBool());
+ QVERIFY(!mpta->property("pressed").toBool());
+
+ // Right click should pass through
+ QTest::mousePress(window.data(), Qt::RightButton, 0, innerPoint);
+ QVERIFY(mouseArea->property("pressed").toBool());
+ QVERIFY(!mpta->property("pressed").toBool());
+ QTest::mouseRelease(window.data(), Qt::RightButton, 0, innerPoint);
+
+ mpta->setProperty("mouseEnabled", false);
+
+ QTest::touchEvent(window.data(), device).press(0, innerPoint);
+ QVERIFY(mpta->property("pressed").toBool());
+ QVERIFY(!mouseArea->property("pressed").toBool());
+ QTest::touchEvent(window.data(), device).release(0, innerPoint);
+ QVERIFY(!mpta->property("pressed").toBool());
+ QVERIFY(!mouseArea->property("pressed").toBool());
+
+ QTest::mousePress(window.data(), Qt::LeftButton, 0, outerPoint);
+ QVERIFY(mouseArea->property("pressed").toBool());
+ QTest::mouseRelease(window.data(), Qt::LeftButton, 0, outerPoint);
+ QVERIFY(!mouseArea->property("pressed").toBool());
+
+ QTest::mousePress(window.data(), Qt::LeftButton, 0, innerPoint);
+ QVERIFY(!mpta->property("pressed").toBool());
+ QVERIFY(mouseArea->property("pressed").toBool());
+ QTest::mouseRelease(window.data(), Qt::LeftButton, 0, innerPoint);
+ QVERIFY(!mpta->property("pressed").toBool());
+ QVERIFY(!mouseArea->property("pressed").toBool());
+
+ QTest::touchEvent(window.data(), device).press(0, innerPoint);
+ QVERIFY(mpta->property("pressed").toBool());
+ QTest::touchEvent(window.data(), device).release(0, innerPoint);
+ QVERIFY(!mpta->property("pressed").toBool());
+
+ QTest::touchEvent(window.data(), device).press(0, outerPoint);
+ QVERIFY(mouseArea->property("pressed").toBool());
+ QVERIFY(!mpta->property("pressed").toBool());
+ QTest::touchEvent(window.data(), device).release(0, outerPoint);
+ QVERIFY(!mouseArea->property("pressed").toBool());
+ QVERIFY(!mpta->property("pressed").toBool());
+}
+
+void tst_QQuickMultiPointTouchArea::mouseAsTouchpoint()
+{
+ QScopedPointer<QQuickView> window(createAndShowView("dualGestures.qml"));
+ QVERIFY(window->rootObject() != 0);
+
+ QQuickMultiPointTouchArea *dualmpta = window->rootObject()->findChild<QQuickMultiPointTouchArea*>("dualTouchArea");
+ QVERIFY(dualmpta != 0);
+
+ QQuickItem *touch1rect = window->rootObject()->findChild<QQuickItem*>("touch1rect");
+ QQuickItem *touch2rect = window->rootObject()->findChild<QQuickItem*>("touch2rect");
+ QQuickItem *touch3rect = window->rootObject()->findChild<QQuickItem*>("touch3rect");
+ QQuickItem *touch4rect = window->rootObject()->findChild<QQuickItem*>("touch4rect");
+ QQuickItem *touch5rect = window->rootObject()->findChild<QQuickItem*>("touch5rect");
+
+ {
+ QPoint touch1(40,10);
+ QPoint touch2(40,100);
+ QPoint touch3(10,10);
+
+ // Touch both, release one, manipulate other touchpoint with mouse
+ QTest::touchEvent(window.data(), device).press(1, touch1);
+ QTest::touchEvent(window.data(), device).press(2, touch2);
+ QCOMPARE(touch1rect->property("x").toInt(), touch1.x());
+ QCOMPARE(touch1rect->property("y").toInt(), touch1.y());
+ QCOMPARE(touch2rect->property("x").toInt(), touch2.x());
+ QCOMPARE(touch2rect->property("y").toInt(), touch2.y());
+ QTest::touchEvent(window.data(), device).release(1, touch1);
+ touch1.setY(20);
+ QTest::mousePress(window.data(), Qt::LeftButton, 0, touch1);
+ QCOMPARE(touch1rect->property("x").toInt(), touch1.x());
+ QCOMPARE(touch1rect->property("y").toInt(), touch1.y());
+ QCOMPARE(touch2rect->property("x").toInt(), touch2.x());
+ QCOMPARE(touch2rect->property("y").toInt(), touch2.y());
+ QTest::touchEvent(window.data(), device).release(2, touch2);
+ QTest::mouseRelease(window.data(), Qt::LeftButton, 0, touch1);
+
+ // Start with mouse, move it, touch second point, move it
+ QTest::mousePress(window.data(), Qt::LeftButton, 0, touch1);
+ touch1.setX(60);
+ QTest::mouseMove(window.data(), touch1);
+ QCOMPARE(touch1rect->property("x").toInt(), touch1.x());
+ QCOMPARE(touch1rect->property("y").toInt(), touch1.y());
+ touch2.setX(60);
+ QTest::touchEvent(window.data(), device).press(3, touch2);
+ QCOMPARE(touch1rect->property("x").toInt(), touch1.x());
+ QCOMPARE(touch1rect->property("y").toInt(), touch1.y());
+ QCOMPARE(touch2rect->property("x").toInt(), touch2.x());
+ QCOMPARE(touch2rect->property("y").toInt(), touch2.y());
+ touch2.setY(150);
+ QTest::touchEvent(window.data(), device).move(3, touch2);
+ QCOMPARE(touch1rect->property("x").toInt(), touch1.x());
+ QCOMPARE(touch1rect->property("y").toInt(), touch1.y());
+ QCOMPARE(touch2rect->property("x").toInt(), touch2.x());
+ QCOMPARE(touch2rect->property("y").toInt(), touch2.y());
+
+ // Touch third point - nothing happens
+ QTest::touchEvent(window.data(), device).press(4, touch3);
+ QCOMPARE(touch1rect->property("x").toInt(), touch1.x());
+ QCOMPARE(touch1rect->property("y").toInt(), touch1.y());
+ QCOMPARE(touch2rect->property("x").toInt(), touch2.x());
+ QCOMPARE(touch2rect->property("y").toInt(), touch2.y());
+
+ // Release all
+ QTest::mouseRelease(window.data(), Qt::LeftButton, 0, touch1);
+ QTest::touchEvent(window.data(), device).release(3, touch2);
+ QTest::touchEvent(window.data(), device).release(4, touch3);
+ QCOMPARE(touch1rect->property("x").toInt(), touch1.x());
+ QCOMPARE(touch1rect->property("y").toInt(), touch1.y());
+ QCOMPARE(touch2rect->property("x").toInt(), touch2.x());
+ QCOMPARE(touch2rect->property("y").toInt(), touch2.y());
+ }
+
+ // Mouse and touch on left, touch 3 points on right
+ {
+ QPoint mouse1(40,10);
+ QPoint touch1(10,10);
+ QPoint touch2(340,10);
+ QPoint touch3(340,100);
+ QPoint touch4(540,10);
+
+ QTest::mousePress(window.data(), Qt::LeftButton, 0, mouse1);
+ QCOMPARE(touch1rect->property("x").toInt(), mouse1.x());
+ QCOMPARE(touch1rect->property("y").toInt(), mouse1.y());
+ QTest::touchEvent(window.data(), device).press(1, touch1);
+ QCOMPARE(touch1rect->property("x").toInt(), mouse1.x());
+ QCOMPARE(touch1rect->property("y").toInt(), mouse1.y());
+ QCOMPARE(touch2rect->property("x").toInt(), touch1.x());
+ QCOMPARE(touch2rect->property("y").toInt(), touch1.y());
+
+ QTest::touchEvent(window.data(), device).press(2, touch2).press(3, touch3).press(4, touch4);
+ QCOMPARE(touch1rect->property("x").toInt(), mouse1.x());
+ QCOMPARE(touch1rect->property("y").toInt(), mouse1.y());
+ QCOMPARE(touch2rect->property("x").toInt(), touch1.x());
+ QCOMPARE(touch2rect->property("y").toInt(), touch1.y());
+ QCOMPARE(touch3rect->property("x").toInt(), touch2.x() - 320);
+ QCOMPARE(touch3rect->property("y").toInt(), touch2.y());
+ QCOMPARE(touch4rect->property("x").toInt(), touch3.x() - 320);
+ QCOMPARE(touch4rect->property("y").toInt(), touch3.y());
+ QCOMPARE(touch5rect->property("x").toInt(), touch4.x() - 320);
+ QCOMPARE(touch5rect->property("y").toInt(), touch4.y());
+
+ // Release all
+ QTest::mouseRelease(window.data(), Qt::LeftButton, 0, mouse1);
+ QTest::touchEvent(window.data(), device).release(1, touch1).release(2, touch2).release(3, touch3).release(4, touch4);
+ }
+
+ dualmpta->setProperty("mouseEnabled", false);
+ {
+ QPoint mouse1(40,10);
+ QPoint touch1(10,10);
+ QPoint touch2(100,10);
+
+ touch1rect->setX(10);
+ touch1rect->setY(10);
+ touch2rect->setX(20);
+ touch2rect->setY(10);
+
+ // Start with mouse, move it, touch a point, move it, touch another.
+ // Mouse is ignored, both touch points are heeded.
+ QTest::mousePress(window.data(), Qt::LeftButton, 0, mouse1);
+ mouse1.setX(60);
+ QTest::mouseMove(window.data(), mouse1);
+ QCOMPARE(touch1rect->property("x").toInt(), 10);
+ QCOMPARE(touch1rect->property("y").toInt(), 10);
+
+ QTest::touchEvent(window.data(), device).press(1, touch1);
+ QCOMPARE(touch1rect->property("x").toInt(), touch1.x());
+ QCOMPARE(touch1rect->property("y").toInt(), touch1.y());
+ touch1.setY(150);
+ QTest::touchEvent(window.data(), device).move(1, touch1);
+ QCOMPARE(touch1rect->property("x").toInt(), touch1.x());
+ QCOMPARE(touch1rect->property("y").toInt(), touch1.y());
+ QTest::touchEvent(window.data(), device).press(2, touch2);
+ QCOMPARE(touch1rect->property("x").toInt(), touch1.x());
+ QCOMPARE(touch1rect->property("y").toInt(), touch1.y());
+ QCOMPARE(touch2rect->property("x").toInt(), touch2.x());
+ QCOMPARE(touch2rect->property("y").toInt(), touch2.y());
+
+ // Release all
+ QTest::mouseRelease(window.data(), Qt::LeftButton, 0, mouse1);
+ QTest::touchEvent(window.data(), device).release(1, touch1);
+ QTest::touchEvent(window.data(), device).release(2, touch2);
+ QCOMPARE(touch1rect->property("x").toInt(), touch1.x());
+ QCOMPARE(touch1rect->property("y").toInt(), touch1.y());
+ QCOMPARE(touch2rect->property("x").toInt(), touch2.x());
+ QCOMPARE(touch2rect->property("y").toInt(), touch2.y());
+ }
+}
+
// QTBUG-23327
void tst_QQuickMultiPointTouchArea::invisible()
{
@@ -841,6 +1084,48 @@ QQuickView *tst_QQuickMultiPointTouchArea::createAndShowView(const QString &file
return window;
}
+void tst_QQuickMultiPointTouchArea::mouseInteraction_data()
+{
+ QTest::addColumn<int>("buttons");
+ QTest::addColumn<int>("accept");
+
+ QTest::newRow("left") << (int) Qt::LeftButton << 1;
+ QTest::newRow("right") << (int) Qt::RightButton << 0;
+ QTest::newRow("middle") << (int) Qt::MiddleButton << 0;
+}
+
+void tst_QQuickMultiPointTouchArea::mouseInteraction()
+{
+ QFETCH(int, buttons);
+ QFETCH(int, accept);
+
+ QScopedPointer<QQuickView> view(createAndShowView("mouse.qml"));
+ QVERIFY(view->rootObject() != 0);
+
+ QQuickMultiPointTouchArea *area = qobject_cast<QQuickMultiPointTouchArea *>(view->rootObject());
+ QVERIFY(area != 0);
+ QQuickTouchPoint *point1 = view->rootObject()->findChild<QQuickTouchPoint*>("point1");
+ QCOMPARE(point1->pressed(), false);
+
+ QCOMPARE(area->property("touchCount").toInt(), 0);
+ QPoint p1 = QPoint(100, 100);
+ QTest::mousePress(view.data(), (Qt::MouseButton) buttons, 0, p1);
+ QCOMPARE(area->property("touchCount").toInt(), accept);
+ QCOMPARE(point1->pressed(), accept);
+ p1 += QPoint(10, 10);
+ QTest::mouseMove(view.data(), p1);
+ QCOMPARE(point1->pressed(), accept);
+ QCOMPARE(area->property("touchCount").toInt(), accept);
+ p1 += QPoint(10, 10);
+ QTest::mouseMove(view.data(), p1);
+ QCOMPARE(point1->pressed(), accept);
+ QCOMPARE(area->property("touchCount").toInt(), accept);
+ QTest::mouseRelease(view.data(), (Qt::MouseButton) buttons);
+ QCOMPARE(point1->pressed(), false);
+ QCOMPARE(area->property("touchCount").toInt(), 0);
+}
+
+
QTEST_MAIN(tst_QQuickMultiPointTouchArea)
#include "tst_qquickmultipointtoucharea.moc"