2018-09-14 14:53:40 +02:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
|
|
/*
|
|
|
|
* This file is part of the LibreOffice project.
|
|
|
|
*
|
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <com/sun/star/lang/XServiceInfo.hpp>
|
|
|
|
#include <com/sun/star/datatransfer/XTransferable.hpp>
|
|
|
|
#include <com/sun/star/datatransfer/clipboard/XSystemClipboard.hpp>
|
|
|
|
#include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp>
|
|
|
|
#include <com/sun/star/datatransfer/clipboard/XClipboardOwner.hpp>
|
|
|
|
#include <com/sun/star/datatransfer/clipboard/XClipboardListener.hpp>
|
2019-06-01 03:36:36 +00:00
|
|
|
#include <cppuhelper/compbase.hxx>
|
2018-09-14 14:53:40 +02:00
|
|
|
|
2019-01-18 10:59:50 +03:00
|
|
|
#include <QtGui/QClipboard>
|
|
|
|
|
2019-05-31 16:40:34 +00:00
|
|
|
/**
|
|
|
|
* This implementation has two main functions, which handle the clipboard content:
|
|
|
|
* the XClipboard::setContent function and the QClipboard::change signal handler.
|
|
|
|
*
|
|
|
|
* The first just sets the respective clipboard to the expected content from LO,
|
|
|
|
* the latter will handle any reported changes.
|
|
|
|
**/
|
|
|
|
class Qt5Clipboard final
|
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@CIB.de>
2019-02-22 14:12:35 +01:00
|
|
|
: public QObject,
|
2019-05-31 16:34:37 +00:00
|
|
|
public cppu::WeakComponentImplHelper<css::datatransfer::clipboard::XSystemClipboard,
|
|
|
|
css::datatransfer::clipboard::XFlushableClipboard,
|
|
|
|
css::lang::XServiceInfo>
|
2018-09-14 14:53:40 +02:00
|
|
|
{
|
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@CIB.de>
2019-02-22 14:12:35 +01:00
|
|
|
Q_OBJECT
|
|
|
|
|
2018-09-14 14:53:40 +02:00
|
|
|
osl::Mutex m_aMutex;
|
2019-05-31 16:40:34 +00:00
|
|
|
const OUString m_aClipboardName;
|
|
|
|
const QClipboard::Mode m_aClipboardMode;
|
2019-10-02 13:31:46 +00:00
|
|
|
// has to be set, if LO changes the QClipboard itself, so it won't instantly lose
|
|
|
|
// ownership by it's self-triggered QClipboard::changed handler
|
|
|
|
bool m_bOwnClipboardChange;
|
2019-05-31 16:40:34 +00:00
|
|
|
|
|
|
|
// if not empty, this holds the setContents provided XTransferable or a Qt5ClipboardTransferable
|
2019-05-31 16:34:37 +00:00
|
|
|
css::uno::Reference<css::datatransfer::XTransferable> m_aContents;
|
2019-05-31 16:40:34 +00:00
|
|
|
// the owner of the current contents, which must be informed on content change
|
2019-05-31 16:34:37 +00:00
|
|
|
css::uno::Reference<css::datatransfer::clipboard::XClipboardOwner> m_aOwner;
|
|
|
|
std::vector<css::uno::Reference<css::datatransfer::clipboard::XClipboardListener>> m_aListeners;
|
2019-05-31 16:40:34 +00:00
|
|
|
|
|
|
|
static bool isOwner(const QClipboard::Mode aMode);
|
|
|
|
static bool isSupported(const QClipboard::Mode aMode);
|
|
|
|
|
|
|
|
explicit Qt5Clipboard(const OUString& aModeString, const QClipboard::Mode aMode);
|
2018-09-14 14:53:40 +02:00
|
|
|
|
2019-05-31 16:34:37 +00:00
|
|
|
private Q_SLOTS:
|
2019-05-31 16:40:34 +00:00
|
|
|
void handleChanged(QClipboard::Mode mode);
|
2019-05-31 16:34:37 +00:00
|
|
|
|
2018-09-14 14:53:40 +02:00
|
|
|
public:
|
2019-05-31 16:40:34 +00:00
|
|
|
// factory function to construct only valid Qt5Clipboard objects by name
|
|
|
|
static css::uno::Reference<css::uno::XInterface> create(const OUString& aModeString);
|
2018-09-14 14:53:40 +02:00
|
|
|
|
2019-05-31 16:40:34 +00:00
|
|
|
// XServiceInfo
|
2018-09-14 14:53:40 +02:00
|
|
|
virtual OUString SAL_CALL getImplementationName() override;
|
|
|
|
virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
|
2019-05-31 16:34:37 +00:00
|
|
|
virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
|
2018-09-14 14:53:40 +02:00
|
|
|
|
2019-05-31 16:40:34 +00:00
|
|
|
// XClipboard
|
2019-05-31 16:34:37 +00:00
|
|
|
virtual css::uno::Reference<css::datatransfer::XTransferable> SAL_CALL getContents() override;
|
2018-09-14 14:53:40 +02:00
|
|
|
virtual void SAL_CALL setContents(
|
2019-05-31 16:34:37 +00:00
|
|
|
const css::uno::Reference<css::datatransfer::XTransferable>& xTrans,
|
|
|
|
const css::uno::Reference<css::datatransfer::clipboard::XClipboardOwner>& xClipboardOwner)
|
|
|
|
override;
|
2018-09-14 14:53:40 +02:00
|
|
|
virtual OUString SAL_CALL getName() override;
|
|
|
|
|
2019-05-31 16:40:34 +00:00
|
|
|
// XClipboardEx
|
2018-09-14 14:53:40 +02:00
|
|
|
virtual sal_Int8 SAL_CALL getRenderingCapabilities() override;
|
|
|
|
|
2019-05-31 16:40:34 +00:00
|
|
|
// XFlushableClipboard
|
2018-09-14 14:53:40 +02:00
|
|
|
virtual void SAL_CALL flushClipboard() override;
|
|
|
|
|
2019-05-31 16:40:34 +00:00
|
|
|
// XClipboardNotifier
|
2018-09-14 14:53:40 +02:00
|
|
|
virtual void SAL_CALL addClipboardListener(
|
2019-05-31 16:34:37 +00:00
|
|
|
const css::uno::Reference<css::datatransfer::clipboard::XClipboardListener>& listener)
|
|
|
|
override;
|
2018-09-14 14:53:40 +02:00
|
|
|
virtual void SAL_CALL removeClipboardListener(
|
2019-05-31 16:34:37 +00:00
|
|
|
const css::uno::Reference<css::datatransfer::clipboard::XClipboardListener>& listener)
|
|
|
|
override;
|
2018-09-14 14:53:40 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|