From caa631bf5b69ef1e39989b8e1e4b3372491cb9b4 Mon Sep 17 00:00:00 2001 From: callum Date: Tue, 27 Oct 2009 17:52:04 -0700 Subject: Added IDropTarget interface. Still lots of cleanup but this works ok. You can drag over from Firefox or IE onto a prim --- indra/llwindow/lldragdropwin32.cpp | 295 +++++++++++++++++++++++++++++++++++++ 1 file changed, 295 insertions(+) create mode 100644 indra/llwindow/lldragdropwin32.cpp (limited to 'indra/llwindow/lldragdropwin32.cpp') diff --git a/indra/llwindow/lldragdropwin32.cpp b/indra/llwindow/lldragdropwin32.cpp new file mode 100644 index 0000000000..0daff85395 --- /dev/null +++ b/indra/llwindow/lldragdropwin32.cpp @@ -0,0 +1,295 @@ +/** + * @file lldragdrop32.cpp + * @brief Handler for Windows specific drag and drop (OS to client) code + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#if LL_WINDOWS + +#include "linden_common.h" + +#define WIN32_LEAN_AND_MEAN +#include + +#include "llwindowwin32.h" +#include "llkeyboardwin32.h" +#include "lldragdropwin32.h" + +#include "llwindowcallbacks.h" + +#include +#include +#include +#include +#include + +// FIXME: this should be done in CMake +#pragma comment( lib, "shlwapi.lib" ) + +class LLDragDropWin32Target: + public IDropTarget +{ + public: + LLDragDropWin32Target( HWND hWnd ) : + mWindowHandle( hWnd ), + mRefCount( 0 ) + { + strcpy(szFileDropped,""); + bDropTargetValid = false; + bTextDropped = false; + }; + + /* IUnknown methods */ + STDMETHOD_( ULONG, AddRef )( void ) + { + return ++mRefCount; + }; + + STDMETHOD_( ULONG, Release )( void ) + { + if ( --mRefCount == 0 ) + { + delete this; + return 0; + } + return mRefCount; + }; + + STDMETHOD ( QueryInterface )( REFIID iid, void ** ppvObject ) + { + if ( iid == IID_IUnknown || iid == IID_IDropTarget ) + { + *ppvObject = this; + AddRef(); + return S_OK; + }; + + *ppvObject = NULL; + return E_NOINTERFACE; + }; + + /* IDropTarget methods */ + STDMETHOD (DragEnter)(LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) + { + HRESULT hr = E_INVALIDARG; + bDropTargetValid = false; + bTextDropped = false; + *pdwEffect=DROPEFFECT_NONE; + + FORMATETC fmte = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; + STGMEDIUM medium; + + if (pDataObj && SUCCEEDED (pDataObj->GetData (&fmte, &medium))) + { + // We can Handle Only one File At a time !!! + if (1 == DragQueryFile ((HDROP)medium.hGlobal,0xFFFFFFFF,NULL,0 )) + { + // Get the File Name + if (DragQueryFileA((HDROP)medium.hGlobal, 0, szFileDropped,MAX_PATH)) + { + if (!PathIsDirectoryA(szFileDropped)) + { + char szTempFile[MAX_PATH]; + _splitpath(szFileDropped,NULL,NULL,NULL,szTempFile); + +// if (!stricmp(szTempFile,".lnk")) +// { +// if (ResolveLink(szFileDropped,szTempFile)) +// { +// strcpy(szFileDropped,szTempFile); +// *pdwEffect=DROPEFFECT_COPY; +// We Want to Create a Copy +// bDropTargetValid = true; +// hr = S_OK; +// } +// } +// else +// { + *pdwEffect=DROPEFFECT_COPY; + //We Want to Create a Copy + bDropTargetValid = true; + hr = S_OK; +// } + } + } + } + + if (medium.pUnkForRelease) + medium.pUnkForRelease->Release (); + else + GlobalFree (medium.hGlobal); + } + else + { + fmte.cfFormat = CF_TEXT; + fmte.ptd = NULL; + fmte.dwAspect = DVASPECT_CONTENT; + fmte.lindex = -1; + fmte.tymed = TYMED_HGLOBAL; + + // Does the drag source provide CF_TEXT ? + if (NOERROR == pDataObj->QueryGetData(&fmte)) + { + bDropTargetValid = true; + bTextDropped = true; + *pdwEffect=DROPEFFECT_COPY; + hr = S_OK; + } + } + return hr; + + + + }; + + STDMETHOD (DragOver)(DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) + { + HRESULT hr = S_OK; + if (bDropTargetValid) + *pdwEffect=DROPEFFECT_COPY; + + return hr; + }; + + STDMETHOD (DragLeave)(void) + { + HRESULT hr = S_OK; + strcpy(szFileDropped,""); + return hr; + }; + + STDMETHOD (Drop)(LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) + { + HRESULT hr = S_OK; + if (bDropTargetValid) + { + *pdwEffect=DROPEFFECT_COPY; + + FORMATETC fmte; + STGMEDIUM medium; + + if (bTextDropped) + { + fmte.cfFormat = CF_TEXT; + fmte.ptd = NULL; + fmte.dwAspect = DVASPECT_CONTENT; + fmte.lindex = -1; + fmte.tymed = TYMED_HGLOBAL; + + hr = pDataObj->GetData(&fmte, &medium); + HGLOBAL hText = medium.hGlobal; + LPSTR lpszText = (LPSTR)GlobalLock(hText); + + LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mWindowHandle, GWL_USERDATA); + if (NULL != window_imp) + { + LLCoordGL gl_coord( pt.x, pt.y); + LLCoordWindow cursor_coord_window( pt.x, pt.y ); + window_imp->convertCoords(cursor_coord_window, &gl_coord); + llinfos << "### (Drop) URL is: " << lpszText << llendl; + llinfos << "### raw coords are: " << pt.x << " x " << pt.y << llendl; + llinfos << "### GL coords are: " << gl_coord.mX << " x " << gl_coord.mY << llendl; + llinfos << llendl; + + MASK mask = gKeyboard->currentMask(TRUE); + window_imp->completeDropRequest( gl_coord, mask, std::string( lpszText ) ); + }; + + GlobalUnlock(hText); + ReleaseStgMedium(&medium); + } + } + return hr; + }; + + private: + ULONG mRefCount; + HWND mWindowHandle; + char szFileDropped[1024]; + bool bDropTargetValid; + bool bTextDropped; + friend class LLWindowWin32; +}; + +LLDragDropWin32::LLDragDropWin32() : + mDropTarget( NULL ), + mDropWindowHandle( NULL ) + +{ +} + +LLDragDropWin32::~LLDragDropWin32() +{ +} + +bool LLDragDropWin32::init( HWND hWnd ) +{ + if (NOERROR != OleInitialize(NULL)) + return FALSE; + + mDropTarget = new LLDragDropWin32Target( hWnd ); + if ( mDropTarget ) + { + HRESULT result = CoLockObjectExternal( mDropTarget, TRUE, TRUE ); + if ( S_OK == result ) + { + result = RegisterDragDrop( hWnd, mDropTarget ); + if ( S_OK != result ) + { + // RegisterDragDrop failed + return false; + }; + + // all ok + mDropWindowHandle = hWnd; + } + else + { + // Unable to lock OLE object + return false; + }; + }; + + // success + return true; +} + +void LLDragDropWin32::reset() +{ + if ( mDropTarget ) + { + CoLockObjectExternal( mDropTarget, FALSE, TRUE ); + RevokeDragDrop( mDropWindowHandle ); + mDropTarget->Release(); + }; + + OleUninitialize(); +} + +#endif -- cgit v1.2.3 From 996740607a11ac7f8633f12b65ead0508e1435fa Mon Sep 17 00:00:00 2001 From: callum Date: Tue, 3 Nov 2009 09:33:21 -0800 Subject: Convert screen coordinates from IDropAction to window coordinates. --- indra/llwindow/lldragdropwin32.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'indra/llwindow/lldragdropwin32.cpp') diff --git a/indra/llwindow/lldragdropwin32.cpp b/indra/llwindow/lldragdropwin32.cpp index 0daff85395..d05dbf19a5 100644 --- a/indra/llwindow/lldragdropwin32.cpp +++ b/indra/llwindow/lldragdropwin32.cpp @@ -209,11 +209,18 @@ class LLDragDropWin32Target: LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mWindowHandle, GWL_USERDATA); if (NULL != window_imp) { - LLCoordGL gl_coord( pt.x, pt.y); - LLCoordWindow cursor_coord_window( pt.x, pt.y ); + LLCoordGL gl_coord( 0, 0 ); + + POINT pt2; + pt2.x = pt.x; + pt2.y = pt.y; + ScreenToClient( mWindowHandle, &pt2 ); + + LLCoordWindow cursor_coord_window( pt2.x, pt2.y ); window_imp->convertCoords(cursor_coord_window, &gl_coord); llinfos << "### (Drop) URL is: " << lpszText << llendl; llinfos << "### raw coords are: " << pt.x << " x " << pt.y << llendl; + llinfos << "### window coords are: " << pt2.x << " x " << pt2.y << llendl; llinfos << "### GL coords are: " << gl_coord.mX << " x " << gl_coord.mY << llendl; llinfos << llendl; -- cgit v1.2.3 From bf5ce0fcbd9a71ce1372db0f42395ba47747fd78 Mon Sep 17 00:00:00 2001 From: Rick Pasetto Date: Thu, 12 Nov 2009 11:06:29 -0800 Subject: Change 'handleDrop()' API to 'handleDragNDrop', which now takes a "drop" BOOL --- indra/llwindow/lldragdropwin32.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'indra/llwindow/lldragdropwin32.cpp') diff --git a/indra/llwindow/lldragdropwin32.cpp b/indra/llwindow/lldragdropwin32.cpp index d05dbf19a5..879f2d2b90 100644 --- a/indra/llwindow/lldragdropwin32.cpp +++ b/indra/llwindow/lldragdropwin32.cpp @@ -171,6 +171,22 @@ class LLDragDropWin32Target: STDMETHOD (DragOver)(DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) { HRESULT hr = S_OK; + // XXX MAJOR MAJOR HACK! + LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mWindowHandle, GWL_USERDATA); + if (NULL != window_imp) + { + LLCoordGL gl_coord( 0, 0 ); + + POINT pt2; + pt2.x = pt.x; + pt2.y = pt.y; + ScreenToClient( mWindowHandle, &pt2 ); + + LLCoordWindow cursor_coord_window( pt2.x, pt2.y ); + window_imp->convertCoords(cursor_coord_window, &gl_coord); + MASK mask = gKeyboard->currentMask(TRUE); + bDropTargetValid = window_imp->completeDragNDropRequest( gl_coord, mask, FALSE, std::string( "" ) ); + } if (bDropTargetValid) *pdwEffect=DROPEFFECT_COPY; @@ -225,7 +241,7 @@ class LLDragDropWin32Target: llinfos << llendl; MASK mask = gKeyboard->currentMask(TRUE); - window_imp->completeDropRequest( gl_coord, mask, std::string( lpszText ) ); + window_imp->completeDragNDropRequest( gl_coord, mask, TRUE, std::string( lpszText ) ); }; GlobalUnlock(hText); -- cgit v1.2.3 From 778005a350308d51f114ece74b4e7f3e7af3d37e Mon Sep 17 00:00:00 2001 From: callum Date: Fri, 13 Nov 2009 17:43:55 -0800 Subject: Reworked IDropTarget COM interface impl - now much cleaner and doesn't crash! --- indra/llwindow/lldragdropwin32.cpp | 287 +++++++++++++++++-------------------- 1 file changed, 130 insertions(+), 157 deletions(-) (limited to 'indra/llwindow/lldragdropwin32.cpp') diff --git a/indra/llwindow/lldragdropwin32.cpp b/indra/llwindow/lldragdropwin32.cpp index d05dbf19a5..aac68e71af 100644 --- a/indra/llwindow/lldragdropwin32.cpp +++ b/indra/llwindow/lldragdropwin32.cpp @@ -34,216 +34,183 @@ #include "linden_common.h" -#define WIN32_LEAN_AND_MEAN -#include - #include "llwindowwin32.h" #include "llkeyboardwin32.h" -#include "lldragdropwin32.h" - #include "llwindowcallbacks.h" - -#include -#include -#include -#include -#include - -// FIXME: this should be done in CMake -#pragma comment( lib, "shlwapi.lib" ) +#include "lldragdropwin32.h" class LLDragDropWin32Target: public IDropTarget { public: + //////////////////////////////////////////////////////////////////////////////// + // LLDragDropWin32Target( HWND hWnd ) : - mWindowHandle( hWnd ), - mRefCount( 0 ) + mRefCount( 1 ), + mAppWindowHandle( hWnd ), + mAllowDrop( false) { - strcpy(szFileDropped,""); - bDropTargetValid = false; - bTextDropped = false; }; - /* IUnknown methods */ - STDMETHOD_( ULONG, AddRef )( void ) + //////////////////////////////////////////////////////////////////////////////// + // + ULONG __stdcall AddRef( void ) { - return ++mRefCount; + return InterlockedIncrement( &mRefCount ); }; - STDMETHOD_( ULONG, Release )( void ) + //////////////////////////////////////////////////////////////////////////////// + // + ULONG __stdcall Release( void ) { - if ( --mRefCount == 0 ) + LONG count = InterlockedDecrement( &mRefCount ); + + if ( count == 0 ) { delete this; return 0; } - return mRefCount; + else + { + return count; + }; }; - STDMETHOD ( QueryInterface )( REFIID iid, void ** ppvObject ) + //////////////////////////////////////////////////////////////////////////////// + // + HRESULT __stdcall QueryInterface( REFIID iid, void** ppvObject ) { if ( iid == IID_IUnknown || iid == IID_IDropTarget ) { - *ppvObject = this; AddRef(); + *ppvObject = this; return S_OK; + } + else + { + *ppvObject = 0; + return E_NOINTERFACE; }; - - *ppvObject = NULL; - return E_NOINTERFACE; }; - - /* IDropTarget methods */ - STDMETHOD (DragEnter)(LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) + + //////////////////////////////////////////////////////////////////////////////// + // + HRESULT __stdcall DragEnter( IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect ) { - HRESULT hr = E_INVALIDARG; - bDropTargetValid = false; - bTextDropped = false; - *pdwEffect=DROPEFFECT_NONE; - - FORMATETC fmte = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; - STGMEDIUM medium; - - if (pDataObj && SUCCEEDED (pDataObj->GetData (&fmte, &medium))) - { - // We can Handle Only one File At a time !!! - if (1 == DragQueryFile ((HDROP)medium.hGlobal,0xFFFFFFFF,NULL,0 )) - { - // Get the File Name - if (DragQueryFileA((HDROP)medium.hGlobal, 0, szFileDropped,MAX_PATH)) - { - if (!PathIsDirectoryA(szFileDropped)) - { - char szTempFile[MAX_PATH]; - _splitpath(szFileDropped,NULL,NULL,NULL,szTempFile); - -// if (!stricmp(szTempFile,".lnk")) -// { -// if (ResolveLink(szFileDropped,szTempFile)) -// { -// strcpy(szFileDropped,szTempFile); -// *pdwEffect=DROPEFFECT_COPY; -// We Want to Create a Copy -// bDropTargetValid = true; -// hr = S_OK; -// } -// } -// else -// { - *pdwEffect=DROPEFFECT_COPY; - //We Want to Create a Copy - bDropTargetValid = true; - hr = S_OK; -// } - } - } - } - - if (medium.pUnkForRelease) - medium.pUnkForRelease->Release (); - else - GlobalFree (medium.hGlobal); - } - else + FORMATETC fmtetc = { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; + + // support CF_TEXT using a HGLOBAL? + if ( S_OK == pDataObject->QueryGetData( &fmtetc ) ) { - fmte.cfFormat = CF_TEXT; - fmte.ptd = NULL; - fmte.dwAspect = DVASPECT_CONTENT; - fmte.lindex = -1; - fmte.tymed = TYMED_HGLOBAL; - - // Does the drag source provide CF_TEXT ? - if (NOERROR == pDataObj->QueryGetData(&fmte)) - { - bDropTargetValid = true; - bTextDropped = true; - *pdwEffect=DROPEFFECT_COPY; - hr = S_OK; - } - } - return hr; + mAllowDrop = true; + *pdwEffect = DROPEFFECT_COPY; + SetFocus( mAppWindowHandle ); + } + else + { + mAllowDrop = false; + *pdwEffect = DROPEFFECT_NONE; + }; + return S_OK; }; - STDMETHOD (DragOver)(DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) + //////////////////////////////////////////////////////////////////////////////// + // + HRESULT __stdcall DragOver( DWORD grfKeyState, POINTL pt, DWORD* pdwEffect ) { - HRESULT hr = S_OK; - if (bDropTargetValid) - *pdwEffect=DROPEFFECT_COPY; + if ( mAllowDrop ) + { + *pdwEffect = DROPEFFECT_COPY; + } + else + { + *pdwEffect = DROPEFFECT_NONE; + }; - return hr; + return S_OK; }; - STDMETHOD (DragLeave)(void) + //////////////////////////////////////////////////////////////////////////////// + // + HRESULT __stdcall DragLeave( void ) { - HRESULT hr = S_OK; - strcpy(szFileDropped,""); - return hr; + return S_OK; }; - STDMETHOD (Drop)(LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) + //////////////////////////////////////////////////////////////////////////////// + // + HRESULT __stdcall Drop( IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect ) { - HRESULT hr = S_OK; - if (bDropTargetValid) + if ( mAllowDrop ) { - *pdwEffect=DROPEFFECT_COPY; - - FORMATETC fmte; - STGMEDIUM medium; + // construct a FORMATETC object + FORMATETC fmtetc = { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; - if (bTextDropped) + // do we have text? + if( S_OK == pDataObject->QueryGetData( &fmtetc ) ) { - fmte.cfFormat = CF_TEXT; - fmte.ptd = NULL; - fmte.dwAspect = DVASPECT_CONTENT; - fmte.lindex = -1; - fmte.tymed = TYMED_HGLOBAL; - - hr = pDataObj->GetData(&fmte, &medium); - HGLOBAL hText = medium.hGlobal; - LPSTR lpszText = (LPSTR)GlobalLock(hText); - - LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mWindowHandle, GWL_USERDATA); - if (NULL != window_imp) + STGMEDIUM stgmed; + if( S_OK == pDataObject->GetData( &fmtetc, &stgmed ) ) { - LLCoordGL gl_coord( 0, 0 ); - - POINT pt2; - pt2.x = pt.x; - pt2.y = pt.y; - ScreenToClient( mWindowHandle, &pt2 ); - - LLCoordWindow cursor_coord_window( pt2.x, pt2.y ); - window_imp->convertCoords(cursor_coord_window, &gl_coord); - llinfos << "### (Drop) URL is: " << lpszText << llendl; - llinfos << "### raw coords are: " << pt.x << " x " << pt.y << llendl; - llinfos << "### window coords are: " << pt2.x << " x " << pt2.y << llendl; - llinfos << "### GL coords are: " << gl_coord.mX << " x " << gl_coord.mY << llendl; - llinfos << llendl; - - MASK mask = gKeyboard->currentMask(TRUE); - window_imp->completeDropRequest( gl_coord, mask, std::string( lpszText ) ); + // note: data is in an HGLOBAL - not 'regular' memory + PVOID data = GlobalLock( stgmed.hGlobal ); + + // window impl stored in Window data (neat!) + LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong( mAppWindowHandle, GWL_USERDATA ); + if ( NULL != window_imp ) + { + LLCoordGL gl_coord( 0, 0 ); + + POINT pt_client; + pt_client.x = pt.x; + pt_client.y = pt.y; + ScreenToClient( mAppWindowHandle, &pt_client ); + + LLCoordWindow cursor_coord_window( pt_client.x, pt_client.y ); + window_imp->convertCoords(cursor_coord_window, &gl_coord); + llinfos << "### (Drop) URL is: " << data << llendl; + llinfos << "### raw coords are: " << pt.x << " x " << pt.y << llendl; + llinfos << "### client coords are: " << pt_client.x << " x " << pt_client.y << llendl; + llinfos << "### GL coords are: " << gl_coord.mX << " x " << gl_coord.mY << llendl; + llinfos << llendl; + + // no keyboard modifier option yet but we could one day + MASK mask = gKeyboard->currentMask( TRUE ); + + // actually do the drop + window_imp->completeDropRequest( gl_coord, mask, std::string( (char*)data ) ); + }; + + GlobalUnlock( stgmed.hGlobal ); + + ReleaseStgMedium( &stgmed ); }; + }; - GlobalUnlock(hText); - ReleaseStgMedium(&medium); - } + *pdwEffect = DROPEFFECT_COPY; } - return hr; + else + { + *pdwEffect = DROPEFFECT_NONE; + }; + + return S_OK; }; - + + //////////////////////////////////////////////////////////////////////////////// + // private: - ULONG mRefCount; - HWND mWindowHandle; - char szFileDropped[1024]; - bool bDropTargetValid; - bool bTextDropped; + LONG mRefCount; + HWND mAppWindowHandle; + bool mAllowDrop; friend class LLWindowWin32; }; +//////////////////////////////////////////////////////////////////////////////// +// LLDragDropWin32::LLDragDropWin32() : mDropTarget( NULL ), mDropWindowHandle( NULL ) @@ -251,19 +218,23 @@ LLDragDropWin32::LLDragDropWin32() : { } +//////////////////////////////////////////////////////////////////////////////// +// LLDragDropWin32::~LLDragDropWin32() { } +//////////////////////////////////////////////////////////////////////////////// +// bool LLDragDropWin32::init( HWND hWnd ) { - if (NOERROR != OleInitialize(NULL)) + if ( NOERROR != OleInitialize( NULL ) ) return FALSE; mDropTarget = new LLDragDropWin32Target( hWnd ); if ( mDropTarget ) { - HRESULT result = CoLockObjectExternal( mDropTarget, TRUE, TRUE ); + HRESULT result = CoLockObjectExternal( mDropTarget, TRUE, FALSE ); if ( S_OK == result ) { result = RegisterDragDrop( hWnd, mDropTarget ); @@ -287,12 +258,14 @@ bool LLDragDropWin32::init( HWND hWnd ) return true; } +//////////////////////////////////////////////////////////////////////////////// +// void LLDragDropWin32::reset() { if ( mDropTarget ) { - CoLockObjectExternal( mDropTarget, FALSE, TRUE ); RevokeDragDrop( mDropWindowHandle ); + CoLockObjectExternal( mDropTarget, FALSE, TRUE ); mDropTarget->Release(); }; -- cgit v1.2.3 From 4419e367bcbe8c1b248e88eab8096f0b8ac4707c Mon Sep 17 00:00:00 2001 From: callum Date: Wed, 18 Nov 2009 21:15:44 -0800 Subject: Add support for removing the Windows specific drag/drop code from the codebase via a new CMake file (DragDrop.cmake). --- indra/llwindow/lldragdropwin32.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'indra/llwindow/lldragdropwin32.cpp') diff --git a/indra/llwindow/lldragdropwin32.cpp b/indra/llwindow/lldragdropwin32.cpp index aac68e71af..471c88675d 100644 --- a/indra/llwindow/lldragdropwin32.cpp +++ b/indra/llwindow/lldragdropwin32.cpp @@ -32,6 +32,8 @@ #if LL_WINDOWS +#if LL_OS_DRAGDROP_ENABLED + #include "linden_common.h" #include "llwindowwin32.h" @@ -272,4 +274,7 @@ void LLDragDropWin32::reset() OleUninitialize(); } -#endif +#endif // LL_OS_DRAGDROP_ENABLED + +#endif // LL_WINDOWS + -- cgit v1.2.3 From d4ba73ed721fa0811474fc53300f560539d38018 Mon Sep 17 00:00:00 2001 From: Rick Pasetto Date: Thu, 19 Nov 2009 09:24:26 -0800 Subject: Fix merge error --- indra/llwindow/lldragdropwin32.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/llwindow/lldragdropwin32.cpp') diff --git a/indra/llwindow/lldragdropwin32.cpp b/indra/llwindow/lldragdropwin32.cpp index 4fc64f2f69..b39cd83698 100644 --- a/indra/llwindow/lldragdropwin32.cpp +++ b/indra/llwindow/lldragdropwin32.cpp @@ -124,7 +124,7 @@ class LLDragDropWin32Target: if ( mAllowDrop ) { // XXX MAJOR MAJOR HACK! - LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mWindowHandle, GWL_USERDATA); + LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mAppWindowHandle, GWL_USERDATA); if (NULL != window_imp) { LLCoordGL gl_coord( 0, 0 ); @@ -132,12 +132,12 @@ class LLDragDropWin32Target: POINT pt2; pt2.x = pt.x; pt2.y = pt.y; - ScreenToClient( mWindowHandle, &pt2 ); + ScreenToClient( mAppWindowHandle, &pt2 ); LLCoordWindow cursor_coord_window( pt2.x, pt2.y ); window_imp->convertCoords(cursor_coord_window, &gl_coord); MASK mask = gKeyboard->currentMask(TRUE); - bDropTargetValid = window_imp->completeDragNDropRequest( gl_coord, mask, FALSE, std::string( "" ) ); + window_imp->completeDragNDropRequest( gl_coord, mask, FALSE, std::string( "" ) ); } *pdwEffect = DROPEFFECT_COPY; } -- cgit v1.2.3 From 8d84b7ae4062d8680aae2bb8325813bdac0335ed Mon Sep 17 00:00:00 2001 From: callum Date: Tue, 24 Nov 2009 18:31:30 -0800 Subject: Add support for changing OS cursor when mouse passes over a prim you can drop on versus one you can't. --- indra/llwindow/lldragdropwin32.cpp | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) (limited to 'indra/llwindow/lldragdropwin32.cpp') diff --git a/indra/llwindow/lldragdropwin32.cpp b/indra/llwindow/lldragdropwin32.cpp index a10cfbf12f..6024931092 100644 --- a/indra/llwindow/lldragdropwin32.cpp +++ b/indra/llwindow/lldragdropwin32.cpp @@ -125,23 +125,29 @@ class LLDragDropWin32Target: { if ( mAllowDrop ) { - // XXX MAJOR MAJOR HACK! - LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mAppWindowHandle, GWL_USERDATA); - if (NULL != window_imp) - { - LLCoordGL gl_coord( 0, 0 ); - - POINT pt2; - pt2.x = pt.x; - pt2.y = pt.y; - ScreenToClient( mAppWindowHandle, &pt2 ); + bool allowed_to_drop = false; - LLCoordWindow cursor_coord_window( pt2.x, pt2.y ); - window_imp->convertCoords(cursor_coord_window, &gl_coord); - MASK mask = gKeyboard->currentMask(TRUE); - window_imp->completeDragNDropRequest( gl_coord, mask, FALSE, std::string( "" ) ); - } - *pdwEffect = DROPEFFECT_COPY; + // XXX MAJOR MAJOR HACK! + LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mAppWindowHandle, GWL_USERDATA); + if (NULL != window_imp) + { + LLCoordGL gl_coord( 0, 0 ); + + POINT pt2; + pt2.x = pt.x; + pt2.y = pt.y; + ScreenToClient( mAppWindowHandle, &pt2 ); + + LLCoordWindow cursor_coord_window( pt2.x, pt2.y ); + window_imp->convertCoords(cursor_coord_window, &gl_coord); + MASK mask = gKeyboard->currentMask(TRUE); + allowed_to_drop = window_imp->completeDragNDropRequest( gl_coord, mask, FALSE, std::string( "" ) ); + } + + if ( allowed_to_drop ) + *pdwEffect = DROPEFFECT_COPY; + else + *pdwEffect = DROPEFFECT_NONE; } else { -- cgit v1.2.3 From e2e7d544b6a114e70e3b46f516a4f0e8d7db4bd1 Mon Sep 17 00:00:00 2001 From: callum Date: Tue, 24 Nov 2009 20:20:53 -0800 Subject: Added support for dropping SURLs onto viewer Does right thing when logged in - needs some work at login page Removed (commented out) WM_DROPFILES code for now --- indra/llwindow/lldragdropwin32.cpp | 103 +++++++++++++++++++------------------ 1 file changed, 54 insertions(+), 49 deletions(-) (limited to 'indra/llwindow/lldragdropwin32.cpp') diff --git a/indra/llwindow/lldragdropwin32.cpp b/indra/llwindow/lldragdropwin32.cpp index 6024931092..74f96f6da3 100644 --- a/indra/llwindow/lldragdropwin32.cpp +++ b/indra/llwindow/lldragdropwin32.cpp @@ -54,6 +54,10 @@ class LLDragDropWin32Target: { }; + virtual ~LLDragDropWin32Target() + { + }; + //////////////////////////////////////////////////////////////////////////////// // ULONG __stdcall AddRef( void ) @@ -105,6 +109,20 @@ class LLDragDropWin32Target: if ( S_OK == pDataObject->QueryGetData( &fmtetc ) ) { mAllowDrop = true; + mDropUrl = std::string(); + mIsSlurl = false; + + STGMEDIUM stgmed; + if( S_OK == pDataObject->GetData( &fmtetc, &stgmed ) ) + { + PVOID data = GlobalLock( stgmed.hGlobal ); + mDropUrl = std::string( (char*)data ); + + mIsSlurl = ( mDropUrl.find( "slurl.com" ) != std::string::npos ); + + GlobalUnlock( stgmed.hGlobal ); + ReleaseStgMedium( &stgmed ); + }; *pdwEffect = DROPEFFECT_COPY; @@ -125,8 +143,6 @@ class LLDragDropWin32Target: { if ( mAllowDrop ) { - bool allowed_to_drop = false; - // XXX MAJOR MAJOR HACK! LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mAppWindowHandle, GWL_USERDATA); if (NULL != window_imp) @@ -141,13 +157,17 @@ class LLDragDropWin32Target: LLCoordWindow cursor_coord_window( pt2.x, pt2.y ); window_imp->convertCoords(cursor_coord_window, &gl_coord); MASK mask = gKeyboard->currentMask(TRUE); - allowed_to_drop = window_imp->completeDragNDropRequest( gl_coord, mask, FALSE, std::string( "" ) ); - } - if ( allowed_to_drop ) - *pdwEffect = DROPEFFECT_COPY; - else - *pdwEffect = DROPEFFECT_NONE; + bool allowed_to_drop = window_imp->completeDragNDropRequest( gl_coord, mask, FALSE, std::string( "" ), mIsSlurl ); + if ( allowed_to_drop ) + *pdwEffect = DROPEFFECT_COPY; + else + *pdwEffect = DROPEFFECT_NONE; + + // special case for SLURLs - you can always drop them on the client window and we need a different cursor + if ( mIsSlurl ) + *pdwEffect = DROPEFFECT_LINK; + }; } else { @@ -161,6 +181,7 @@ class LLDragDropWin32Target: // HRESULT __stdcall DragLeave( void ) { + mDropUrl = std::string(); return S_OK; }; @@ -170,48 +191,30 @@ class LLDragDropWin32Target: { if ( mAllowDrop ) { - // construct a FORMATETC object - FORMATETC fmtetc = { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; - - // do we have text? - if( S_OK == pDataObject->QueryGetData( &fmtetc ) ) + // window impl stored in Window data (neat!) + LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong( mAppWindowHandle, GWL_USERDATA ); + if ( NULL != window_imp ) { - STGMEDIUM stgmed; - if( S_OK == pDataObject->GetData( &fmtetc, &stgmed ) ) - { - // note: data is in an HGLOBAL - not 'regular' memory - PVOID data = GlobalLock( stgmed.hGlobal ); - - // window impl stored in Window data (neat!) - LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong( mAppWindowHandle, GWL_USERDATA ); - if ( NULL != window_imp ) - { - LLCoordGL gl_coord( 0, 0 ); - - POINT pt_client; - pt_client.x = pt.x; - pt_client.y = pt.y; - ScreenToClient( mAppWindowHandle, &pt_client ); - - LLCoordWindow cursor_coord_window( pt_client.x, pt_client.y ); - window_imp->convertCoords(cursor_coord_window, &gl_coord); - llinfos << "### (Drop) URL is: " << data << llendl; - llinfos << "### raw coords are: " << pt.x << " x " << pt.y << llendl; - llinfos << "### client coords are: " << pt_client.x << " x " << pt_client.y << llendl; - llinfos << "### GL coords are: " << gl_coord.mX << " x " << gl_coord.mY << llendl; - llinfos << llendl; - - // no keyboard modifier option yet but we could one day - MASK mask = gKeyboard->currentMask( TRUE ); - - // actually do the drop - window_imp->completeDragNDropRequest( gl_coord, mask, TRUE, std::string( (char*)data ) ); - }; - - GlobalUnlock( stgmed.hGlobal ); - - ReleaseStgMedium( &stgmed ); - }; + LLCoordGL gl_coord( 0, 0 ); + + POINT pt_client; + pt_client.x = pt.x; + pt_client.y = pt.y; + ScreenToClient( mAppWindowHandle, &pt_client ); + + LLCoordWindow cursor_coord_window( pt_client.x, pt_client.y ); + window_imp->convertCoords(cursor_coord_window, &gl_coord); + llinfos << "### (Drop) URL is: " << mDropUrl << llendl; + llinfos << "### raw coords are: " << pt.x << " x " << pt.y << llendl; + llinfos << "### client coords are: " << pt_client.x << " x " << pt_client.y << llendl; + llinfos << "### GL coords are: " << gl_coord.mX << " x " << gl_coord.mY << llendl; + llinfos << llendl; + + // no keyboard modifier option yet but we could one day + MASK mask = gKeyboard->currentMask( TRUE ); + + // actually do the drop + window_imp->completeDragNDropRequest( gl_coord, mask, TRUE, mDropUrl, mIsSlurl ); }; *pdwEffect = DROPEFFECT_COPY; @@ -230,6 +233,8 @@ class LLDragDropWin32Target: LONG mRefCount; HWND mAppWindowHandle; bool mAllowDrop; + std::string mDropUrl; + bool mIsSlurl; friend class LLWindowWin32; }; -- cgit v1.2.3 From ff53d4ff9b497f4f0f30035d7e02e6df290db6a4 Mon Sep 17 00:00:00 2001 From: Rick Pasetto Date: Thu, 3 Dec 2009 12:19:02 -0800 Subject: Fix Windows build based on API change to handleDragNDrop() --- indra/llwindow/lldragdropwin32.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/llwindow/lldragdropwin32.cpp') diff --git a/indra/llwindow/lldragdropwin32.cpp b/indra/llwindow/lldragdropwin32.cpp index 74f96f6da3..a96f04ff1f 100644 --- a/indra/llwindow/lldragdropwin32.cpp +++ b/indra/llwindow/lldragdropwin32.cpp @@ -158,7 +158,7 @@ class LLDragDropWin32Target: window_imp->convertCoords(cursor_coord_window, &gl_coord); MASK mask = gKeyboard->currentMask(TRUE); - bool allowed_to_drop = window_imp->completeDragNDropRequest( gl_coord, mask, FALSE, std::string( "" ), mIsSlurl ); + bool allowed_to_drop = window_imp->completeDragNDropRequest( gl_coord, mask, FALSE, std::string( "" ) ); if ( allowed_to_drop ) *pdwEffect = DROPEFFECT_COPY; else @@ -214,7 +214,7 @@ class LLDragDropWin32Target: MASK mask = gKeyboard->currentMask( TRUE ); // actually do the drop - window_imp->completeDragNDropRequest( gl_coord, mask, TRUE, mDropUrl, mIsSlurl ); + window_imp->completeDragNDropRequest( gl_coord, mask, TRUE, mDropUrl ); }; *pdwEffect = DROPEFFECT_COPY; -- cgit v1.2.3 From 4c33c54ce03bffd3ad75be3dccaed2d26a68e157 Mon Sep 17 00:00:00 2001 From: Rick Pasetto Date: Thu, 3 Dec 2009 19:02:12 -0800 Subject: Fix windows build to now use DragNDropAction instead of a bool 'drop' --- indra/llwindow/lldragdropwin32.cpp | 95 +++++++++++++++++++++++++++++++------- 1 file changed, 79 insertions(+), 16 deletions(-) (limited to 'indra/llwindow/lldragdropwin32.cpp') diff --git a/indra/llwindow/lldragdropwin32.cpp b/indra/llwindow/lldragdropwin32.cpp index a96f04ff1f..4865570f07 100644 --- a/indra/llwindow/lldragdropwin32.cpp +++ b/indra/llwindow/lldragdropwin32.cpp @@ -117,15 +117,45 @@ class LLDragDropWin32Target: { PVOID data = GlobalLock( stgmed.hGlobal ); mDropUrl = std::string( (char*)data ); - - mIsSlurl = ( mDropUrl.find( "slurl.com" ) != std::string::npos ); + // XXX MAJOR MAJOR HACK! + LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mAppWindowHandle, GWL_USERDATA); + if (NULL != window_imp) + { + LLCoordGL gl_coord( 0, 0 ); + + POINT pt2; + pt2.x = pt.x; + pt2.y = pt.y; + ScreenToClient( mAppWindowHandle, &pt2 ); + + LLCoordWindow cursor_coord_window( pt2.x, pt2.y ); + window_imp->convertCoords(cursor_coord_window, &gl_coord); + MASK mask = gKeyboard->currentMask(TRUE); + + LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask, + LLWindowCallbacks::DNDA_START_TRACKING, mDropUrl ); + + switch (result) + { + case LLWindowCallbacks::DND_COPY: + *pdwEffect = DROPEFFECT_COPY; + break; + case LLWindowCallbacks::DND_LINK: + *pdwEffect = DROPEFFECT_LINK; + break; + case LLWindowCallbacks::DND_MOVE: + *pdwEffect = DROPEFFECT_MOVE; + break; + case LLWindowCallbacks::DND_NONE: + default: + *pdwEffect = DROPEFFECT_NONE; + break; + } + }; GlobalUnlock( stgmed.hGlobal ); ReleaseStgMedium( &stgmed ); }; - - *pdwEffect = DROPEFFECT_COPY; - SetFocus( mAppWindowHandle ); } else @@ -158,15 +188,25 @@ class LLDragDropWin32Target: window_imp->convertCoords(cursor_coord_window, &gl_coord); MASK mask = gKeyboard->currentMask(TRUE); - bool allowed_to_drop = window_imp->completeDragNDropRequest( gl_coord, mask, FALSE, std::string( "" ) ); - if ( allowed_to_drop ) + LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask, + LLWindowCallbacks::DNDA_TRACK, std::string( "" ) ); + + switch (result) + { + case LLWindowCallbacks::DND_COPY: *pdwEffect = DROPEFFECT_COPY; - else - *pdwEffect = DROPEFFECT_NONE; - - // special case for SLURLs - you can always drop them on the client window and we need a different cursor - if ( mIsSlurl ) + break; + case LLWindowCallbacks::DND_LINK: *pdwEffect = DROPEFFECT_LINK; + break; + case LLWindowCallbacks::DND_MOVE: + *pdwEffect = DROPEFFECT_MOVE; + break; + case LLWindowCallbacks::DND_NONE: + default: + *pdwEffect = DROPEFFECT_NONE; + break; + } }; } else @@ -181,7 +221,14 @@ class LLDragDropWin32Target: // HRESULT __stdcall DragLeave( void ) { - mDropUrl = std::string(); + // XXX MAJOR MAJOR HACK! + LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mAppWindowHandle, GWL_USERDATA); + if (NULL != window_imp) + { + LLCoordGL gl_coord( 0, 0 ); + MASK mask = gKeyboard->currentMask(TRUE); + window_imp->completeDragNDropRequest( gl_coord, mask, LLWindowCallbacks::DNDA_STOP_TRACKING, mDropUrl ); + }; return S_OK; }; @@ -214,10 +261,26 @@ class LLDragDropWin32Target: MASK mask = gKeyboard->currentMask( TRUE ); // actually do the drop - window_imp->completeDragNDropRequest( gl_coord, mask, TRUE, mDropUrl ); - }; + LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask, + LLWindowCallbacks::DNDA_DROPPED, mDropUrl ); - *pdwEffect = DROPEFFECT_COPY; + switch (result) + { + case LLWindowCallbacks::DND_COPY: + *pdwEffect = DROPEFFECT_COPY; + break; + case LLWindowCallbacks::DND_LINK: + *pdwEffect = DROPEFFECT_LINK; + break; + case LLWindowCallbacks::DND_MOVE: + *pdwEffect = DROPEFFECT_MOVE; + break; + case LLWindowCallbacks::DND_NONE: + default: + *pdwEffect = DROPEFFECT_NONE; + break; + } + }; } else { -- cgit v1.2.3 From e57f6a5cee1cf03df2bf43cd7a8b2c42c3918f8b Mon Sep 17 00:00:00 2001 From: Callum Prentice Date: Thu, 7 Jan 2010 14:21:57 -0800 Subject: Fix drag and drop for windows. Makes Win32 state machine behave more like Mac. --- indra/llwindow/lldragdropwin32.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llwindow/lldragdropwin32.cpp') diff --git a/indra/llwindow/lldragdropwin32.cpp b/indra/llwindow/lldragdropwin32.cpp index 4865570f07..1e10626e8a 100644 --- a/indra/llwindow/lldragdropwin32.cpp +++ b/indra/llwindow/lldragdropwin32.cpp @@ -189,7 +189,7 @@ class LLDragDropWin32Target: MASK mask = gKeyboard->currentMask(TRUE); LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask, - LLWindowCallbacks::DNDA_TRACK, std::string( "" ) ); + LLWindowCallbacks::DNDA_TRACK, mDropUrl ); switch (result) { -- cgit v1.2.3 From 9430b8de6585e0c0aa980fc87cf73fdbc8a8c5d2 Mon Sep 17 00:00:00 2001 From: Rick Pasetto Date: Mon, 1 Feb 2010 16:29:52 -0800 Subject: dos2unix these files --- indra/llwindow/lldragdropwin32.cpp | 740 ++++++++++++++++++------------------- 1 file changed, 370 insertions(+), 370 deletions(-) (limited to 'indra/llwindow/lldragdropwin32.cpp') diff --git a/indra/llwindow/lldragdropwin32.cpp b/indra/llwindow/lldragdropwin32.cpp index 1e10626e8a..9b80fe0a84 100644 --- a/indra/llwindow/lldragdropwin32.cpp +++ b/indra/llwindow/lldragdropwin32.cpp @@ -1,370 +1,370 @@ -/** - * @file lldragdrop32.cpp - * @brief Handler for Windows specific drag and drop (OS to client) code - * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#if LL_WINDOWS - -#if LL_OS_DRAGDROP_ENABLED - -#include "linden_common.h" - -#include "llwindowwin32.h" -#include "llkeyboardwin32.h" -#include "llwindowcallbacks.h" -#include "lldragdropwin32.h" - -class LLDragDropWin32Target: - public IDropTarget -{ - public: - //////////////////////////////////////////////////////////////////////////////// - // - LLDragDropWin32Target( HWND hWnd ) : - mRefCount( 1 ), - mAppWindowHandle( hWnd ), - mAllowDrop( false) - { - }; - - virtual ~LLDragDropWin32Target() - { - }; - - //////////////////////////////////////////////////////////////////////////////// - // - ULONG __stdcall AddRef( void ) - { - return InterlockedIncrement( &mRefCount ); - }; - - //////////////////////////////////////////////////////////////////////////////// - // - ULONG __stdcall Release( void ) - { - LONG count = InterlockedDecrement( &mRefCount ); - - if ( count == 0 ) - { - delete this; - return 0; - } - else - { - return count; - }; - }; - - //////////////////////////////////////////////////////////////////////////////// - // - HRESULT __stdcall QueryInterface( REFIID iid, void** ppvObject ) - { - if ( iid == IID_IUnknown || iid == IID_IDropTarget ) - { - AddRef(); - *ppvObject = this; - return S_OK; - } - else - { - *ppvObject = 0; - return E_NOINTERFACE; - }; - }; - - //////////////////////////////////////////////////////////////////////////////// - // - HRESULT __stdcall DragEnter( IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect ) - { - FORMATETC fmtetc = { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; - - // support CF_TEXT using a HGLOBAL? - if ( S_OK == pDataObject->QueryGetData( &fmtetc ) ) - { - mAllowDrop = true; - mDropUrl = std::string(); - mIsSlurl = false; - - STGMEDIUM stgmed; - if( S_OK == pDataObject->GetData( &fmtetc, &stgmed ) ) - { - PVOID data = GlobalLock( stgmed.hGlobal ); - mDropUrl = std::string( (char*)data ); - // XXX MAJOR MAJOR HACK! - LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mAppWindowHandle, GWL_USERDATA); - if (NULL != window_imp) - { - LLCoordGL gl_coord( 0, 0 ); - - POINT pt2; - pt2.x = pt.x; - pt2.y = pt.y; - ScreenToClient( mAppWindowHandle, &pt2 ); - - LLCoordWindow cursor_coord_window( pt2.x, pt2.y ); - window_imp->convertCoords(cursor_coord_window, &gl_coord); - MASK mask = gKeyboard->currentMask(TRUE); - - LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask, - LLWindowCallbacks::DNDA_START_TRACKING, mDropUrl ); - - switch (result) - { - case LLWindowCallbacks::DND_COPY: - *pdwEffect = DROPEFFECT_COPY; - break; - case LLWindowCallbacks::DND_LINK: - *pdwEffect = DROPEFFECT_LINK; - break; - case LLWindowCallbacks::DND_MOVE: - *pdwEffect = DROPEFFECT_MOVE; - break; - case LLWindowCallbacks::DND_NONE: - default: - *pdwEffect = DROPEFFECT_NONE; - break; - } - }; - - GlobalUnlock( stgmed.hGlobal ); - ReleaseStgMedium( &stgmed ); - }; - SetFocus( mAppWindowHandle ); - } - else - { - mAllowDrop = false; - *pdwEffect = DROPEFFECT_NONE; - }; - - return S_OK; - }; - - //////////////////////////////////////////////////////////////////////////////// - // - HRESULT __stdcall DragOver( DWORD grfKeyState, POINTL pt, DWORD* pdwEffect ) - { - if ( mAllowDrop ) - { - // XXX MAJOR MAJOR HACK! - LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mAppWindowHandle, GWL_USERDATA); - if (NULL != window_imp) - { - LLCoordGL gl_coord( 0, 0 ); - - POINT pt2; - pt2.x = pt.x; - pt2.y = pt.y; - ScreenToClient( mAppWindowHandle, &pt2 ); - - LLCoordWindow cursor_coord_window( pt2.x, pt2.y ); - window_imp->convertCoords(cursor_coord_window, &gl_coord); - MASK mask = gKeyboard->currentMask(TRUE); - - LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask, - LLWindowCallbacks::DNDA_TRACK, mDropUrl ); - - switch (result) - { - case LLWindowCallbacks::DND_COPY: - *pdwEffect = DROPEFFECT_COPY; - break; - case LLWindowCallbacks::DND_LINK: - *pdwEffect = DROPEFFECT_LINK; - break; - case LLWindowCallbacks::DND_MOVE: - *pdwEffect = DROPEFFECT_MOVE; - break; - case LLWindowCallbacks::DND_NONE: - default: - *pdwEffect = DROPEFFECT_NONE; - break; - } - }; - } - else - { - *pdwEffect = DROPEFFECT_NONE; - }; - - return S_OK; - }; - - //////////////////////////////////////////////////////////////////////////////// - // - HRESULT __stdcall DragLeave( void ) - { - // XXX MAJOR MAJOR HACK! - LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mAppWindowHandle, GWL_USERDATA); - if (NULL != window_imp) - { - LLCoordGL gl_coord( 0, 0 ); - MASK mask = gKeyboard->currentMask(TRUE); - window_imp->completeDragNDropRequest( gl_coord, mask, LLWindowCallbacks::DNDA_STOP_TRACKING, mDropUrl ); - }; - return S_OK; - }; - - //////////////////////////////////////////////////////////////////////////////// - // - HRESULT __stdcall Drop( IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect ) - { - if ( mAllowDrop ) - { - // window impl stored in Window data (neat!) - LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong( mAppWindowHandle, GWL_USERDATA ); - if ( NULL != window_imp ) - { - LLCoordGL gl_coord( 0, 0 ); - - POINT pt_client; - pt_client.x = pt.x; - pt_client.y = pt.y; - ScreenToClient( mAppWindowHandle, &pt_client ); - - LLCoordWindow cursor_coord_window( pt_client.x, pt_client.y ); - window_imp->convertCoords(cursor_coord_window, &gl_coord); - llinfos << "### (Drop) URL is: " << mDropUrl << llendl; - llinfos << "### raw coords are: " << pt.x << " x " << pt.y << llendl; - llinfos << "### client coords are: " << pt_client.x << " x " << pt_client.y << llendl; - llinfos << "### GL coords are: " << gl_coord.mX << " x " << gl_coord.mY << llendl; - llinfos << llendl; - - // no keyboard modifier option yet but we could one day - MASK mask = gKeyboard->currentMask( TRUE ); - - // actually do the drop - LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask, - LLWindowCallbacks::DNDA_DROPPED, mDropUrl ); - - switch (result) - { - case LLWindowCallbacks::DND_COPY: - *pdwEffect = DROPEFFECT_COPY; - break; - case LLWindowCallbacks::DND_LINK: - *pdwEffect = DROPEFFECT_LINK; - break; - case LLWindowCallbacks::DND_MOVE: - *pdwEffect = DROPEFFECT_MOVE; - break; - case LLWindowCallbacks::DND_NONE: - default: - *pdwEffect = DROPEFFECT_NONE; - break; - } - }; - } - else - { - *pdwEffect = DROPEFFECT_NONE; - }; - - return S_OK; - }; - - //////////////////////////////////////////////////////////////////////////////// - // - private: - LONG mRefCount; - HWND mAppWindowHandle; - bool mAllowDrop; - std::string mDropUrl; - bool mIsSlurl; - friend class LLWindowWin32; -}; - -//////////////////////////////////////////////////////////////////////////////// -// -LLDragDropWin32::LLDragDropWin32() : - mDropTarget( NULL ), - mDropWindowHandle( NULL ) - -{ -} - -//////////////////////////////////////////////////////////////////////////////// -// -LLDragDropWin32::~LLDragDropWin32() -{ -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLDragDropWin32::init( HWND hWnd ) -{ - if ( NOERROR != OleInitialize( NULL ) ) - return FALSE; - - mDropTarget = new LLDragDropWin32Target( hWnd ); - if ( mDropTarget ) - { - HRESULT result = CoLockObjectExternal( mDropTarget, TRUE, FALSE ); - if ( S_OK == result ) - { - result = RegisterDragDrop( hWnd, mDropTarget ); - if ( S_OK != result ) - { - // RegisterDragDrop failed - return false; - }; - - // all ok - mDropWindowHandle = hWnd; - } - else - { - // Unable to lock OLE object - return false; - }; - }; - - // success - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLDragDropWin32::reset() -{ - if ( mDropTarget ) - { - RevokeDragDrop( mDropWindowHandle ); - CoLockObjectExternal( mDropTarget, FALSE, TRUE ); - mDropTarget->Release(); - }; - - OleUninitialize(); -} - -#endif // LL_OS_DRAGDROP_ENABLED - -#endif // LL_WINDOWS - +/** + * @file lldragdrop32.cpp + * @brief Handler for Windows specific drag and drop (OS to client) code + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#if LL_WINDOWS + +#if LL_OS_DRAGDROP_ENABLED + +#include "linden_common.h" + +#include "llwindowwin32.h" +#include "llkeyboardwin32.h" +#include "llwindowcallbacks.h" +#include "lldragdropwin32.h" + +class LLDragDropWin32Target: + public IDropTarget +{ + public: + //////////////////////////////////////////////////////////////////////////////// + // + LLDragDropWin32Target( HWND hWnd ) : + mRefCount( 1 ), + mAppWindowHandle( hWnd ), + mAllowDrop( false) + { + }; + + virtual ~LLDragDropWin32Target() + { + }; + + //////////////////////////////////////////////////////////////////////////////// + // + ULONG __stdcall AddRef( void ) + { + return InterlockedIncrement( &mRefCount ); + }; + + //////////////////////////////////////////////////////////////////////////////// + // + ULONG __stdcall Release( void ) + { + LONG count = InterlockedDecrement( &mRefCount ); + + if ( count == 0 ) + { + delete this; + return 0; + } + else + { + return count; + }; + }; + + //////////////////////////////////////////////////////////////////////////////// + // + HRESULT __stdcall QueryInterface( REFIID iid, void** ppvObject ) + { + if ( iid == IID_IUnknown || iid == IID_IDropTarget ) + { + AddRef(); + *ppvObject = this; + return S_OK; + } + else + { + *ppvObject = 0; + return E_NOINTERFACE; + }; + }; + + //////////////////////////////////////////////////////////////////////////////// + // + HRESULT __stdcall DragEnter( IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect ) + { + FORMATETC fmtetc = { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; + + // support CF_TEXT using a HGLOBAL? + if ( S_OK == pDataObject->QueryGetData( &fmtetc ) ) + { + mAllowDrop = true; + mDropUrl = std::string(); + mIsSlurl = false; + + STGMEDIUM stgmed; + if( S_OK == pDataObject->GetData( &fmtetc, &stgmed ) ) + { + PVOID data = GlobalLock( stgmed.hGlobal ); + mDropUrl = std::string( (char*)data ); + // XXX MAJOR MAJOR HACK! + LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mAppWindowHandle, GWL_USERDATA); + if (NULL != window_imp) + { + LLCoordGL gl_coord( 0, 0 ); + + POINT pt2; + pt2.x = pt.x; + pt2.y = pt.y; + ScreenToClient( mAppWindowHandle, &pt2 ); + + LLCoordWindow cursor_coord_window( pt2.x, pt2.y ); + window_imp->convertCoords(cursor_coord_window, &gl_coord); + MASK mask = gKeyboard->currentMask(TRUE); + + LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask, + LLWindowCallbacks::DNDA_START_TRACKING, mDropUrl ); + + switch (result) + { + case LLWindowCallbacks::DND_COPY: + *pdwEffect = DROPEFFECT_COPY; + break; + case LLWindowCallbacks::DND_LINK: + *pdwEffect = DROPEFFECT_LINK; + break; + case LLWindowCallbacks::DND_MOVE: + *pdwEffect = DROPEFFECT_MOVE; + break; + case LLWindowCallbacks::DND_NONE: + default: + *pdwEffect = DROPEFFECT_NONE; + break; + } + }; + + GlobalUnlock( stgmed.hGlobal ); + ReleaseStgMedium( &stgmed ); + }; + SetFocus( mAppWindowHandle ); + } + else + { + mAllowDrop = false; + *pdwEffect = DROPEFFECT_NONE; + }; + + return S_OK; + }; + + //////////////////////////////////////////////////////////////////////////////// + // + HRESULT __stdcall DragOver( DWORD grfKeyState, POINTL pt, DWORD* pdwEffect ) + { + if ( mAllowDrop ) + { + // XXX MAJOR MAJOR HACK! + LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mAppWindowHandle, GWL_USERDATA); + if (NULL != window_imp) + { + LLCoordGL gl_coord( 0, 0 ); + + POINT pt2; + pt2.x = pt.x; + pt2.y = pt.y; + ScreenToClient( mAppWindowHandle, &pt2 ); + + LLCoordWindow cursor_coord_window( pt2.x, pt2.y ); + window_imp->convertCoords(cursor_coord_window, &gl_coord); + MASK mask = gKeyboard->currentMask(TRUE); + + LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask, + LLWindowCallbacks::DNDA_TRACK, mDropUrl ); + + switch (result) + { + case LLWindowCallbacks::DND_COPY: + *pdwEffect = DROPEFFECT_COPY; + break; + case LLWindowCallbacks::DND_LINK: + *pdwEffect = DROPEFFECT_LINK; + break; + case LLWindowCallbacks::DND_MOVE: + *pdwEffect = DROPEFFECT_MOVE; + break; + case LLWindowCallbacks::DND_NONE: + default: + *pdwEffect = DROPEFFECT_NONE; + break; + } + }; + } + else + { + *pdwEffect = DROPEFFECT_NONE; + }; + + return S_OK; + }; + + //////////////////////////////////////////////////////////////////////////////// + // + HRESULT __stdcall DragLeave( void ) + { + // XXX MAJOR MAJOR HACK! + LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mAppWindowHandle, GWL_USERDATA); + if (NULL != window_imp) + { + LLCoordGL gl_coord( 0, 0 ); + MASK mask = gKeyboard->currentMask(TRUE); + window_imp->completeDragNDropRequest( gl_coord, mask, LLWindowCallbacks::DNDA_STOP_TRACKING, mDropUrl ); + }; + return S_OK; + }; + + //////////////////////////////////////////////////////////////////////////////// + // + HRESULT __stdcall Drop( IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect ) + { + if ( mAllowDrop ) + { + // window impl stored in Window data (neat!) + LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong( mAppWindowHandle, GWL_USERDATA ); + if ( NULL != window_imp ) + { + LLCoordGL gl_coord( 0, 0 ); + + POINT pt_client; + pt_client.x = pt.x; + pt_client.y = pt.y; + ScreenToClient( mAppWindowHandle, &pt_client ); + + LLCoordWindow cursor_coord_window( pt_client.x, pt_client.y ); + window_imp->convertCoords(cursor_coord_window, &gl_coord); + llinfos << "### (Drop) URL is: " << mDropUrl << llendl; + llinfos << "### raw coords are: " << pt.x << " x " << pt.y << llendl; + llinfos << "### client coords are: " << pt_client.x << " x " << pt_client.y << llendl; + llinfos << "### GL coords are: " << gl_coord.mX << " x " << gl_coord.mY << llendl; + llinfos << llendl; + + // no keyboard modifier option yet but we could one day + MASK mask = gKeyboard->currentMask( TRUE ); + + // actually do the drop + LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask, + LLWindowCallbacks::DNDA_DROPPED, mDropUrl ); + + switch (result) + { + case LLWindowCallbacks::DND_COPY: + *pdwEffect = DROPEFFECT_COPY; + break; + case LLWindowCallbacks::DND_LINK: + *pdwEffect = DROPEFFECT_LINK; + break; + case LLWindowCallbacks::DND_MOVE: + *pdwEffect = DROPEFFECT_MOVE; + break; + case LLWindowCallbacks::DND_NONE: + default: + *pdwEffect = DROPEFFECT_NONE; + break; + } + }; + } + else + { + *pdwEffect = DROPEFFECT_NONE; + }; + + return S_OK; + }; + + //////////////////////////////////////////////////////////////////////////////// + // + private: + LONG mRefCount; + HWND mAppWindowHandle; + bool mAllowDrop; + std::string mDropUrl; + bool mIsSlurl; + friend class LLWindowWin32; +}; + +//////////////////////////////////////////////////////////////////////////////// +// +LLDragDropWin32::LLDragDropWin32() : + mDropTarget( NULL ), + mDropWindowHandle( NULL ) + +{ +} + +//////////////////////////////////////////////////////////////////////////////// +// +LLDragDropWin32::~LLDragDropWin32() +{ +} + +//////////////////////////////////////////////////////////////////////////////// +// +bool LLDragDropWin32::init( HWND hWnd ) +{ + if ( NOERROR != OleInitialize( NULL ) ) + return FALSE; + + mDropTarget = new LLDragDropWin32Target( hWnd ); + if ( mDropTarget ) + { + HRESULT result = CoLockObjectExternal( mDropTarget, TRUE, FALSE ); + if ( S_OK == result ) + { + result = RegisterDragDrop( hWnd, mDropTarget ); + if ( S_OK != result ) + { + // RegisterDragDrop failed + return false; + }; + + // all ok + mDropWindowHandle = hWnd; + } + else + { + // Unable to lock OLE object + return false; + }; + }; + + // success + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLDragDropWin32::reset() +{ + if ( mDropTarget ) + { + RevokeDragDrop( mDropWindowHandle ); + CoLockObjectExternal( mDropTarget, FALSE, TRUE ); + mDropTarget->Release(); + }; + + OleUninitialize(); +} + +#endif // LL_OS_DRAGDROP_ENABLED + +#endif // LL_WINDOWS + -- cgit v1.2.3