148123e16SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 348123e16SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 448123e16SAndrew Rist * or more contributor license agreements. See the NOTICE file 548123e16SAndrew Rist * distributed with this work for additional information 648123e16SAndrew Rist * regarding copyright ownership. The ASF licenses this file 748123e16SAndrew Rist * to you under the Apache License, Version 2.0 (the 848123e16SAndrew Rist * "License"); you may not use this file except in compliance 948123e16SAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 1148123e16SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 1348123e16SAndrew Rist * Unless required by applicable law or agreed to in writing, 1448123e16SAndrew Rist * software distributed under the License is distributed on an 1548123e16SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 1648123e16SAndrew Rist * KIND, either express or implied. See the License for the 1748123e16SAndrew Rist * specific language governing permissions and limitations 1848123e16SAndrew Rist * under the License. 19cdf0e10cSrcweir * 2048123e16SAndrew Rist *************************************************************/ 2148123e16SAndrew Rist 2248123e16SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_dtrans.hxx" 26cdf0e10cSrcweir #include <com/sun/star/datatransfer/dnd/DNDConstants.hpp> 27cdf0e10cSrcweir #include <com/sun/star/datatransfer/XTransferable.hpp> 28cdf0e10cSrcweir #include <com/sun/star/awt/MouseButton.hpp> 29cdf0e10cSrcweir #include <com/sun/star/awt/MouseEvent.hpp> 30cdf0e10cSrcweir #include <rtl/unload.h> 31cdf0e10cSrcweir 32cdf0e10cSrcweir #include <process.h> 33cdf0e10cSrcweir #include <memory> 34cdf0e10cSrcweir 35cdf0e10cSrcweir #include "source.hxx" 36cdf0e10cSrcweir #include "globals.hxx" 37cdf0e10cSrcweir #include "sourcecontext.hxx" 38cdf0e10cSrcweir #include "../../inc/DtObjFactory.hxx" 39cdf0e10cSrcweir #include <rtl/ustring.h> 40cdf0e10cSrcweir #include <process.h> 41cdf0e10cSrcweir #include <winuser.h> 42cdf0e10cSrcweir #include <stdio.h> 43cdf0e10cSrcweir 44cdf0e10cSrcweir #ifdef __MINGW32__ 45cdf0e10cSrcweir #define __uuidof(I) IID_##I 46cdf0e10cSrcweir #endif 47cdf0e10cSrcweir 48cdf0e10cSrcweir using namespace rtl; 49cdf0e10cSrcweir using namespace cppu; 50cdf0e10cSrcweir using namespace osl; 51cdf0e10cSrcweir using namespace com::sun::star::datatransfer; 52cdf0e10cSrcweir using namespace com::sun::star::datatransfer::dnd; 53cdf0e10cSrcweir using namespace com::sun::star::datatransfer::dnd::DNDConstants; 54cdf0e10cSrcweir using namespace com::sun::star::uno; 55cdf0e10cSrcweir using namespace com::sun::star::awt::MouseButton; 56cdf0e10cSrcweir using namespace com::sun::star::awt; 57cdf0e10cSrcweir using namespace com::sun::star::lang; 58cdf0e10cSrcweir 59cdf0e10cSrcweir extern rtl_StandardModuleCount g_moduleCount; 60cdf0e10cSrcweir 61cdf0e10cSrcweir //--> TRA 62cdf0e10cSrcweir 63cdf0e10cSrcweir extern Reference< XTransferable > g_XTransferable; 64cdf0e10cSrcweir 65cdf0e10cSrcweir //<-- TRA 66cdf0e10cSrcweir 67cdf0e10cSrcweir unsigned __stdcall DndOleSTAFunc(LPVOID pParams); 68cdf0e10cSrcweir 69cdf0e10cSrcweir //---------------------------------------------------- 70cdf0e10cSrcweir /** Ctor 71cdf0e10cSrcweir */ 72cdf0e10cSrcweir DragSource::DragSource( const Reference<XMultiServiceFactory>& sf): 73cdf0e10cSrcweir m_serviceFactory( sf), 74cdf0e10cSrcweir WeakComponentImplHelper3< XDragSource, XInitialization, XServiceInfo >(m_mutex), 75cdf0e10cSrcweir // m_pcurrentContext_impl(0), 76cdf0e10cSrcweir m_hAppWindow(0), 77cdf0e10cSrcweir m_MouseButton(0), 78cdf0e10cSrcweir m_RunningDndOperationCount(0) 79cdf0e10cSrcweir { 80cdf0e10cSrcweir g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); 81cdf0e10cSrcweir } 82cdf0e10cSrcweir 83cdf0e10cSrcweir //---------------------------------------------------- 84cdf0e10cSrcweir /** Dtor 85cdf0e10cSrcweir */ 86cdf0e10cSrcweir DragSource::~DragSource() 87cdf0e10cSrcweir { 88cdf0e10cSrcweir g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); 89cdf0e10cSrcweir } 90cdf0e10cSrcweir 91cdf0e10cSrcweir //---------------------------------------------------- 92cdf0e10cSrcweir /** First start a new drag and drop thread if 93cdf0e10cSrcweir the last one has finished 94cdf0e10cSrcweir 95cdf0e10cSrcweir ???? 96cdf0e10cSrcweir Do we really need a separate thread for 97*41e09fa9Smseidel every Dnd operation or only if the source 98cdf0e10cSrcweir thread is an MTA thread 99cdf0e10cSrcweir ???? 100cdf0e10cSrcweir */ 101cdf0e10cSrcweir void DragSource::StartDragImpl( 102cdf0e10cSrcweir const DragGestureEvent& trigger, 103cdf0e10cSrcweir sal_Int8 sourceActions, 104cdf0e10cSrcweir sal_Int32 /*cursor*/, 105cdf0e10cSrcweir sal_Int32 /*image*/, 106cdf0e10cSrcweir const Reference<XTransferable >& trans, 107cdf0e10cSrcweir const Reference<XDragSourceListener >& listener ) 108cdf0e10cSrcweir { 109cdf0e10cSrcweir // The actions supported by the drag source 110cdf0e10cSrcweir m_sourceActions= sourceActions; 111cdf0e10cSrcweir // We need to know which mouse button triggered the operation. 112cdf0e10cSrcweir // If it was the left one, then the drop occurs when that button 113cdf0e10cSrcweir // has been released and if it was the right one then the drop 114cdf0e10cSrcweir // occurs when the right button has been released. If the event is not 115cdf0e10cSrcweir // set then we assume that the left button is pressed. 116cdf0e10cSrcweir MouseEvent evtMouse; 117cdf0e10cSrcweir trigger.Event >>= evtMouse; 118cdf0e10cSrcweir m_MouseButton= evtMouse.Buttons; 119cdf0e10cSrcweir 120cdf0e10cSrcweir // The SourceContext class administers the XDragSourceListener s and 121cdf0e10cSrcweir // fires events to them. An instance only exists in the scope of this 122cdf0e10cSrcweir // functions. However, the drag and drop operation causes callbacks 123cdf0e10cSrcweir // to the IDropSource interface implemented in this class (but only 124cdf0e10cSrcweir // while this function executes). The source context is also used 125cdf0e10cSrcweir // in DragSource::QueryContinueDrag. 126cdf0e10cSrcweir m_currentContext= static_cast<XDragSourceContext*>( new SourceContext( 127cdf0e10cSrcweir static_cast<DragSource*>(this), listener ) ); 128cdf0e10cSrcweir 129cdf0e10cSrcweir // Convert the XTransferable data object into an IDataObject object; 130cdf0e10cSrcweir 131cdf0e10cSrcweir //--> TRA 132cdf0e10cSrcweir g_XTransferable = trans; 133cdf0e10cSrcweir //<-- TRA 134cdf0e10cSrcweir 135cdf0e10cSrcweir m_spDataObject= m_aDataConverter.createDataObjFromTransferable( 136cdf0e10cSrcweir m_serviceFactory, trans); 137cdf0e10cSrcweir 138cdf0e10cSrcweir // Obtain the id of the thread that created the window 139cdf0e10cSrcweir DWORD processId; 140cdf0e10cSrcweir m_threadIdWindow= GetWindowThreadProcessId( m_hAppWindow, &processId); 141cdf0e10cSrcweir 142cdf0e10cSrcweir // hold the instance for the DnD thread, it's to late 143cdf0e10cSrcweir // to acquire at the start of the thread procedure 144cdf0e10cSrcweir // the thread procedure is responsible for the release 145cdf0e10cSrcweir acquire(); 146cdf0e10cSrcweir 147*41e09fa9Smseidel // The thread accesses members of this instance but does not call acquire. 148cdf0e10cSrcweir // Hopefully this instance is not destroyed before the thread has terminated. 149cdf0e10cSrcweir unsigned threadId; 150cdf0e10cSrcweir HANDLE hThread= reinterpret_cast<HANDLE>(_beginthreadex( 151cdf0e10cSrcweir 0, 0, DndOleSTAFunc, reinterpret_cast<void*>(this), 0, &threadId)); 152cdf0e10cSrcweir 153cdf0e10cSrcweir // detach from thread 154cdf0e10cSrcweir CloseHandle(hThread); 155cdf0e10cSrcweir } 156cdf0e10cSrcweir 157cdf0e10cSrcweir // XInitialization 158cdf0e10cSrcweir 159cdf0e10cSrcweir //---------------------------------------------------- 160cdf0e10cSrcweir /** aArguments contains a machine id 161cdf0e10cSrcweir */ 162cdf0e10cSrcweir void SAL_CALL DragSource::initialize( const Sequence< Any >& aArguments ) 163cdf0e10cSrcweir throw(Exception, RuntimeException) 164cdf0e10cSrcweir { 165cdf0e10cSrcweir if( aArguments.getLength() >=2) 166cdf0e10cSrcweir m_hAppWindow= *(HWND*)aArguments[1].getValue(); 167cdf0e10cSrcweir OSL_ASSERT( IsWindow( m_hAppWindow) ); 168cdf0e10cSrcweir } 169cdf0e10cSrcweir 170cdf0e10cSrcweir //---------------------------------------------------- 171cdf0e10cSrcweir /** XDragSource 172cdf0e10cSrcweir */ 173cdf0e10cSrcweir sal_Bool SAL_CALL DragSource::isDragImageSupported( ) 174cdf0e10cSrcweir throw(RuntimeException) 175cdf0e10cSrcweir { 176cdf0e10cSrcweir return 0; 177cdf0e10cSrcweir } 178cdf0e10cSrcweir 179cdf0e10cSrcweir //---------------------------------------------------- 180cdf0e10cSrcweir /** 181cdf0e10cSrcweir */ 182cdf0e10cSrcweir sal_Int32 SAL_CALL DragSource::getDefaultCursor( sal_Int8 /*dragAction*/ ) 183cdf0e10cSrcweir throw( IllegalArgumentException, RuntimeException) 184cdf0e10cSrcweir { 185cdf0e10cSrcweir return 0; 186cdf0e10cSrcweir } 187cdf0e10cSrcweir 188cdf0e10cSrcweir //---------------------------------------------------- 189cdf0e10cSrcweir /** Notifies the XDragSourceListener by 190cdf0e10cSrcweir calling dragDropEnd 191cdf0e10cSrcweir */ 192cdf0e10cSrcweir void SAL_CALL DragSource::startDrag( 193cdf0e10cSrcweir const DragGestureEvent& trigger, 194cdf0e10cSrcweir sal_Int8 sourceActions, 195cdf0e10cSrcweir sal_Int32 cursor, 196cdf0e10cSrcweir sal_Int32 image, 197cdf0e10cSrcweir const Reference<XTransferable >& trans, 198cdf0e10cSrcweir const Reference<XDragSourceListener >& listener ) throw( RuntimeException) 199cdf0e10cSrcweir { 200cdf0e10cSrcweir // Allow only one running dnd operation at a time, 201cdf0e10cSrcweir // see XDragSource documentation 202cdf0e10cSrcweir 203cdf0e10cSrcweir long cnt = InterlockedIncrement(&m_RunningDndOperationCount); 204cdf0e10cSrcweir 205cdf0e10cSrcweir if (1 == cnt) 206cdf0e10cSrcweir { 207cdf0e10cSrcweir StartDragImpl(trigger, sourceActions, cursor, image, trans, listener); 208cdf0e10cSrcweir } 209cdf0e10cSrcweir else 210cdf0e10cSrcweir { 211cdf0e10cSrcweir //OSL_ENSURE(false, "Overlapping Drag&Drop operation rejected!"); 212cdf0e10cSrcweir 213cdf0e10cSrcweir cnt = InterlockedDecrement(&m_RunningDndOperationCount); 214cdf0e10cSrcweir 215cdf0e10cSrcweir DragSourceDropEvent dsde; 216cdf0e10cSrcweir 217cdf0e10cSrcweir dsde.DropAction = ACTION_NONE; 218cdf0e10cSrcweir dsde.DropSuccess = false; 219cdf0e10cSrcweir 220cdf0e10cSrcweir try 221cdf0e10cSrcweir { 222cdf0e10cSrcweir listener->dragDropEnd(dsde); 223cdf0e10cSrcweir } 224cdf0e10cSrcweir catch(RuntimeException&) 225cdf0e10cSrcweir { 226cdf0e10cSrcweir OSL_ENSURE(false, "Runtime exception during event dispatching"); 227cdf0e10cSrcweir } 228cdf0e10cSrcweir } 229cdf0e10cSrcweir } 230cdf0e10cSrcweir 231cdf0e10cSrcweir //---------------------------------------------------- 232cdf0e10cSrcweir /**IDropTarget 233cdf0e10cSrcweir */ 234cdf0e10cSrcweir HRESULT STDMETHODCALLTYPE DragSource::QueryInterface( REFIID riid, void **ppvObject) 235cdf0e10cSrcweir { 236cdf0e10cSrcweir if( !ppvObject) 237cdf0e10cSrcweir return E_POINTER; 238cdf0e10cSrcweir *ppvObject= NULL; 239cdf0e10cSrcweir 240cdf0e10cSrcweir if( riid == __uuidof( IUnknown) ) 241cdf0e10cSrcweir *ppvObject= static_cast<IUnknown*>( this); 242cdf0e10cSrcweir else if ( riid == __uuidof( IDropSource) ) 243cdf0e10cSrcweir *ppvObject= static_cast<IDropSource*>( this); 244cdf0e10cSrcweir 245cdf0e10cSrcweir if(*ppvObject) 246cdf0e10cSrcweir { 247cdf0e10cSrcweir AddRef(); 248cdf0e10cSrcweir return S_OK; 249cdf0e10cSrcweir } 250cdf0e10cSrcweir else 251cdf0e10cSrcweir return E_NOINTERFACE; 252cdf0e10cSrcweir 253cdf0e10cSrcweir } 254cdf0e10cSrcweir 255cdf0e10cSrcweir //---------------------------------------------------- 256cdf0e10cSrcweir /** 257cdf0e10cSrcweir */ 258cdf0e10cSrcweir ULONG STDMETHODCALLTYPE DragSource::AddRef( void) 259cdf0e10cSrcweir { 260cdf0e10cSrcweir acquire(); 261cdf0e10cSrcweir return (ULONG) m_refCount; 262cdf0e10cSrcweir } 263cdf0e10cSrcweir 264cdf0e10cSrcweir //---------------------------------------------------- 265cdf0e10cSrcweir /** 266cdf0e10cSrcweir */ 267cdf0e10cSrcweir ULONG STDMETHODCALLTYPE DragSource::Release( void) 268cdf0e10cSrcweir { 269cdf0e10cSrcweir ULONG ref= m_refCount; 270cdf0e10cSrcweir release(); 271cdf0e10cSrcweir return --ref; 272cdf0e10cSrcweir } 273cdf0e10cSrcweir 274cdf0e10cSrcweir //---------------------------------------------------- 275cdf0e10cSrcweir /** IDropSource 276cdf0e10cSrcweir */ 277cdf0e10cSrcweir HRESULT STDMETHODCALLTYPE DragSource::QueryContinueDrag( 278cdf0e10cSrcweir /* [in] */ BOOL fEscapePressed, 279cdf0e10cSrcweir /* [in] */ DWORD grfKeyState) 280cdf0e10cSrcweir { 281cdf0e10cSrcweir #if defined DBG_CONSOLE_OUT 282cdf0e10cSrcweir printf("\nDragSource::QueryContinueDrag"); 283cdf0e10cSrcweir #endif 284cdf0e10cSrcweir 285cdf0e10cSrcweir HRESULT retVal= S_OK; // default continue DnD 286cdf0e10cSrcweir 287cdf0e10cSrcweir if (fEscapePressed) 288cdf0e10cSrcweir { 289cdf0e10cSrcweir retVal= DRAGDROP_S_CANCEL; 290cdf0e10cSrcweir } 291cdf0e10cSrcweir else 292cdf0e10cSrcweir { 293cdf0e10cSrcweir if( ( m_MouseButton == MouseButton::RIGHT && !(grfKeyState & MK_RBUTTON) ) || 294cdf0e10cSrcweir ( m_MouseButton == MouseButton::MIDDLE && !(grfKeyState & MK_MBUTTON) ) || 295cdf0e10cSrcweir ( m_MouseButton == MouseButton::LEFT && !(grfKeyState & MK_LBUTTON) ) || 296cdf0e10cSrcweir ( m_MouseButton == 0 && !(grfKeyState & MK_LBUTTON) ) ) 297cdf0e10cSrcweir { 298cdf0e10cSrcweir retVal= DRAGDROP_S_DROP; 299cdf0e10cSrcweir } 300cdf0e10cSrcweir } 301cdf0e10cSrcweir 302cdf0e10cSrcweir // fire dropActionChanged event. 303cdf0e10cSrcweir // this is actually done by the context, which also detects whether the action 304cdf0e10cSrcweir // changed at all 305cdf0e10cSrcweir sal_Int8 dropAction= fEscapePressed ? ACTION_NONE : 306cdf0e10cSrcweir dndOleKeysToAction( grfKeyState, m_sourceActions); 307cdf0e10cSrcweir 308cdf0e10cSrcweir sal_Int8 userAction= fEscapePressed ? ACTION_NONE : 309cdf0e10cSrcweir dndOleKeysToAction( grfKeyState, -1 ); 310cdf0e10cSrcweir 311cdf0e10cSrcweir static_cast<SourceContext*>(m_currentContext.get())->fire_dropActionChanged( 312cdf0e10cSrcweir dropAction, userAction); 313cdf0e10cSrcweir 314cdf0e10cSrcweir return retVal; 315cdf0e10cSrcweir } 316cdf0e10cSrcweir 317cdf0e10cSrcweir //---------------------------------------------------- 318cdf0e10cSrcweir /** 319cdf0e10cSrcweir */ 320cdf0e10cSrcweir HRESULT STDMETHODCALLTYPE DragSource::GiveFeedback( 321cdf0e10cSrcweir /* [in] */ DWORD 322cdf0e10cSrcweir #if defined DBG_CONSOLE_OUT 323cdf0e10cSrcweir dwEffect 324cdf0e10cSrcweir #endif 325cdf0e10cSrcweir ) 326cdf0e10cSrcweir { 327cdf0e10cSrcweir #if defined DBG_CONSOLE_OUT 328cdf0e10cSrcweir printf("\nDragSource::GiveFeedback %d", dwEffect); 329cdf0e10cSrcweir #endif 330cdf0e10cSrcweir 331cdf0e10cSrcweir return DRAGDROP_S_USEDEFAULTCURSORS; 332cdf0e10cSrcweir } 333cdf0e10cSrcweir 334cdf0e10cSrcweir // XServiceInfo 335cdf0e10cSrcweir OUString SAL_CALL DragSource::getImplementationName( ) throw (RuntimeException) 336cdf0e10cSrcweir { 337cdf0e10cSrcweir return OUString(RTL_CONSTASCII_USTRINGPARAM(DNDSOURCE_IMPL_NAME));; 338cdf0e10cSrcweir } 339cdf0e10cSrcweir // XServiceInfo 340cdf0e10cSrcweir sal_Bool SAL_CALL DragSource::supportsService( const OUString& ServiceName ) throw (RuntimeException) 341cdf0e10cSrcweir { 342cdf0e10cSrcweir if( ServiceName.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(DNDSOURCE_SERVICE_NAME )))) 343cdf0e10cSrcweir return sal_True; 344cdf0e10cSrcweir return sal_False; 345cdf0e10cSrcweir } 346cdf0e10cSrcweir 347cdf0e10cSrcweir Sequence< OUString > SAL_CALL DragSource::getSupportedServiceNames( ) throw (RuntimeException) 348cdf0e10cSrcweir { 349cdf0e10cSrcweir OUString names[1]= {OUString(RTL_CONSTASCII_USTRINGPARAM(DNDSOURCE_SERVICE_NAME))}; 350cdf0e10cSrcweir 351cdf0e10cSrcweir return Sequence<OUString>(names, 1); 352cdf0e10cSrcweir } 353cdf0e10cSrcweir 354cdf0e10cSrcweir //---------------------------------------------------- 355cdf0e10cSrcweir /**This function is called as extra thread from 356cdf0e10cSrcweir DragSource::executeDrag. The function 357cdf0e10cSrcweir carries out a drag and drop operation by calling 358cdf0e10cSrcweir DoDragDrop. The thread also notifies all 359cdf0e10cSrcweir XSourceListener. 360cdf0e10cSrcweir */ 361cdf0e10cSrcweir unsigned __stdcall DndOleSTAFunc(LPVOID pParams) 362cdf0e10cSrcweir { 363cdf0e10cSrcweir // The structure contains all arguments for DoDragDrop and other 364cdf0e10cSrcweir DragSource *pSource= (DragSource*)pParams; 365cdf0e10cSrcweir 366cdf0e10cSrcweir // Drag and drop only works in a thread in which OleInitialize is called. 367cdf0e10cSrcweir HRESULT hr= OleInitialize( NULL); 368cdf0e10cSrcweir 369cdf0e10cSrcweir if(SUCCEEDED(hr)) 370cdf0e10cSrcweir { 371cdf0e10cSrcweir // We force the creation of a thread message queue. This is necessary 372cdf0e10cSrcweir // for a later call to AttachThreadInput 373cdf0e10cSrcweir MSG msgtemp; 374cdf0e10cSrcweir PeekMessage( &msgtemp, NULL, WM_USER, WM_USER, PM_NOREMOVE); 375cdf0e10cSrcweir 376cdf0e10cSrcweir DWORD threadId= GetCurrentThreadId(); 377cdf0e10cSrcweir 378cdf0e10cSrcweir // This thread is attached to the thread that created the window. Hence 379cdf0e10cSrcweir // this thread also receives all mouse and keyboard messages which are 380cdf0e10cSrcweir // needed by DoDragDrop 381cdf0e10cSrcweir AttachThreadInput( threadId , pSource->m_threadIdWindow, TRUE ); 382cdf0e10cSrcweir 383cdf0e10cSrcweir DWORD dwEffect= 0; 384cdf0e10cSrcweir hr= DoDragDrop( 385cdf0e10cSrcweir pSource->m_spDataObject.get(), 386cdf0e10cSrcweir static_cast<IDropSource*>(pSource), 387cdf0e10cSrcweir dndActionsToDropEffects( pSource->m_sourceActions), 388cdf0e10cSrcweir &dwEffect); 389cdf0e10cSrcweir 390cdf0e10cSrcweir // #105428 detach my message queue from the other threads 391cdf0e10cSrcweir // message queue before calling fire_dragDropEnd else 392cdf0e10cSrcweir // the office may appear to hang sometimes 393cdf0e10cSrcweir AttachThreadInput( threadId, pSource->m_threadIdWindow, FALSE); 394cdf0e10cSrcweir 395cdf0e10cSrcweir //--> TRA 396cdf0e10cSrcweir // clear the global transferable again 397cdf0e10cSrcweir g_XTransferable = Reference< XTransferable >( ); 398cdf0e10cSrcweir //<-- TRA 399cdf0e10cSrcweir 400cdf0e10cSrcweir OSL_ENSURE( hr != E_INVALIDARG, "IDataObject impl does not contain valid data"); 401cdf0e10cSrcweir 402cdf0e10cSrcweir //Fire event 403cdf0e10cSrcweir sal_Int8 action= hr == DRAGDROP_S_DROP ? dndOleDropEffectsToActions( dwEffect) : ACTION_NONE; 404cdf0e10cSrcweir 405cdf0e10cSrcweir static_cast<SourceContext*>(pSource->m_currentContext.get())->fire_dragDropEnd( 406cdf0e10cSrcweir hr == DRAGDROP_S_DROP ? sal_True : sal_False, action); 407cdf0e10cSrcweir 408cdf0e10cSrcweir // Destroy SourceContextslkfgj 409cdf0e10cSrcweir pSource->m_currentContext= 0; 410cdf0e10cSrcweir // Destroy the XTransferable wrapper 411cdf0e10cSrcweir pSource->m_spDataObject=0; 412cdf0e10cSrcweir 413cdf0e10cSrcweir OleUninitialize(); 414cdf0e10cSrcweir } 415cdf0e10cSrcweir 416cdf0e10cSrcweir InterlockedDecrement(&pSource->m_RunningDndOperationCount); 417cdf0e10cSrcweir 418cdf0e10cSrcweir // the DragSource was manually acquired by 419cdf0e10cSrcweir // thread starting method DelayedStartDrag 420cdf0e10cSrcweir pSource->release(); 421cdf0e10cSrcweir 422cdf0e10cSrcweir return 0; 423cdf0e10cSrcweir } 424cdf0e10cSrcweir 425