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