vcl/win/dtrans/DOTransferable.cxx |  110 ++++++++++++++++++++------------------
 vcl/win/dtrans/DOTransferable.hxx |   19 ++++--
 vcl/win/dtrans/DataFmtTransl.cxx  |    4 -
 vcl/win/dtrans/DataFmtTransl.hxx  |    2 
 vcl/win/dtrans/FetcList.cxx       |    5 -
 vcl/win/dtrans/WinClipboard.cxx   |   36 +++++++++---
 vcl/win/dtrans/WinClipboard.hxx   |    6 +-
 vcl/win/dtrans/XTDataObject.cxx   |    6 +-
 vcl/win/dtrans/target.cxx         |    3 -
 9 files changed, 113 insertions(+), 78 deletions(-)

New commits:
commit 7b6c0e63e64eb2ad1e83bd744a0d20f78c7a6b84
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Fri Mar 5 20:45:08 2021 +0300
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Sat Mar 6 07:11:57 2021 +0100

    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.
    
    Change-Id: Ife30f57605a42d59233bfcb97f8bc297b3ace463
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/112044
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/vcl/win/dtrans/DOTransferable.cxx 
b/vcl/win/dtrans/DOTransferable.cxx
index 0c61ddcccc77..7a911a0fa567 100644
--- a/vcl/win/dtrans/DOTransferable.cxx
+++ b/vcl/win/dtrans/DOTransferable.cxx
@@ -25,6 +25,7 @@
 #include "DOTransferable.hxx"
 #include "ImplHelper.hxx"
 #include "WinClip.hxx"
+#include "WinClipboard.hxx"
 #include "DTransHelper.hxx"
 #include "TxtCnvtHlp.hxx"
 #include "MimeAttrib.hxx"
@@ -208,19 +209,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 ),
@@ -229,6 +217,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 )
@@ -312,6 +314,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 ) )
@@ -321,39 +324,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));
     }
 }
 
@@ -370,18 +372,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
@@ -411,6 +404,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.
@@ -418,6 +423,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 af2d2008cf37..0e652f9b6a0d 100644
--- a/vcl/win/dtrans/DOTransferable.hxx
+++ b/vcl/win/dtrans/DOTransferable.hxx
@@ -23,12 +23,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;
 
@@ -39,9 +43,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;
@@ -54,18 +55,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( );
 
@@ -75,6 +83,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 f666f8c75401..5e2382213a0e 100644
--- a/vcl/win/dtrans/DataFmtTransl.cxx
+++ b/vcl/win/dtrans/DataFmtTransl.cxx
@@ -92,13 +92,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 3d748751b79c..e003f2538b2d 100644
--- a/vcl/win/dtrans/DataFmtTransl.hxx
+++ b/vcl/win/dtrans/DataFmtTransl.hxx
@@ -42,7 +42,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 6ed9e967d7e5..2100510b5d34 100644
--- a/vcl/win/dtrans/WinClipboard.cxx
+++ b/vcl/win/dtrans/WinClipboard.cxx
@@ -112,6 +112,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);
@@ -120,16 +146,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 aGuard2(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 1b0a05a3450d..8e64029b9ae3 100644
--- a/vcl/win/dtrans/WinClipboard.hxx
+++ b/vcl/win/dtrans/WinClipboard.hxx
@@ -32,10 +32,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
@@ -113,6 +113,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();
 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/win/dtrans/XTDataObject.cxx b/vcl/win/dtrans/XTDataObject.cxx
index 9300d2969997..adbed6bbec9f 100644
--- a/vcl/win/dtrans/XTDataObject.cxx
+++ b/vcl/win/dtrans/XTDataObject.cxx
@@ -636,10 +636,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 2492c8a3cc94..32cf95ffa647 100644
--- a/vcl/win/dtrans/target.cxx
+++ b/vcl/win/dtrans/target.cxx
@@ -333,8 +333,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
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to