[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