Drag'n'Drop: fix attached Drag object deleted when DnD is progressing

The attached Drag object's owner, i.e. its parent, is also the dragged
item. So the attached Drag object will also be destroyed as the dragged
item is deleted.

Fixes: QTBUG-65701
Change-Id: I39b0a3180f205c427deed5c70cd1912524f9324e
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
bb10
Yulong Bai 2019-10-10 23:05:16 +02:00
parent 73cb5cb01e
commit a21d4395f4
4 changed files with 19 additions and 9 deletions

View File

@ -113,11 +113,12 @@ Qt::DropAction QDragManager::drag(QDrag *o)
m_object->d_func()->target = 0;
QGuiApplicationPrivate::instance()->notifyDragStarted(o);
QGuiApplicationPrivate::instance()->notifyDragStarted(m_object.data());
const Qt::DropAction result = m_platformDrag->drag(m_object);
m_object = 0;
if (!m_platformDrag->ownsDragObject())
o->deleteLater();
if (!m_object.isNull() && !m_platformDrag->ownsDragObject())
m_object->deleteLater();
m_object.clear();
return result;
}

View File

@ -101,13 +101,13 @@ public:
void setCurrentTarget(QObject *target, bool dropped = false);
QObject *currentTarget() const;
QDrag *object() const { return m_object; }
QPointer<QDrag> object() const { return m_object; }
QObject *source() const;
private:
QObject *m_currentDropTarget;
QPlatformDrag *m_platformDrag;
QDrag *m_object;
QPointer<QDrag> m_object;
static QDragManager *m_instance;
Q_DISABLE_COPY_MOVE(QDragManager)

View File

@ -279,8 +279,11 @@ Qt::DropAction QDrag::exec(Qt::DropActions supportedActions, Qt::DropAction defa
}
d->supported_actions = supportedActions;
d->default_action = transformedDefaultDropAction;
d->executed_action = QDragManager::self()->drag(this);
QPointer<QDrag> self = this;
auto executed_action = QDragManager::self()->drag(self.data());
if (self.isNull())
return Qt::IgnoreAction;
d->executed_action = executed_action;
return d->executed_action;
}

View File

@ -354,6 +354,11 @@ bool QXcbDrag::findXdndAwareTarget(const QPoint &globalPos, xcb_window_t *target
void QXcbDrag::move(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
{
// currentDrag() might be deleted while 'drag' is progressing
if (!currentDrag()) {
cancel();
return;
}
// The source sends XdndEnter and XdndPosition to the target.
if (source_sameanswer.contains(globalPos) && source_sameanswer.isValid())
return;
@ -1076,7 +1081,8 @@ void QXcbDrag::cancel()
send_leave();
// remove canceled object
currentDrag()->deleteLater();
if (currentDrag())
currentDrag()->deleteLater();
canceled = true;
}