[vlc-commits] skins2(Win): support more DragNdrop formats on Windows

Erwan Tulou git at videolan.org
Sun Jan 21 20:37:33 CET 2018


vlc | branch: master | Erwan Tulou <erwan10 at videolan.org> | Sun Jan 21 12:01:12 2018 +0100| [bb1fddd2003f61a943702a120c3421669d4503a2] | committer: Erwan Tulou

skins2(Win): support more DragNdrop formats on Windows

Add support for urls with the following formats :
- CFSTR_INETURLW (e.g. youtube on Firefox et Google Chrome)
- CF_TEXT (e.g. youtube on Internet Edge)

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=bb1fddd2003f61a943702a120c3421669d4503a2
---

 modules/gui/skins2/win32/win32_dragdrop.cpp | 148 ++++++++++++++++++----------
 modules/gui/skins2/win32/win32_dragdrop.hpp |  13 ++-
 2 files changed, 103 insertions(+), 58 deletions(-)

diff --git a/modules/gui/skins2/win32/win32_dragdrop.cpp b/modules/gui/skins2/win32/win32_dragdrop.cpp
index bb936ac6f9..b36b543195 100644
--- a/modules/gui/skins2/win32/win32_dragdrop.cpp
+++ b/modules/gui/skins2/win32/win32_dragdrop.cpp
@@ -28,12 +28,13 @@
 #include "../commands/cmd_add_item.hpp"
 #include "../events/evt_dragndrop.hpp"
 #include <list>
+#include <shlobj.h>
 
 
 Win32DragDrop::Win32DragDrop( intf_thread_t *pIntf,
                               bool playOnDrop, GenericWindow* pWin )
     : SkinObject( pIntf ), IDropTarget(), m_references( 1 ),
-      m_playOnDrop( playOnDrop ), m_pWin( pWin)
+      m_playOnDrop( playOnDrop ), m_pWin( pWin), m_format( { 0, NULL} )
 {
 }
 
@@ -48,24 +49,25 @@ STDMETHODIMP Win32DragDrop::QueryInterface( REFIID iid, void FAR* FAR* ppv )
         return S_OK;
     }
     *ppv = NULL;
-    return ResultFromScode( E_NOINTERFACE );
+    return E_NOINTERFACE;
 }
 
 
 STDMETHODIMP_(ULONG) Win32DragDrop::AddRef()
 {
-    return ++m_references;
+    return InterlockedIncrement( &m_references );
 }
 
 
 STDMETHODIMP_(ULONG) Win32DragDrop::Release()
 {
-    if( --m_references == 0 )
+    LONG count = InterlockedDecrement( &m_references );
+    if( count == 0 )
     {
         delete this;
         return 0;
     }
-    return m_references;
+    return count;
 }
 
 
@@ -73,24 +75,63 @@ STDMETHODIMP Win32DragDrop::DragEnter( LPDATAOBJECT pDataObj,
     DWORD grfKeyState, POINTL pt, DWORD *pdwEffect )
 {
     (void)grfKeyState; (void)pt;
-    FORMATETC fmtetc;
 
-    fmtetc.cfFormat = CF_HDROP;
+    // enumerate all data formats of HGLOBAL medium type
+    // that the source is offering
+    std::list<UINT> formats;
+    IEnumFORMATETC *pEnum;
+    if( pDataObj->EnumFormatEtc( DATADIR_GET, &pEnum ) == S_OK )
+    {
+        FORMATETC fe;
+        while( pEnum->Next( 1, &fe, NULL ) == S_OK )
+        {
+            if( fe.tymed == TYMED_HGLOBAL )
+                formats.push_back( fe.cfFormat );
+        }
+    }
+
+    // List of all data formats that we are interested in
+    // sorted by order of preference
+    static UINT ft_url = RegisterClipboardFormat( CFSTR_INETURLW );
+    static const struct {
+        UINT format;
+        const char* name;
+    } preferred[] = {
+        { ft_url, "CFSTR_INETURLW" },
+        { CF_HDROP, "CF_HDROP" },
+        { CF_TEXT, "CF_TEXT" },
+    };
+
+    // select the preferred format among those offered by the source
+    m_format = { 0, NULL };
+    for( unsigned i = 0; i < sizeof(preferred)/sizeof(preferred[0]); i++ )
+    {
+        for( std::list<UINT>::iterator it = formats.begin();
+             it != formats.end(); ++it )
+        {
+            if( *it == preferred[i].format )
+            {
+                m_format = { preferred[i].format, preferred[i].name };
+                msg_Dbg( getIntf(), "drag&drop selected format: %s",
+                                     m_format.name );
+                break;
+            }
+        }
+        if( m_format.format )
+            break;
+    }
+
+    // Check that the drag source provides the selected format
+    FORMATETC fmtetc;
+    fmtetc.cfFormat = m_format.format;
     fmtetc.ptd      = NULL;
     fmtetc.dwAspect = DVASPECT_CONTENT;
     fmtetc.lindex   = -1;
     fmtetc.tymed    = TYMED_HGLOBAL;
-
-    // Check that the drag source provides CF_HDROP,
-    // which is the only format we accept
-    if( pDataObj->QueryGetData( &fmtetc ) == S_OK )
-    {
+    if( m_format.format && pDataObj->QueryGetData( &fmtetc ) == S_OK )
         *pdwEffect = DROPEFFECT_COPY;
-    }
     else
-    {
         *pdwEffect = DROPEFFECT_NONE;
-    }
 
     // transmit DragEnter event
     EvtDragEnter evt( getIntf() );
@@ -108,6 +149,7 @@ STDMETHODIMP Win32DragDrop::DragOver( DWORD grfKeyState, POINTL pt,
     EvtDragOver evt( getIntf(), pt.x, pt.y );
     m_pWin->processEvent( evt );
 
+    *pdwEffect = DROPEFFECT_COPY;
     return S_OK;
 }
 
@@ -127,62 +169,62 @@ STDMETHODIMP Win32DragDrop::Drop( LPDATAOBJECT pDataObj, DWORD grfKeyState,
     POINTL pt, DWORD *pdwEffect )
 {
     (void)grfKeyState;
-    // User has dropped on us -- get the CF_HDROP data from drag source
+
+    // On Drop, retrieve and process the data
     FORMATETC fmtetc;
-    fmtetc.cfFormat = CF_HDROP;
+    fmtetc.cfFormat = m_format.format;
     fmtetc.ptd      = NULL;
     fmtetc.dwAspect = DVASPECT_CONTENT;
     fmtetc.lindex   = -1;
     fmtetc.tymed    = TYMED_HGLOBAL;
 
     STGMEDIUM medium;
-    HRESULT hr = pDataObj->GetData( &fmtetc, &medium );
-
-    if( !FAILED(hr) )
-    {
-        // Grab a pointer to the data
-        HGLOBAL HFiles = medium.hGlobal;
-        HDROP HDrop = (HDROP)GlobalLock( HFiles );
-
-        // Notify VLC of the drop
-        HandleDrop( HDrop, pt.x, pt.y );
-
-        // Release the pointer to the memory
-        GlobalUnlock( HFiles );
-//        ReleaseStgMedium( &medium );
-    }
-    else
+    if( FAILED( pDataObj->GetData( &fmtetc, &medium ) ) )
     {
         *pdwEffect = DROPEFFECT_NONE;
-        return hr;
+        return S_OK;
     }
-    return S_OK;
-}
-
 
-void Win32DragDrop::HandleDrop( HDROP HDrop, int x, int y )
-{
     std::list<std::string> files;
-
-    // Get the number of dropped files
-    int nbFiles = DragQueryFileW( HDrop, 0xFFFFFFFF, NULL, 0 );
-
-    for( int i = 0; i < nbFiles; i++ )
+    if( !strcmp( m_format.name, "CFSTR_INETURLW" ) )
     {
-        // Get the name of the file
-        int nameLength = DragQueryFileW( HDrop, i, NULL, 0 ) + 1;
-        wchar_t *psz_fileName = new WCHAR[nameLength];
-        DragQueryFileW( HDrop, i, psz_fileName, nameLength );
-
-        files.push_back( sFromWide(psz_fileName) );
-        delete[] psz_fileName;
+        wchar_t* data = (wchar_t*)GlobalLock( medium.hGlobal );
+        files.push_back( sFromWide(data) );
+        GlobalUnlock( medium.hGlobal );
+    }
+    else if( m_format.format == CF_HDROP )
+    {
+        HDROP HDrop = (HDROP)GlobalLock( medium.hGlobal );
+        // Get the number of dropped files
+        int nbFiles = DragQueryFileW( HDrop, 0xFFFFFFFF, NULL, 0 );
+        for( int i = 0; i < nbFiles; i++ )
+        {
+            // Get the name of the files
+            int nameLength = DragQueryFileW( HDrop, i, NULL, 0 ) + 1;
+            wchar_t *psz_fileName = new WCHAR[nameLength];
+            DragQueryFileW( HDrop, i, psz_fileName, nameLength );
+
+            files.push_back( sFromWide(psz_fileName) );
+            delete[] psz_fileName;
+         }
+         GlobalUnlock( medium.hGlobal );
+    }
+    else if( m_format.format == CF_TEXT )
+    {
+        char* data = (char*)GlobalLock( medium.hGlobal );
+        files.push_back( data );
+        GlobalUnlock( medium.hGlobal );
     }
 
-    DragFinish( HDrop );
+    // Release the pointer to the memory
+    ReleaseStgMedium( &medium );
 
     // transmit DragDrop event
-    EvtDragDrop evt( getIntf(), x, y, files );
+    EvtDragDrop evt( getIntf(), pt.x, pt.y, files );
     m_pWin->processEvent( evt );
+
+    *pdwEffect = DROPEFFECT_COPY;
+    return S_OK;
 }
 
 
diff --git a/modules/gui/skins2/win32/win32_dragdrop.hpp b/modules/gui/skins2/win32/win32_dragdrop.hpp
index 4b76f22df0..d1b0008c1e 100644
--- a/modules/gui/skins2/win32/win32_dragdrop.hpp
+++ b/modules/gui/skins2/win32/win32_dragdrop.hpp
@@ -32,6 +32,7 @@
 #include <windows.h>
 #include <shellapi.h>
 #include <ole2.h>
+#include <list>
 #include "../src/skin_common.hpp"
 #include "../src/generic_window.hpp"
 
@@ -58,14 +59,16 @@ protected:
 
 private:
     /// Internal reference counter
-    unsigned long m_references;
+    LONG m_references;
     /// Indicates whether the file(s) must be played immediately
     bool m_playOnDrop;
-    ///
+    /// Window associated
     GenericWindow* m_pWin;
-
-    /// Helper function
-    void HandleDrop( HDROP HDrop, int x, int y );
+    /// format used for DrapNDrop
+    struct {
+        UINT format;
+        const char* name;
+    } m_format;
 };
 
 



More information about the vlc-commits mailing list