Client: Don't freeze in QDrag::exec if there was no drag focus
002fade6 fixed a crash when starting a drag without a valid focus, but there is still a problem, because QDrag::exec will never return because it's waiting indefinitely in an event loop. - QWaylandDataDevice::startDrag can now fail by returning false. - When starting a drag fails, we cancel the drag through QWaylandDrag::cancelDrag wrapped in invokeMethod. - Also, don't unnecessarily create a data_source if we cannot start a drag. [ChangeLog][QPA plugin] Fixed a freeze that happened when starting a drag-and-drop operation without a valid source surface. Change-Id: Iea19b0c92c196a44d1274a966bee4ff519632d34 Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
This commit is contained in:
parent
d87b6d8231
commit
59486fdf3b
@ -102,19 +102,22 @@ QWaylandDataOffer *QWaylandDataDevice::dragOffer() const
|
||||
return m_dragOffer.data();
|
||||
}
|
||||
|
||||
void QWaylandDataDevice::startDrag(QMimeData *mimeData, QWaylandWindow *icon)
|
||||
bool QWaylandDataDevice::startDrag(QMimeData *mimeData, QWaylandWindow *icon)
|
||||
{
|
||||
m_dragSource.reset(new QWaylandDataSource(m_display->dndSelectionHandler(), mimeData));
|
||||
connect(m_dragSource.data(), &QWaylandDataSource::cancelled, this, &QWaylandDataDevice::dragSourceCancelled);
|
||||
|
||||
QWaylandWindow *origin = m_display->currentInputDevice()->pointerFocus();
|
||||
if (!origin)
|
||||
origin = m_display->currentInputDevice()->touchFocus();
|
||||
|
||||
if (origin)
|
||||
start_drag(m_dragSource->object(), origin->object(), icon->object(), m_display->currentInputDevice()->serial());
|
||||
else
|
||||
if (!origin) {
|
||||
qCDebug(lcQpaWayland) << "Couldn't start a drag because the origin window could not be found.";
|
||||
return false;
|
||||
}
|
||||
|
||||
m_dragSource.reset(new QWaylandDataSource(m_display->dndSelectionHandler(), mimeData));
|
||||
connect(m_dragSource.data(), &QWaylandDataSource::cancelled, this, &QWaylandDataDevice::dragSourceCancelled);
|
||||
|
||||
start_drag(m_dragSource->object(), origin->object(), icon->object(), m_display->currentInputDevice()->serial());
|
||||
return true;
|
||||
}
|
||||
|
||||
void QWaylandDataDevice::cancelDrag()
|
||||
|
@ -89,7 +89,7 @@ public:
|
||||
|
||||
#if QT_CONFIG(draganddrop)
|
||||
QWaylandDataOffer *dragOffer() const;
|
||||
void startDrag(QMimeData *mimeData, QWaylandWindow *icon);
|
||||
bool startDrag(QMimeData *mimeData, QWaylandWindow *icon);
|
||||
void cancelDrag();
|
||||
#endif
|
||||
|
||||
|
@ -66,8 +66,13 @@ void QWaylandDrag::startDrag()
|
||||
{
|
||||
QBasicDrag::startDrag();
|
||||
QWaylandWindow *icon = static_cast<QWaylandWindow *>(shapedPixmapWindow()->handle());
|
||||
m_display->currentInputDevice()->dataDevice()->startDrag(drag()->mimeData(), icon);
|
||||
icon->addAttachOffset(-drag()->hotSpot());
|
||||
if (m_display->currentInputDevice()->dataDevice()->startDrag(drag()->mimeData(), icon)) {
|
||||
icon->addAttachOffset(-drag()->hotSpot());
|
||||
} else {
|
||||
// Cancelling immediately does not work, since the event loop for QDrag::exec is started
|
||||
// after this function returns.
|
||||
QMetaObject::invokeMethod(this, [this](){ cancelDrag(); }, Qt::QueuedConnection);
|
||||
}
|
||||
}
|
||||
|
||||
void QWaylandDrag::cancel()
|
||||
|
Loading…
x
Reference in New Issue
Block a user