Fix retrieving the selection/dnd data

Installing a roudtrip on the custom event queue in the wl_data_offer.offer
handler is broken because that triggers a wl_data_device.selection event,
which emits the QClipboard changed signal, so code listening to it may end
up trying to retrieve the clipboard data before the roundtrip ends.
Additionally, we're calling wl_data_offer.receive for each mime type, even
if then we never read from the fd, making the source client do work for no
reason. Instead, call wl_data_offer.receive retrieveData_sys, that is when
actually retreiving the data.

We don't need to install a roundtrip after that, just flushing out the
requests is enough, because we wait up to one second for the source client
to write into the fd.

Change-Id: I180779e375ebd5a22af7084458505a41107fab19
Reviewed-by: Robin Burchell <robin.burchell@viroteck.net>
This commit is contained in:
Giulio Camuffo 2014-09-12 13:44:42 +03:00
parent b9f7e26a49
commit 1aeeab6e33
2 changed files with 17 additions and 19 deletions

View File

@ -94,30 +94,18 @@ QWaylandMimeData::~QWaylandMimeData()
void QWaylandMimeData::appendFormat(const QString &mimeType) void QWaylandMimeData::appendFormat(const QString &mimeType)
{ {
if (m_types.contains(mimeType)) m_types << mimeType;
close(m_types.take(mimeType)); // Unconsumed data
m_data.remove(mimeType); // Clear previous contents m_data.remove(mimeType); // Clear previous contents
int pipefd[2];
if (::pipe2(pipefd, O_CLOEXEC|O_NONBLOCK) == -1) {
qWarning("QWaylandMimeData: pipe2() failed");
return;
}
m_dataOffer->receive(mimeType, pipefd[1]);
m_display->forceRoundTrip();
close(pipefd[1]);
m_types.insert(mimeType, pipefd[0]);
} }
bool QWaylandMimeData::hasFormat_sys(const QString &mimeType) const bool QWaylandMimeData::hasFormat_sys(const QString &mimeType) const
{ {
return m_types.contains(mimeType) || m_data.contains(mimeType); return m_types.contains(mimeType);
} }
QStringList QWaylandMimeData::formats_sys() const QStringList QWaylandMimeData::formats_sys() const
{ {
return m_types.keys() << m_data.keys(); return m_types;
} }
QVariant QWaylandMimeData::retrieveData_sys(const QString &mimeType, QVariant::Type type) const QVariant QWaylandMimeData::retrieveData_sys(const QString &mimeType, QVariant::Type type) const
@ -130,14 +118,24 @@ QVariant QWaylandMimeData::retrieveData_sys(const QString &mimeType, QVariant::T
if (!m_types.contains(mimeType)) if (!m_types.contains(mimeType))
return QVariant(); return QVariant();
int pipefd[2];
if (::pipe2(pipefd, O_CLOEXEC|O_NONBLOCK) == -1) {
qWarning("QWaylandMimeData: pipe2() failed");
return QVariant();
}
m_dataOffer->receive(mimeType, pipefd[1]);
m_display->flushRequests();
close(pipefd[1]);
QByteArray content; QByteArray content;
int fd = m_types.take(mimeType); if (readData(pipefd[0], content) != 0) {
if (readData(fd, content) != 0) {
qWarning("QWaylandDataOffer: error reading data for mimeType %s", qPrintable(mimeType)); qWarning("QWaylandDataOffer: error reading data for mimeType %s", qPrintable(mimeType));
content = QByteArray(); content = QByteArray();
} }
close(fd); close(pipefd[0]);
m_data.insert(mimeType, content); m_data.insert(mimeType, content);
return content; return content;
} }

View File

@ -87,7 +87,7 @@ private:
mutable QWaylandDataOffer *m_dataOffer; mutable QWaylandDataOffer *m_dataOffer;
QWaylandDisplay *m_display; QWaylandDisplay *m_display;
mutable QHash<QString, int> m_types; mutable QStringList m_types;
mutable QHash<QString, QByteArray> m_data; mutable QHash<QString, QByteArray> m_data;
}; };