aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items/qquickdrag.cpp
diff options
context:
space:
mode:
authorAndrew den Exter <andrew.den-exter@nokia.com>2012-01-27 14:56:07 +1000
committerQt by Nokia <qt-info@nokia.com>2012-02-01 08:37:49 +0100
commit94c85b4e0b449c8a29e17c5aadea243d3d35da77 (patch)
tree404f5ee3e4052ad70f4c783a938fd3ee8f8ead4d /src/quick/items/qquickdrag.cpp
parent331ea0aee6d0bb54625b25a6c8d2e59d2378fd50 (diff)
Guard against event recursion in QQuickDrag.
Do not emit drag events recursively as this will send events out of order and corrupt the grab stack. Change-Id: Ieede7123c96304e23c809ac895318ed76c8c95c1 Reviewed-by: Martin Jones <martin.jones@nokia.com>
Diffstat (limited to 'src/quick/items/qquickdrag.cpp')
-rw-r--r--src/quick/items/qquickdrag.cpp47
1 files changed, 38 insertions, 9 deletions
diff --git a/src/quick/items/qquickdrag.cpp b/src/quick/items/qquickdrag.cpp
index a906af3d71..c44e1acd4b 100644
--- a/src/quick/items/qquickdrag.cpp
+++ b/src/quick/items/qquickdrag.cpp
@@ -45,7 +45,7 @@
#include <QtQuick/private/qquickevents_p_p.h>
#include <private/qquickitemchangelistener_p.h>
#include <private/qv8engine_p.h>
-
+#include <QtDeclarative/qdeclarativeinfo.h>
#include <QtGui/qevent.h>
QT_BEGIN_NAMESPACE
@@ -64,10 +64,12 @@ public:
, supportedActions(Qt::MoveAction | Qt::CopyAction | Qt::LinkAction)
, active(false)
, listening(false)
+ , inEvent(false)
{
}
void itemGeometryChanged(QQuickItem *, const QRectF &, const QRectF &);
+ void deliverEvent(QQuickCanvas *canvas, QEvent *event);
void start() { start(supportedActions); }
void start(Qt::DropActions supportedActions);
void setTarget(QQuickItem *item);
@@ -82,6 +84,7 @@ public:
Qt::DropActions supportedActions;
bool active : 1;
bool listening : 1;
+ bool inEvent : 1;
QPointF hotSpot;
QStringList keys;
};
@@ -116,14 +119,14 @@ public:
void QQuickDragAttachedPrivate::itemGeometryChanged(QQuickItem *, const QRectF &newGeometry, const QRectF &oldGeometry)
{
Q_Q(QQuickDragAttached);
- if (newGeometry.topLeft() == oldGeometry.topLeft() || !active)
+ if (newGeometry.topLeft() == oldGeometry.topLeft() || !active || inEvent)
return;
if (QQuickCanvas *canvas = attachedItem->canvas()) {
QPoint scenePos = attachedItem->mapToScene(hotSpot).toPoint();
QDragMoveEvent event(scenePos, mimeData->m_supportedActions, mimeData, Qt::NoButton, Qt::NoModifier);
QQuickDropEventEx::setProposedAction(&event, proposedAction);
- QQuickCanvasPrivate::get(canvas)->deliverDragEvent(&dragGrabber, &event);
+ deliverEvent(canvas, &event);
if (target != dragGrabber.target()) {
target = dragGrabber.target();
emit q->targetChanged();
@@ -131,6 +134,14 @@ void QQuickDragAttachedPrivate::itemGeometryChanged(QQuickItem *, const QRectF &
}
}
+void QQuickDragAttachedPrivate::deliverEvent(QQuickCanvas *canvas, QEvent *event)
+{
+ Q_ASSERT(!inEvent);
+ inEvent = true;
+ QQuickCanvasPrivate::get(canvas)->deliverDragEvent(&dragGrabber, event);
+ inEvent = false;
+}
+
QQuickDragAttached::QQuickDragAttached(QObject *parent)
: QObject(*new QQuickDragAttachedPrivate, parent)
{
@@ -168,7 +179,9 @@ void QQuickDragAttached::setActive(bool active)
{
Q_D(QQuickDragAttached);
if (d->active != active) {
- if (active)
+ if (d->inEvent)
+ qmlInfo(this) << "active cannot be changed from within a drag event handler";
+ else if (active)
d->start(d->supportedActions);
else
cancel();
@@ -345,7 +358,7 @@ void QQuickDragAttachedPrivate::start(Qt::DropActions supportedActions)
QPoint scenePos = attachedItem->mapToScene(hotSpot).toPoint();
QDragEnterEvent event(scenePos, supportedActions, mimeData, Qt::NoButton, Qt::NoModifier);
QQuickDropEventEx::setProposedAction(&event, proposedAction);
- QQuickCanvasPrivate::get(canvas)->deliverDragEvent(&dragGrabber, &event);
+ deliverEvent(canvas, &event);
emit q->activeChanged();
if (target != dragGrabber.target()) {
@@ -367,6 +380,11 @@ void QQuickDragAttachedPrivate::start(Qt::DropActions supportedActions)
void QQuickDragAttached::start(QDeclarativeV8Function *args)
{
Q_D(QQuickDragAttached);
+ if (d->inEvent) {
+ qmlInfo(this) << "start() cannot be called from within a drag event handler";
+ return;
+ }
+
if (d->active)
cancel();
@@ -405,8 +423,14 @@ int QQuickDragAttached::drop()
Q_D(QQuickDragAttached);
Qt::DropAction acceptedAction = Qt::IgnoreAction;
+ if (d->inEvent) {
+ qmlInfo(this) << "drop() cannot be called from within a drag event handler";
+ return acceptedAction;
+ }
+
if (!d->active)
return acceptedAction;
+ d->active = false;
QObject *target = 0;
@@ -416,7 +440,7 @@ int QQuickDragAttached::drop()
QDropEvent event(
scenePos, d->mimeData->m_supportedActions, d->mimeData, Qt::NoButton, Qt::NoModifier);
QQuickDropEventEx::setProposedAction(&event, d->proposedAction);
- QQuickCanvasPrivate::get(canvas)->deliverDragEvent(&d->dragGrabber, &event);
+ d->deliverEvent(canvas, &event);
if (event.isAccepted()) {
acceptedAction = event.dropAction();
@@ -424,7 +448,6 @@ int QQuickDragAttached::drop()
}
}
- d->active = false;
if (d->target != target) {
d->target = target;
emit targetChanged();
@@ -443,15 +466,21 @@ int QQuickDragAttached::drop()
void QQuickDragAttached::cancel()
{
Q_D(QQuickDragAttached);
+
+ if (d->inEvent) {
+ qmlInfo(this) << "cancel() cannot be called from within a drag event handler";
+ return;
+ }
+
if (!d->active)
return;
+ d->active = false;
if (QQuickCanvas *canvas = d->attachedItem->canvas()) {
QDragLeaveEvent event;
- QQuickCanvasPrivate::get(canvas)->deliverDragEvent(&d->dragGrabber, &event);
+ d->deliverEvent(canvas, &event);
}
- d->active = false;
if (d->target) {
d->target = 0;
emit targetChanged();