Commit c193fd4c authored by Marco Martin's avatar Marco Martin Committed by Fushan Wen
Browse files

never delete any dialog if there is a drag in progress anywhere

on Wayland deleting either the source or the target of a qdrag
causes crashes due to the nested event loops.
keep a global track if any item started a drag anywhere, if so
don't delete any dialog but queue it for destruction

BUG:399864
parent 48693cd9
......@@ -33,6 +33,7 @@ FocusScope {
property alias positions: positioner.positions
property alias errorString: dir.errorString
property alias dragging: dir.dragging
property alias dragInProgressAnywhere: dir.dragInProgressAnywhere
property alias locked: dir.locked
property alias sortMode: dir.sortMode
property alias filterMode: dir.filterMode
......
......@@ -70,8 +70,8 @@ Folder.SubDialog {
flow: GridView.FlowLeftToRight
layoutDirection: Qt.LeftToRight
onDraggingChanged: {
if (!dragging && !dialog.visible) {
onDragInProgressAnywhereChanged: {
if (!dragInProgressAnywhere && !dialog.visible) {
dialog.destroy();
}
}
......@@ -97,7 +97,7 @@ Folder.SubDialog {
]
function requestDestroy() {
if (folderView.dragging) {
if (folderView.dragInProgressAnywhere) {
visible = false;
} else {
destroy();
......
......@@ -72,6 +72,56 @@
Q_LOGGING_CATEGORY(FOLDERMODEL, "plasma.containments.desktop.folder.foldermodel")
class DragTrackerSingleton
{
public:
DragTracker self;
};
Q_GLOBAL_STATIC(DragTrackerSingleton, privateDragTrackerSelf)
DragTracker::DragTracker(QObject *parent)
: QObject(parent)
{
}
DragTracker::~DragTracker()
{
}
bool DragTracker::isDragInProgress() const
{
return m_dragInProgress;
}
void DragTracker::setDragInProgress(FolderModel *dragOwner, bool dragInProgress)
{
if (dragInProgress == m_dragInProgress) {
return;
}
m_dragInProgress = dragInProgress;
if (dragInProgress) {
m_dragOwner = dragOwner;
} else {
m_dragOwner.clear();
}
Q_EMIT dragInProgressChanged(m_dragInProgress);
}
FolderModel *DragTracker::dragOwner()
{
return m_dragOwner;
}
DragTracker *DragTracker::self()
{
return &privateDragTrackerSelf()->self;
}
DirLister::DirLister(QObject *parent)
: KDirLister(parent)
{
......@@ -94,7 +144,6 @@ void DirLister::handleError(KIO::Job *job)
FolderModel::FolderModel(QObject *parent)
: QSortFilterProxyModel(parent)
, m_dirWatch(nullptr)
, m_dragInProgress(false)
, m_urlChangedWhileDragging(false)
, m_dropTargetPositionsCleanup(new QTimer(this))
, m_previewGenerator(nullptr)
......@@ -115,6 +164,8 @@ FolderModel::FolderModel(QObject *parent)
, m_screenMapper(ScreenMapper::instance())
, m_complete(false)
{
connect(DragTracker::self(), &DragTracker::dragInProgressChanged, this, &FolderModel::draggingChanged);
connect(DragTracker::self(), &DragTracker::dragInProgressChanged, this, &FolderModel::dragInProgressAnywhereChanged);
// needed to pass the job around with qml
qmlRegisterType<KIO::DropJob>();
DirLister *dirLister = new DirLister(this);
......@@ -324,7 +375,7 @@ void FolderModel::setUrl(const QString &url)
m_dirWatch->addFile(resolvedNewUrl.toLocalFile() + QLatin1String("/.directory"));
}
if (m_dragInProgress) {
if (dragging()) {
m_urlChangedWhileDragging = true;
}
......@@ -385,7 +436,12 @@ QString FolderModel::errorString() const
bool FolderModel::dragging() const
{
return m_dragInProgress;
return DragTracker::self()->isDragInProgress() && DragTracker::self()->dragOwner() == this;
}
bool FolderModel::isDragInProgressAnywhere() const
{
return DragTracker::self()->isDragInProgress();
}
bool FolderModel::usedByContainment() const
......@@ -945,12 +1001,11 @@ void FolderModel::addDragImage(QDrag *drag, int x, int y)
void FolderModel::dragSelected(int x, int y)
{
if (m_dragInProgress) {
if (dragging()) {
return;
}
m_dragInProgress = true;
Q_EMIT draggingChanged();
DragTracker::self()->setDragInProgress(this, true);
m_urlChangedWhileDragging = false;
// Avoid starting a drag synchronously in a mouse handler or interferes with
......@@ -962,8 +1017,7 @@ void FolderModel::dragSelected(int x, int y)
void FolderModel::dragSelectedInternal(int x, int y)
{
if (!m_viewAdapter || !m_selectionModel->hasSelection()) {
m_dragInProgress = false;
Q_EMIT draggingChanged();
DragTracker::self()->setDragInProgress(nullptr, false);
return;
}
......@@ -1000,8 +1054,7 @@ void FolderModel::dragSelectedInternal(int x, int y)
item->ungrabMouse();
m_dragInProgress = false;
Q_EMIT draggingChanged();
DragTracker::self()->setDragInProgress(nullptr, false);
m_urlChangedWhileDragging = false;
if (m_dirModel->dirLister()->url() == currentUrl) {
......@@ -1107,7 +1160,7 @@ void FolderModel::drop(QQuickItem *target, QObject *dropEvent, int row, bool sho
const int y = dropEvent->property("y").toInt();
const QPoint dropPos = {x, y};
if (m_dragInProgress && row == -1 && !m_urlChangedWhileDragging) {
if (dragging() && row == -1 && !m_urlChangedWhileDragging) {
if (m_locked || mimeData->urls().isEmpty()) {
return;
}
......
......@@ -74,6 +74,7 @@ class FOLDERPLUGIN_TESTS_EXPORT FolderModel : public QSortFilterProxyModel, publ
Q_PROPERTY(Status status READ status NOTIFY statusChanged)
Q_PROPERTY(QString errorString READ errorString NOTIFY errorStringChanged)
Q_PROPERTY(bool dragging READ dragging NOTIFY draggingChanged)
Q_PROPERTY(bool dragInProgressAnywhere READ isDragInProgressAnywhere NOTIFY dragInProgressAnywhereChanged)
Q_PROPERTY(bool usedByContainment READ usedByContainment WRITE setUsedByContainment NOTIFY usedByContainmentChanged)
Q_PROPERTY(bool locked READ locked WRITE setLocked NOTIFY lockedChanged)
Q_PROPERTY(int sortMode READ sortMode WRITE setSortMode NOTIFY sortModeChanged)
......@@ -140,6 +141,7 @@ public:
QString errorString() const;
bool dragging() const;
bool isDragInProgressAnywhere() const;
bool usedByContainment() const;
void setUsedByContainment(bool used);
......@@ -248,6 +250,7 @@ Q_SIGNALS:
void statusChanged() const;
void errorStringChanged() const;
void draggingChanged() const;
void dragInProgressAnywhereChanged() const;
void usedByContainmentChanged() const;
void lockedChanged() const;
void sortModeChanged() const;
......@@ -312,7 +315,6 @@ private:
QModelIndexList m_dragIndexes;
QHash<int, DragImage *> m_dragImages;
QPoint m_dragHotSpotScrollOffset;
bool m_dragInProgress;
bool m_urlChangedWhileDragging;
// target filename to target position of a drop event, note that this deliberately
// is not using the URL to easily support desktop:/ URL schemes
......@@ -351,4 +353,26 @@ private:
QPoint m_menuPosition;
};
class DragTracker : public QObject
{
Q_OBJECT
public:
DragTracker(QObject *parent = nullptr);
~DragTracker();
bool isDragInProgress() const;
void setDragInProgress(FolderModel *dragOwner, bool drag);
FolderModel *dragOwner();
static DragTracker *self();
Q_SIGNALS:
void dragInProgressChanged(bool dragInProgress);
private:
bool m_dragInProgress = false;
QPointer<FolderModel> m_dragOwner;
};
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment