aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/quick/qquickwindow
diff options
context:
space:
mode:
authorAlan Alpert <alan.alpert@nokia.com>2012-07-11 17:32:16 +1000
committerQt by Nokia <qt-info@nokia.com>2012-07-17 07:26:15 +0200
commitfeb996e3ab44e68082c97102556ea396f5df3f44 (patch)
tree7613a8a4eaf5a8e0fb2801e9d0d9d1869524c348 /tests/auto/quick/qquickwindow
parent68bbdacd2d5a6fa02f085a996411fb2b71875174 (diff)
QQuickCanvas renames
QQuickCanvas is now called QQuickWindow QQuickCanvas::rootItem is now QQuickWindow::contentItem QQuickItem::canvas is now QQuickItem::window QQuickItem::ItemChangeData::canvas is also renamed window QQuickCanvas::grabFrameBuffer is now QQuickWindow::grabWindow The functions related to the color property have dropped the clear from their names. The first three changes have interim compatibility measures in place to ease the transition. Change-Id: Id34e29546a22a74a7ae2ad90ee3a8def6fc541d2 Reviewed-by: Martin Jones <martin.jones@nokia.com>
Diffstat (limited to 'tests/auto/quick/qquickwindow')
-rw-r--r--tests/auto/quick/qquickwindow/data/AnimationsWhileHidden.qml17
-rw-r--r--tests/auto/quick/qquickwindow/data/Headless.qml33
-rw-r--r--tests/auto/quick/qquickwindow/data/colors.pngbin0 -> 1655 bytes
-rw-r--r--tests/auto/quick/qquickwindow/data/focus.qml11
-rw-r--r--tests/auto/quick/qquickwindow/data/ownershipRootItem.qml11
-rw-r--r--tests/auto/quick/qquickwindow/data/window.qml9
-rw-r--r--tests/auto/quick/qquickwindow/qquickwindow.pro17
-rw-r--r--tests/auto/quick/qquickwindow/tst_qquickwindow.cpp1065
8 files changed, 1163 insertions, 0 deletions
diff --git a/tests/auto/quick/qquickwindow/data/AnimationsWhileHidden.qml b/tests/auto/quick/qquickwindow/data/AnimationsWhileHidden.qml
new file mode 100644
index 0000000000..e95b029210
--- /dev/null
+++ b/tests/auto/quick/qquickwindow/data/AnimationsWhileHidden.qml
@@ -0,0 +1,17 @@
+import QtQuick 2.0
+import QtQuick.Window 2.0 as Window
+
+Window.Window
+{
+ id: win
+ visible: true
+ width: 250
+ height: 250
+
+ SequentialAnimation {
+ PauseAnimation { duration: 500 }
+ PropertyAction { target: win; property: "visible"; value: true }
+ loops: Animation.Infinite
+ running: true
+ }
+}
diff --git a/tests/auto/quick/qquickwindow/data/Headless.qml b/tests/auto/quick/qquickwindow/data/Headless.qml
new file mode 100644
index 0000000000..2e09cb1f24
--- /dev/null
+++ b/tests/auto/quick/qquickwindow/data/Headless.qml
@@ -0,0 +1,33 @@
+import QtQuick 2.0
+import QtQuick.Window 2.0 as Window
+
+Window.Window {
+
+ width: 300
+ height: 200
+ visible: true
+
+ Text {
+ anchors.left: parent.left
+ anchors.top: parent.top
+ text: "Testing headless mode"
+ }
+
+ Rectangle {
+ anchors.centerIn: parent
+ width: 100
+ height: 50
+ rotation: -30
+ gradient: Gradient {
+ GradientStop { position: 0; color: "lightsteelblue" }
+ GradientStop { position: 1; color: "black" }
+ }
+ }
+
+ Image {
+ source: "colors.png"
+ anchors.bottom: parent.bottom
+ anchors.right: parent.right
+ }
+
+}
diff --git a/tests/auto/quick/qquickwindow/data/colors.png b/tests/auto/quick/qquickwindow/data/colors.png
new file mode 100644
index 0000000000..dfb62f3d64
--- /dev/null
+++ b/tests/auto/quick/qquickwindow/data/colors.png
Binary files differ
diff --git a/tests/auto/quick/qquickwindow/data/focus.qml b/tests/auto/quick/qquickwindow/data/focus.qml
new file mode 100644
index 0000000000..901f2fcf2e
--- /dev/null
+++ b/tests/auto/quick/qquickwindow/data/focus.qml
@@ -0,0 +1,11 @@
+import QtQuick 2.0
+import QtQuick.Window 2.0 as Window
+
+Window.Window {
+ Item {
+ objectName: "item1"
+ }
+ Item {
+ objectName: "item2"
+ }
+}
diff --git a/tests/auto/quick/qquickwindow/data/ownershipRootItem.qml b/tests/auto/quick/qquickwindow/data/ownershipRootItem.qml
new file mode 100644
index 0000000000..dfc4159f4e
--- /dev/null
+++ b/tests/auto/quick/qquickwindow/data/ownershipRootItem.qml
@@ -0,0 +1,11 @@
+import QtQuick 2.0
+import QtQuick.Window 2.0 as Window
+
+Window.Window {
+RootItemAccessor {
+ id:accessor
+ objectName:"accessor"
+ Component.onCompleted:accessor.rootItem();
+}
+
+} \ No newline at end of file
diff --git a/tests/auto/quick/qquickwindow/data/window.qml b/tests/auto/quick/qquickwindow/data/window.qml
new file mode 100644
index 0000000000..d79d5161b5
--- /dev/null
+++ b/tests/auto/quick/qquickwindow/data/window.qml
@@ -0,0 +1,9 @@
+import QtQuick 2.0
+import QtQuick.Window 2.0 as Window
+
+Window.Window {
+ color: "#00FF00"
+ Item {
+ objectName: "item"
+ }
+}
diff --git a/tests/auto/quick/qquickwindow/qquickwindow.pro b/tests/auto/quick/qquickwindow/qquickwindow.pro
new file mode 100644
index 0000000000..8f3ff82ceb
--- /dev/null
+++ b/tests/auto/quick/qquickwindow/qquickwindow.pro
@@ -0,0 +1,17 @@
+CONFIG += testcase
+TARGET = tst_qquickwindow
+SOURCES += tst_qquickwindow.cpp
+
+include (../../shared/util.pri)
+
+macx:CONFIG -= app_bundle
+
+CONFIG += parallel_test
+QT += core-private gui-private qml-private quick-private v8-private testlib
+
+TESTDATA = data/*
+
+OTHER_FILES += \
+ data/AnimationsWhileHidden.qml \
+ data/Headless.qml
+
diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
new file mode 100644
index 0000000000..ebea271565
--- /dev/null
+++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
@@ -0,0 +1,1065 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qtest.h>
+#include <QDebug>
+#include <QTouchEvent>
+#include <QtQuick/QQuickItem>
+#include <QtQuick/QQuickWindow>
+#include <QtQml/QQmlEngine>
+#include <QtQml/QQmlComponent>
+#include <QtQuick/private/qquickrectangle_p.h>
+#include "../../shared/util.h"
+#include <QSignalSpy>
+#include <private/qquickwindow_p.h>
+#include <private/qguiapplication_p.h>
+
+struct TouchEventData {
+ QEvent::Type type;
+ QWidget *widget;
+ QWindow *window;
+ Qt::TouchPointStates states;
+ QList<QTouchEvent::TouchPoint> touchPoints;
+};
+
+static QTouchEvent::TouchPoint makeTouchPoint(QQuickItem *item, const QPointF &p, const QPointF &lastPoint = QPointF())
+{
+ QPointF last = lastPoint.isNull() ? p : lastPoint;
+
+ QTouchEvent::TouchPoint tp;
+
+ tp.setPos(p);
+ tp.setLastPos(last);
+ tp.setScenePos(item->mapToScene(p));
+ tp.setLastScenePos(item->mapToScene(last));
+ tp.setScreenPos(item->window()->mapToGlobal(tp.scenePos().toPoint()));
+ tp.setLastScreenPos(item->window()->mapToGlobal(tp.lastScenePos().toPoint()));
+ return tp;
+}
+
+static TouchEventData makeTouchData(QEvent::Type type, QWindow *w, Qt::TouchPointStates states = 0,
+ const QList<QTouchEvent::TouchPoint>& touchPoints = QList<QTouchEvent::TouchPoint>())
+{
+ TouchEventData d = { type, 0, w, states, touchPoints };
+ return d;
+}
+static TouchEventData makeTouchData(QEvent::Type type, QWindow *w, Qt::TouchPointStates states, const QTouchEvent::TouchPoint &touchPoint)
+{
+ QList<QTouchEvent::TouchPoint> points;
+ points << touchPoint;
+ return makeTouchData(type, w, states, points);
+}
+
+#define COMPARE_TOUCH_POINTS(tp1, tp2) \
+{ \
+ QCOMPARE(tp1.pos(), tp2.pos()); \
+ QCOMPARE(tp1.lastPos(), tp2.lastPos()); \
+ QCOMPARE(tp1.scenePos(), tp2.scenePos()); \
+ QCOMPARE(tp1.lastScenePos(), tp2.lastScenePos()); \
+ QCOMPARE(tp1.screenPos(), tp2.screenPos()); \
+ QCOMPARE(tp1.lastScreenPos(), tp2.lastScreenPos()); \
+}
+
+#define COMPARE_TOUCH_DATA(d1, d2) \
+{ \
+ QCOMPARE((int)d1.type, (int)d2.type); \
+ QCOMPARE(d1.widget, d2.widget); \
+ QCOMPARE((int)d1.states, (int)d2.states); \
+ QCOMPARE(d1.touchPoints.count(), d2.touchPoints.count()); \
+ for (int i=0; i<d1.touchPoints.count(); i++) { \
+ COMPARE_TOUCH_POINTS(d1.touchPoints[i], d2.touchPoints[i]); \
+ } \
+}
+
+
+class RootItemAccessor : public QQuickItem
+{
+ Q_OBJECT
+public:
+ RootItemAccessor()
+ : m_rootItemDestroyed(false)
+ , m_rootItem(0)
+ {
+ }
+ Q_INVOKABLE QQuickItem *rootItem()
+ {
+ if (!m_rootItem) {
+ QQuickWindowPrivate *c = QQuickWindowPrivate::get(window());
+ m_rootItem = c->rootItem;
+ QObject::connect(m_rootItem, SIGNAL(destroyed()), this, SLOT(rootItemDestroyed()));
+ }
+ return m_rootItem;
+ }
+ bool isRootItemDestroyed() {return m_rootItemDestroyed;}
+public slots:
+ void rootItemDestroyed() {
+ m_rootItemDestroyed = true;
+ }
+
+private:
+ bool m_rootItemDestroyed;
+ QQuickItem *m_rootItem;
+};
+
+class TestTouchItem : public QQuickRectangle
+{
+ Q_OBJECT
+public:
+ TestTouchItem(QQuickItem *parent = 0)
+ : QQuickRectangle(parent), acceptTouchEvents(true), acceptMouseEvents(true),
+ mousePressId(0),
+ spinLoopWhenPressed(false), touchEventCount(0)
+ {
+ border()->setWidth(1);
+ setAcceptedMouseButtons(Qt::LeftButton);
+ setFiltersChildMouseEvents(true);
+ }
+
+ void reset() {
+ acceptTouchEvents = acceptMouseEvents = true;
+ setEnabled(true);
+ setVisible(true);
+
+ lastEvent = makeTouchData(QEvent::None, window(), 0, QList<QTouchEvent::TouchPoint>());//CHECK_VALID
+
+ lastVelocity = lastVelocityFromMouseMove = QVector2D();
+ lastMousePos = QPointF();
+ lastMouseCapabilityFlags = 0;
+ }
+
+ static void clearMousePressCounter()
+ {
+ mousePressNum = mouseMoveNum = mouseReleaseNum = 0;
+ }
+
+ void clearTouchEventCounter()
+ {
+ touchEventCount = 0;
+ }
+
+ bool acceptTouchEvents;
+ bool acceptMouseEvents;
+ TouchEventData lastEvent;
+ int mousePressId;
+ bool spinLoopWhenPressed;
+ int touchEventCount;
+ QVector2D lastVelocity;
+ QVector2D lastVelocityFromMouseMove;
+ QPointF lastMousePos;
+ int lastMouseCapabilityFlags;
+
+ void touchEvent(QTouchEvent *event) {
+ if (!acceptTouchEvents) {
+ event->ignore();
+ return;
+ }
+ ++touchEventCount;
+ lastEvent = makeTouchData(event->type(), event->window(), event->touchPointStates(), event->touchPoints());
+ if (event->device()->capabilities().testFlag(QTouchDevice::Velocity) && !event->touchPoints().isEmpty()) {
+ lastVelocity = event->touchPoints().first().velocity();
+ } else {
+ lastVelocity = QVector2D();
+ }
+ if (spinLoopWhenPressed && event->touchPointStates().testFlag(Qt::TouchPointPressed)) {
+ QCoreApplication::processEvents();
+ }
+ }
+
+ void mousePressEvent(QMouseEvent *e) {
+ if (!acceptMouseEvents) {
+ e->ignore();
+ return;
+ }
+ mousePressId = ++mousePressNum;
+ lastMousePos = e->pos();
+ lastMouseCapabilityFlags = QGuiApplicationPrivate::mouseEventCaps(e);
+ }
+
+ void mouseMoveEvent(QMouseEvent *e) {
+ if (!acceptMouseEvents) {
+ e->ignore();
+ return;
+ }
+ ++mouseMoveNum;
+ lastVelocityFromMouseMove = QGuiApplicationPrivate::mouseEventVelocity(e);
+ lastMouseCapabilityFlags = QGuiApplicationPrivate::mouseEventCaps(e);
+ lastMousePos = e->pos();
+ }
+
+ void mouseReleaseEvent(QMouseEvent *e) {
+ if (!acceptMouseEvents) {
+ e->ignore();
+ return;
+ }
+ ++mouseReleaseNum;
+ lastMousePos = e->pos();
+ lastMouseCapabilityFlags = QGuiApplicationPrivate::mouseEventCaps(e);
+ }
+
+ bool childMouseEventFilter(QQuickItem *, QEvent *event) {
+ // TODO Is it a bug if a QTouchEvent comes here?
+ if (event->type() == QEvent::MouseButtonPress)
+ mousePressId = ++mousePressNum;
+ return false;
+ }
+
+ static int mousePressNum, mouseMoveNum, mouseReleaseNum;
+};
+
+int TestTouchItem::mousePressNum = 0;
+int TestTouchItem::mouseMoveNum = 0;
+int TestTouchItem::mouseReleaseNum = 0;
+
+class ConstantUpdateItem : public QQuickItem
+{
+Q_OBJECT
+public:
+ ConstantUpdateItem(QQuickItem *parent = 0) : QQuickItem(parent), iterations(0) {setFlag(ItemHasContents);}
+
+ int iterations;
+protected:
+ QSGNode* updatePaintNode(QSGNode *, UpdatePaintNodeData *){
+ iterations++;
+ update();
+ return 0;
+ }
+};
+
+class tst_qquickwindow : public QQmlDataTest
+{
+ Q_OBJECT
+public:
+
+private slots:
+ void initTestCase()
+ {
+ QQmlDataTest::initTestCase();
+ touchDevice = new QTouchDevice;
+ touchDevice->setType(QTouchDevice::TouchScreen);
+ QWindowSystemInterface::registerTouchDevice(touchDevice);
+ touchDeviceWithVelocity = new QTouchDevice;
+ touchDeviceWithVelocity->setType(QTouchDevice::TouchScreen);
+ touchDeviceWithVelocity->setCapabilities(QTouchDevice::Position | QTouchDevice::Velocity);
+ QWindowSystemInterface::registerTouchDevice(touchDeviceWithVelocity);
+ }
+
+
+ void constantUpdates();
+ void mouseFiltering();
+ void headless();
+
+ void touchEvent_basic();
+ void touchEvent_propagation();
+ void touchEvent_propagation_data();
+ void touchEvent_cancel();
+ void touchEvent_reentrant();
+ void touchEvent_velocity();
+
+ void mouseFromTouch_basic();
+
+ void clearWindow();
+
+ void qmlCreation();
+ void clearColor();
+
+ void grab();
+ void multipleWindows();
+
+ void animationsWhileHidden();
+
+ void focusObject();
+
+ void ignoreUnhandledMouseEvents();
+
+ void ownershipRootItem();
+private:
+ QTouchDevice *touchDevice;
+ QTouchDevice *touchDeviceWithVelocity;
+};
+
+//If the item calls update inside updatePaintNode, it should schedule another update
+void tst_qquickwindow::constantUpdates()
+{
+ QQuickWindow window;
+ window.resize(250, 250);
+ ConstantUpdateItem item(window.rootItem());
+ window.show();
+ QTRY_VERIFY(item.iterations > 60);
+}
+
+void tst_qquickwindow::touchEvent_basic()
+{
+ TestTouchItem::clearMousePressCounter();
+
+ QQuickWindow *window = new QQuickWindow;
+ window->resize(250, 250);
+ window->setPos(100, 100);
+ window->show();
+ QTest::qWaitForWindowShown(window);
+
+ TestTouchItem *bottomItem = new TestTouchItem(window->rootItem());
+ bottomItem->setObjectName("Bottom Item");
+ bottomItem->setSize(QSizeF(150, 150));
+
+ TestTouchItem *middleItem = new TestTouchItem(bottomItem);
+ middleItem->setObjectName("Middle Item");
+ middleItem->setPos(QPointF(50, 50));
+ middleItem->setSize(QSizeF(150, 150));
+
+ TestTouchItem *topItem = new TestTouchItem(middleItem);
+ topItem->setObjectName("Top Item");
+ topItem->setPos(QPointF(50, 50));
+ topItem->setSize(QSizeF(150, 150));
+
+ QPointF pos(10, 10);
+
+ // press single point
+ QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(),window);
+ QTest::qWait(50);
+
+ QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
+
+ QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
+ QVERIFY(bottomItem->lastEvent.touchPoints.isEmpty());
+ // At one point this was failing with kwin (KDE window manager) because window->setPos(100, 100)
+ // would put the decorated window at that position rather than the window itself.
+ COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchBegin, window, Qt::TouchPointPressed, makeTouchPoint(topItem, pos)));
+ topItem->reset();
+
+ // press multiple points
+ QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(),window)
+ .press(1, bottomItem->mapToScene(pos).toPoint(), window);
+ QTest::qWait(50);
+ QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
+ QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
+ QCOMPARE(bottomItem->lastEvent.touchPoints.count(), 1);
+ COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchBegin, window, Qt::TouchPointPressed, makeTouchPoint(topItem, pos)));
+ COMPARE_TOUCH_DATA(bottomItem->lastEvent, makeTouchData(QEvent::TouchBegin, window, Qt::TouchPointPressed, makeTouchPoint(bottomItem, pos)));
+ topItem->reset();
+ bottomItem->reset();
+
+ // touch point on top item moves to bottom item, but top item should still receive the event
+ QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(), window);
+ QTest::qWait(50);
+ QTest::touchEvent(window, touchDevice).move(0, bottomItem->mapToScene(pos).toPoint(), window);
+ QTest::qWait(50);
+ QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
+ COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchUpdate, window, Qt::TouchPointMoved,
+ makeTouchPoint(topItem, topItem->mapFromItem(bottomItem, pos), pos)));
+ topItem->reset();
+
+ // touch point on bottom item moves to top item, but bottom item should still receive the event
+ QTest::touchEvent(window, touchDevice).press(0, bottomItem->mapToScene(pos).toPoint(), window);
+ QTest::qWait(50);
+ QTest::touchEvent(window, touchDevice).move(0, topItem->mapToScene(pos).toPoint(), window);
+ QTest::qWait(50);
+ QCOMPARE(bottomItem->lastEvent.touchPoints.count(), 1);
+ COMPARE_TOUCH_DATA(bottomItem->lastEvent, makeTouchData(QEvent::TouchUpdate, window, Qt::TouchPointMoved,
+ makeTouchPoint(bottomItem, bottomItem->mapFromItem(topItem, pos), pos)));
+ bottomItem->reset();
+
+ // a single stationary press on an item shouldn't cause an event
+ QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(), window);
+ QTest::qWait(50);
+ QTest::touchEvent(window, touchDevice).stationary(0)
+ .press(1, bottomItem->mapToScene(pos).toPoint(), window);
+ QTest::qWait(50);
+ QCOMPARE(topItem->lastEvent.touchPoints.count(), 1); // received press only, not stationary
+ QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
+ QCOMPARE(bottomItem->lastEvent.touchPoints.count(), 1);
+ COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchBegin, window, Qt::TouchPointPressed, makeTouchPoint(topItem, pos)));
+ COMPARE_TOUCH_DATA(bottomItem->lastEvent, makeTouchData(QEvent::TouchBegin, window, Qt::TouchPointPressed, makeTouchPoint(bottomItem, pos)));
+ topItem->reset();
+ bottomItem->reset();
+ // cleanup: what is pressed must be released
+ // Otherwise you will get an assertion failure:
+ // ASSERT: "itemForTouchPointId.isEmpty()" in file items/qquickwindow.cpp
+ QTest::touchEvent(window, touchDevice).release(0, pos.toPoint(), window).release(1, pos.toPoint(), window);
+
+ // move touch point from top item to bottom, and release
+ QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(),window);
+ QTest::qWait(50);
+ QTest::touchEvent(window, touchDevice).release(0, bottomItem->mapToScene(pos).toPoint(),window);
+ QTest::qWait(50);
+ QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
+ COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchEnd, window, Qt::TouchPointReleased,
+ makeTouchPoint(topItem, topItem->mapFromItem(bottomItem, pos), pos)));
+ topItem->reset();
+
+ // release while another point is pressed
+ QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(),window)
+ .press(1, bottomItem->mapToScene(pos).toPoint(), window);
+ QTest::qWait(50);
+ QTest::touchEvent(window, touchDevice).move(0, bottomItem->mapToScene(pos).toPoint(), window);
+ QTest::qWait(50);
+ QTest::touchEvent(window, touchDevice).release(0, bottomItem->mapToScene(pos).toPoint(), window)
+ .stationary(1);
+ QTest::qWait(50);
+ QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
+ QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
+ QCOMPARE(bottomItem->lastEvent.touchPoints.count(), 1);
+ COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchEnd, window, Qt::TouchPointReleased,
+ makeTouchPoint(topItem, topItem->mapFromItem(bottomItem, pos))));
+ COMPARE_TOUCH_DATA(bottomItem->lastEvent, makeTouchData(QEvent::TouchBegin, window, Qt::TouchPointPressed, makeTouchPoint(bottomItem, pos)));
+ topItem->reset();
+ bottomItem->reset();
+
+ delete topItem;
+ delete middleItem;
+ delete bottomItem;
+ delete window;
+}
+
+void tst_qquickwindow::touchEvent_propagation()
+{
+ TestTouchItem::clearMousePressCounter();
+
+ QFETCH(bool, acceptTouchEvents);
+ QFETCH(bool, acceptMouseEvents);
+ QFETCH(bool, enableItem);
+ QFETCH(bool, showItem);
+
+ QQuickWindow *window = new QQuickWindow;
+ window->resize(250, 250);
+ window->setPos(100, 100);
+ window->show();
+ QTest::qWaitForWindowShown(window);
+
+ TestTouchItem *bottomItem = new TestTouchItem(window->rootItem());
+ bottomItem->setObjectName("Bottom Item");
+ bottomItem->setSize(QSizeF(150, 150));
+
+ TestTouchItem *middleItem = new TestTouchItem(bottomItem);
+ middleItem->setObjectName("Middle Item");
+ middleItem->setPos(QPointF(50, 50));
+ middleItem->setSize(QSizeF(150, 150));
+
+ TestTouchItem *topItem = new TestTouchItem(middleItem);
+ topItem->setObjectName("Top Item");
+ topItem->setPos(QPointF(50, 50));
+ topItem->setSize(QSizeF(150, 150));
+
+ QPointF pos(10, 10);
+ QPoint pointInBottomItem = bottomItem->mapToScene(pos).toPoint(); // (10, 10)
+ QPoint pointInMiddleItem = middleItem->mapToScene(pos).toPoint(); // (60, 60) overlaps with bottomItem
+ QPoint pointInTopItem = topItem->mapToScene(pos).toPoint(); // (110, 110) overlaps with bottom & top items
+
+ // disable topItem
+ topItem->acceptTouchEvents = acceptTouchEvents;
+ topItem->acceptMouseEvents = acceptMouseEvents;
+ topItem->setEnabled(enableItem);
+ topItem->setVisible(showItem);
+
+ // single touch to top item, should be received by middle item
+ QTest::touchEvent(window, touchDevice).press(0, pointInTopItem, window);
+ QTest::qWait(50);
+ QVERIFY(topItem->lastEvent.touchPoints.isEmpty());
+ QCOMPARE(middleItem->lastEvent.touchPoints.count(), 1);
+ QVERIFY(bottomItem->lastEvent.touchPoints.isEmpty());
+ COMPARE_TOUCH_DATA(middleItem->lastEvent, makeTouchData(QEvent::TouchBegin, window, Qt::TouchPointPressed,
+ makeTouchPoint(middleItem, middleItem->mapFromItem(topItem, pos))));
+
+ // touch top and middle items, middle item should get both events
+ QTest::touchEvent(window, touchDevice).press(0, pointInTopItem, window)
+ .press(1, pointInMiddleItem, window);
+ QTest::qWait(50);
+ QVERIFY(topItem->lastEvent.touchPoints.isEmpty());
+ QCOMPARE(middleItem->lastEvent.touchPoints.count(), 2);
+ QVERIFY(bottomItem->lastEvent.touchPoints.isEmpty());
+ COMPARE_TOUCH_DATA(middleItem->lastEvent, makeTouchData(QEvent::TouchBegin, window, Qt::TouchPointPressed,
+ (QList<QTouchEvent::TouchPoint>() << makeTouchPoint(middleItem, middleItem->mapFromItem(topItem, pos))
+ << makeTouchPoint(middleItem, pos) )));
+ middleItem->reset();
+
+ // disable middleItem as well
+ middleItem->acceptTouchEvents = acceptTouchEvents;
+ middleItem->acceptMouseEvents = acceptMouseEvents;
+ middleItem->setEnabled(enableItem);
+ middleItem->setVisible(showItem);
+
+ // touch top and middle items, bottom item should get all events
+ QTest::touchEvent(window, touchDevice).press(0, pointInTopItem, window)
+ .press(1, pointInMiddleItem, window);
+ QTest::qWait(50);
+ QVERIFY(topItem->lastEvent.touchPoints.isEmpty());
+ QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
+ QCOMPARE(bottomItem->lastEvent.touchPoints.count(), 2);
+ COMPARE_TOUCH_DATA(bottomItem->lastEvent, makeTouchData(QEvent::TouchBegin, window, Qt::TouchPointPressed,
+ (QList<QTouchEvent::TouchPoint>() << makeTouchPoint(bottomItem, bottomItem->mapFromItem(topItem, pos))
+ << makeTouchPoint(bottomItem, bottomItem->mapFromItem(middleItem, pos)) )));
+ bottomItem->reset();
+
+ // disable bottom item as well
+ bottomItem->acceptTouchEvents = acceptTouchEvents;
+ bottomItem->setEnabled(enableItem);
+ bottomItem->setVisible(showItem);
+
+ // no events should be received
+ QTest::touchEvent(window, touchDevice).press(0, pointInTopItem, window)
+ .press(1, pointInMiddleItem, window)
+ .press(2, pointInBottomItem, window);
+ QTest::qWait(50);
+ QVERIFY(topItem->lastEvent.touchPoints.isEmpty());
+ QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
+ QVERIFY(bottomItem->lastEvent.touchPoints.isEmpty());
+
+ topItem->reset();
+ middleItem->reset();
+ bottomItem->reset();
+
+ // disable middle item, touch on top item
+ middleItem->acceptTouchEvents = acceptTouchEvents;
+ middleItem->setEnabled(enableItem);
+ middleItem->setVisible(showItem);
+ QTest::touchEvent(window, touchDevice).press(0, pointInTopItem, window);
+ QTest::qWait(50);
+ if (!enableItem || !showItem) {
+ // middle item is disabled or has 0 opacity, bottom item receives the event
+ QVERIFY(topItem->lastEvent.touchPoints.isEmpty());
+ QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
+ QCOMPARE(bottomItem->lastEvent.touchPoints.count(), 1);
+ COMPARE_TOUCH_DATA(bottomItem->lastEvent, makeTouchData(QEvent::TouchBegin, window, Qt::TouchPointPressed,
+ makeTouchPoint(bottomItem, bottomItem->mapFromItem(topItem, pos))));
+ } else {
+ // middle item ignores event, sends it to the top item (top-most child)
+ QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
+ QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
+ QVERIFY(bottomItem->lastEvent.touchPoints.isEmpty());
+ COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchBegin, window, Qt::TouchPointPressed,
+ makeTouchPoint(topItem, pos)));
+ }
+
+ delete topItem;
+ delete middleItem;
+ delete bottomItem;
+ delete window;
+}
+
+void tst_qquickwindow::touchEvent_propagation_data()
+{
+ QTest::addColumn<bool>("acceptTouchEvents");
+ QTest::addColumn<bool>("acceptMouseEvents");
+ QTest::addColumn<bool>("enableItem");
+ QTest::addColumn<bool>("showItem");
+
+ QTest::newRow("disable events") << false << false << true << true;
+ QTest::newRow("disable item") << true << true << false << true;
+ QTest::newRow("hide item") << true << true << true << false;
+}
+
+void tst_qquickwindow::touchEvent_cancel()
+{
+ TestTouchItem::clearMousePressCounter();
+
+ QQuickWindow *window = new QQuickWindow;
+ window->resize(250, 250);
+ window->setPos(100, 100);
+ window->show();
+ QTest::qWaitForWindowShown(window);
+
+ TestTouchItem *item = new TestTouchItem(window->rootItem());
+ item->setPos(QPointF(50, 50));
+ item->setSize(QSizeF(150, 150));
+
+ QPointF pos(10, 10);
+ QTest::touchEvent(window, touchDevice).press(0, item->mapToScene(pos).toPoint(),window);
+ QCoreApplication::processEvents();
+
+ QTRY_COMPARE(item->lastEvent.touchPoints.count(), 1);
+ TouchEventData d = makeTouchData(QEvent::TouchBegin, window, Qt::TouchPointPressed, makeTouchPoint(item,pos));
+ COMPARE_TOUCH_DATA(item->lastEvent, d);
+ item->reset();
+
+ QWindowSystemInterface::handleTouchCancelEvent(0, touchDevice);
+ QCoreApplication::processEvents();
+ d = makeTouchData(QEvent::TouchCancel, window);
+ COMPARE_TOUCH_DATA(item->lastEvent, d);
+
+ delete item;
+ delete window;
+}
+
+void tst_qquickwindow::touchEvent_reentrant()
+{
+ TestTouchItem::clearMousePressCounter();
+
+ QQuickWindow *window = new QQuickWindow;
+ window->resize(250, 250);
+ window->setPos(100, 100);
+ window->show();
+ QTest::qWaitForWindowShown(window);
+
+ TestTouchItem *item = new TestTouchItem(window->rootItem());
+
+ item->spinLoopWhenPressed = true; // will call processEvents() from the touch handler
+
+ item->setPos(QPointF(50, 50));
+ item->setSize(QSizeF(150, 150));
+ QPointF pos(60, 60);
+
+ // None of these should commit from the dtor.
+ QTest::QTouchEventSequence press = QTest::touchEvent(window, touchDevice, false).press(0, pos.toPoint(), window);
+ pos += QPointF(2, 2);
+ QTest::QTouchEventSequence move = QTest::touchEvent(window, touchDevice, false).move(0, pos.toPoint(), window);
+ QTest::QTouchEventSequence release = QTest::touchEvent(window, touchDevice, false).release(0, pos.toPoint(), window);
+
+ // Now commit (i.e. call QWindowSystemInterface::handleTouchEvent), but do not process the events yet.
+ press.commit(false);
+ move.commit(false);
+ release.commit(false);
+
+ QCoreApplication::processEvents();
+
+ QTRY_COMPARE(item->touchEventCount, 3);
+
+ delete item;
+ delete window;
+}
+
+void tst_qquickwindow::touchEvent_velocity()
+{
+ TestTouchItem::clearMousePressCounter();
+
+ QQuickWindow *window = new QQuickWindow;
+ window->resize(250, 250);
+ window->setPos(100, 100);
+ window->show();
+ QTest::qWaitForWindowShown(window);
+ QTest::qWait(10);
+
+ TestTouchItem *item = new TestTouchItem(window->rootItem());
+ item->setPos(QPointF(50, 50));
+ item->setSize(QSizeF(150, 150));
+
+ QList<QWindowSystemInterface::TouchPoint> points;
+ QWindowSystemInterface::TouchPoint tp;
+ tp.id = 1;
+ tp.state = Qt::TouchPointPressed;
+ QPoint pos = window->mapToGlobal(item->mapToScene(QPointF(10, 10)).toPoint());
+ tp.area = QRectF(pos, QSizeF(4, 4));
+ points << tp;
+ QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
+ points[0].state = Qt::TouchPointMoved;
+ points[0].area.adjust(5, 5, 5, 5);
+ QVector2D velocity(1.5, 2.5);
+ points[0].velocity = velocity;
+ QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
+ QCoreApplication::processEvents();
+ QCOMPARE(item->touchEventCount, 2);
+ QCOMPARE(item->lastEvent.touchPoints.count(), 1);
+ QCOMPARE(item->lastVelocity, velocity);
+
+ // Now have a transformation on the item and check if velocity and position are transformed accordingly.
+ item->setRotation(90); // clockwise
+ QMatrix4x4 transformMatrix;
+ transformMatrix.rotate(-90, 0, 0, 1); // counterclockwise
+ QVector2D transformedVelocity = transformMatrix.mapVector(velocity).toVector2D();
+ points[0].area.adjust(5, 5, 5, 5);
+ QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
+ QCoreApplication::processEvents();
+ QCOMPARE(item->lastVelocity, transformedVelocity);
+ QPoint itemLocalPos = item->mapFromScene(window->mapFromGlobal(points[0].area.center().toPoint())).toPoint();
+ QPoint itemLocalPosFromEvent = item->lastEvent.touchPoints[0].pos().toPoint();
+ QCOMPARE(itemLocalPos, itemLocalPosFromEvent);
+
+ points[0].state = Qt::TouchPointReleased;
+ QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
+ QCoreApplication::processEvents();
+ delete item;
+ delete window;
+}
+
+void tst_qquickwindow::mouseFromTouch_basic()
+{
+ // Turn off accepting touch events with acceptTouchEvents. This
+ // should result in sending mouse events generated from the touch
+ // with the new event propagation system.
+
+ TestTouchItem::clearMousePressCounter();
+ QQuickWindow *window = new QQuickWindow;
+ window->resize(250, 250);
+ window->setPos(100, 100);
+ window->show();
+ QTest::qWaitForWindowShown(window);
+ QTest::qWait(10);
+
+ TestTouchItem *item = new TestTouchItem(window->rootItem());
+ item->setPos(QPointF(50, 50));
+ item->setSize(QSizeF(150, 150));
+ item->acceptTouchEvents = false;
+
+ QList<QWindowSystemInterface::TouchPoint> points;
+ QWindowSystemInterface::TouchPoint tp;
+ tp.id = 1;
+ tp.state = Qt::TouchPointPressed;
+ QPoint pos = window->mapToGlobal(item->mapToScene(QPointF(10, 10)).toPoint());
+ tp.area = QRectF(pos, QSizeF(4, 4));
+ points << tp;
+ QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
+ points[0].state = Qt::TouchPointMoved;
+ points[0].area.adjust(5, 5, 5, 5);
+ QVector2D velocity(1.5, 2.5);
+ points[0].velocity = velocity;
+ QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
+ points[0].state = Qt::TouchPointReleased;
+ QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
+ QCoreApplication::processEvents();
+
+ // The item should have received a mouse press, move, and release.
+ QCOMPARE(item->mousePressNum, 1);
+ QCOMPARE(item->mouseMoveNum, 1);
+ QCOMPARE(item->mouseReleaseNum, 1);
+ QCOMPARE(item->lastMousePos.toPoint(), item->mapFromScene(window->mapFromGlobal(points[0].area.center().toPoint())).toPoint());
+ QCOMPARE(item->lastVelocityFromMouseMove, velocity);
+ QVERIFY((item->lastMouseCapabilityFlags & QTouchDevice::Velocity) != 0);
+
+ // Now the same with a transformation.
+ item->setRotation(90); // clockwise
+ QMatrix4x4 transformMatrix;
+ transformMatrix.rotate(-90, 0, 0, 1); // counterclockwise
+ QVector2D transformedVelocity = transformMatrix.mapVector(velocity).toVector2D();
+ points[0].state = Qt::TouchPointPressed;
+ points[0].velocity = velocity;
+ points[0].area = QRectF(pos, QSizeF(4, 4));
+ QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
+ points[0].state = Qt::TouchPointMoved;
+ points[0].area.adjust(5, 5, 5, 5);
+ QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
+ QCoreApplication::processEvents();
+ QCOMPARE(item->lastMousePos.toPoint(), item->mapFromScene(window->mapFromGlobal(points[0].area.center().toPoint())).toPoint());
+ QCOMPARE(item->lastVelocityFromMouseMove, transformedVelocity);
+
+ points[0].state = Qt::TouchPointReleased;
+ QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
+ QCoreApplication::processEvents();
+ delete item;
+ delete window;
+}
+
+void tst_qquickwindow::clearWindow()
+{
+ QQuickWindow *window = new QQuickWindow;
+ QQuickItem *item = new QQuickItem;
+ item->setParentItem(window->rootItem());
+
+ QVERIFY(item->window() == window);
+
+ delete window;
+
+ QVERIFY(item->window() == 0);
+
+ delete item;
+}
+
+void tst_qquickwindow::mouseFiltering()
+{
+ TestTouchItem::clearMousePressCounter();
+
+ QQuickWindow *window = new QQuickWindow;
+ window->resize(250, 250);
+ window->setPos(100, 100);
+ window->show();
+ QTest::qWaitForWindowShown(window);
+
+ TestTouchItem *bottomItem = new TestTouchItem(window->rootItem());
+ bottomItem->setObjectName("Bottom Item");
+ bottomItem->setSize(QSizeF(150, 150));
+
+ TestTouchItem *middleItem = new TestTouchItem(bottomItem);
+ middleItem->setObjectName("Middle Item");
+ middleItem->setPos(QPointF(50, 50));
+ middleItem->setSize(QSizeF(150, 150));
+
+ TestTouchItem *topItem = new TestTouchItem(middleItem);
+ topItem->setObjectName("Top Item");
+ topItem->setPos(QPointF(50, 50));
+ topItem->setSize(QSizeF(150, 150));
+
+ QPoint pos(100, 100);
+
+ QTest::mousePress(window, Qt::LeftButton, 0, pos);
+
+ // Mouse filtering propagates down the stack, so the
+ // correct order is
+ // 1. middleItem filters event
+ // 2. bottomItem filters event
+ // 3. topItem receives event
+ QTRY_COMPARE(middleItem->mousePressId, 1);
+ QTRY_COMPARE(bottomItem->mousePressId, 2);
+ QTRY_COMPARE(topItem->mousePressId, 3);
+
+ delete window;
+}
+
+void tst_qquickwindow::qmlCreation()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.loadUrl(testFileUrl("window.qml"));
+ QObject* created = component.create();
+ QVERIFY(created);
+
+ QQuickWindow* window = qobject_cast<QQuickWindow*>(created);
+ QVERIFY(window);
+ QCOMPARE(window->color(), QColor(Qt::green));
+
+ QQuickItem* item = window->findChild<QQuickItem*>("item");
+ QVERIFY(item);
+ QCOMPARE(item->window(), window);
+
+ delete window;
+}
+
+void tst_qquickwindow::clearColor()
+{
+ //::grab examines rendering to make sure it works visually
+ QQuickWindow *window = new QQuickWindow;
+ window->resize(250, 250);
+ window->setPos(100, 100);
+ window->setColor(Qt::blue);
+ window->show();
+ QTest::qWaitForWindowShown(window);
+ QCOMPARE(window->color(), QColor(Qt::blue));
+ delete window;
+}
+
+void tst_qquickwindow::grab()
+{
+ QQuickWindow window;
+ window.setColor(Qt::red);
+
+ window.resize(250, 250);
+ window.show();
+
+ QTest::qWaitForWindowShown(&window);
+
+ QImage content = window.grabWindow();
+ QCOMPARE(content.width(), window.width());
+ QCOMPARE(content.height(), window.height());
+ QCOMPARE((uint) content.convertToFormat(QImage::Format_RGB32).pixel(0, 0), (uint) 0xffff0000);
+}
+
+void tst_qquickwindow::multipleWindows()
+{
+ QList<QQuickWindow *> windows;
+ for (int i=0; i<6; ++i) {
+ QQuickWindow *c = new QQuickWindow();
+ c->setColor(Qt::GlobalColor(Qt::red + i));
+ c->resize(300, 200);
+ c->setPos(100 + i * 30, 100 + i * 20);
+ c->show();
+ windows << c;
+ QVERIFY(c->isVisible());
+ }
+
+ // move them
+ for (int i=0; i<windows.size(); ++i) {
+ QQuickWindow *c = windows.at(i);
+ c->setPos(c->x() - 10, c->y() - 10);
+ }
+
+ // resize them
+ for (int i=0; i<windows.size(); ++i) {
+ QQuickWindow *c = windows.at(i);
+ c->resize(200, 150);
+ }
+
+ qDeleteAll(windows);
+}
+
+void tst_qquickwindow::animationsWhileHidden()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.loadUrl(testFileUrl("AnimationsWhileHidden.qml"));
+ QObject* created = component.create();
+
+ QQuickWindow* window = qobject_cast<QQuickWindow*>(created);
+ QVERIFY(window);
+ QVERIFY(window->isVisible());
+
+ // Now hide the window and verify that it went off screen
+ window->hide();
+ QTest::qWait(10);
+ QVERIFY(!window->isVisible());
+
+ // Running animaiton should cause it to become visible again shortly.
+ QTRY_VERIFY(window->isVisible());
+
+ delete window;
+}
+
+
+void tst_qquickwindow::headless()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.loadUrl(testFileUrl("Headless.qml"));
+ QObject* created = component.create();
+
+ QQuickWindow* window = qobject_cast<QQuickWindow*>(created);
+ QVERIFY(window);
+
+ QTest::qWaitForWindowShown(window);
+ QVERIFY(window->isVisible());
+
+ QSignalSpy initialized(window, SIGNAL(sceneGraphInitialized()));
+ QSignalSpy invalidated(window, SIGNAL(sceneGraphInvalidated()));
+
+ // Verify that the window is alive and kicking
+ QVERIFY(window->openglContext() != 0);
+
+ // Store the visual result
+ QImage originalContent = window->grabWindow();
+
+ // Hide the window and verify signal emittion and GL context deletion
+ window->hide();
+ window->releaseResources();
+
+ QTRY_COMPARE(invalidated.size(), 1);
+ QVERIFY(window->openglContext() == 0);
+
+ // Destroy the native windowing system buffers
+ window->destroy();
+ QVERIFY(window->handle() == 0);
+
+ // Show and verify that we are back and running
+ window->show();
+ QTest::qWaitForWindowShown(window);
+
+ QTRY_COMPARE(initialized.size(), 1);
+ QVERIFY(window->openglContext() != 0);
+
+ // Verify that the visual output is the same
+ QImage newContent = window->grabWindow();
+
+ QCOMPARE(originalContent, newContent);
+
+ delete window;
+}
+
+void tst_qquickwindow::focusObject()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.loadUrl(testFileUrl("focus.qml"));
+ QObject *created = component.create();
+ QVERIFY(created);
+
+ QQuickWindow *window = qobject_cast<QQuickWindow*>(created);
+ QVERIFY(window);
+
+ QQuickItem *item1 = window->findChild<QQuickItem*>("item1");
+ QVERIFY(item1);
+ item1->setFocus(true);
+ QCOMPARE(item1, window->focusObject());
+
+ QQuickItem *item2 = window->findChild<QQuickItem*>("item2");
+ QVERIFY(item2);
+ item2->setFocus(true);
+ QCOMPARE(item2, window->focusObject());
+
+ delete window;
+}
+
+void tst_qquickwindow::ignoreUnhandledMouseEvents()
+{
+ QQuickWindow* window = new QQuickWindow;
+ window->resize(100, 100);
+ window->show();
+ QTest::qWaitForWindowShown(window);
+
+ QQuickItem* item = new QQuickItem;
+ item->setSize(QSizeF(100, 100));
+ item->setParentItem(window->rootItem());
+
+ {
+ QMouseEvent me(QEvent::MouseButtonPress, QPointF(50, 50), Qt::LeftButton, Qt::LeftButton,
+ Qt::NoModifier);
+ me.setAccepted(true);
+ QVERIFY(QCoreApplication::sendEvent(window, &me));
+ QVERIFY(!me.isAccepted());
+ }
+
+ {
+ QMouseEvent me(QEvent::MouseMove, QPointF(51, 51), Qt::LeftButton, Qt::LeftButton,
+ Qt::NoModifier);
+ me.setAccepted(true);
+ QVERIFY(QCoreApplication::sendEvent(window, &me));
+ QVERIFY(!me.isAccepted());
+ }
+
+ {
+ QMouseEvent me(QEvent::MouseButtonRelease, QPointF(51, 51), Qt::LeftButton, Qt::LeftButton,
+ Qt::NoModifier);
+ me.setAccepted(true);
+ QVERIFY(QCoreApplication::sendEvent(window, &me));
+ QVERIFY(!me.isAccepted());
+ }
+
+ delete window;
+}
+
+
+void tst_qquickwindow::ownershipRootItem()
+{
+ qmlRegisterType<RootItemAccessor>("QtQuick", 2, 0, "RootItemAccessor");
+
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.loadUrl(testFileUrl("ownershipRootItem.qml"));
+ QObject* created = component.create();
+
+ QQuickWindow* window = qobject_cast<QQuickWindow*>(created);
+ QVERIFY(window);
+ QTest::qWaitForWindowShown(window);
+
+ RootItemAccessor* accessor = window->findChild<RootItemAccessor*>("accessor");
+ QVERIFY(accessor);
+ engine.collectGarbage();
+
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::processEvents();
+ QVERIFY(!accessor->isRootItemDestroyed());
+}
+QTEST_MAIN(tst_qquickwindow)
+
+#include "tst_qquickwindow.moc"