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);
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:
// 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;
}
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;
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;
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);
}
}
void mouseOverTouch();
void buttonOnFlickable();
+ void buttonOnDelayedPressFlickable();
void buttonOnTouch();
void pinchOnFlickable();
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()
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);
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