aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/quick/items/qquickflickable.cpp5
-rw-r--r--src/quick/items/qquickitem.cpp10
-rw-r--r--src/quick/items/qquickwindow.cpp34
-rw-r--r--src/quick/items/qquickwindow_p.h1
-rw-r--r--tests/auto/quick/qquickitem/tst_qquickitem.cpp15
-rw-r--r--tests/auto/quick/touchmouse/tst_touchmouse.cpp100
6 files changed, 147 insertions, 18 deletions
diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp
index 15627aad84..fa18d4aa30 100644
--- a/src/quick/items/qquickflickable.cpp
+++ b/src/quick/items/qquickflickable.cpp
@@ -2048,12 +2048,13 @@ bool QQuickFlickable::sendMouseEvent(QQuickItem *item, QMouseEvent *event)
if ((grabber && stealThisEvent && !grabber->keepMouseGrab() && grabber != this) || grabberDisabled) {
d->clearDelayedPress();
grabMouse();
+ } else if (d->delayedPressEvent) {
+ grabMouse();
}
- // Do not accept this event when filtering, as this would force the mouse grab to the child
const bool filtered = stealThisEvent || d->delayedPressEvent || grabberDisabled;
if (filtered) {
- event->setAccepted(false);
+ event->setAccepted(true);
}
return filtered;
} else if (d->lastPosTime != -1) {
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index a0329f7afc..f565fba1bb 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -6629,15 +6629,7 @@ void QQuickItem::grabMouse()
if (!d->window)
return;
QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(d->window);
- if (windowPriv->mouseGrabberItem == this)
- return;
-
- QQuickItem *oldGrabber = windowPriv->mouseGrabberItem;
- windowPriv->mouseGrabberItem = this;
- if (oldGrabber) {
- QEvent ev(QEvent::UngrabMouse);
- d->window->sendEvent(oldGrabber, &ev);
- }
+ windowPriv->setMouseGrabber(this);
}
/*!
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index dfc70d7e68..f355afcea5 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -599,6 +599,28 @@ bool QQuickWindowPrivate::translateTouchToMouse(QQuickItem *item, QTouchEvent *e
return false;
}
+void QQuickWindowPrivate::setMouseGrabber(QQuickItem *grabber)
+{
+ Q_Q(QQuickWindow);
+ if (mouseGrabberItem == grabber)
+ return;
+
+ QQuickItem *oldGrabber = mouseGrabberItem;
+ mouseGrabberItem = grabber;
+
+ if (touchMouseId != -1) {
+ // update the touch item for mouse touch id to the new grabber
+ itemForTouchPointId.remove(touchMouseId);
+ if (grabber)
+ itemForTouchPointId[touchMouseId] = grabber;
+ }
+
+ if (oldGrabber) {
+ QEvent ev(QEvent::UngrabMouse);
+ q->sendEvent(oldGrabber, &ev);
+ }
+}
+
void QQuickWindowPrivate::transformTouchPoints(QList<QTouchEvent::TouchPoint> &touchPoints, const QTransform &transform)
{
QMatrix4x4 transformMatrix(transform);
@@ -1221,8 +1243,11 @@ bool QQuickWindow::event(QEvent *e)
case QEvent::TouchEnd: {
QTouchEvent *touch = static_cast<QTouchEvent*>(e);
d->translateTouchEvent(touch);
- // return in order to avoid the QWindow::event below
- return d->deliverTouchEvent(touch);
+ d->deliverTouchEvent(touch);
+ // we consume all touch events ourselves to avoid duplicate
+ // mouse delivery by QtGui mouse synthesis
+ e->accept();
+ return true;
}
break;
case QEvent::TouchCancel:
@@ -1776,7 +1801,10 @@ bool QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QTouchEv
// First check whether the parent wants to be a filter,
// and if the parent accepts the event we are done.
if (sendFilteredTouchEvent(item->parentItem(), item, event)) {
- event->accept();
+ // If the touch was accepted (regardless by whom or in what form),
+ // update acceptedNewPoints
+ foreach (int id, matchingNewPoints)
+ acceptedNewPoints->insert(id);
return true;
}
diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h
index c23745b5f1..418633b6ac 100644
--- a/src/quick/items/qquickwindow_p.h
+++ b/src/quick/items/qquickwindow_p.h
@@ -127,6 +127,7 @@ public:
QPointF lastMousePosition;
bool translateTouchToMouse(QQuickItem *item, QTouchEvent *event);
void translateTouchEvent(QTouchEvent *touchEvent);
+ void setMouseGrabber(QQuickItem *grabber);
static void transformTouchPoints(QList<QTouchEvent::TouchPoint> &touchPoints, const QTransform &transform);
static QMouseEvent *cloneMouseEvent(QMouseEvent *event, QPointF *transformedLocalPos = 0);
bool deliverInitialMousePressEvent(QQuickItem *, QMouseEvent *);
diff --git a/tests/auto/quick/qquickitem/tst_qquickitem.cpp b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
index 2c6dcd72ba..ad3c4fc208 100644
--- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp
+++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
@@ -1310,7 +1310,10 @@ void tst_qquickitem::touchEventAcceptIgnore()
bool accepted = window.event(&event);
QVERIFY(item->touchEventReached);
- QCOMPARE(accepted && event.isAccepted(), itemSupportsTouch);
+
+ // always true because QtQuick always eats touch events so as to not
+ // allow QtGui to synthesise them for us.
+ QCOMPARE(accepted && event.isAccepted(), true);
}
{
QTouchEvent::TouchPoint point;
@@ -1330,7 +1333,10 @@ void tst_qquickitem::touchEventAcceptIgnore()
bool accepted = window.event(&event);
QCOMPARE(item->touchEventReached, itemSupportsTouch);
- QCOMPARE(accepted && event.isAccepted(), itemSupportsTouch);
+
+ // always true because QtQuick always eats touch events so as to not
+ // allow QtGui to synthesise them for us.
+ QCOMPARE(accepted && event.isAccepted(), true);
}
{
QTouchEvent::TouchPoint point;
@@ -1350,7 +1356,10 @@ void tst_qquickitem::touchEventAcceptIgnore()
bool accepted = window.event(&event);
QCOMPARE(item->touchEventReached, itemSupportsTouch);
- QCOMPARE(accepted && event.isAccepted(), itemSupportsTouch);
+
+ // always true because QtQuick always eats touch events so as to not
+ // allow QtGui to synthesise them for us.
+ QCOMPARE(accepted && event.isAccepted(), true);
}
}
diff --git a/tests/auto/quick/touchmouse/tst_touchmouse.cpp b/tests/auto/quick/touchmouse/tst_touchmouse.cpp
index 6cf0aa4749..5b4ad0ffa3 100644
--- a/tests/auto/quick/touchmouse/tst_touchmouse.cpp
+++ b/tests/auto/quick/touchmouse/tst_touchmouse.cpp
@@ -154,6 +154,7 @@ private slots:
void mouseOverTouch();
void buttonOnFlickable();
+ void buttonOnDelayedPressFlickable();
void buttonOnTouch();
void pinchOnFlickable();
@@ -162,9 +163,22 @@ private slots:
void tapOnDismissiveTopMouseAreaClicksBottomOne();
+protected:
+ bool eventFilter(QObject *, QEvent *event)
+ {
+ if (event->type() == QEvent::MouseButtonPress ||
+ event->type() == QEvent::MouseMove ||
+ event->type() == QEvent::MouseButtonRelease) {
+ QMouseEvent *me = static_cast<QMouseEvent*>(event);
+ filteredEventList.append(Event(me->type(), me->pos(), me->globalPos()));
+ }
+ return false;
+ }
+
private:
QQuickView *createView();
QTouchDevice *device;
+ QList<Event> filteredEventList;
};
QQuickView *tst_TouchMouse::createView()
@@ -496,7 +510,7 @@ void tst_TouchMouse::buttonOnFlickable()
QCOMPARE(eventItem1->eventList.size(), 0);
QPoint p1 = QPoint(20, 130);
QTest::touchEvent(window, device).press(0, p1, window);
- QCOMPARE(eventItem1->eventList.size(), 2);
+ QTRY_COMPARE(eventItem1->eventList.size(), 2);
QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
QTest::touchEvent(window, device).release(0, p1, window);
@@ -559,12 +573,96 @@ void tst_TouchMouse::buttonOnFlickable()
QCOMPARE(eventItem1->eventList.at(3).type, QEvent::MouseMove);
QCOMPARE(windowPriv->mouseGrabberItem, flickable);
+ QCOMPARE(windowPriv->touchMouseId, 0);
+ QCOMPARE(windowPriv->itemForTouchPointId[0], flickable);
QVERIFY(flickable->isMovingVertically());
QTest::touchEvent(window, device).release(0, p3, window);
delete window;
}
+void tst_TouchMouse::buttonOnDelayedPressFlickable()
+{
+ // flickable - height 500 / 1000
+ // - eventItem1 y: 100, height 100
+ // - eventItem2 y: 300, height 100
+
+ qApp->setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, true);
+ filteredEventList.clear();
+
+ QQuickView *window = createView();
+
+ window->setSource(testFileUrl("buttononflickable.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+ window->requestActivate();
+ QVERIFY(QTest::qWaitForWindowActive(window));
+ QVERIFY(window->rootObject() != 0);
+
+ QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>("flickable");
+ QVERIFY(flickable);
+
+ window->installEventFilter(this);
+
+ flickable->setPressDelay(60);
+
+ // should a mouse area button be clickable on top of flickable? yes :)
+ EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
+ QVERIFY(eventItem1);
+ eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
+ eventItem1->acceptMouse = true;
+
+ // should a touch button be touchable on top of flickable? yes :)
+ EventItem *eventItem2 = window->rootObject()->findChild<EventItem*>("eventItem2");
+ QVERIFY(eventItem2);
+ QCOMPARE(eventItem2->eventList.size(), 0);
+ eventItem2->acceptTouch = true;
+
+ // wait to avoid getting a double click event
+ QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
+
+ // check that flickable moves - mouse button
+ QCOMPARE(eventItem1->eventList.size(), 0);
+ QPoint p1 = QPoint(10, 110);
+ QTest::touchEvent(window, device).press(0, p1, window);
+ // Flickable initially steals events
+ QCOMPARE(eventItem1->eventList.size(), 0);
+ // but we'll get the delayed mouse press after a delay
+ QTRY_COMPARE(eventItem1->eventList.size(), 1);
+ QCOMPARE(eventItem1->eventList.at(0).type, QEvent::MouseButtonPress);
+
+ // eventItem1 should have the mouse grab, and have moved the itemForTouchPointId
+ // for the touchMouseId to the new grabber.
+ QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window);
+ QCOMPARE(windowPriv->touchMouseId, 0);
+ QCOMPARE(windowPriv->itemForTouchPointId[0], eventItem1);
+ QCOMPARE(windowPriv->mouseGrabberItem, eventItem1);
+
+ p1 += QPoint(0, -10);
+ QPoint p2 = p1 + QPoint(0, -10);
+ QPoint p3 = p2 + QPoint(0, -10);
+ QTest::qWait(10);
+ QTest::touchEvent(window, device).move(0, p1, window);
+ QTest::qWait(10);
+ QTest::touchEvent(window, device).move(0, p2, window);
+ QTest::qWait(10);
+ QTest::touchEvent(window, device).move(0, p3, window);
+ QVERIFY(flickable->isMovingVertically());
+
+ // flickable should have the mouse grab, and have moved the itemForTouchPointId
+ // for the touchMouseId to the new grabber.
+ QCOMPARE(windowPriv->mouseGrabberItem, flickable);
+ QCOMPARE(windowPriv->touchMouseId, 0);
+ QCOMPARE(windowPriv->itemForTouchPointId[0], flickable);
+
+ QTest::touchEvent(window, device).release(0, p3, window);
+
+ // We should not have received any synthesised mouse events from Qt gui.
+ QCOMPARE(filteredEventList.count(), 0);
+
+ delete window;
+}
+
void tst_TouchMouse::buttonOnTouch()
{
// 400x800