summaryrefslogtreecommitdiff
path: root/src/declarative/items/qquickcanvas.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative/items/qquickcanvas.cpp')
-rw-r--r--src/declarative/items/qquickcanvas.cpp102
1 files changed, 87 insertions, 15 deletions
diff --git a/src/declarative/items/qquickcanvas.cpp b/src/declarative/items/qquickcanvas.cpp
index b39c9721bf..d191e8fd15 100644
--- a/src/declarative/items/qquickcanvas.cpp
+++ b/src/declarative/items/qquickcanvas.cpp
@@ -132,9 +132,13 @@ public:
: updatePending(false)
, animationRunning(false)
{
- qWarning("QQuickCanvas: using non-threaded render loop. Be very sure to not access scene graph "
- "objects outside the QQuickItem::updatePaintNode() call. Failing to do so will cause "
- "your code to crash on other platforms!");
+ static bool warningMessage = false;
+ if (!warningMessage) {
+ warningMessage = true;
+ qWarning("QQuickCanvas: using non-threaded render loop. Be very sure to not access scene "
+ "graph objects outside the QQuickItem::updatePaintNode() call. Failing to do so "
+ "will cause your code to crash on other platforms!");
+ }
}
virtual void paint() {
@@ -495,6 +499,12 @@ void QQuickCanvasPrivate::init(QQuickCanvas *c)
rootItemPrivate->canvas = q;
rootItemPrivate->flags |= QQuickItem::ItemIsFocusScope;
+ // In the absence of a focus in event on some platforms assume the window will
+ // be activated immediately and set focus on the rootItem
+ // ### Remove when QTBUG-22415 is resolved.
+ //It is important that this call happens after the rootItem has a canvas..
+ rootItem->setFocus(true);
+
bool threaded = !qmlNoThreadedRenderer();
if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ThreadedOpenGL)) {
@@ -633,13 +643,13 @@ void QQuickCanvasPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *item, F
}
if (!(options & DontChangeFocusProperty)) {
- if (item != rootItem || QGuiApplication::focusWindow() == q) {
+// if (item != rootItem || QGuiApplication::focusWindow() == q) { // QTBUG-22415
itemPrivate->focus = true;
changed << item;
- }
+// }
}
- if (newActiveFocusItem && QGuiApplication::focusWindow() == q) {
+ if (newActiveFocusItem && rootItem->hasFocus()) {
activeFocusItem = newActiveFocusItem;
QQuickItemPrivate::get(newActiveFocusItem)->activeFocus = true;
@@ -783,6 +793,9 @@ void QQuickCanvasPrivate::updateInputMethodData()
qApp->inputPanel()->setInputItem(inputItem);
}
+/*!
+ Queries the Input Method.
+*/
QVariant QQuickCanvas::inputMethodQuery(Qt::InputMethodQuery query) const
{
Q_D(const QQuickCanvas);
@@ -818,6 +831,19 @@ void QQuickCanvasPrivate::cleanup(QSGNode *n)
}
+/*!
+ \class QQuickCanvas
+ \since QtQuick 2.0
+ \brief The QQuickCanvas class provides the canvas for displaying a graphical QML scene
+
+ QQuickCanvas provides the graphical scene management needed to interact with and display
+ a scene of QQuickItems.
+
+ A QQuickCanvas always has a single invisible root item. To add items to this canvas,
+ reparent the items to the root item or to an existing item in the scene.
+
+ For easily displaying a scene from a QML file, see \l{QQuickView}.
+*/
QQuickCanvas::QQuickCanvas(QWindow *parent)
: QWindow(*(new QQuickCanvasPrivate), parent)
{
@@ -853,6 +879,12 @@ QQuickCanvas::~QQuickCanvas()
d->cleanupNodes();
}
+/*!
+ Returns the invisible root item of the scene.
+
+ A QQuickCanvas always has a single invisible root item. To add items to this canvas,
+ reparent the items to the root item or to an existing item in the scene.
+*/
QQuickItem *QQuickCanvas::rootItem() const
{
Q_D(const QQuickCanvas);
@@ -860,6 +892,9 @@ QQuickItem *QQuickCanvas::rootItem() const
return d->rootItem;
}
+/*!
+ Returns the item which currently has active focus.
+*/
QQuickItem *QQuickCanvas::activeFocusItem() const
{
Q_D(const QQuickCanvas);
@@ -867,6 +902,9 @@ QQuickItem *QQuickCanvas::activeFocusItem() const
return d->activeFocusItem;
}
+/*!
+ Returns the item which currently has the mouse grab.
+*/
QQuickItem *QQuickCanvas::mouseGrabberItem() const
{
Q_D(const QQuickCanvas);
@@ -1496,7 +1534,7 @@ bool QQuickCanvasPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QQuickIte
return accepted;
}
-bool QQuickCanvasPrivate::sendFilteredMouseEvent(QQuickItem *target, QQuickItem *item, QMouseEvent *event)
+bool QQuickCanvasPrivate::sendFilteredMouseEvent(QQuickItem *target, QQuickItem *item, QEvent *event)
{
if (!target)
return false;
@@ -1512,6 +1550,9 @@ bool QQuickCanvasPrivate::sendFilteredMouseEvent(QQuickItem *target, QQuickItem
return false;
}
+/*!
+ Propagates an event to a QQuickItem on the canvas
+*/
bool QQuickCanvas::sendEvent(QQuickItem *item, QEvent *e)
{
Q_D(QQuickCanvas);
@@ -1550,12 +1591,9 @@ bool QQuickCanvas::sendEvent(QQuickItem *item, QEvent *e)
case QEvent::MouseButtonDblClick:
case QEvent::MouseMove:
// XXX todo - should sendEvent be doing this? how does it relate to forwarded events?
- {
- QMouseEvent *se = static_cast<QMouseEvent *>(e);
- if (!d->sendFilteredMouseEvent(item->parentItem(), item, se)) {
- se->accept();
- QQuickItemPrivate::get(item)->deliverMouseEvent(se);
- }
+ if (!d->sendFilteredMouseEvent(item->parentItem(), item, e)) {
+ e->accept();
+ QQuickItemPrivate::get(item)->deliverMouseEvent(static_cast<QMouseEvent *>(e));
}
break;
case QEvent::Wheel:
@@ -1569,7 +1607,11 @@ bool QQuickCanvas::sendEvent(QQuickItem *item, QEvent *e)
case QEvent::TouchBegin:
case QEvent::TouchUpdate:
case QEvent::TouchEnd:
- QQuickItemPrivate::get(item)->deliverTouchEvent(static_cast<QTouchEvent *>(e));
+ // XXX todo - should sendEvent be doing this? how does it relate to forwarded events?
+ if (!d->sendFilteredMouseEvent(item->parentItem(), item, e)) {
+ e->accept();
+ QQuickItemPrivate::get(item)->deliverTouchEvent(static_cast<QTouchEvent *>(e));
+ }
break;
case QEvent::DragEnter:
case QEvent::DragMove:
@@ -1591,6 +1633,30 @@ void QQuickCanvasPrivate::cleanupNodes()
cleanupNodeList.clear();
}
+void QQuickCanvasPrivate::cleanupNodesOnShutdown(QQuickItem *item)
+{
+ QQuickItemPrivate *p = QQuickItemPrivate::get(item);
+ if (p->itemNodeInstance) {
+ delete p->itemNodeInstance;
+ p->itemNodeInstance = 0;
+ p->opacityNode = 0;
+ p->clipNode = 0;
+ p->groupNode = 0;
+ p->paintNode = 0;
+ }
+
+ for (int ii = 0; ii < p->childItems.count(); ++ii)
+ cleanupNodesOnShutdown(p->childItems.at(ii));
+}
+
+// This must be called from the render thread, with the main thread frozen
+void QQuickCanvasPrivate::cleanupNodesOnShutdown()
+{
+ cleanupNodes();
+
+ cleanupNodesOnShutdown(rootItem);
+}
+
void QQuickCanvasPrivate::updateDirtyNodes()
{
#ifdef DIRTY_DEBUG
@@ -1937,7 +2003,8 @@ QImage QQuickCanvas::grabFrameBuffer()
/*!
Returns an incubation controller that splices incubation between frames
- for this canvas. QQuickView automatically installs this controller for you.
+ for this canvas. QQuickView automatically installs this controller for you,
+ otherwise you will need to install it yourself using \l{QDeclarativeEngine::setIncubationController}
The controller is owned by the canvas and will be destroyed when the canvas
is deleted.
@@ -2094,6 +2161,11 @@ void QQuickCanvasRenderThread::run()
}
#ifdef THREAD_DEBUG
+ printf(" RenderThread: deleting all outstanding nodes\n");
+#endif
+ cleanupNodesOnShutdown();
+
+#ifdef THREAD_DEBUG
printf(" RenderThread: render loop exited... Good Night!\n");
#endif