PageRenderTime 39ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llwindow/lldragdropwin32.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 365 lines | 257 code | 46 blank | 62 comment | 31 complexity | 4c63a23075d78f255d698ca8afb10fb7 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file lldragdrop32.cpp
  3. * @brief Handler for Windows specific drag and drop (OS to client) code
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #if LL_WINDOWS
  27. #if LL_OS_DRAGDROP_ENABLED
  28. #include "linden_common.h"
  29. #include "llwindowwin32.h"
  30. #include "llkeyboardwin32.h"
  31. #include "llwindowcallbacks.h"
  32. #include "lldragdropwin32.h"
  33. class LLDragDropWin32Target:
  34. public IDropTarget
  35. {
  36. public:
  37. ////////////////////////////////////////////////////////////////////////////////
  38. //
  39. LLDragDropWin32Target( HWND hWnd ) :
  40. mRefCount( 1 ),
  41. mAppWindowHandle( hWnd ),
  42. mAllowDrop(false),
  43. mIsSlurl(false)
  44. {
  45. };
  46. virtual ~LLDragDropWin32Target()
  47. {
  48. };
  49. ////////////////////////////////////////////////////////////////////////////////
  50. //
  51. ULONG __stdcall AddRef( void )
  52. {
  53. return InterlockedIncrement( &mRefCount );
  54. };
  55. ////////////////////////////////////////////////////////////////////////////////
  56. //
  57. ULONG __stdcall Release( void )
  58. {
  59. LONG count = InterlockedDecrement( &mRefCount );
  60. if ( count == 0 )
  61. {
  62. delete this;
  63. return 0;
  64. }
  65. else
  66. {
  67. return count;
  68. };
  69. };
  70. ////////////////////////////////////////////////////////////////////////////////
  71. //
  72. HRESULT __stdcall QueryInterface( REFIID iid, void** ppvObject )
  73. {
  74. if ( iid == IID_IUnknown || iid == IID_IDropTarget )
  75. {
  76. AddRef();
  77. *ppvObject = this;
  78. return S_OK;
  79. }
  80. else
  81. {
  82. *ppvObject = 0;
  83. return E_NOINTERFACE;
  84. };
  85. };
  86. ////////////////////////////////////////////////////////////////////////////////
  87. //
  88. HRESULT __stdcall DragEnter( IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect )
  89. {
  90. FORMATETC fmtetc = { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
  91. // support CF_TEXT using a HGLOBAL?
  92. if ( S_OK == pDataObject->QueryGetData( &fmtetc ) )
  93. {
  94. mAllowDrop = true;
  95. mDropUrl = std::string();
  96. mIsSlurl = false;
  97. STGMEDIUM stgmed;
  98. if( S_OK == pDataObject->GetData( &fmtetc, &stgmed ) )
  99. {
  100. PVOID data = GlobalLock( stgmed.hGlobal );
  101. mDropUrl = std::string( (char*)data );
  102. // XXX MAJOR MAJOR HACK!
  103. LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mAppWindowHandle, GWL_USERDATA);
  104. if (NULL != window_imp)
  105. {
  106. LLCoordGL gl_coord( 0, 0 );
  107. POINT pt2;
  108. pt2.x = pt.x;
  109. pt2.y = pt.y;
  110. ScreenToClient( mAppWindowHandle, &pt2 );
  111. LLCoordWindow cursor_coord_window( pt2.x, pt2.y );
  112. window_imp->convertCoords(cursor_coord_window, &gl_coord);
  113. MASK mask = gKeyboard->currentMask(TRUE);
  114. LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask,
  115. LLWindowCallbacks::DNDA_START_TRACKING, mDropUrl );
  116. switch (result)
  117. {
  118. case LLWindowCallbacks::DND_COPY:
  119. *pdwEffect = DROPEFFECT_COPY;
  120. break;
  121. case LLWindowCallbacks::DND_LINK:
  122. *pdwEffect = DROPEFFECT_LINK;
  123. break;
  124. case LLWindowCallbacks::DND_MOVE:
  125. *pdwEffect = DROPEFFECT_MOVE;
  126. break;
  127. case LLWindowCallbacks::DND_NONE:
  128. default:
  129. *pdwEffect = DROPEFFECT_NONE;
  130. break;
  131. }
  132. };
  133. GlobalUnlock( stgmed.hGlobal );
  134. ReleaseStgMedium( &stgmed );
  135. };
  136. SetFocus( mAppWindowHandle );
  137. }
  138. else
  139. {
  140. mAllowDrop = false;
  141. *pdwEffect = DROPEFFECT_NONE;
  142. };
  143. return S_OK;
  144. };
  145. ////////////////////////////////////////////////////////////////////////////////
  146. //
  147. HRESULT __stdcall DragOver( DWORD grfKeyState, POINTL pt, DWORD* pdwEffect )
  148. {
  149. if ( mAllowDrop )
  150. {
  151. // XXX MAJOR MAJOR HACK!
  152. LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mAppWindowHandle, GWL_USERDATA);
  153. if (NULL != window_imp)
  154. {
  155. LLCoordGL gl_coord( 0, 0 );
  156. POINT pt2;
  157. pt2.x = pt.x;
  158. pt2.y = pt.y;
  159. ScreenToClient( mAppWindowHandle, &pt2 );
  160. LLCoordWindow cursor_coord_window( pt2.x, pt2.y );
  161. window_imp->convertCoords(cursor_coord_window, &gl_coord);
  162. MASK mask = gKeyboard->currentMask(TRUE);
  163. LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask,
  164. LLWindowCallbacks::DNDA_TRACK, mDropUrl );
  165. switch (result)
  166. {
  167. case LLWindowCallbacks::DND_COPY:
  168. *pdwEffect = DROPEFFECT_COPY;
  169. break;
  170. case LLWindowCallbacks::DND_LINK:
  171. *pdwEffect = DROPEFFECT_LINK;
  172. break;
  173. case LLWindowCallbacks::DND_MOVE:
  174. *pdwEffect = DROPEFFECT_MOVE;
  175. break;
  176. case LLWindowCallbacks::DND_NONE:
  177. default:
  178. *pdwEffect = DROPEFFECT_NONE;
  179. break;
  180. }
  181. };
  182. }
  183. else
  184. {
  185. *pdwEffect = DROPEFFECT_NONE;
  186. };
  187. return S_OK;
  188. };
  189. ////////////////////////////////////////////////////////////////////////////////
  190. //
  191. HRESULT __stdcall DragLeave( void )
  192. {
  193. // XXX MAJOR MAJOR HACK!
  194. LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mAppWindowHandle, GWL_USERDATA);
  195. if (NULL != window_imp)
  196. {
  197. LLCoordGL gl_coord( 0, 0 );
  198. MASK mask = gKeyboard->currentMask(TRUE);
  199. window_imp->completeDragNDropRequest( gl_coord, mask, LLWindowCallbacks::DNDA_STOP_TRACKING, mDropUrl );
  200. };
  201. return S_OK;
  202. };
  203. ////////////////////////////////////////////////////////////////////////////////
  204. //
  205. HRESULT __stdcall Drop( IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect )
  206. {
  207. if ( mAllowDrop )
  208. {
  209. // window impl stored in Window data (neat!)
  210. LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong( mAppWindowHandle, GWL_USERDATA );
  211. if ( NULL != window_imp )
  212. {
  213. LLCoordGL gl_coord( 0, 0 );
  214. POINT pt_client;
  215. pt_client.x = pt.x;
  216. pt_client.y = pt.y;
  217. ScreenToClient( mAppWindowHandle, &pt_client );
  218. LLCoordWindow cursor_coord_window( pt_client.x, pt_client.y );
  219. window_imp->convertCoords(cursor_coord_window, &gl_coord);
  220. llinfos << "### (Drop) URL is: " << mDropUrl << llendl;
  221. llinfos << "### raw coords are: " << pt.x << " x " << pt.y << llendl;
  222. llinfos << "### client coords are: " << pt_client.x << " x " << pt_client.y << llendl;
  223. llinfos << "### GL coords are: " << gl_coord.mX << " x " << gl_coord.mY << llendl;
  224. llinfos << llendl;
  225. // no keyboard modifier option yet but we could one day
  226. MASK mask = gKeyboard->currentMask( TRUE );
  227. // actually do the drop
  228. LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask,
  229. LLWindowCallbacks::DNDA_DROPPED, mDropUrl );
  230. switch (result)
  231. {
  232. case LLWindowCallbacks::DND_COPY:
  233. *pdwEffect = DROPEFFECT_COPY;
  234. break;
  235. case LLWindowCallbacks::DND_LINK:
  236. *pdwEffect = DROPEFFECT_LINK;
  237. break;
  238. case LLWindowCallbacks::DND_MOVE:
  239. *pdwEffect = DROPEFFECT_MOVE;
  240. break;
  241. case LLWindowCallbacks::DND_NONE:
  242. default:
  243. *pdwEffect = DROPEFFECT_NONE;
  244. break;
  245. }
  246. };
  247. }
  248. else
  249. {
  250. *pdwEffect = DROPEFFECT_NONE;
  251. };
  252. return S_OK;
  253. };
  254. ////////////////////////////////////////////////////////////////////////////////
  255. //
  256. private:
  257. LONG mRefCount;
  258. HWND mAppWindowHandle;
  259. bool mAllowDrop;
  260. std::string mDropUrl;
  261. bool mIsSlurl;
  262. friend class LLWindowWin32;
  263. };
  264. ////////////////////////////////////////////////////////////////////////////////
  265. //
  266. LLDragDropWin32::LLDragDropWin32() :
  267. mDropTarget( NULL ),
  268. mDropWindowHandle( NULL )
  269. {
  270. }
  271. ////////////////////////////////////////////////////////////////////////////////
  272. //
  273. LLDragDropWin32::~LLDragDropWin32()
  274. {
  275. }
  276. ////////////////////////////////////////////////////////////////////////////////
  277. //
  278. bool LLDragDropWin32::init( HWND hWnd )
  279. {
  280. if ( NOERROR != OleInitialize( NULL ) )
  281. return FALSE;
  282. mDropTarget = new LLDragDropWin32Target( hWnd );
  283. if ( mDropTarget )
  284. {
  285. HRESULT result = CoLockObjectExternal( mDropTarget, TRUE, FALSE );
  286. if ( S_OK == result )
  287. {
  288. result = RegisterDragDrop( hWnd, mDropTarget );
  289. if ( S_OK != result )
  290. {
  291. // RegisterDragDrop failed
  292. return false;
  293. };
  294. // all ok
  295. mDropWindowHandle = hWnd;
  296. }
  297. else
  298. {
  299. // Unable to lock OLE object
  300. return false;
  301. };
  302. };
  303. // success
  304. return true;
  305. }
  306. ////////////////////////////////////////////////////////////////////////////////
  307. //
  308. void LLDragDropWin32::reset()
  309. {
  310. if ( mDropTarget )
  311. {
  312. RevokeDragDrop( mDropWindowHandle );
  313. CoLockObjectExternal( mDropTarget, FALSE, TRUE );
  314. mDropTarget->Release();
  315. };
  316. OleUninitialize();
  317. }
  318. #endif // LL_OS_DRAGDROP_ENABLED
  319. #endif // LL_WINDOWS