/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/


#include <QtTest/QtTest>
#include <QDebug>

#include <QtGui/qstylehints.h>
#include <private/qdebug_p.h>

#include <QtQuick/qquickview.h>
#include <QtQuick/qquickitem.h>
#include <QtQuick/private/qquickevents_p_p.h>
#include <QtQuick/private/qquickmousearea_p.h>
#include <QtQuick/private/qquickmultipointtoucharea_p.h>
#include <QtQuick/private/qquickpincharea_p.h>
#include <QtQuick/private/qquickflickable_p.h>
#include <QtQuick/private/qquickwindow_p.h>

#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlproperty.h>

#include "../../shared/util.h"
#include "../shared/viewtestutil.h"

Q_LOGGING_CATEGORY(lcTests, "qt.quick.tests")

struct Event
{
    Event(QEvent::Type t, QPoint mouse, QPoint global)
        :type(t), mousePos(mouse), mousePosGlobal(global)
    {}

    Event(QEvent::Type t, QList<QTouchEvent::TouchPoint> touch)
        :type(t), points(touch)
    {}

    QEvent::Type type;
    QPoint mousePos;
    QPoint mousePosGlobal;
    QList<QTouchEvent::TouchPoint> points;
};

#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const struct Event &event) {
    QDebugStateSaver saver(dbg);
    dbg.nospace();
    dbg << "Event(";
    QtDebugUtils::formatQEnum(dbg, event.type);
    if (event.points.isEmpty())
        dbg << " @ " << event.mousePos << " global " << event.mousePosGlobal;
    else
        dbg << ", " << event.points.count() << " touchpoints: " << event.points;
    dbg << ')';
    return dbg;
}
#endif

class EventItem : public QQuickItem
{
    Q_OBJECT

Q_SIGNALS:
    void onTouchEvent(QQuickItem *receiver);

public:
    EventItem(QQuickItem *parent = nullptr)
        : QQuickItem(parent)
    {
        setAcceptedMouseButtons(Qt::LeftButton);
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
        setAcceptTouchEvents(true);
#endif
    }

    void touchEvent(QTouchEvent *event)
    {
        eventList.append(Event(event->type(), event->touchPoints()));
        QList<QTouchEvent::TouchPoint> tps = event->touchPoints();
        Q_ASSERT(!tps.isEmpty());
        point0 = tps.first().id();
        event->setAccepted(acceptTouch);
        emit onTouchEvent(this);
    }
    void mousePressEvent(QMouseEvent *event)
    {
        eventList.append(Event(event->type(), event->pos(), event->globalPos()));
        event->setAccepted(acceptMouse);
    }
    void mouseMoveEvent(QMouseEvent *event)
    {
        eventList.append(Event(event->type(), event->pos(), event->globalPos()));
        event->setAccepted(acceptMouse);
    }
    void mouseReleaseEvent(QMouseEvent *event)
    {
        eventList.append(Event(event->type(), event->pos(), event->globalPos()));
        event->setAccepted(acceptMouse);
    }
    void mouseDoubleClickEvent(QMouseEvent *event)
    {
        eventList.append(Event(event->type(), event->pos(), event->globalPos()));
        event->setAccepted(acceptMouse);
    }

    void mouseUngrabEvent()
    {
        eventList.append(Event(QEvent::UngrabMouse, QPoint(0,0), QPoint(0,0)));
    }

    void touchUngrabEvent()
    {
        ++touchUngrabCount;
    }

    bool event(QEvent *event) {
        return QQuickItem::event(event);
    }

    QList<Event> eventList;
    int touchUngrabCount = 0;
    bool acceptMouse = false;
    bool acceptTouch = false;
    bool filterTouch = false; // when used as event filter

    bool eventFilter(QObject *, QEvent *event)
    {
        if (event->type() == QEvent::TouchBegin ||
                event->type() == QEvent::TouchUpdate ||
                event->type() == QEvent::TouchCancel ||
                event->type() == QEvent::TouchEnd) {
            QTouchEvent *touch = static_cast<QTouchEvent*>(event);
            eventList.append(Event(event->type(), touch->touchPoints()));
            QList<QTouchEvent::TouchPoint> tps = touch->touchPoints();
            Q_ASSERT(!tps.isEmpty());
            point0 = tps.first().id();
            if (filterTouch)
                event->accept();
            return true;
        }
        return false;
    }
    int point0 = -1;
};

class tst_TouchMouse : public QQmlDataTest
{
    Q_OBJECT
public:
    tst_TouchMouse()
        :device(QTest::createTouchDevice())
    {}

private slots:
    void initTestCase();

    void simpleTouchEvent_data();
    void simpleTouchEvent();
    void testEventFilter();
    void mouse();
    void touchOverMouse();
    void mouseOverTouch();

    void buttonOnFlickable();
    void touchButtonOnFlickable();
    void buttonOnDelayedPressFlickable_data();
    void buttonOnDelayedPressFlickable();
    void buttonOnTouch();

    void pinchOnFlickable();
    void flickableOnPinch();
    void mouseOnFlickableOnPinch();

    void tapOnDismissiveTopMouseAreaClicksBottomOne();

    void touchGrabCausesMouseUngrab();
    void touchPointDeliveryOrder();

    void hoverEnabled();
    void implicitUngrab();

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()
{
    QQuickView *window = new QQuickView(nullptr);
    return window;
}

void tst_TouchMouse::initTestCase()
{
    QQmlDataTest::initTestCase();
    qmlRegisterType<EventItem>("Qt.test", 1, 0, "EventItem");
}

void tst_TouchMouse::simpleTouchEvent_data()
{
    QTest::addColumn<bool>("synthMouse"); // AA_SynthesizeMouseForUnhandledTouchEvents
    QTest::newRow("no synth") << false;
    QTest::newRow("synth") << true;
}

void tst_TouchMouse::simpleTouchEvent()
{
    QFETCH(bool, synthMouse);
    qApp->setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, synthMouse);

    QScopedPointer<QQuickView> window(createView());
    window->setSource(testFileUrl("singleitem.qml"));
    window->show();
    QQuickViewTestUtil::centerOnScreen(window.data());
    QVERIFY(QTest::qWaitForWindowActive(window.data()));
    QVERIFY(window->rootObject() != nullptr);

    EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
    QVERIFY(eventItem1);

    // Do not accept touch or mouse
    QPoint p1;
    p1 = QPoint(20, 20);
    QTest::touchEvent(window.data(), device).press(0, p1, window.data());
    QQuickTouchUtils::flush(window.data());
    // Get a touch and then mouse event offered
    QCOMPARE(eventItem1->eventList.size(), synthMouse ? 2 : 1);
    QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
    p1 += QPoint(10, 0);
    QTest::touchEvent(window.data(), device).move(0, p1, window.data());
    QQuickTouchUtils::flush(window.data());
    // Not accepted, no updates
    QCOMPARE(eventItem1->eventList.size(), synthMouse ? 2 : 1);
    QTest::touchEvent(window.data(), device).release(0, p1, window.data());
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(eventItem1->eventList.size(), synthMouse ? 2 : 1);
    eventItem1->eventList.clear();

    // Accept touch
    eventItem1->acceptTouch = true;
    p1 = QPoint(20, 20);
    QTest::touchEvent(window.data(), device).press(0, p1, window.data());
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(eventItem1->eventList.size(), 1);
    p1 += QPoint(10, 0);
    QTest::touchEvent(window.data(), device).move(0, p1, window.data());
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(eventItem1->eventList.size(), 2);
    QTest::touchEvent(window.data(), device).release(0, p1, window.data());
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(eventItem1->eventList.size(), 3);
    eventItem1->eventList.clear();

    // wait to avoid getting a double click event
    QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);

    // Accept mouse
    eventItem1->acceptTouch = false;
    eventItem1->acceptMouse = true;
    eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
    p1 = QPoint(20, 20);
    QTest::touchEvent(window.data(), device).press(0, p1, window.data());
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(eventItem1->eventList.size(), synthMouse ? 2 : 1);
    QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
    if (synthMouse)
        QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
    QCOMPARE(window->mouseGrabberItem(), synthMouse ? eventItem1 : nullptr);

    QPoint localPos = eventItem1->mapFromScene(p1).toPoint();
    QPoint globalPos = window->mapToGlobal(p1);
    QPoint scenePos = p1; // item is at 0,0
    QCOMPARE(eventItem1->eventList.at(0).points.at(0).pos().toPoint(), localPos);
    QCOMPARE(eventItem1->eventList.at(0).points.at(0).scenePos().toPoint(), scenePos);
    QCOMPARE(eventItem1->eventList.at(0).points.at(0).screenPos().toPoint(), globalPos);
    if (synthMouse) {
        QCOMPARE(eventItem1->eventList.at(1).mousePos, localPos);
        QCOMPARE(eventItem1->eventList.at(1).mousePosGlobal, globalPos);
    }

    p1 += QPoint(10, 0);
    QTest::touchEvent(window.data(), device).move(0, p1, window.data());
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(eventItem1->eventList.size(), synthMouse ? 4 : 1);
    if (synthMouse) {
        QCOMPARE(eventItem1->eventList.at(2).type, QEvent::TouchUpdate);
        QCOMPARE(eventItem1->eventList.at(3).type, QEvent::MouseMove);
    }
    // else, if there was no synth-mouse and we didn't accept the touch,
    // TouchUpdate was not sent to eventItem1 either.
    QTest::touchEvent(window.data(), device).release(0, p1, window.data());
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(eventItem1->eventList.size(), synthMouse ? 7 : 1);
    if (synthMouse) {
        QCOMPARE(eventItem1->eventList.at(4).type, QEvent::TouchEnd);
        QCOMPARE(eventItem1->eventList.at(5).type, QEvent::MouseButtonRelease);
        QCOMPARE(eventItem1->eventList.at(6).type, QEvent::UngrabMouse);
    }
    // else, if there was no synth-mouse and we didn't accept the touch,
    // TouchEnd was not sent to eventItem1 either.
    eventItem1->eventList.clear();

    // wait to avoid getting a double click event
    QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);

    // Accept mouse buttons but not the event
    eventItem1->acceptTouch = false;
    eventItem1->acceptMouse = false;
    eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
    p1 = QPoint(20, 20);
    QTest::touchEvent(window.data(), device).press(0, p1, window.data());
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(eventItem1->eventList.size(), synthMouse ? 2 : 1);
    QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
    if (synthMouse)
        QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
    p1 += QPoint(10, 0);
    QTest::touchEvent(window.data(), device).move(0, p1, window.data());
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(eventItem1->eventList.size(), synthMouse ? 2 : 1);
    QTest::touchEvent(window.data(), device).release(0, p1, window.data());
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(eventItem1->eventList.size(), synthMouse ? 2 : 1);
    eventItem1->eventList.clear();

    // wait to avoid getting a double click event
    QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);

    // Accept touch and mouse
    eventItem1->acceptTouch = true;
    eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
    p1 = QPoint(20, 20);
    QTest::touchEvent(window.data(), device).press(0, p1, window.data());
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(eventItem1->eventList.size(), 1);
    QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
    p1 += QPoint(10, 0);
    QTest::touchEvent(window.data(), device).move(0, p1, window.data());
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(eventItem1->eventList.size(), 2);
    QCOMPARE(eventItem1->eventList.at(1).type, QEvent::TouchUpdate);
    QTest::touchEvent(window.data(), device).release(0, p1, window.data());
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(eventItem1->eventList.size(), 3);
    QCOMPARE(eventItem1->eventList.at(2).type, QEvent::TouchEnd);
    eventItem1->eventList.clear();
}

void tst_TouchMouse::testEventFilter()
{
//    // install event filter on item and see that it can grab events
//    QScopedPointer<QQuickView> window(createView());
//    window->setSource(testFileUrl("singleitem.qml"));
//    window->show();
//    QQuickViewTestUtil::centerOnScreen(window.data());
//    QVERIFY(QTest::qWaitForWindowActive(window.data()));
//    QVERIFY(window->rootObject() != 0);

//    EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
//    QVERIFY(eventItem1);
//    eventItem1->acceptTouch = true;

//    EventItem *filter = new EventItem;
//    filter->filterTouch = true;
//    eventItem1->installEventFilter(filter);

//    QPoint p1 = QPoint(20, 20);
//    QTest::touchEvent(window.data(), device).press(0, p1, window.data());
//    // QEXPECT_FAIL("", "We do not implement event filters correctly", Abort);
//    QCOMPARE(eventItem1->eventList.size(), 0);
//    QCOMPARE(filter->eventList.size(), 1);
//    QTest::touchEvent(window.data(), device).release(0, p1, window.data());
//    QCOMPARE(eventItem1->eventList.size(), 0);
//    QCOMPARE(filter->eventList.size(), 2);

//    delete filter;
}

void tst_TouchMouse::mouse()
{
    // eventItem1
    //   - eventItem2

    QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
    QScopedPointer<QQuickView> window(createView());
    window->setSource(testFileUrl("twoitems.qml"));
    window->show();
    QQuickViewTestUtil::centerOnScreen(window.data());
    QVERIFY(QTest::qWaitForWindowActive(window.data()));
    QVERIFY(window->rootObject() != nullptr);

    EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
    QVERIFY(eventItem1);
    EventItem *eventItem2 = window->rootObject()->findChild<EventItem*>("eventItem2");
    QVERIFY(eventItem2);

    // bottom item likes mouse, top likes touch
    eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
    eventItem1->acceptMouse = true;
    // item 2 doesn't accept anything, thus it sees a touch pass by
    QPoint p1 = QPoint(30, 30);
    QTest::touchEvent(window.data(), device).press(0, p1, window.data());
    QQuickTouchUtils::flush(window.data());

    QCOMPARE(eventItem1->eventList.size(), 2);
    QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
    QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
}

void tst_TouchMouse::touchOverMouse()
{
    // eventItem1
    //   - eventItem2

    QScopedPointer<QQuickView> window(createView());
    window->setSource(testFileUrl("twoitems.qml"));
    window->show();
    QQuickViewTestUtil::centerOnScreen(window.data());
    QVERIFY(QTest::qWaitForWindowActive(window.data()));
    QVERIFY(window->rootObject() != nullptr);

    EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
    QVERIFY(eventItem1);
    EventItem *eventItem2 = window->rootObject()->findChild<EventItem*>("eventItem2");
    QVERIFY(eventItem2);

    // bottom item likes mouse, top likes touch
    eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
    eventItem2->acceptTouch = true;

    QCOMPARE(eventItem1->eventList.size(), 0);
    QPoint p1 = QPoint(20, 20);
    QTest::touchEvent(window.data(), device).press(0, p1, window.data());
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(eventItem1->eventList.size(), 0);
    QCOMPARE(eventItem2->eventList.size(), 1);
    QCOMPARE(eventItem2->eventList.at(0).type, QEvent::TouchBegin);
    p1 += QPoint(10, 0);
    QTest::touchEvent(window.data(), device).move(0, p1, window.data());
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(eventItem2->eventList.size(), 2);
    QCOMPARE(eventItem2->eventList.at(1).type, QEvent::TouchUpdate);
    QTest::touchEvent(window.data(), device).release(0, p1, window.data());
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(eventItem2->eventList.size(), 3);
    QCOMPARE(eventItem2->eventList.at(2).type, QEvent::TouchEnd);
    eventItem2->eventList.clear();
}

void tst_TouchMouse::mouseOverTouch()
{
    // eventItem1
    //   - eventItem2

    QScopedPointer<QQuickView> window(createView());
    window->setSource(testFileUrl("twoitems.qml"));
    window->show();
    QQuickViewTestUtil::centerOnScreen(window.data());
    QVERIFY(QTest::qWaitForWindowActive(window.data()));
    QVERIFY(window->rootObject() != nullptr);

    EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
    QVERIFY(eventItem1);
    EventItem *eventItem2 = window->rootObject()->findChild<EventItem*>("eventItem2");
    QVERIFY(eventItem2);

    // bottom item likes mouse, top likes touch
    eventItem1->acceptTouch = true;
    eventItem2->setAcceptedMouseButtons(Qt::LeftButton);
    eventItem2->acceptMouse = true;

    QPoint p1 = QPoint(20, 20);
    QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
    QTest::touchEvent(window.data(), device).press(0, p1, window.data());
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(eventItem1->eventList.size(), 0);
    QCOMPARE(eventItem2->eventList.size(), 2);
    QCOMPARE(eventItem2->eventList.at(0).type, QEvent::TouchBegin);
    QCOMPARE(eventItem2->eventList.at(1).type, QEvent::MouseButtonPress);


//    p1 += QPoint(10, 0);
//    QTest::touchEvent(window.data(), device).move(0, p1, window.data());
//    QCOMPARE(eventItem2->eventList.size(), 1);
//    QTest::touchEvent(window.data(), device).release(0, p1, window.data());
//    QCOMPARE(eventItem2->eventList.size(), 1);
//    eventItem2->eventList.clear();
}

void tst_TouchMouse::buttonOnFlickable()
{
    // flickable - height 500 / 1000
    //   - eventItem1 y: 100, height 100
    //   - eventItem2 y: 300, height 100

    QScopedPointer<QQuickView> window(createView());
    window->setSource(testFileUrl("buttononflickable.qml"));
    window->show();
    QQuickViewTestUtil::centerOnScreen(window.data());
    QVERIFY(QTest::qWaitForWindowActive(window.data()));
    QVERIFY(window->rootObject() != nullptr);

    QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>("flickable");
    QVERIFY(flickable);

    // 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 buttons are clickable
    // mouse button
    QCOMPARE(eventItem1->eventList.size(), 0);
    QPoint p1 = QPoint(20, 130);
    QTest::touchEvent(window.data(), device).press(0, p1, window.data());
    QQuickTouchUtils::flush(window.data());
    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.data(), device).release(0, p1, window.data());
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(eventItem1->eventList.size(), 5);
    QCOMPARE(eventItem1->eventList.at(2).type, QEvent::TouchEnd);
    QCOMPARE(eventItem1->eventList.at(3).type, QEvent::MouseButtonRelease);
    QCOMPARE(eventItem1->eventList.at(4).type, QEvent::UngrabMouse);
    eventItem1->eventList.clear();

    // touch button
    p1 = QPoint(10, 310);
    QTest::touchEvent(window.data(), device).press(0, p1, window.data());
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(eventItem2->eventList.size(), 1);
    QCOMPARE(eventItem2->eventList.at(0).type, QEvent::TouchBegin);
    QTest::touchEvent(window.data(), device).release(0, p1, window.data());
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(eventItem2->eventList.size(), 2);
    QCOMPARE(eventItem2->eventList.at(1).type, QEvent::TouchEnd);
    QCOMPARE(eventItem1->eventList.size(), 0);
    eventItem2->eventList.clear();

    // wait to avoid getting a double click event
    QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);

    // click above button, no events please
    p1 = QPoint(10, 90);
    QTest::touchEvent(window.data(), device).press(0, p1, window.data());
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(eventItem1->eventList.size(), 0);
    QTest::touchEvent(window.data(), device).release(0, p1, window.data());
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(eventItem1->eventList.size(), 0);
    eventItem1->eventList.clear();

    // 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);
    p1 = QPoint(10, 110);
    QTest::touchEvent(window.data(), device).press(0, p1, window.data());
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(eventItem1->eventList.size(), 2);
    QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
    QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);

    QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window.data());
    QVERIFY(windowPriv->touchMouseId != -1);
    auto pointerEvent = windowPriv->pointerEventInstance(QQuickPointerDevice::touchDevices().at(0));
    QCOMPARE(pointerEvent->point(0)->exclusiveGrabber(), eventItem1);
    QCOMPARE(window->mouseGrabberItem(), eventItem1);

    int dragDelta = -qApp->styleHints()->startDragDistance();
    p1 += QPoint(0, dragDelta);
    QPoint p2 = p1 + QPoint(0, dragDelta);
    QPoint p3 = p2 + QPoint(0, dragDelta);
    QQuickTouchUtils::flush(window.data());
    QTest::touchEvent(window.data(), device).move(0, p1, window.data());
    QQuickTouchUtils::flush(window.data());
    QTest::touchEvent(window.data(), device).move(0, p2, window.data());
    QQuickTouchUtils::flush(window.data());
    QTest::touchEvent(window.data(), device).move(0, p3, window.data());
    QQuickTouchUtils::flush(window.data());

    // we cannot really know when the events get grabbed away
    QVERIFY(eventItem1->eventList.size() >= 4);
    QCOMPARE(eventItem1->eventList.at(2).type, QEvent::TouchUpdate);
    QCOMPARE(eventItem1->eventList.at(3).type, QEvent::MouseMove);

    QCOMPARE(window->mouseGrabberItem(), flickable);
    QVERIFY(windowPriv->touchMouseId != -1);
    QCOMPARE(pointerEvent->point(0)->exclusiveGrabber(), flickable);
    QVERIFY(flickable->isMovingVertically());

    QTest::touchEvent(window.data(), device).release(0, p3, window.data());
    QQuickTouchUtils::flush(window.data());
}

void tst_TouchMouse::touchButtonOnFlickable()
{
    // flickable - height 500 / 1000
    //   - eventItem1 y: 100, height 100
    //   - eventItem2 y: 300, height 100

    QScopedPointer<QQuickView> window(createView());
    window->setSource(testFileUrl("buttononflickable.qml"));
    window->show();
    QQuickViewTestUtil::centerOnScreen(window.data());
    QVERIFY(QTest::qWaitForWindowActive(window.data()));
    QVERIFY(window->rootObject() != nullptr);

    QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>("flickable");
    QVERIFY(flickable);

    EventItem *eventItem2 = window->rootObject()->findChild<EventItem*>("eventItem2");
    QVERIFY(eventItem2);
    QCOMPARE(eventItem2->eventList.size(), 0);
    eventItem2->acceptTouch = true;

    // press via touch, then drag: check that flickable moves and that the button gets ungrabbed
    QCOMPARE(eventItem2->eventList.size(), 0);
    QPoint p1 = QPoint(10, 310);
    QTest::touchEvent(window.data(), device).press(0, p1, window.data());
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(eventItem2->eventList.size(), 1);
    QCOMPARE(eventItem2->eventList.at(0).type, QEvent::TouchBegin);

    QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window.data());
    QVERIFY(windowPriv->touchMouseId == -1);
    auto pointerEvent = windowPriv->pointerEventInstance(QQuickPointerDevice::touchDevices().at(0));
    QCOMPARE(pointerEvent->point(0)->grabberItem(), eventItem2);
    QCOMPARE(window->mouseGrabberItem(), nullptr);

    int dragDelta = qApp->styleHints()->startDragDistance() * -0.7;
    p1 += QPoint(0, dragDelta);
    QPoint p2 = p1 + QPoint(0, dragDelta);
    QPoint p3 = p2 + QPoint(0, dragDelta);

    QQuickTouchUtils::flush(window.data());
    QTest::touchEvent(window.data(), device).move(0, p1, window.data());
    QQuickTouchUtils::flush(window.data());
    QTest::touchEvent(window.data(), device).move(0, p2, window.data());
    QQuickTouchUtils::flush(window.data());
    QTest::touchEvent(window.data(), device).move(0, p3, window.data());
    QQuickTouchUtils::flush(window.data());

    QTRY_COMPARE(eventItem2->touchUngrabCount, 1);
    QVERIFY(eventItem2->eventList.size() > 2);
    QCOMPARE(eventItem2->eventList.at(1).type, QEvent::TouchUpdate);
    QCOMPARE(window->mouseGrabberItem(), flickable);
    QVERIFY(windowPriv->touchMouseId != -1);
    QCOMPARE(pointerEvent->point(0)->grabberItem(), flickable);
    QVERIFY(flickable->isMovingVertically());

    QTest::touchEvent(window.data(), device).release(0, p3, window.data());
    QQuickTouchUtils::flush(window.data());
}

void tst_TouchMouse::buttonOnDelayedPressFlickable_data()
{
    QTest::addColumn<bool>("scrollBeforeDelayIsOver");
    QTest::addColumn<bool>("releaseBeforeDelayIsOver");

    // the item should never see the event,
    // due to the pressDelay which never delivers if we start moving
    QTest::newRow("scroll before press delay is over") << true << false;

    // after release, the item should see the press and release via event replay (QTBUG-61144)
    QTest::newRow("release before press delay is over") << false << true;

    // wait until the "button" sees the press but then
    // start moving: the button gets a press and cancel event
    QTest::newRow("scroll after press delay is over") << false << false;
}

void tst_TouchMouse::buttonOnDelayedPressFlickable()
{
    // flickable - height 500 / 1000
    //   - eventItem1 y: 100, height 100
    //   - eventItem2 y: 300, height 100
    QFETCH(bool, scrollBeforeDelayIsOver);
    QFETCH(bool, releaseBeforeDelayIsOver);

    qApp->setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, true);
    filteredEventList.clear();

    QScopedPointer<QQuickView> window(createView());
    window->setSource(testFileUrl("buttononflickable.qml"));
    window->show();
    QQuickViewTestUtil::centerOnScreen(window.data());
    QVERIFY(QTest::qWaitForWindowActive(window.data()));
    QVERIFY(window->rootObject() != nullptr);

    QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>("flickable");
    QVERIFY(flickable);

    window->installEventFilter(this);

    // wait 600 ms before letting the child see the press event
    flickable->setPressDelay(600);

    // 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);
    QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window.data());
    QCOMPARE(windowPriv->touchMouseId, -1); // no grabber

    // touch press
    QPoint p1 = QPoint(10, 110);
    QPoint pEnd = p1;
    QTest::touchEvent(window.data(), device).press(0, p1, window.data());
    QQuickTouchUtils::flush(window.data());

    if (scrollBeforeDelayIsOver || releaseBeforeDelayIsOver) {
        // no events yet: press is delayed
        QCOMPARE(eventItem1->eventList.size(), 0);
    } else {
        // wait until the button sees the press
        QTRY_COMPARE(eventItem1->eventList.size(), 1);
        QCOMPARE(eventItem1->eventList.at(0).type, QEvent::MouseButtonPress);
        QCOMPARE(filteredEventList.count(), 1);
    }

    if (!releaseBeforeDelayIsOver) {
        // move the touchpoint: try to flick
        p1 += QPoint(0, -10);
        QPoint p2 = p1 + QPoint(0, -10);
        pEnd = p2 + QPoint(0, -10);
        QQuickTouchUtils::flush(window.data());
        QTest::touchEvent(window.data(), device).move(0, p1, window.data());
        QQuickTouchUtils::flush(window.data());
        QTest::touchEvent(window.data(), device).move(0, p2, window.data());
        QQuickTouchUtils::flush(window.data());
        QTest::touchEvent(window.data(), device).move(0, pEnd, window.data());
        QQuickTouchUtils::flush(window.data());
        QTRY_VERIFY(flickable->isMovingVertically());

        if (scrollBeforeDelayIsOver) {
            QCOMPARE(eventItem1->eventList.size(), 0);
            QCOMPARE(filteredEventList.count(), 0);
        } else {
            // see at least press, move and ungrab
            QTRY_VERIFY(eventItem1->eventList.size() > 2);
            QCOMPARE(eventItem1->eventList.at(0).type, QEvent::MouseButtonPress);
            QCOMPARE(eventItem1->eventList.last().type, QEvent::UngrabMouse);
            QCOMPARE(filteredEventList.count(), 1);
        }

        // flickable should have the mouse grab, and have moved the itemForTouchPointId
        // for the touchMouseId to the new grabber.
        QCOMPARE(window->mouseGrabberItem(), flickable);
        QVERIFY(windowPriv->touchMouseId != -1);
        auto pointerEvent = windowPriv->pointerEventInstance(QQuickPointerDevice::touchDevices().at(0));
        QCOMPARE(pointerEvent->point(0)->grabberItem(), flickable);
    }

    QTest::touchEvent(window.data(), device).release(0, pEnd, window.data());
    QQuickTouchUtils::flush(window.data());

    if (releaseBeforeDelayIsOver) {
        // when the touchpoint was released, the child saw the delayed press and the release in sequence
        qCDebug(lcTests) << "expected delivered events: press, release, ungrab" << eventItem1->eventList;
        qCDebug(lcTests) << "expected filtered events: delayed press, release" << filteredEventList;
        QTRY_COMPARE(eventItem1->eventList.size(), 3);
        QCOMPARE(eventItem1->eventList.at(0).type, QEvent::MouseButtonPress);
        QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonRelease);
        QCOMPARE(eventItem1->eventList.last().type, QEvent::UngrabMouse);
        // QQuickWindow filters the delayed press and release
        QCOMPARE(filteredEventList.count(), 2);
        QCOMPARE(filteredEventList.at(0).type, QEvent::MouseButtonPress);
        QCOMPARE(filteredEventList.at(1).type, QEvent::MouseButtonRelease);
    } else {
        // QQuickWindow filters the delayed press if there was one; otherwise nothing
        if (scrollBeforeDelayIsOver) {
            QCOMPARE(filteredEventList.count(), 0);
        } else {
            qCDebug(lcTests) << "expected filtered event: delayed press" << filteredEventList;
            QCOMPARE(filteredEventList.count(), 1);
            QCOMPARE(filteredEventList.at(0).type, QEvent::MouseButtonPress);
        }
    }
}

void tst_TouchMouse::buttonOnTouch()
{
    // 400x800
    //   PinchArea - height 400
    //     - eventItem1 y: 100, height 100
    //     - eventItem2 y: 300, height 100
    //   MultiPointTouchArea - height 400
    //     - eventItem1 y: 100, height 100
    //     - eventItem2 y: 300, height 100

    QScopedPointer<QQuickView> window(createView());
    window->setSource(testFileUrl("buttonontouch.qml"));
    window->show();
    QQuickViewTestUtil::centerOnScreen(window.data());
    QVERIFY(QTest::qWaitForWindowActive(window.data()));
    QVERIFY(window->rootObject() != nullptr);

    QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea");
    QVERIFY(pinchArea);
    QQuickItem *button1 = window->rootObject()->findChild<QQuickItem*>("button1");
    QVERIFY(button1);
    EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
    QVERIFY(eventItem1);
    EventItem *eventItem2 = window->rootObject()->findChild<EventItem*>("eventItem2");
    QVERIFY(eventItem2);

    QQuickMultiPointTouchArea *touchArea = window->rootObject()->findChild<QQuickMultiPointTouchArea*>("toucharea");
    QVERIFY(touchArea);
    EventItem *eventItem3 = window->rootObject()->findChild<EventItem*>("eventItem3");
    QVERIFY(eventItem3);
    EventItem *eventItem4 = window->rootObject()->findChild<EventItem*>("eventItem4");
    QVERIFY(eventItem4);

    QTest::QTouchEventSequence touchSeq = QTest::touchEvent(window.data(), device, false);

    // Test the common case of a mouse area on top of pinch
    eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
    eventItem1->acceptMouse = true;


    // wait to avoid getting a double click event
    QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);

    // Normal touch click
    QPoint p1 = QPoint(10, 110);
    touchSeq.press(0, p1, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    touchSeq.release(0, p1, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(eventItem1->eventList.size(), 5);
    QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
    QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
    QCOMPARE(eventItem1->eventList.at(2).type, QEvent::TouchEnd);
    QCOMPARE(eventItem1->eventList.at(3).type, QEvent::MouseButtonRelease);
    QCOMPARE(eventItem1->eventList.at(4).type, QEvent::UngrabMouse);
    eventItem1->eventList.clear();

    // Normal mouse click
    QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier, p1);
    QCOMPARE(eventItem1->eventList.size(), 3);
    QCOMPARE(eventItem1->eventList.at(0).type, QEvent::MouseButtonPress);
    QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonRelease);
    QCOMPARE(eventItem1->eventList.at(2).type, QEvent::UngrabMouse);
    eventItem1->eventList.clear();

    // Pinch starting on the PinchArea should work
    p1 = QPoint(40, 10);
    QPoint p2 = QPoint(60, 10);

    // Start the events after each other
    touchSeq.press(0, p1, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    touchSeq.stationary(0).press(1, p2, window.data()).commit();
    QQuickTouchUtils::flush(window.data());

    QCOMPARE(button1->scale(), 1.0);

    // This event seems to be discarded, let's ignore it for now until someone digs into pincharea
    p1 -= QPoint(10, 0);
    p2 += QPoint(10, 0);
    touchSeq.move(0, p1, window.data()).move(1, p2, window.data()).commit();
    QQuickTouchUtils::flush(window.data());

    p1 -= QPoint(10, 0);
    p2 += QPoint(10, 0);
    touchSeq.move(0, p1, window.data()).move(1, p2, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
//    QCOMPARE(button1->scale(), 1.5);
    qDebug() << "Button scale: " << button1->scale();

    p1 -= QPoint(10, 0);
    p2 += QPoint(10, 0);
    touchSeq.move(0, p1, window.data()).move(1, p2, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
//    QCOMPARE(button1->scale(), 2.0);
    qDebug() << "Button scale: " << button1->scale();

    touchSeq.release(0, p1, window.data()).release(1, p2, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
//    QVERIFY(eventItem1->eventList.isEmpty());
//    QCOMPARE(button1->scale(), 2.0);
    qDebug() << "Button scale: " << button1->scale();


    // wait to avoid getting a double click event
    QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);

    // Start pinching while on the button
    button1->setScale(1.0);
    p1 = QPoint(40, 110);
    p2 = QPoint(60, 110);
    touchSeq.press(0, p1, window.data()).press(1, p2, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(button1->scale(), 1.0);
    QCOMPARE(eventItem1->eventList.count(), 2);
    QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
    QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);

    // This event seems to be discarded, let's ignore it for now until someone digs into pincharea
    p1 -= QPoint(10, 0);
    p2 += QPoint(10, 0);
    touchSeq.move(0, p1, window.data()).move(1, p2, window.data()).commit();
    QQuickTouchUtils::flush(window.data());

    p1 -= QPoint(10, 0);
    p2 += QPoint(10, 0);
    touchSeq.move(0, p1, window.data()).move(1, p2, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    //QCOMPARE(button1->scale(), 1.5);
    qDebug() << button1->scale();

    p1 -= QPoint(10, 0);
    p2 += QPoint(10, 0);
    touchSeq.move(0, p1, window.data()).move(1, p2, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    qDebug() << button1->scale();
    //QCOMPARE(button1->scale(), 2.0);

    touchSeq.release(0, p1, window.data()).release(1, p2, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
//    QCOMPARE(eventItem1->eventList.size(), 99);
    qDebug() << button1->scale();
    //QCOMPARE(button1->scale(), 2.0);
}

void tst_TouchMouse::pinchOnFlickable()
{
    QScopedPointer<QQuickView> window(createView());
    window->setSource(testFileUrl("pinchonflickable.qml"));
    window->show();
    QQuickViewTestUtil::centerOnScreen(window.data());
    QVERIFY(QTest::qWaitForWindowActive(window.data()));
    QVERIFY(window->rootObject() != nullptr);

    QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea");
    QVERIFY(pinchArea);
    QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>("flickable");
    QVERIFY(flickable);
    QQuickItem *rect = window->rootObject()->findChild<QQuickItem*>("rect");
    QVERIFY(rect);

    // flickable - single touch point
    QCOMPARE(flickable->contentX(), 0.0);
    QPoint p = QPoint(100, 100);
    QTest::touchEvent(window.data(), device).press(0, p, window.data());
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(rect->position(), QPointF(200.0, 200.0));
    p -= QPoint(10, 0);
    QTest::touchEvent(window.data(), device).move(0, p, window.data());
    QQuickTouchUtils::flush(window.data());
    p -= QPoint(10, 0);
    QTest::touchEvent(window.data(), device).move(0, p, window.data());
    QQuickTouchUtils::flush(window.data());
    p -= QPoint(10, 0);
    QTest::touchEvent(window.data(), device).move(0, p, window.data());
    QQuickTouchUtils::flush(window.data());
    p -= QPoint(10, 0);
    QTest::touchEvent(window.data(), device).move(0, p, window.data());
    QQuickTouchUtils::flush(window.data());
    QTest::touchEvent(window.data(), device).release(0, p, window.data());
    QQuickTouchUtils::flush(window.data());

    QGuiApplication::processEvents();
    QTest::qWait(10);
    QVERIFY(!flickable->isAtXBeginning());
    // wait until flicking is done
    QTRY_VERIFY(!flickable->isFlicking());

    // pinch
    QPoint p1 = QPoint(40, 20);
    QPoint p2 = QPoint(60, 20);

    QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window.data(), device);
    QQuickTouchUtils::flush(window.data());
    pinchSequence.press(0, p1, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    // In order for the stationary point to remember its previous position,
    // we have to reuse the same pinchSequence object.  Otherwise if we let it
    // be destroyed and then start a new sequence, point 0 will default to being
    // stationary at 0, 0, and PinchArea will filter out that touchpoint because
    // it is outside its bounds.
    pinchSequence.stationary(0).press(1, p2, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    p1 -= QPoint(10,10);
    p2 += QPoint(10,10);
    pinchSequence.move(0, p1, window.data()).move(1, p2, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(rect->scale(), 1.0);
    p1 -= QPoint(10, 0);
    p2 += QPoint(10, 0);
    pinchSequence.move(0, p1, window.data()).move(1, p2, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    p1 -= QPoint(10, 0);
    p2 += QPoint(10, 0);
    pinchSequence.move(0, p1, window.data()).move(1, p2, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    p1 -= QPoint(10, 0);
    p2 += QPoint(10, 0);
    pinchSequence.move(0, p1, window.data()).move(1, p2, window.data()).commit();
    QVERIFY(!flickable->isDragging());
    QQuickTouchUtils::flush(window.data());
    pinchSequence.release(0, p1, window.data()).release(1, p2, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    QVERIFY(rect->scale() > 1.0);
}

void tst_TouchMouse::flickableOnPinch()
{
    QScopedPointer<QQuickView> window(createView());
    window->setSource(testFileUrl("flickableonpinch.qml"));
    window->show();
    QQuickViewTestUtil::centerOnScreen(window.data());
    QVERIFY(QTest::qWaitForWindowActive(window.data()));
    QVERIFY(window->rootObject() != nullptr);

    QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea");
    QVERIFY(pinchArea);
    QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>("flickable");
    QVERIFY(flickable);
    QQuickItem *rect = window->rootObject()->findChild<QQuickItem*>("rect");
    QVERIFY(rect);

    // flickable - single touch point
    QCOMPARE(flickable->contentX(), 0.0);
    QPoint p = QPoint(100, 100);
    QTest::touchEvent(window.data(), device).press(0, p, window.data());
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(rect->position(), QPointF(200.0, 200.0));
    p -= QPoint(10, 0);
    QTest::touchEvent(window.data(), device).move(0, p, window.data());
    QQuickTouchUtils::flush(window.data());
    p -= QPoint(10, 0);
    QTest::touchEvent(window.data(), device).move(0, p, window.data());
    QQuickTouchUtils::flush(window.data());

    QTest::qWait(1000);

    p -= QPoint(10, 0);
    QTest::touchEvent(window.data(), device).move(0, p, window.data());
    QQuickTouchUtils::flush(window.data());
    QTest::touchEvent(window.data(), device).release(0, p, window.data());
    QQuickTouchUtils::flush(window.data());

    QTest::qWait(1000);

    //QVERIFY(flickable->isMovingHorizontally());
    qDebug() << "Pos: " << rect->position();
    // wait until flicking is done
    QTRY_VERIFY(!flickable->isFlicking());

    // pinch
    QPoint p1 = QPoint(40, 20);
    QPoint p2 = QPoint(60, 20);
    QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window.data(), device);
    pinchSequence.press(0, p1, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    // In order for the stationary point to remember its previous position,
    // we have to reuse the same pinchSequence object.  Otherwise if we let it
    // be destroyed and then start a new sequence, point 0 will default to being
    // stationary at 0, 0, and PinchArea will filter out that touchpoint because
    // it is outside its bounds.
    pinchSequence.stationary(0).press(1, p2, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    p1 -= QPoint(10,10);
    p2 += QPoint(10,10);
    pinchSequence.move(0, p1, window.data()).move(1, p2, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(rect->scale(), 1.0);
    p1 -= QPoint(10, 0);
    p2 += QPoint(10, 0);
    pinchSequence.move(0, p1, window.data()).move(1, p2, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    p1 -= QPoint(10, 0);
    p2 += QPoint(10, 0);
    pinchSequence.move(0, p1, window.data()).move(1, p2, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    p1 -= QPoint(10, 0);
    p2 += QPoint(10, 0);
    pinchSequence.move(0, p1, window.data()).move(1, p2, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    pinchSequence.release(0, p1, window.data()).release(1, p2, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    QVERIFY(rect->scale() > 1.0);
}

void tst_TouchMouse::mouseOnFlickableOnPinch()
{
    QScopedPointer<QQuickView> window(createView());
    window->setSource(testFileUrl("mouseonflickableonpinch.qml"));
    window->show();
    QQuickViewTestUtil::centerOnScreen(window.data());
    QVERIFY(QTest::qWaitForWindowActive(window.data()));
    QVERIFY(window->rootObject() != nullptr);

    QRect windowRect = QRect(window->position(), window->size());
    QCursor::setPos(windowRect.center());

    QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea");
    QVERIFY(pinchArea);
    QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>("flickable");
    QVERIFY(flickable);
    QQuickItem *rect = window->rootObject()->findChild<QQuickItem*>("rect");
    QVERIFY(rect);

    // flickable - single touch point
    QCOMPARE(flickable->contentX(), 0.0);
    QPoint p = QPoint(100, 100);
    QTest::touchEvent(window.data(), device).press(0, p, window.data());
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(rect->position(), QPointF(200.0, 200.0));
    p -= QPoint(10, 0);
    QTest::touchEvent(window.data(), device).move(0, p, window.data());
    QQuickTouchUtils::flush(window.data());
    p -= QPoint(10, 0);
    QTest::touchEvent(window.data(), device).move(0, p, window.data());
    QQuickTouchUtils::flush(window.data());
    p -= QPoint(10, 0);
    QTest::touchEvent(window.data(), device).move(0, p, window.data());
    QQuickTouchUtils::flush(window.data());
    QTest::touchEvent(window.data(), device).release(0, p, window.data());
    QQuickTouchUtils::flush(window.data());

    //QVERIFY(flickable->isMovingHorizontally());

    // Wait for flick to end
    QTRY_VERIFY(!flickable->isMoving());
    qDebug() << "Pos: " << rect->position();

    // pinch
    QPoint p1 = QPoint(40, 20);
    QPoint p2 = QPoint(60, 20);
    QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window.data(), device);
    pinchSequence.press(0, p1, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    // In order for the stationary point to remember its previous position,
    // we have to reuse the same pinchSequence object.  Otherwise if we let it
    // be destroyed and then start a new sequence, point 0 will default to being
    // stationary at 0, 0, and PinchArea will filter out that touchpoint because
    // it is outside its bounds.
    pinchSequence.stationary(0).press(1, p2, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    p1 -= QPoint(10,10);
    p2 += QPoint(10,10);
    pinchSequence.move(0, p1, window.data()).move(1, p2, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(rect->scale(), 1.0);
    p1 -= QPoint(10, 0);
    p2 += QPoint(10, 0);
    pinchSequence.move(0, p1, window.data()).move(1, p2, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    p1 -= QPoint(10, 0);
    p2 += QPoint(10, 0);
    pinchSequence.move(0, p1, window.data()).move(1, p2, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    p1 -= QPoint(10, 0);
    p2 += QPoint(10, 0);
    pinchSequence.move(0, p1, window.data()).move(1, p2, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    pinchSequence.release(0, p1, window.data()).release(1, p2, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    QVERIFY(rect->scale() > 1.0);

    // PinchArea should steal the event after flicking started
    rect->setScale(1.0);
    flickable->setContentX(0.0);
    p = QPoint(100, 100);
    pinchSequence.press(0, p, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(rect->position(), QPointF(200.0, 200.0));
    p -= QPoint(10, 0);
    pinchSequence.move(0, p, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    p -= QPoint(10, 0);
    pinchSequence.move(0, p, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    QGuiApplication::processEvents();
    p -= QPoint(10, 0);
    pinchSequence.move(0, p, window.data()).commit();
    QQuickTouchUtils::flush(window.data());

    QCOMPARE(window->mouseGrabberItem(), flickable);

    // Add a second finger, this should lead to stealing
    p1 = QPoint(40, 100);
    p2 = QPoint(60, 100);
    pinchSequence.stationary(0).press(1, p2, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(rect->scale(), 1.0);

    p1 -= QPoint(5, 0);
    p2 += QPoint(5, 0);
    pinchSequence.move(0, p1, window.data()).move(1, p2, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    p1 -= QPoint(5, 0);
    p2 += QPoint(5, 0);
    pinchSequence.move(0, p1, window.data()).move(1, p2, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    p1 -= QPoint(5, 0);
    p2 += QPoint(5, 0);
    pinchSequence.move(0, p1, window.data()).move(1, p2, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    pinchSequence.release(0, p1, window.data()).release(1, p2, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    QVERIFY(rect->scale() > 1.0);
    pinchSequence.release(0, p, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
}

/*
   Regression test for the following use case:
   You have two mouse areas, on on top of the other.
   1 - You tap the top one.
   2 - That top mouse area receives a mouse press event but doesn't accept it
   Expected outcome:
     3 - the bottom mouse area gets clicked (besides press and release mouse events)
   Bogus outcome:
     3 - the bottom mouse area gets double clicked.
 */
void tst_TouchMouse::tapOnDismissiveTopMouseAreaClicksBottomOne()
{
    QScopedPointer<QQuickView> window(createView());
    window->setSource(testFileUrl("twoMouseAreas.qml"));
    window->show();
    QQuickViewTestUtil::centerOnScreen(window.data());
    QVERIFY(QTest::qWaitForWindowActive(window.data()));
    QVERIFY(window->rootObject() != nullptr);

    QQuickMouseArea *bottomMouseArea =
        window->rootObject()->findChild<QQuickMouseArea*>("rear mouseArea");

    QSignalSpy bottomClickedSpy(bottomMouseArea, SIGNAL(clicked(QQuickMouseEvent*)));
    QSignalSpy bottomDoubleClickedSpy(bottomMouseArea,
                                      SIGNAL(doubleClicked(QQuickMouseEvent*)));

    // tap the front mouse area (see qml file)
    QPoint p1(20, 20);
    QTest::touchEvent(window.data(), device).press(0, p1, window.data());
    QQuickTouchUtils::flush(window.data());
    QTest::touchEvent(window.data(), device).release(0, p1, window.data());
    QQuickTouchUtils::flush(window.data());

    QCOMPARE(bottomClickedSpy.count(), 1);
    QCOMPARE(bottomDoubleClickedSpy.count(), 0);

    QTest::touchEvent(window.data(), device).press(0, p1, window.data());
    QQuickTouchUtils::flush(window.data());
    QTest::touchEvent(window.data(), device).release(0, p1, window.data());
    QQuickTouchUtils::flush(window.data());

    QCOMPARE(bottomClickedSpy.count(), 1);
    QCOMPARE(bottomDoubleClickedSpy.count(), 1);
}

/*
    If an item grabs a touch that is currently being used for mouse pointer emulation,
    the current mouse grabber should lose the mouse as mouse events will no longer
    be generated from that touch point.
 */
void tst_TouchMouse::touchGrabCausesMouseUngrab()
{
    QScopedPointer<QQuickView> window(createView());
    window->setSource(testFileUrl("twosiblingitems.qml"));
    window->show();
    QQuickViewTestUtil::centerOnScreen(window.data());
    QVERIFY(QTest::qWaitForWindowActive(window.data()));
    QVERIFY(window->rootObject() != nullptr);

    EventItem *leftItem = window->rootObject()->findChild<EventItem*>("leftItem");
    QVERIFY(leftItem);

    EventItem *rightItem = window->rootObject()->findChild<EventItem*>("rightItem");
    QVERIFY(leftItem);

    // Send a touch to the leftItem. But leftItem accepts only mouse events, thus
    // a mouse event will be synthesized out of this touch and will get accepted by
    // leftItem.
    leftItem->acceptMouse = true;
    leftItem->setAcceptedMouseButtons(Qt::LeftButton);
    QPoint p1;
    p1 = QPoint(leftItem->width() / 2, leftItem->height() / 2);
    QTest::touchEvent(window.data(), device).press(0, p1, window.data());
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(leftItem->eventList.size(), 2);
    QCOMPARE(leftItem->eventList.at(0).type, QEvent::TouchBegin);
    QCOMPARE(leftItem->eventList.at(1).type, QEvent::MouseButtonPress);
    QCOMPARE(window->mouseGrabberItem(), leftItem);
    leftItem->eventList.clear();

    rightItem->acceptTouch = true;
    {
        QVector<int> ids;
        ids.append(leftItem->point0);
        rightItem->grabTouchPoints(ids);
    }

    // leftItem should have lost the mouse as the touch point that was being used to emulate it
    // has been grabbed by another item.
    QCOMPARE(leftItem->eventList.size(), 1);
    QCOMPARE(leftItem->eventList.at(0).type, QEvent::UngrabMouse);
    QCOMPARE(window->mouseGrabberItem(), (QQuickItem*)nullptr);
}

void tst_TouchMouse::touchPointDeliveryOrder()
{
    // Touch points should be first delivered to the item under the primary finger
    QScopedPointer<QQuickView> window(createView());
    window->setSource(testFileUrl("touchpointdeliveryorder.qml"));
    window->show();
    QQuickViewTestUtil::centerOnScreen(window.data());
    QVERIFY(QTest::qWaitForWindowActive(window.data()));

    /*
    The items are positioned from left to right:
    |      background     |
    |   left   |
    |          |   right  |
          |  middle |
    0   150   300  450  600
    */
    QPoint pLeft = QPoint(100, 100);
    QPoint pRight = QPoint(500, 100);
    QPoint pLeftMiddle = QPoint(200, 100);
    QPoint pRightMiddle = QPoint(350, 100);

    QTest::QTouchEventSequence touchSeq = QTest::touchEvent(window.data(), device, false);

    QVector<QQuickItem*> events;
    EventItem *background = window->rootObject()->findChild<EventItem*>("background");
    EventItem *left = window->rootObject()->findChild<EventItem*>("left");
    EventItem *middle = window->rootObject()->findChild<EventItem*>("middle");
    EventItem *right = window->rootObject()->findChild<EventItem*>("right");
    QVERIFY(background);
    QVERIFY(left);
    QVERIFY(middle);
    QVERIFY(right);
    connect(background, &EventItem::onTouchEvent, [&events](QQuickItem* receiver){ events.append(receiver); });
    connect(left, &EventItem::onTouchEvent, [&events](QQuickItem* receiver){ events.append(receiver); });
    connect(middle, &EventItem::onTouchEvent, [&events](QQuickItem* receiver){ events.append(receiver); });
    connect(right, &EventItem::onTouchEvent, [&events](QQuickItem* receiver){ events.append(receiver); });

    touchSeq.press(0, pLeft, window.data()).commit();
    QQuickTouchUtils::flush(window.data());

    // Touch on left, then background
    QCOMPARE(events.size(), 2);
    QCOMPARE(events.at(0), left);
    QCOMPARE(events.at(1), background);
    events.clear();

    // New press events are deliverd first, the stationary point was not accepted, thus it doesn't get delivered
    touchSeq.stationary(0).press(1, pRightMiddle, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(events.size(), 3);
    QCOMPARE(events.at(0), middle);
    QCOMPARE(events.at(1), right);
    QCOMPARE(events.at(2), background);
    events.clear();

    touchSeq.release(0, pLeft, window.data()).release(1, pRightMiddle, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(events.size(), 0); // no accepted events

    // Two presses, the first point should come first
    touchSeq.press(0, pLeft, window.data()).press(1, pRight, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(events.size(), 3);
    QCOMPARE(events.at(0), left);
    QCOMPARE(events.at(1), right);
    QCOMPARE(events.at(2), background);
    touchSeq.release(0, pLeft, window.data()).release(1, pRight, window.data()).commit();
    events.clear();

    // Again, pressing right first
    touchSeq.press(0, pRight, window.data()).press(1, pLeft, window.data()).commit();
    QQuickTouchUtils::flush(window.data());
    QCOMPARE(events.size(), 3);
    QCOMPARE(events.at(0), right);
    QCOMPARE(events.at(1), left);
    QCOMPARE(events.at(2), background);
    touchSeq.release(0, pRight, window.data()).release(1, pLeft, window.data()).commit();
    events.clear();

    // Two presses, both hitting the middle item on top, then branching left and right, then bottom
    // Each target should be offered the events exactly once, middle first, left must come before right (id 0)
    touchSeq.press(0, pLeftMiddle, window.data()).press(1, pRightMiddle, window.data()).commit();
    QCOMPARE(events.size(), 4);
    QCOMPARE(events.at(0), middle);
    QCOMPARE(events.at(1), left);
    QCOMPARE(events.at(2), right);
    QCOMPARE(events.at(3), background);
    touchSeq.release(0, pLeftMiddle, window.data()).release(1, pRightMiddle, window.data()).commit();
    events.clear();

    touchSeq.press(0, pRightMiddle, window.data()).press(1, pLeftMiddle, window.data()).commit();
    qDebug() << events;
    QCOMPARE(events.size(), 4);
    QCOMPARE(events.at(0), middle);
    QCOMPARE(events.at(1), right);
    QCOMPARE(events.at(2), left);
    QCOMPARE(events.at(3), background);
    touchSeq.release(0, pRightMiddle, window.data()).release(1, pLeftMiddle, window.data()).commit();
}

void tst_TouchMouse::hoverEnabled()
{
    // QTouchDevice *device = new QTouchDevice;
    // device->setType(QTouchDevice::TouchScreen);
    // QWindowSystemInterface::registerTouchDevice(device);

    QScopedPointer<QQuickView> window(createView());
    window->setSource(testFileUrl("hoverMouseAreas.qml"));
    QQuickViewTestUtil::centerOnScreen(window.data());
    QQuickViewTestUtil::moveMouseAway(window.data());
    window->show();
    QVERIFY(QTest::qWaitForWindowActive(window.data()));
    QQuickItem *root = window->rootObject();
    QVERIFY(root != nullptr);

    QQuickMouseArea *mouseArea1 = root->findChild<QQuickMouseArea*>("mouseArea1");
    QVERIFY(mouseArea1 != nullptr);

    QQuickMouseArea *mouseArea2 = root->findChild<QQuickMouseArea*>("mouseArea2");
    QVERIFY(mouseArea2 != nullptr);

    QSignalSpy enterSpy1(mouseArea1, SIGNAL(entered()));
    QSignalSpy exitSpy1(mouseArea1, SIGNAL(exited()));
    QSignalSpy clickSpy1(mouseArea1, SIGNAL(clicked(QQuickMouseEvent *)));

    QSignalSpy enterSpy2(mouseArea2, SIGNAL(entered()));
    QSignalSpy exitSpy2(mouseArea2, SIGNAL(exited()));
    QSignalSpy clickSpy2(mouseArea2, SIGNAL(clicked(QQuickMouseEvent *)));

    QPoint p1(150, 150);
    QPoint p2(150, 250);

    // ------------------------- Mouse move to mouseArea1
    QTest::mouseMove(window.data(), p1);

    QVERIFY(enterSpy1.count() == 1);
    QVERIFY(mouseArea1->hovered());
    QVERIFY(!mouseArea2->hovered());

    // ------------------------- Touch click on mouseArea1
    QTest::touchEvent(window.data(), device).press(0, p1, window.data());

    QCOMPARE(enterSpy1.count(), 1);
    QCOMPARE(enterSpy2.count(), 0);
    QVERIFY(mouseArea1->pressed());
    QVERIFY(mouseArea1->hovered());
    QVERIFY(!mouseArea2->hovered());

    QTest::touchEvent(window.data(), device).release(0, p1, window.data());
    QVERIFY(clickSpy1.count() == 1);
    QVERIFY(mouseArea1->hovered());
    QVERIFY(!mouseArea2->hovered());

    // ------------------------- Touch click on mouseArea2
    QTest::touchEvent(window.data(), device).press(0, p2, window.data());

    QVERIFY(mouseArea1->hovered());
    QVERIFY(mouseArea2->hovered());
    QVERIFY(mouseArea2->pressed());
    QCOMPARE(enterSpy1.count(), 1);
    QCOMPARE(enterSpy2.count(), 1);

    QTest::touchEvent(window.data(), device).release(0, p2, window.data());

    QVERIFY(clickSpy2.count() == 1);
    QVERIFY(mouseArea1->hovered());
    QVERIFY(!mouseArea2->hovered());
    QCOMPARE(exitSpy1.count(), 0);
    QCOMPARE(exitSpy2.count(), 1);

    // ------------------------- Another touch click on mouseArea1
    QTest::touchEvent(window.data(), device).press(0, p1, window.data());

    QCOMPARE(enterSpy1.count(), 1);
    QCOMPARE(enterSpy2.count(), 1);
    QVERIFY(mouseArea1->pressed());
    QVERIFY(mouseArea1->hovered());
    QVERIFY(!mouseArea2->hovered());

    QTest::touchEvent(window.data(), device).release(0, p1, window.data());
    QCOMPARE(clickSpy1.count(), 2);
    QVERIFY(mouseArea1->hovered());
    QVERIFY(!mouseArea1->pressed());
    QVERIFY(!mouseArea2->hovered());
}

void tst_TouchMouse::implicitUngrab()
{
    QScopedPointer<QQuickView> window(createView());
    window->setSource(testFileUrl("singleitem.qml"));
    window->show();
    QQuickViewTestUtil::centerOnScreen(window.data());
    QQuickViewTestUtil::moveMouseAway(window.data());
    QVERIFY(QTest::qWaitForWindowActive(window.data()));

    QQuickItem *root = window->rootObject();
    QVERIFY(root != nullptr);
    EventItem *eventItem = root->findChild<EventItem*>("eventItem1");
    eventItem->acceptMouse = true;
    QPoint p1(20, 20);
    QTest::touchEvent(window.data(), device).press(0, p1);

    QCOMPARE(window->mouseGrabberItem(), eventItem);
    eventItem->eventList.clear();
    eventItem->setEnabled(false);
    QVERIFY(!eventItem->eventList.isEmpty());
    QCOMPARE(eventItem->eventList.at(0).type, QEvent::UngrabMouse);
    QTest::touchEvent(window.data(), device).release(0, p1);   // clean up potential state

    eventItem->setEnabled(true);
    QTest::touchEvent(window.data(), device).press(0, p1);
    eventItem->eventList.clear();
    eventItem->setVisible(false);
    QVERIFY(!eventItem->eventList.isEmpty());
    QCOMPARE(eventItem->eventList.at(0).type, QEvent::UngrabMouse);
    QTest::touchEvent(window.data(), device).release(0, p1);   // clean up potential state
}
QTEST_MAIN(tst_TouchMouse)

#include "tst_touchmouse.moc"

