Set rootItem'ownership as CppOwnerShip
authorCharles Yin <charles.yin@nokia.com>
Tue, 17 Apr 2012 06:47:33 +0000 (16:47 +1000)
committerQt by Nokia <qt-info@nokia.com>
Tue, 17 Apr 2012 11:36:22 +0000 (13:36 +0200)
rootItem should not be deleted until the QQuickCanvas itself has been deleted.
Set the rootItem's object ownership to CppOwnerShip can prevent it being destroyed
by javascript destroy() method or v8 garbage collection.

Change-Id: I7d83fec8ffcb8062d143b1b050a38368a2af800f
Reviewed-by: Gunnar Sletta <gunnar.sletta@nokia.com>
Reviewed-by: Martin Jones <martin.jones@nokia.com>
Reviewed-by: J-P Nurmi <j-p.nurmi@nokia.com>
src/quick/items/qquickcanvas.cpp
tests/auto/quick/qquickcanvas/data/ownershipRootItem.qml [new file with mode: 0644]
tests/auto/quick/qquickcanvas/qquickcanvas.pro
tests/auto/quick/qquickcanvas/tst_qquickcanvas.cpp

index 382c5e8..0748dad 100644 (file)
@@ -330,6 +330,7 @@ void QQuickCanvasPrivate::init(QQuickCanvas *c)
     Q_Q(QQuickCanvas);
 
     rootItem = new QQuickRootItem;
+    QQmlEngine::setObjectOwnership(rootItem, QQmlEngine::CppOwnership);
     QQuickItemPrivate *rootItemPrivate = QQuickItemPrivate::get(rootItem);
     rootItemPrivate->canvas = q;
     rootItemPrivate->canvasRefCount = 1;
diff --git a/tests/auto/quick/qquickcanvas/data/ownershipRootItem.qml b/tests/auto/quick/qquickcanvas/data/ownershipRootItem.qml
new file mode 100644 (file)
index 0000000..dfc4159
--- /dev/null
@@ -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
index 817eb25..b9ed73d 100644 (file)
@@ -7,7 +7,7 @@ include (../../shared/util.pri)
 macx:CONFIG -= app_bundle
 
 CONFIG += parallel_test
-QT += core-private gui-private qml-private quick-private testlib
+QT += core-private gui-private qml-private quick-private v8-private testlib
 
 TESTDATA = data/*
 
@@ -15,4 +15,3 @@ OTHER_FILES += \
     data/AnimationsWhileHidden.qml \
     data/Headless.qml
 
-
index 9b33fb1..402e81e 100644 (file)
@@ -50,6 +50,7 @@
 #include <QtGui/QWindowSystemInterface>
 #include "../../shared/util.h"
 #include <QSignalSpy>
+#include <private/qquickcanvas_p.h>
 
 struct TouchEventData {
     QEvent::Type type;
@@ -108,6 +109,36 @@ static TouchEventData makeTouchData(QEvent::Type type, QWindow *w, Qt::TouchPoin
     } \
 }
 
+
+class RootItemAccessor : public QQuickItem
+{
+    Q_OBJECT
+public:
+    RootItemAccessor()
+        : m_rootItemDestroyed(false)
+        , m_rootItem(0)
+    {
+    }
+    Q_INVOKABLE QQuickItem *rootItem()
+    {
+        if (!m_rootItem) {
+            QQuickCanvasPrivate *c = QQuickCanvasPrivate::get(canvas());
+            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
@@ -214,6 +245,7 @@ private slots:
 
     void ignoreUnhandledMouseEvents();
 
+    void ownershipRootItem();
 private:
     QTouchDevice *touchDevice;
 };
@@ -770,6 +802,28 @@ void tst_qquickcanvas::ignoreUnhandledMouseEvents()
     delete canvas;
 }
 
+
+void tst_qquickcanvas::ownershipRootItem()
+{
+    qmlRegisterType<RootItemAccessor>("QtQuick", 2, 0, "RootItemAccessor");
+
+    QQmlEngine engine;
+    QQmlComponent component(&engine);
+    component.loadUrl(testFileUrl("ownershipRootItem.qml"));
+    QObject* created = component.create();
+
+    QQuickCanvas* canvas = qobject_cast<QQuickCanvas*>(created);
+    QVERIFY(canvas);
+    QTest::qWaitForWindowShown(canvas);
+
+    RootItemAccessor* accessor = canvas->findChild<RootItemAccessor*>("accessor");
+    QVERIFY(accessor);
+    engine.collectGarbage();
+
+    QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+    QCoreApplication::processEvents();
+    QVERIFY(!accessor->isRootItemDestroyed());
+}
 QTEST_MAIN(tst_qquickcanvas)
 
 #include "tst_qquickcanvas.moc"