summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Kaganski <mike.kaganski@collabora.com>2021-03-05 20:45:08 +0300
committerBalazs Varga <balazs.varga.extern@allotropia.de>2022-11-24 12:27:00 +0100
commit76ddbf0baf9079c62ae62a4083309b9c3a3cbf9a (patch)
tree28caee258697ea07bcb7b553d58387bc56efbde3
parentWIN merge CWinClipbImpl into CWinClipboard (diff)
downloadcore-76ddbf0baf9079c62ae62a4083309b9c3a3cbf9a.tar.gz
core-76ddbf0baf9079c62ae62a4083309b9c3a3cbf9a.zip
tdf#140813: Use GetUpdatedClipboardFormats to enumerate clipboard formats
We really don't have to provide plain text formats other than Unicode, so we may avoid checking CF_LOCALE data when initializing flavor list. Let's pretend that any textual format in the clipboard is Unicode, and ensure that we only actually access system clipboard when we paste. Reviewed-on: https://gerrit.libreoffice.org/c/core/+/112044 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com> (cherry picked from commit 7b6c0e63e64eb2ad1e83bd744a0d20f78c7a6b84) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/112971 Reviewed-by: Michael Stahl <michael.stahl@allotropia.de> Reviewed-by: Adolfo Jayme Barrientos <fitojb@ubuntu.com> Change-Id: Ife30f57605a42d59233bfcb97f8bc297b3ace463 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143176 Tested-by: Gabor Kelemen <kelemeng@ubuntu.com> Reviewed-by: Balazs Varga <balazs.varga.extern@allotropia.de>
-rw-r--r--vcl/win/dtrans/DOTransferable.cxx110
-rw-r--r--vcl/win/dtrans/DOTransferable.hxx19
-rw-r--r--vcl/win/dtrans/DataFmtTransl.cxx4
-rw-r--r--vcl/win/dtrans/DataFmtTransl.hxx2
-rw-r--r--vcl/win/dtrans/FetcList.cxx5
-rw-r--r--vcl/win/dtrans/WinClipboard.cxx36
-rw-r--r--vcl/win/dtrans/WinClipboard.hxx6
-rw-r--r--vcl/win/dtrans/XTDataObject.cxx6
-rw-r--r--vcl/win/dtrans/target.cxx3
9 files changed, 113 insertions, 78 deletions
diff --git a/vcl/win/dtrans/DOTransferable.cxx b/vcl/win/dtrans/DOTransferable.cxx
index 24fc847cfa14..11692781a683 100644
--- a/vcl/win/dtrans/DOTransferable.cxx
+++ b/vcl/win/dtrans/DOTransferable.cxx
@@ -24,6 +24,7 @@
#include "DOTransferable.hxx"
#include "ImplHelper.hxx"
#include "WinClip.hxx"
+#include "WinClipboard.hxx"
#include "DTransHelper.hxx"
#include "TxtCnvtHlp.hxx"
#include "MimeAttrib.hxx"
@@ -167,19 +168,6 @@ bool cmpAllContentTypeParameter(
} // end namespace
-Reference< XTransferable > CDOTransferable::create( const Reference< XComponentContext >& rxContext,
- IDataObjectPtr pIDataObject )
-{
- CDOTransferable* pTransf = new CDOTransferable(rxContext, pIDataObject);
- Reference<XTransferable> refDOTransf(pTransf);
-
- pTransf->acquire();
- pTransf->initFlavorList();
- pTransf->release();
-
- return refDOTransf;
-}
-
CDOTransferable::CDOTransferable(
const Reference< XComponentContext >& rxContext, IDataObjectPtr rDataObject ) :
m_rDataObject( rDataObject ),
@@ -188,6 +176,20 @@ CDOTransferable::CDOTransferable(
m_bUnicodeRegistered( false ),
m_TxtFormatOnClipboard( CF_INVALID )
{
+ initFlavorList();
+}
+
+CDOTransferable::CDOTransferable(
+ const Reference<XComponentContext>& rxContext,
+ const css::uno::Reference<css::datatransfer::clipboard::XClipboard>& xClipboard,
+ const std::vector<sal_uInt32>& rFormats)
+ : m_xClipboard(xClipboard)
+ , m_xContext(rxContext)
+ , m_DataFormatTranslator(rxContext)
+ , m_bUnicodeRegistered(false)
+ , m_TxtFormatOnClipboard(CF_INVALID)
+{
+ initFlavorListFromFormatList(rFormats);
}
Any SAL_CALL CDOTransferable::getTransferData( const DataFlavor& aFlavor )
@@ -271,6 +273,7 @@ sal_Bool SAL_CALL CDOTransferable::isDataFlavorSupported( const DataFlavor& aFla
void CDOTransferable::initFlavorList( )
{
+ std::vector<sal_uInt32> aFormats;
sal::systools::COMReference<IEnumFORMATETC> pEnumFormatEtc;
HRESULT hr = m_rDataObject->EnumFormatEtc( DATADIR_GET, &pEnumFormatEtc );
if ( SUCCEEDED( hr ) )
@@ -280,39 +283,38 @@ void CDOTransferable::initFlavorList( )
FORMATETC fetc;
while ( S_OK == pEnumFormatEtc->Next( 1, &fetc, nullptr ) )
{
- // we use locales only to determine the
- // charset if there is text on the cliboard
- // we don't offer this format
- if ( CF_LOCALE == fetc.cfFormat )
- continue;
-
- DataFlavor aFlavor = formatEtcToDataFlavor( fetc );
+ aFormats.push_back(fetc.cfFormat);
+ // see MSDN IEnumFORMATETC
+ CoTaskMemFree( fetc.ptd );
+ }
+ initFlavorListFromFormatList(aFormats);
+ }
+}
- // if text or oemtext is offered we also pretend to have unicode text
- if ( CDataFormatTranslator::isOemOrAnsiTextFormat( fetc.cfFormat ) &&
- !m_bUnicodeRegistered )
+void CDOTransferable::initFlavorListFromFormatList(const std::vector<sal_uInt32>& rFormats)
+{
+ for (sal_uInt32 cfFormat : rFormats)
+ {
+ // we use locales only to determine the
+ // charset if there is text on the cliboard
+ // we don't offer this format
+ if (CF_LOCALE == cfFormat)
+ continue;
+
+ // if text or oemtext is offered we pretend to have unicode text
+ if (CDataFormatTranslator::isTextFormat(cfFormat))
+ {
+ if (!m_bUnicodeRegistered)
{
- addSupportedFlavor( aFlavor );
-
- m_TxtFormatOnClipboard = fetc.cfFormat;
+ m_TxtFormatOnClipboard = cfFormat;
m_bUnicodeRegistered = true;
- // register unicode text as accompany format
- aFlavor = formatEtcToDataFlavor(
- CDataFormatTranslator::getFormatEtcForClipformat( CF_UNICODETEXT ) );
- addSupportedFlavor( aFlavor );
+ // register unicode text as format
+ addSupportedFlavor(formatEtcToDataFlavor(CF_UNICODETEXT));
}
- else if ( (CF_UNICODETEXT == fetc.cfFormat) && !m_bUnicodeRegistered )
- {
- addSupportedFlavor( aFlavor );
- m_bUnicodeRegistered = true;
- }
- else
- addSupportedFlavor( aFlavor );
-
- // see MSDN IEnumFORMATETC
- CoTaskMemFree( fetc.ptd );
}
+ else
+ addSupportedFlavor(formatEtcToDataFlavor(cfFormat));
}
}
@@ -329,18 +331,9 @@ void CDOTransferable::addSupportedFlavor( const DataFlavor& aFlavor )
}
}
-DataFlavor CDOTransferable::formatEtcToDataFlavor( const FORMATETC& aFormatEtc )
+DataFlavor CDOTransferable::formatEtcToDataFlavor(sal_uInt32 cfFormat)
{
- LCID lcid = 0;
-
- // for non-unicode text format we must provide a locale to get
- // the character-set of the text, if there is no locale on the
- // clipboard we assume the text is in a charset appropriate for
- // the current thread locale
- if ( (CF_TEXT == aFormatEtc.cfFormat) || (CF_OEMTEXT == aFormatEtc.cfFormat) )
- lcid = getLocaleFromClipboard( );
-
- return m_DataFormatTranslator.getDataFlavorFromFormatEtc( aFormatEtc, lcid );
+ return m_DataFormatTranslator.getDataFlavorFromFormatEtc(cfFormat);
}
// returns the current locale on clipboard; if there is no locale on
@@ -370,6 +363,18 @@ LCID CDOTransferable::getLocaleFromClipboard( )
return lcid;
}
+void CDOTransferable::tryToGetIDataObjectIfAbsent()
+{
+ if (!m_rDataObject.is())
+ {
+ auto xClipboard = m_xClipboard.get(); // holding the reference while we get the object
+ if (CWinClipboard* pWinClipboard = dynamic_cast<CWinClipboard*>(xClipboard.get()))
+ {
+ m_rDataObject = pWinClipboard->getIDataObject();
+ }
+ }
+}
+
// I think it's not necessary to call ReleaseStgMedium
// in case of failures because nothing should have been
// allocated etc.
@@ -377,6 +382,9 @@ LCID CDOTransferable::getLocaleFromClipboard( )
CDOTransferable::ByteSequence_t CDOTransferable::getClipboardData( CFormatEtc& aFormatEtc )
{
STGMEDIUM stgmedium;
+ tryToGetIDataObjectIfAbsent();
+ if (!m_rDataObject.is()) // Maybe we are shutting down, and clipboard is already destroyed?
+ throw RuntimeException();
HRESULT hr = m_rDataObject->GetData( aFormatEtc, &stgmedium );
// in case of failure to get a WMF metafile handle, try to get a memory block
diff --git a/vcl/win/dtrans/DOTransferable.hxx b/vcl/win/dtrans/DOTransferable.hxx
index f45e18c4f85a..cc33ff70c6a9 100644
--- a/vcl/win/dtrans/DOTransferable.hxx
+++ b/vcl/win/dtrans/DOTransferable.hxx
@@ -24,12 +24,16 @@
#include <cppuhelper/implbase.hxx>
#include "DataFmtTransl.hxx"
+#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
#include <com/sun/star/datatransfer/XMimeContentTypeFactory.hpp>
#include <com/sun/star/datatransfer/XMimeContentType.hpp>
#include <com/sun/star/datatransfer/XSystemTransferable.hpp>
+#include <cppuhelper/weakref.hxx>
#include <systools/win32/comtools.hxx>
+#include <vector>
+
// forward
class CFormatEtc;
@@ -40,9 +44,6 @@ class CDOTransferable : public ::cppu::WeakImplHelper<
public:
typedef css::uno::Sequence< sal_Int8 > ByteSequence_t;
- static css::uno::Reference< css::datatransfer::XTransferable > create(
- const css::uno::Reference< css::uno::XComponentContext >& rxContext, IDataObjectPtr pIDataObject );
-
// XTransferable
virtual css::uno::Any SAL_CALL getTransferData( const css::datatransfer::DataFlavor& aFlavor ) override;
@@ -55,18 +56,25 @@ public:
virtual css::uno::Any SAL_CALL getData( const css::uno::Sequence<sal_Int8>& aProcessId ) override;
-private:
+ explicit CDOTransferable(
+ const css::uno::Reference< css::uno::XComponentContext >& rxContext,
+ const css::uno::Reference<css::datatransfer::clipboard::XClipboard>& xClipboard,
+ const std::vector<sal_uInt32>& rFormats);
+
explicit CDOTransferable(
const css::uno::Reference< css::uno::XComponentContext >& rxContext,
IDataObjectPtr rDataObject );
+private:
// some helper functions
void initFlavorList( );
+ void initFlavorListFromFormatList(const std::vector<sal_uInt32>& rFormats);
void addSupportedFlavor( const css::datatransfer::DataFlavor& aFlavor );
- css::datatransfer::DataFlavor formatEtcToDataFlavor( const FORMATETC& aFormatEtc );
+ css::datatransfer::DataFlavor formatEtcToDataFlavor(sal_uInt32 cfFormat);
+ void tryToGetIDataObjectIfAbsent();
ByteSequence_t getClipboardData( CFormatEtc& aFormatEtc );
OUString synthesizeUnicodeText( );
@@ -76,6 +84,7 @@ private:
const css::datatransfer::DataFlavor& rhs );
private:
+ css::uno::WeakReference<css::datatransfer::clipboard::XClipboard> m_xClipboard;
IDataObjectPtr m_rDataObject;
css::uno::Sequence< css::datatransfer::DataFlavor > m_FlavorList;
const css::uno::Reference< css::uno::XComponentContext > m_xContext;
diff --git a/vcl/win/dtrans/DataFmtTransl.cxx b/vcl/win/dtrans/DataFmtTransl.cxx
index 837acac6056f..46947b81c6fa 100644
--- a/vcl/win/dtrans/DataFmtTransl.cxx
+++ b/vcl/win/dtrans/DataFmtTransl.cxx
@@ -98,13 +98,13 @@ CFormatEtc CDataFormatTranslator::getFormatEtcFromDataFlavor( const DataFlavor&
return sal::static_int_cast<CFormatEtc>(getFormatEtcForClipformat( sal::static_int_cast<CLIPFORMAT>(cf) ));
}
-DataFlavor CDataFormatTranslator::getDataFlavorFromFormatEtc( const FORMATETC& aFormatEtc, LCID lcid ) const
+DataFlavor CDataFormatTranslator::getDataFlavorFromFormatEtc(sal_uInt32 cfFormat, LCID lcid) const
{
DataFlavor aFlavor;
try
{
- CLIPFORMAT aClipformat = aFormatEtc.cfFormat;
+ CLIPFORMAT aClipformat = cfFormat;
Any aAny;
aAny <<= static_cast< sal_Int32 >( aClipformat );
diff --git a/vcl/win/dtrans/DataFmtTransl.hxx b/vcl/win/dtrans/DataFmtTransl.hxx
index 3fad9bbdc89a..0a8f08582b9c 100644
--- a/vcl/win/dtrans/DataFmtTransl.hxx
+++ b/vcl/win/dtrans/DataFmtTransl.hxx
@@ -43,7 +43,7 @@ public:
CFormatEtc getFormatEtcFromDataFlavor( const css::datatransfer::DataFlavor& aDataFlavor ) const;
css::datatransfer::DataFlavor getDataFlavorFromFormatEtc(
- const FORMATETC& aFormatEtc, LCID lcid = GetThreadLocale( ) ) const;
+ sal_uInt32 cfFormat, LCID lcid = GetThreadLocale()) const;
static CFormatEtc getFormatEtcForClipformat( CLIPFORMAT cf );
static CFormatEtc getFormatEtcForClipformatName( const OUString& aClipFmtName );
diff --git a/vcl/win/dtrans/FetcList.cxx b/vcl/win/dtrans/FetcList.cxx
index d8fc6a52548a..e9a1c0dac5f1 100644
--- a/vcl/win/dtrans/FetcList.cxx
+++ b/vcl/win/dtrans/FetcList.cxx
@@ -285,10 +285,7 @@ OUString CFormatRegistrar::getCharsetFromDataFlavor( const DataFlavor& aFlavor )
bool CFormatRegistrar::hasUnicodeFlavor( const Reference< XTransferable >& aXTransferable ) const
{
- CFormatEtc fetc( CF_UNICODETEXT );
-
- DataFlavor aFlavor =
- m_DataFormatTranslator.getDataFlavorFromFormatEtc( fetc );
+ DataFlavor aFlavor = m_DataFormatTranslator.getDataFlavorFromFormatEtc(CF_UNICODETEXT);
return aXTransferable->isDataFlavorSupported( aFlavor );
}
diff --git a/vcl/win/dtrans/WinClipboard.cxx b/vcl/win/dtrans/WinClipboard.cxx
index c1e4dde81c82..2e5dc2ad2d88 100644
--- a/vcl/win/dtrans/WinClipboard.cxx
+++ b/vcl/win/dtrans/WinClipboard.cxx
@@ -108,6 +108,32 @@ uno::Reference<datatransfer::XTransferable> SAL_CALL CWinClipboard::getContents(
uno::Reference<datatransfer::XTransferable> rClipContent;
+ // get the current format list from clipboard
+ if (UINT nFormats; !GetUpdatedClipboardFormats(nullptr, 0, &nFormats)
+ && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ std::vector<UINT> aUINTFormats(nFormats);
+ if (GetUpdatedClipboardFormats(aUINTFormats.data(), nFormats, &nFormats))
+ {
+ std::vector<sal_uInt32> aFormats(aUINTFormats.begin(), aUINTFormats.end());
+ rClipContent = new CDOTransferable(m_xContext, this, aFormats);
+
+ osl::MutexGuard aGuard2(m_ClipContentMutex);
+ m_foreignContent = rClipContent;
+ }
+ }
+
+ return rClipContent;
+}
+
+IDataObjectPtr CWinClipboard::getIDataObject()
+{
+ osl::MutexGuard aGuard(m_aMutex);
+
+ if (rBHelper.bDisposed)
+ throw lang::DisposedException("object is already disposed",
+ static_cast<XClipboardEx*>(this));
+
// get the current dataobject from clipboard
IDataObjectPtr pIDataObject;
HRESULT hr = m_MtaOleClipboard.getClipboard(&pIDataObject);
@@ -116,16 +142,10 @@ uno::Reference<datatransfer::XTransferable> SAL_CALL CWinClipboard::getContents(
{
// create an apartment neutral dataobject and initialize it with a
// com smart pointer to the IDataObject from clipboard
- IDataObjectPtr pIDo(new CAPNDataObject(pIDataObject));
-
- // remember pIDo destroys itself due to the smart pointer
- rClipContent = CDOTransferable::create(m_xContext, pIDo);
-
- osl::MutexGuard aGuard(m_ClipContentMutex);
- m_foreignContent = rClipContent;
+ pIDataObject = new CAPNDataObject(pIDataObject);
}
- return rClipContent;
+ return pIDataObject;
}
void SAL_CALL CWinClipboard::setContents(
diff --git a/vcl/win/dtrans/WinClipboard.hxx b/vcl/win/dtrans/WinClipboard.hxx
index aa3c35ab8490..56a1da34226a 100644
--- a/vcl/win/dtrans/WinClipboard.hxx
+++ b/vcl/win/dtrans/WinClipboard.hxx
@@ -33,10 +33,10 @@
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>
#include <osl/conditn.hxx>
+#include <systools/win32/comtools.hxx>
#include "MtaOleClipb.hxx"
-
-class CXNotifyingDataObject;
+#include "XNotifyingDataObject.hxx"
// implements the XClipboard[Ex] ... interfaces
// for the clipboard viewer mechanism we need a static callback function
@@ -114,6 +114,8 @@ public:
virtual OUString SAL_CALL getImplementationName() override;
virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+ IDataObjectPtr getIDataObject();
};
#endif
diff --git a/vcl/win/dtrans/XTDataObject.cxx b/vcl/win/dtrans/XTDataObject.cxx
index 80c19e5de93e..b829d2cdf3c1 100644
--- a/vcl/win/dtrans/XTDataObject.cxx
+++ b/vcl/win/dtrans/XTDataObject.cxx
@@ -635,10 +635,10 @@ DataFlavor CXTDataObject::formatEtcToDataFlavor( const FORMATETC& aFormatEtc ) c
DataFlavor aFlavor;
if ( m_FormatRegistrar.hasSynthesizedLocale( ) )
- aFlavor =
- m_DataFormatTranslator.getDataFlavorFromFormatEtc( aFormatEtc, CFormatRegistrar::getSynthesizedLocale( ) );
+ aFlavor = m_DataFormatTranslator.getDataFlavorFromFormatEtc(
+ aFormatEtc.cfFormat, CFormatRegistrar::getSynthesizedLocale());
else
- aFlavor = m_DataFormatTranslator.getDataFlavorFromFormatEtc( aFormatEtc );
+ aFlavor = m_DataFormatTranslator.getDataFlavorFromFormatEtc(aFormatEtc.cfFormat);
if ( !aFlavor.MimeType.getLength( ) )
throw UnsupportedFlavorException( );
diff --git a/vcl/win/dtrans/target.cxx b/vcl/win/dtrans/target.cxx
index 0aa04ea1f7ab..86229f23914c 100644
--- a/vcl/win/dtrans/target.cxx
+++ b/vcl/win/dtrans/target.cxx
@@ -321,8 +321,7 @@ HRESULT DropTarget::DragEnter( IDataObject *pDataObj,
else
{
// Convert the IDataObject to a XTransferable
- m_currentData= CDOTransferable::create(
- m_xContext, IDataObjectPtr(pDataObj));
+ m_currentData = new CDOTransferable(m_xContext, IDataObjectPtr(pDataObj));
}
//<-- TRA