Kaydet (Commit) 9c5dbbe4 authored tarafından Michael Weghorn's avatar Michael Weghorn Kaydeden (comit) Thorsten Behrens

tdf#122689 qt5: Consider external clipboard updates

Previously, once 'm_aContents' had been assigned in
'VclQt5Clipboard::setContents()', its value (or the one set
in a subsequent call to the same method) was always
returned in 'VclQt5Clipboard::getContents()', thus
ignoring all system clipboard updates done by any other
third-party applications, preventing copy-paste from other
applications.

In order to take external clipboard updates into account,
add a slot for the 'QClipboard::changed' signal and
drop the current own clipboard content if the clipboard
has been updated by another application.

In order to detect whether the clipboard update was made
by this 'VclQt5Clipboard' itself or elsewhere, a custom MIME type
"application/x-libreoffice-clipboard-uuid" is added, whose
value is set to the clipboard's (randomly generated) UUID.
If the entry is present and has the correct value, the clipboard
content was added by this clipboard and can be kept.

Otherwise, clear 'm_aContents', so that it's newly assigned
in 'VclQt5Clipboard::getContents()', taking into account
the external clipboard update.

[Side note: Testing showed that, on Wayland, more
'QClipboard::changed' events were emitted without the clipboard
content actually having changed (e.g. when switching focus between
windows), which is why an approach of simply setting a flag and
checking for that one is not enough, like "wrapping" the
'QClipboard::setMimeData()' call in 'VclQt5Clipboard::setContents()'
as follows

    m_bIsFillingClipboard = true;
    clipboard->setMimeData(pMimeData.release(), m_aClipboardMode);
    m_bIsFillingClipboard = false;

and then evaluating the 'm_bIsfillingClipboard' flag in
'VclQt5Clipboard::handleClipboardChange' instead of using the UUID-based
approach. These additional 'QClipboard::changed' events did not
show up the same way while testing on X11.]

Change-Id: Ib3a6a4f9b7f5ca3573666fb9c072ae97cf2e0049
Reviewed-on: https://gerrit.libreoffice.org/68214
Tested-by: Jenkins
Reviewed-by: 's avatarThorsten Behrens <Thorsten.Behrens@CIB.de>
üst c74cc709
......@@ -11,6 +11,7 @@ $(eval $(call gb_CustomTarget_CustomTarget,vcl/qt5))
$(call gb_CustomTarget_get_target,vcl/qt5) : \
$(call gb_CustomTarget_get_workdir,vcl/qt5)/Qt5AccessibleWidget.moc \
$(call gb_CustomTarget_get_workdir,vcl/qt5)/Qt5Clipboard.moc \
$(call gb_CustomTarget_get_workdir,vcl/qt5)/Qt5FilePicker.moc \
$(call gb_CustomTarget_get_workdir,vcl/qt5)/Qt5Frame.moc \
$(call gb_CustomTarget_get_workdir,vcl/qt5)/Qt5Instance.moc \
......
......@@ -45,16 +45,26 @@ private:
};
class VclQt5Clipboard
: public cppu::WeakComponentImplHelper<datatransfer::clipboard::XSystemClipboard,
: public QObject,
public cppu::WeakComponentImplHelper<datatransfer::clipboard::XSystemClipboard,
datatransfer::clipboard::XFlushableClipboard,
XServiceInfo>
{
Q_OBJECT
private Q_SLOTS:
void handleClipboardChange(QClipboard::Mode mode);
private:
osl::Mutex m_aMutex;
Reference<css::datatransfer::XTransferable> m_aContents;
Reference<css::datatransfer::clipboard::XClipboardOwner> m_aOwner;
std::vector<Reference<css::datatransfer::clipboard::XClipboardListener>> m_aListeners;
OUString m_aClipboardName;
QClipboard::Mode m_aClipboardMode;
// custom MIME type to detect whether clipboard content was added by self or externally
const QString m_sMimeTypeUuid = "application/x-libreoffice-clipboard-uuid";
const QByteArray m_aUuid;
public:
explicit VclQt5Clipboard(const OUString& aModeString);
......
......@@ -17,8 +17,10 @@
#include <QtWidgets/QApplication>
#include <QtCore/QBuffer>
#include <QtCore/QMimeData>
#include <QtCore/QUuid>
#include <Qt5Clipboard.hxx>
#include <Qt5Clipboard.moc>
#include <Qt5Tools.hxx>
#include <map>
......@@ -169,7 +171,10 @@ VclQt5Clipboard::VclQt5Clipboard(const OUString& aModeString)
m_aMutex)
, m_aClipboardName(aModeString)
, m_aClipboardMode(getClipboardTypeFromName(aModeString))
, m_aUuid(QUuid::createUuid().toByteArray())
{
connect(QApplication::clipboard(), &QClipboard::changed, this,
&VclQt5Clipboard::handleClipboardChange, Qt::DirectConnection);
}
void VclQt5Clipboard::flushClipboard()
......@@ -301,6 +306,9 @@ void VclQt5Clipboard::setContents(
}
}
// set value for custom MIME type to indicate that content was added by this clipboard
pMimeData->setData(m_sMimeTypeUuid, m_aUuid);
clipboard->setMimeData(pMimeData.release(), m_aClipboardMode);
}
......@@ -337,4 +345,16 @@ void VclQt5Clipboard::removeClipboardListener(
m_aListeners.end());
}
void VclQt5Clipboard::handleClipboardChange(QClipboard::Mode aMode)
{
// if system clipboard content has changed and current content was not created by
// this clipboard itself, clear the own current content
// (e.g. to take into account clipboard updates from other applications)
if (aMode == m_aClipboardMode
&& QApplication::clipboard()->mimeData(aMode)->data(m_sMimeTypeUuid) != m_aUuid)
{
m_aContents.clear();
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
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