Merge branch 'master' of git://scm.dev.nokia.troll.no/qt/qtbase-staging

* 'master' of git://scm.dev.nokia.troll.no/qt/qtbase-staging:
  Fix deadlocks in wayland clipboard that can occur in special scenarios.
This commit is contained in:
Qt Continuous Integration System 2011-05-13 17:31:10 +10:00
commit 305577936d
2 changed files with 24 additions and 10 deletions

View File

@ -96,7 +96,6 @@ public:
QWaylandSelection(QWaylandDisplay *display, QMimeData *data); QWaylandSelection(QWaylandDisplay *display, QMimeData *data);
~QWaylandSelection(); ~QWaylandSelection();
private:
static uint32_t getTime(); static uint32_t getTime();
static void send(void *data, struct wl_selection *selection, const char *mime_type, int fd); static void send(void *data, struct wl_selection *selection, const char *mime_type, int fd);
static void cancelled(void *data, struct wl_selection *selection); static void cancelled(void *data, struct wl_selection *selection);
@ -164,7 +163,7 @@ void QWaylandSelection::cancelled(void *data, struct wl_selection *selection)
} }
QWaylandClipboard::QWaylandClipboard(QWaylandDisplay *display) QWaylandClipboard::QWaylandClipboard(QWaylandDisplay *display)
: mDisplay(display), mSelection(0), mMimeDataIn(0), mOffer(0) : mDisplay(display), mMimeDataIn(0), mOffer(0)
{ {
clipboard = this; clipboard = this;
} }
@ -222,6 +221,8 @@ QVariant QWaylandClipboard::retrieveData(const QString &mimeType, QVariant::Type
QMimeData *QWaylandClipboard::mimeData(QClipboard::Mode mode) QMimeData *QWaylandClipboard::mimeData(QClipboard::Mode mode)
{ {
Q_ASSERT(mode == QClipboard::Clipboard); Q_ASSERT(mode == QClipboard::Clipboard);
if (!mSelections.isEmpty())
return mSelections.last()->mMimeData;
if (!mMimeDataIn) if (!mMimeDataIn)
mMimeDataIn = new QWaylandMimeData; mMimeDataIn = new QWaylandMimeData;
mMimeDataIn->clearAll(); mMimeDataIn->clearAll();
@ -236,7 +237,7 @@ void QWaylandClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode)
if (!mDisplay->inputDevices().isEmpty()) { if (!mDisplay->inputDevices().isEmpty()) {
if (!data) if (!data)
data = new QMimeData; data = new QMimeData;
mSelection = new QWaylandSelection(mDisplay, data); mSelections.append(new QWaylandSelection(mDisplay, data));
} else { } else {
qWarning("QWaylandClipboard::setMimeData: No input devices"); qWarning("QWaylandClipboard::setMimeData: No input devices");
} }
@ -266,21 +267,27 @@ void QWaylandClipboard::offer(void *data,
struct wl_selection_offer *selection_offer, struct wl_selection_offer *selection_offer,
const char *type) const char *type)
{ {
Q_UNUSED(data);
Q_UNUSED(selection_offer); Q_UNUSED(selection_offer);
QWaylandClipboard *self = static_cast<QWaylandClipboard *>(data); clipboard->mOfferedMimeTypes.append(QString::fromLatin1(type));
self->mOfferedMimeTypes.append(QString::fromLatin1(type));
} }
void QWaylandClipboard::keyboardFocus(void *data, void QWaylandClipboard::keyboardFocus(void *data,
struct wl_selection_offer *selection_offer, struct wl_selection_offer *selection_offer,
wl_input_device *input_device) wl_input_device *input_device)
{ {
QWaylandClipboard *self = static_cast<QWaylandClipboard *>(data); Q_UNUSED(data);
if (!input_device) { if (!input_device) {
wl_selection_offer_destroy(selection_offer); wl_selection_offer_destroy(selection_offer);
self->mOffer = 0; clipboard->mOffer = 0;
return; return;
} }
self->mOffer = selection_offer; clipboard->mOffer = selection_offer;
self->emitChanged(QClipboard::Clipboard); if (clipboard->mSelections.isEmpty())
QMetaObject::invokeMethod(&clipboard->mEmitter, "emitChanged", Qt::QueuedConnection);
}
void QWaylandClipboardSignalEmitter::emitChanged()
{
clipboard->emitChanged(QClipboard::Clipboard);
} }

View File

@ -51,6 +51,13 @@ class QWaylandSelection;
class QWaylandMimeData; class QWaylandMimeData;
struct wl_selection_offer; struct wl_selection_offer;
class QWaylandClipboardSignalEmitter : public QObject
{
Q_OBJECT
public slots:
void emitChanged();
};
class QWaylandClipboard : public QPlatformClipboard class QWaylandClipboard : public QPlatformClipboard
{ {
public: public:
@ -80,11 +87,11 @@ private:
static void forceRoundtrip(struct wl_display *display); static void forceRoundtrip(struct wl_display *display);
QWaylandDisplay *mDisplay; QWaylandDisplay *mDisplay;
QWaylandSelection *mSelection;
QWaylandMimeData *mMimeDataIn; QWaylandMimeData *mMimeDataIn;
QList<QWaylandSelection *> mSelections; QList<QWaylandSelection *> mSelections;
QStringList mOfferedMimeTypes; QStringList mOfferedMimeTypes;
struct wl_selection_offer *mOffer; struct wl_selection_offer *mOffer;
QWaylandClipboardSignalEmitter mEmitter;
}; };
#endif // QWAYLANDCLIPBOARD_H #endif // QWAYLANDCLIPBOARD_H