aboutsummaryrefslogtreecommitdiffstats
path: root/src/declarative/items/qsgcanvas.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative/items/qsgcanvas.cpp')
-rw-r--r--src/declarative/items/qsgcanvas.cpp97
1 files changed, 96 insertions, 1 deletions
diff --git a/src/declarative/items/qsgcanvas.cpp b/src/declarative/items/qsgcanvas.cpp
index dce5fe0888..3a88fbb790 100644
--- a/src/declarative/items/qsgcanvas.cpp
+++ b/src/declarative/items/qsgcanvas.cpp
@@ -45,6 +45,8 @@
#include "qsgitem.h"
#include "qsgitem_p.h"
+#include "qsgevent.h"
+
#include <private/qsgrenderer_p.h>
#include <private/qsgflashnode_p.h>
@@ -987,6 +989,12 @@ bool QSGCanvas::event(QEvent *e)
d->clearHover();
d->lastMousePosition = QPoint();
break;
+ case QSGEvent::SGDragEnter:
+ case QSGEvent::SGDragExit:
+ case QSGEvent::SGDragMove:
+ case QSGEvent::SGDragDrop:
+ d->deliverDragEvent(static_cast<QSGDragEvent *>(e));
+ break;
default:
break;
}
@@ -1446,6 +1454,78 @@ bool QSGCanvasPrivate::deliverTouchPoints(QSGItem *item, QTouchEvent *event, con
return false;
}
+void QSGCanvasPrivate::deliverDragEvent(QSGDragEvent *event)
+{
+ Q_Q(QSGCanvas);
+ if (event->type() == QSGEvent::SGDragExit || event->type() == QSGEvent::SGDragDrop) {
+ if (QSGItem *grabItem = event->grabItem()) {
+ event->setPosition(grabItem->mapFromScene(event->scenePosition()));
+ q->sendEvent(grabItem, event);
+ }
+ } else if (!deliverDragEvent(rootItem, event)) {
+ if (QSGItem *grabItem = event->grabItem()) {
+ QSGDragEvent exitEvent(QSGEvent::SGDragExit, *event);
+ exitEvent.setPosition(grabItem->mapFromScene(event->scenePosition()));
+ q->sendEvent(grabItem, &exitEvent);
+ event->setDropItem(0);
+ event->setGrabItem(0);
+ }
+ event->setAccepted(false);
+ }
+}
+
+bool QSGCanvasPrivate::deliverDragEvent(QSGItem *item, QSGDragEvent *event)
+{
+ Q_Q(QSGCanvas);
+ QSGItemPrivate *itemPrivate = QSGItemPrivate::get(item);
+ if (itemPrivate->opacity == 0.0)
+ return false;
+
+ if (itemPrivate->flags & QSGItem::ItemClipsChildrenToShape) {
+ QPointF p = item->mapFromScene(event->scenePosition());
+ if (!QRectF(0, 0, item->width(), item->height()).contains(p))
+ return false;
+ }
+
+ QList<QSGItem *> children = itemPrivate->paintOrderChildItems();
+ for (int ii = children.count() - 1; ii >= 0; --ii) {
+ QSGItem *child = children.at(ii);
+ if (!child->isVisible() || !child->isEnabled())
+ continue;
+ if (deliverDragEvent(child, event))
+ return true;
+ }
+
+ QPointF p = item->mapFromScene(event->scenePosition());
+ if (QRectF(0, 0, item->width(), item->height()).contains(p)) {
+ event->setPosition(p);
+
+ if (event->type() == QSGEvent::SGDragMove && item != event->grabItem()) {
+ QSGDragEvent enterEvent(QSGEvent::SGDragEnter, *event);
+ q->sendEvent(item, &enterEvent);
+ if (enterEvent.isAccepted()) {
+ if (QSGItem *grabItem = event->grabItem()) {
+ QSGDragEvent exitEvent(QSGEvent::SGDragExit, *event);
+ q->sendEvent(grabItem, &exitEvent);
+ }
+ event->setDropItem(enterEvent.dropItem());
+ event->setGrabItem(item);
+ } else {
+ return false;
+ }
+ }
+
+ q->sendEvent(item, event);
+ if (event->isAccepted()) {
+ event->setGrabItem(item);
+ return true;
+ }
+ event->setAccepted(true);
+ }
+
+ return false;
+}
+
bool QSGCanvasPrivate::sendFilteredMouseEvent(QSGItem *target, QSGItem *item, QGraphicsSceneMouseEvent *event)
{
if (!target)
@@ -1521,6 +1601,12 @@ bool QSGCanvas::sendEvent(QSGItem *item, QEvent *e)
case QEvent::TouchEnd:
QSGItemPrivate::get(item)->deliverTouchEvent(static_cast<QTouchEvent *>(e));
break;
+ case QSGEvent::SGDragEnter:
+ case QSGEvent::SGDragExit:
+ case QSGEvent::SGDragMove:
+ case QSGEvent::SGDragDrop:
+ QSGItemPrivate::get(item)->deliverDragEvent(static_cast<QSGDragEvent *>(e));
+ break;
default:
break;
}
@@ -1804,7 +1890,14 @@ void QSGCanvas::maybeUpdate()
Q_D(QSGCanvas);
if (d->threadedRendering && d->thread && d->thread->isRunning()) {
- if (!d->renderThreadAwakened) {
+ Q_ASSERT_X(QThread::currentThread() == QApplication::instance()->thread() || d->thread->inSync,
+ "QSGCanvas::update",
+ "Function can only be called from GUI thread or during QSGItem::updatePaintNode()");
+
+ if (d->thread->inSync) {
+ d->thread->isExternalUpdatePending = true;
+
+ } else if (!d->renderThreadAwakened) {
#ifdef THREAD_DEBUG
printf("GUI: doing update...\n");
#endif
@@ -1911,7 +2004,9 @@ void QSGCanvasRenderThread::run()
#ifdef THREAD_DEBUG
printf(" RenderThread: Doing locked sync\n");
#endif
+ inSync = true;
d->syncSceneGraph();
+ inSync = false;
// Wake GUI after sync to let it continue animating and event processing.
wake();