Client: Manage QMimeData lifecycle

QMimeData is created by user, it is not taken care of in qtwayland,
which will cause memory leak.

It is now handled in qtwayland that when a new QMimeData is set,
the previous QMimeData is freed.

Change-Id: Ic502021fe700c7ee10454d94f0d1868901809af7
Reviewed-by: David Edmundson <davidedmundson@kde.org>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
Tang Haixiang 2022-12-22 15:19:53 +08:00
parent 051b3ce2ee
commit 5925c3110d
4 changed files with 22 additions and 13 deletions

View File

@ -18,10 +18,15 @@ namespace QtWaylandClient {
QWaylandClipboard::QWaylandClipboard(QWaylandDisplay *display) QWaylandClipboard::QWaylandClipboard(QWaylandDisplay *display)
: mDisplay(display) : mDisplay(display)
{ {
m_clientClipboard[QClipboard::Clipboard] = nullptr;
m_clientClipboard[QClipboard::Selection] = nullptr;
} }
QWaylandClipboard::~QWaylandClipboard() QWaylandClipboard::~QWaylandClipboard()
{ {
if (m_clientClipboard[QClipboard::Clipboard] != m_clientClipboard[QClipboard::Selection])
delete m_clientClipboard[QClipboard::Clipboard];
delete m_clientClipboard[QClipboard::Selection];
} }
QMimeData *QWaylandClipboard::mimeData(QClipboard::Mode mode) QMimeData *QWaylandClipboard::mimeData(QClipboard::Mode mode)
@ -33,8 +38,8 @@ QMimeData *QWaylandClipboard::mimeData(QClipboard::Mode mode)
switch (mode) { switch (mode) {
case QClipboard::Clipboard: case QClipboard::Clipboard:
if (auto *dataDevice = seat->dataDevice()) { if (auto *dataDevice = seat->dataDevice()) {
if (auto *source = dataDevice->selectionSource()) if (dataDevice->selectionSource())
return source->mimeData(); return m_clientClipboard[QClipboard::Clipboard];
if (auto *offer = dataDevice->selectionOffer()) if (auto *offer = dataDevice->selectionOffer())
return offer->mimeData(); return offer->mimeData();
} }
@ -42,8 +47,8 @@ QMimeData *QWaylandClipboard::mimeData(QClipboard::Mode mode)
case QClipboard::Selection: case QClipboard::Selection:
#if QT_CONFIG(wayland_client_primary_selection) #if QT_CONFIG(wayland_client_primary_selection)
if (auto *selectionDevice = seat->primarySelectionDevice()) { if (auto *selectionDevice = seat->primarySelectionDevice()) {
if (auto *source = selectionDevice->selectionSource()) if (selectionDevice->selectionSource())
return source->mimeData(); return m_clientClipboard[QClipboard::Selection];
if (auto *offer = selectionDevice->selectionOffer()) if (auto *offer = selectionDevice->selectionOffer())
return offer->mimeData(); return offer->mimeData();
} }
@ -68,17 +73,27 @@ void QWaylandClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode)
if (data && data->hasFormat(plain) && !data->hasFormat(utf8)) if (data && data->hasFormat(plain) && !data->hasFormat(utf8))
data->setData(utf8, data->data(plain)); data->setData(utf8, data->data(plain));
if (m_clientClipboard[mode]) {
if (m_clientClipboard[QClipboard::Clipboard] != m_clientClipboard[QClipboard::Selection])
delete m_clientClipboard[mode];
m_clientClipboard[mode] = nullptr;
}
m_clientClipboard[mode] = data;
switch (mode) { switch (mode) {
case QClipboard::Clipboard: case QClipboard::Clipboard:
if (auto *dataDevice = seat->dataDevice()) { if (auto *dataDevice = seat->dataDevice()) {
dataDevice->setSelectionSource(data ? new QWaylandDataSource(mDisplay->dndSelectionHandler(), data) : nullptr); dataDevice->setSelectionSource(data ? new QWaylandDataSource(mDisplay->dndSelectionHandler(),
m_clientClipboard[QClipboard::Clipboard]) : nullptr);
emitChanged(mode); emitChanged(mode);
} }
break; break;
case QClipboard::Selection: case QClipboard::Selection:
#if QT_CONFIG(wayland_client_primary_selection) #if QT_CONFIG(wayland_client_primary_selection)
if (auto *selectionDevice = seat->primarySelectionDevice()) { if (auto *selectionDevice = seat->primarySelectionDevice()) {
selectionDevice->setSelectionSource(data ? new QWaylandPrimarySelectionSourceV1(mDisplay->primarySelectionManager(), data) : nullptr); selectionDevice->setSelectionSource(data ? new QWaylandPrimarySelectionSourceV1(mDisplay->primarySelectionManager(),
m_clientClipboard[QClipboard::Selection]) : nullptr);
emitChanged(mode); emitChanged(mode);
} }
#endif #endif

View File

@ -45,6 +45,7 @@ public:
private: private:
QWaylandDisplay *mDisplay = nullptr; QWaylandDisplay *mDisplay = nullptr;
QMimeData m_emptyData; QMimeData m_emptyData;
QMimeData *m_clientClipboard[2];
}; };
} }

View File

@ -36,11 +36,6 @@ QWaylandDataSource::~QWaylandDataSource()
destroy(); destroy();
} }
QMimeData * QWaylandDataSource::mimeData() const
{
return m_mime_data;
}
void QWaylandDataSource::data_source_cancelled() void QWaylandDataSource::data_source_cancelled()
{ {
Q_EMIT cancelled(); Q_EMIT cancelled();

View File

@ -38,8 +38,6 @@ public:
QWaylandDataSource(QWaylandDataDeviceManager *dataDeviceManager, QMimeData *mimeData); QWaylandDataSource(QWaylandDataDeviceManager *dataDeviceManager, QMimeData *mimeData);
~QWaylandDataSource() override; ~QWaylandDataSource() override;
QMimeData *mimeData() const;
Q_SIGNALS: Q_SIGNALS:
void cancelled(); void cancelled();
void finished(); void finished();