[Libreoffice-commits] core.git: Branch 'libreoffice-6-2' - vcl/CustomTarget_qt5_moc.mk vcl/inc vcl/qt5

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Thu Feb 28 11:58:07 UTC 2019


 vcl/CustomTarget_qt5_moc.mk  |    1 +
 vcl/inc/qt5/Qt5Clipboard.hxx |   12 +++++++++++-
 vcl/qt5/Qt5Clipboard.cxx     |   20 ++++++++++++++++++++
 3 files changed, 32 insertions(+), 1 deletion(-)

New commits:
commit 1cc66501179f2a396e221d6803f2e1f8019ada5c
Author:     Michael Weghorn <m.weghorn at posteo.de>
AuthorDate: Fri Feb 22 14:12:35 2019 +0100
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Thu Feb 28 12:57:43 2019 +0100

    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: Thorsten Behrens <Thorsten.Behrens at CIB.de>
    (cherry picked from commit 9c5dbbe4b0a62ff1af009beb00f1fc45318dad79)
    Reviewed-on: https://gerrit.libreoffice.org/68460

diff --git a/vcl/CustomTarget_qt5_moc.mk b/vcl/CustomTarget_qt5_moc.mk
index 289fea74aa2e..6d85eeff637b 100644
--- a/vcl/CustomTarget_qt5_moc.mk
+++ b/vcl/CustomTarget_qt5_moc.mk
@@ -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 \
diff --git a/vcl/inc/qt5/Qt5Clipboard.hxx b/vcl/inc/qt5/Qt5Clipboard.hxx
index beff6b71a968..7539b748dc23 100644
--- a/vcl/inc/qt5/Qt5Clipboard.hxx
+++ b/vcl/inc/qt5/Qt5Clipboard.hxx
@@ -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);
diff --git a/vcl/qt5/Qt5Clipboard.cxx b/vcl/qt5/Qt5Clipboard.cxx
index 92bb3a89da3d..5fdbc47dfd2c 100644
--- a/vcl/qt5/Qt5Clipboard.cxx
+++ b/vcl/qt5/Qt5Clipboard.cxx
@@ -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: */


More information about the Libreoffice-commits mailing list