xref: /trunk/main/dtrans/source/win32/dnd/target.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_dtrans.hxx"
30 #include <com/sun/star/datatransfer/dnd/DNDConstants.hpp>
31 #include <com/sun/star/datatransfer/XTransferable.hpp>
32 #include <rtl/unload.h>
33 
34 #include <stdio.h>
35 #include "target.hxx"
36 #include "idroptarget.hxx"
37 #include "globals.hxx"
38 #include "targetdropcontext.hxx"
39 #include "targetdragcontext.hxx"
40 #include <rtl/ustring.h>
41 using namespace rtl;
42 using namespace cppu;
43 using namespace osl;
44 using namespace com::sun::star::datatransfer;
45 using namespace com::sun::star::datatransfer::dnd;
46 using namespace com::sun::star::datatransfer::dnd::DNDConstants;
47 
48 #define WM_REGISTERDRAGDROP WM_USER + 1
49 #define WM_REVOKEDRAGDROP WM_USER + 2
50 //--> TRA
51 extern Reference< XTransferable > g_XTransferable;
52 
53 //<-- TRA
54 
55 extern rtl_StandardModuleCount g_moduleCount;
56 DWORD WINAPI DndTargetOleSTAFunc(LPVOID pParams);
57 
58 DropTarget::DropTarget( const Reference<XMultiServiceFactory>& sf):
59     m_hWnd( NULL),
60     m_serviceFactory( sf),
61     WeakComponentImplHelper3<XInitialization,XDropTarget, XServiceInfo>(m_mutex),
62     m_bActive(sal_True),
63     m_nDefaultActions(ACTION_COPY|ACTION_MOVE|ACTION_LINK|ACTION_DEFAULT),
64     m_nCurrentDropAction( ACTION_NONE),
65     m_oleThreadId( 0),
66     m_pDropTarget( NULL),
67     m_threadIdWindow(0),
68     m_threadIdTarget(0),
69     m_hOleThread(0),
70     m_nLastDropAction(0)
71 
72 
73 {
74     g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
75 }
76 
77 
78 DropTarget::~DropTarget()
79 {
80     g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
81 
82 }
83 // called from WeakComponentImplHelperX::dispose
84 // WeakComponentImplHelper calls disposing before it destroys
85 // itself.
86 // NOTE: RevokeDragDrop decrements the ref count on the IDropTarget
87 // interface. (m_pDropTarget)
88 // If the HWND is invalid then it doesn't decrement and
89 // the IDropTarget object will live on. MEMORY LEAK
90 void SAL_CALL DropTarget::disposing()
91 {
92     HRESULT hr= S_OK;
93     if( m_threadIdTarget)
94     {
95         // Call RevokeDragDrop and wait for the OLE thread to die;
96         PostThreadMessage( m_threadIdTarget, WM_REVOKEDRAGDROP, (WPARAM)this, 0);
97         WaitForSingleObject( m_hOleThread, INFINITE);
98         CloseHandle( m_hOleThread);
99         //OSL_ENSURE( SUCCEEDED( hr), "HWND not valid!" );
100     }
101     else
102     {
103         hr= RevokeDragDrop( m_hWnd);
104         m_hWnd= 0;
105     }
106     if( m_pDropTarget)
107     {
108         CoLockObjectExternal( m_pDropTarget, FALSE, TRUE);
109         m_pDropTarget->Release();
110     }
111 
112     if( m_oleThreadId)
113     {
114         if( m_oleThreadId == CoGetCurrentProcess() )
115             OleUninitialize();
116     }
117 
118 }
119 
120 void SAL_CALL DropTarget::initialize( const Sequence< Any >& aArguments )
121         throw(Exception, RuntimeException)
122 {
123     // The window must be registered for Dnd by RegisterDragDrop. We must ensure
124     // that RegisterDragDrop is called from an STA ( OleInitialize) thread.
125     // As long as the window is registered we need to receive OLE messages in
126     // an OLE thread. That is to say, if DropTarget::initialize was called from an
127     // MTA thread then we create an OLE thread in which the window is registered.
128     // The thread will stay alive until aver RevokeDragDrop has been called.
129 
130     // Additionally even if RegisterDragDrop is called from an STA thread we have
131     // to ensure that it is called from the same thread that created the Window
132     // otherwise meesages sent during DND won't reach the windows message queue.
133     // Calling AttachThreadInput first would resolve this problem but would block
134     // the message queue of the calling thread. So if the current thread
135     // (even if it's an STA thread) and the thread that created the window are not
136     // identical we need to create a new thread as we do when the calling thread is
137     // an MTA thread.
138 
139     if( aArguments.getLength() > 0)
140     {
141         // Get the window handle from aArgument. It is needed for RegisterDragDrop.
142         m_hWnd= *(HWND*)aArguments[0].getValue();
143         OSL_ASSERT( IsWindow( m_hWnd) );
144 
145         // Obtain the id of the thread that created the window
146         m_threadIdWindow= GetWindowThreadProcessId( m_hWnd, NULL);
147 
148         HRESULT hr= OleInitialize( NULL);
149 
150         // Current thread is MTA or Current thread and Window thread are not identical
151         if( hr == RPC_E_CHANGED_MODE || GetCurrentThreadId() != m_threadIdWindow  )
152         {
153             OSL_ENSURE( ! m_threadIdTarget,"initialize was called twice");
154             // create the IDropTargetImplementation
155             m_pDropTarget= new IDropTargetImpl( *static_cast<DropTarget*>( this) );
156             m_pDropTarget->AddRef();
157 
158 
159             // Obtain the id of the thread that created the window
160             m_threadIdWindow= GetWindowThreadProcessId( m_hWnd, NULL);
161             // The event is set by the thread that we will create momentarily.
162             // It indicates that the thread is ready to receive messages.
163             HANDLE m_evtThreadReady= CreateEvent( NULL, FALSE, FALSE, NULL);
164 
165             m_hOleThread= CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)DndTargetOleSTAFunc,
166                                             &m_evtThreadReady, 0, &m_threadIdTarget);
167             WaitForSingleObject( m_evtThreadReady, INFINITE);
168             CloseHandle( m_evtThreadReady);
169             PostThreadMessage( m_threadIdTarget, WM_REGISTERDRAGDROP, (WPARAM)static_cast<DropTarget*>(this), 0);
170         }
171         else if( hr == S_OK || hr == S_FALSE)
172         {
173             // current thread is STA
174             // If OleInitialize has been called by the caller then we must not call
175             // OleUninitialize
176             if( hr == S_OK)
177             {
178                 // caller did not call OleInitialize, so we call OleUninitialize
179                 // remember the thread that will call OleUninitialize
180                 m_oleThreadId= CoGetCurrentProcess(); // get a unique thread id
181             }
182 
183             // Get the window handle from aArgument. It is needed for RegisterDragDrop.
184             // create the IDropTargetImplementation
185             m_pDropTarget= new IDropTargetImpl( *static_cast<DropTarget*>( this) );
186             m_pDropTarget->AddRef();
187             // CoLockObjectExternal is prescribed by the protocol. It bumps up the ref count
188             if( SUCCEEDED( CoLockObjectExternal( m_pDropTarget, TRUE, FALSE)))
189             {
190                 if( FAILED( RegisterDragDrop( m_hWnd,  m_pDropTarget) ) )
191                 {
192                     // do clean up if drag and drop is not possible
193                     CoLockObjectExternal( m_pDropTarget, FALSE, FALSE);
194                     m_pDropTarget->Release();
195                     m_hWnd= NULL;
196                 }
197             }
198         }
199         else
200             throw Exception();
201 
202     }
203 }
204 
205 // This function is called as extra thread from DragSource::startDrag.
206 // The function carries out a drag and drop operation by calling
207 // DoDragDrop. The thread also notifies all XSourceListener.
208 DWORD WINAPI DndTargetOleSTAFunc(LPVOID pParams)
209 {
210     HRESULT hr= OleInitialize( NULL);
211     if( SUCCEEDED( hr) )
212     {
213         MSG msg;
214         // force the creation of a message queue
215         PeekMessage( &msg, (HWND)NULL, 0, 0, PM_NOREMOVE);
216         // Signal the creator ( DropTarget::initialize) that the thread is
217         // ready to receive messages.
218         SetEvent( *(HANDLE*) pParams);
219         // Thread id is needed for attaching this message queue to the one of the
220         // thread where the window was created.
221         DWORD threadId= GetCurrentThreadId();
222         // We force the creation of a thread message queue. This is necessary
223         // for a later call to AttachThreadInput
224         while( GetMessage(&msg, (HWND)NULL, 0, 0) )
225         {
226             if( msg.message == WM_REGISTERDRAGDROP)
227             {
228                 DropTarget *pTarget= (DropTarget*)msg.wParam;
229                 // This thread is attached to the thread that created the window. Hence
230                 // this thread also receives all mouse and keyboard messages which are
231                 // needed
232                 AttachThreadInput( threadId , pTarget->m_threadIdWindow, TRUE );
233 
234                 if( SUCCEEDED( CoLockObjectExternal(pTarget-> m_pDropTarget, TRUE, FALSE)))
235                 {
236                     if( FAILED( RegisterDragDrop( pTarget-> m_hWnd, pTarget-> m_pDropTarget) ) )
237                     {
238                         // do clean up if drag and drop is not possible
239                         CoLockObjectExternal( pTarget->m_pDropTarget, FALSE, FALSE);
240                         pTarget->m_pDropTarget->Release();
241                         pTarget->m_hWnd= NULL;
242                     }
243                 }
244             }
245             else if( msg.message == WM_REVOKEDRAGDROP)
246             {
247                 DropTarget *pTarget= (DropTarget*)msg.wParam;
248                 RevokeDragDrop( pTarget-> m_hWnd);
249                 // Detach this thread from the window thread
250                 AttachThreadInput( threadId, pTarget->m_threadIdWindow, FALSE);
251                 pTarget->m_hWnd= 0;
252                 break;
253             }
254             TranslateMessage(  &msg);
255             DispatchMessage( &msg);
256         }
257         OleUninitialize();
258     }
259     return 0;
260 }
261 
262 
263 
264 
265 // XServiceInfo
266 OUString SAL_CALL DropTarget::getImplementationName(  ) throw (RuntimeException)
267 {
268     return OUString(RTL_CONSTASCII_USTRINGPARAM(DNDTARGET_IMPL_NAME));;
269 }
270 // XServiceInfo
271 sal_Bool SAL_CALL DropTarget::supportsService( const OUString& ServiceName ) throw (RuntimeException)
272 {
273     if( ServiceName.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(DNDTARGET_SERVICE_NAME ))))
274         return sal_True;
275     return sal_False;
276 }
277 
278 Sequence< OUString > SAL_CALL DropTarget::getSupportedServiceNames(  ) throw (RuntimeException)
279 {
280     OUString names[1]= {OUString(RTL_CONSTASCII_USTRINGPARAM(DNDTARGET_SERVICE_NAME))};
281     return Sequence<OUString>(names, 1);
282 }
283 
284 
285 // XDropTarget ----------------------------------------------------------------
286 void SAL_CALL DropTarget::addDropTargetListener( const Reference< XDropTargetListener >& dtl )
287         throw(RuntimeException)
288 {
289     rBHelper.addListener( ::getCppuType( &dtl ), dtl );
290 }
291 
292 void SAL_CALL DropTarget::removeDropTargetListener( const Reference< XDropTargetListener >& dtl )
293         throw(RuntimeException)
294 {
295     rBHelper.removeListener( ::getCppuType( &dtl ), dtl );
296 }
297 
298 sal_Bool SAL_CALL DropTarget::isActive(  ) throw(RuntimeException)
299 {
300     return m_bActive; //m_bDropTargetRegistered;
301 }
302 
303 
304 void SAL_CALL DropTarget::setActive( sal_Bool _b ) throw(RuntimeException)
305 {
306     MutexGuard g(m_mutex);
307     m_bActive= _b;
308 }
309 
310 
311 sal_Int8 SAL_CALL DropTarget::getDefaultActions(  ) throw(RuntimeException)
312 {
313     return m_nDefaultActions;
314 }
315 
316 void SAL_CALL DropTarget::setDefaultActions( sal_Int8 actions ) throw(RuntimeException)
317 {
318     OSL_ENSURE( actions < 8, "No valid default actions");
319     m_nDefaultActions= actions;
320 }
321 
322 
323 HRESULT DropTarget::DragEnter( IDataObject *pDataObj,
324                                     DWORD grfKeyState,
325                                     POINTL pt,
326                                     DWORD  *pdwEffect)
327 {
328 #if defined DBG_CONSOLE_OUT
329     printf("\nDropTarget::DragEnter state: %x effect %d", grfKeyState, *pdwEffect);
330 #endif
331     if( m_bActive )
332     {
333         // Intersection of pdwEffect and the allowed actions ( setDefaultActions)
334         m_nCurrentDropAction= getFilteredActions( grfKeyState, *pdwEffect);
335         // m_nLastDropAction has to be set by a listener. If no listener calls
336         //XDropTargetDragContext::acceptDrag and specifies an action then pdwEffect
337         // will be DROPEFFECT_NONE throughout
338         m_nLastDropAction= ACTION_DEFAULT | ACTION_MOVE;
339 
340         m_currentDragContext= static_cast<XDropTargetDragContext*>( new TargetDragContext(
341             static_cast<DropTarget*>(this) ) );
342 
343         //--> TRA
344 
345         // shortcut
346         if ( g_XTransferable.is( ) )
347             m_currentData = g_XTransferable;
348         else
349         {
350             // Convert the IDataObject to a XTransferable
351             m_currentData= m_aDataConverter.createTransferableFromDataObj(
352                                             m_serviceFactory, IDataObjectPtr(pDataObj));
353         }
354 
355         //<-- TRA
356 
357         if( m_nCurrentDropAction != ACTION_NONE)
358         {
359             DropTargetDragEnterEvent e;
360             e.SupportedDataFlavors= m_currentData->getTransferDataFlavors();
361             e.DropAction= m_nCurrentDropAction;
362             e.Source= Reference<XInterface>( static_cast<XDropTarget*>(this),UNO_QUERY);
363             e.Context= m_currentDragContext;
364             POINT point={ pt.x, pt.y};
365             ScreenToClient( m_hWnd, &point);
366             e.LocationX= point.x;
367             e.LocationY= point.y;
368             e.SourceActions= dndOleDropEffectsToActions( *pdwEffect);
369 
370             fire_dragEnter( e);
371             // Check if the action derived from grfKeyState (m_nCurrentDropAction) or the action set
372             // by the listener (m_nCurrentDropAction) is allowed by the source. Only a allowed action is set
373             // in pdwEffect. The listener notification is asynchron, that is we cannot expext that the listener
374             // has already reacted to the notification.
375             // If there is more then one valid action which is the case when ALT or RIGHT MOUSE BUTTON is pressed
376             // then getDropEffect returns DROPEFFECT_MOVE which is the default value if no other modifier is pressed.
377             // On drop the target should present the user a dialog from which the user may change the action.
378             sal_Int8 allowedActions= dndOleDropEffectsToActions( *pdwEffect);
379             *pdwEffect= dndActionsToSingleDropEffect( m_nLastDropAction & allowedActions);
380         }
381         else
382         {
383             *pdwEffect= DROPEFFECT_NONE;
384         }
385     }
386     return S_OK;
387 }
388 
389 HRESULT DropTarget::DragOver( DWORD grfKeyState,
390                                    POINTL pt,
391                                    DWORD  *pdwEffect)
392 {
393     if( m_bActive)
394     {
395         m_nCurrentDropAction= getFilteredActions( grfKeyState, *pdwEffect);
396 
397         if( m_nCurrentDropAction)
398         {
399             DropTargetDragEvent e;
400             e.DropAction= m_nCurrentDropAction;
401             e.Source= Reference<XInterface>(static_cast<XDropTarget*>(this),UNO_QUERY);
402             e.Context= m_currentDragContext;
403             POINT point={ pt.x, pt.y};
404             ScreenToClient( m_hWnd, &point);
405             e.LocationX= point.x;
406             e.LocationY= point.y;
407             e.SourceActions= dndOleDropEffectsToActions( *pdwEffect);
408 
409             // if grfKeyState has changed since the last DragOver then fire events.
410             // A listener might change m_nCurrentDropAction by calling the
411             // XDropTargetDragContext::acceptDrag function. But this is not important
412             // because in the afterwards fired dragOver event the action reflects
413             // grgKeyState again.
414             if( m_nLastDropAction != m_nCurrentDropAction)
415                 fire_dropActionChanged( e);
416 
417             // The Event contains a XDropTargetDragContext implementation.
418             fire_dragOver( e);
419             // Check if the action derived from grfKeyState (m_nCurrentDropAction) or the action set
420             // by the listener (m_nCurrentDropAction) is allowed by the source. Only a allowed action is set
421             // in pdwEffect. The listener notification is asynchron, that is we cannot expext that the listener
422             // has already reacted to the notification.
423             // If there is more then one valid action which is the case when ALT or RIGHT MOUSE BUTTON is pressed
424             // then getDropEffect returns DROPEFFECT_MOVE which is the default value if no other modifier is pressed.
425             // On drop the target should present the user a dialog from which the user may change the action.
426             sal_Int8 allowedActions= dndOleDropEffectsToActions( *pdwEffect);
427             // set the last action to the current if listener has not changed the value yet
428             *pdwEffect= dndActionsToSingleDropEffect( m_nLastDropAction & allowedActions);
429         }
430         else
431         {
432             *pdwEffect= DROPEFFECT_NONE;
433         }
434     }
435 #if defined DBG_CONSOLE_OUT
436     printf("\nDropTarget::DragOver %d", *pdwEffect );
437 #endif
438     return S_OK;
439 }
440 
441 HRESULT DropTarget::DragLeave( void)
442 {
443 #if defined DBG_CONSOLE_OUT
444     printf("\nDropTarget::DragLeave");
445 #endif
446     if( m_bActive)
447     {
448 
449         m_currentData=0;
450         m_currentDragContext= 0;
451         m_currentDropContext= 0;
452         m_nLastDropAction= 0;
453 
454         if( m_nDefaultActions != ACTION_NONE)
455         {
456             DropTargetEvent e;
457             e.Source=  static_cast<XDropTarget*>(this);
458 
459             fire_dragExit( e);
460         }
461     }
462     return S_OK;
463 }
464 
465 HRESULT DropTarget::Drop( IDataObject  * /*pDataObj*/,
466                    DWORD grfKeyState,
467                    POINTL pt,
468                    DWORD *pdwEffect)
469 {
470 #if defined DBG_CONSOLE_OUT
471     printf("\nDropTarget::Drop");
472 #endif
473     if( m_bActive)
474     {
475 
476         m_bDropComplete= sal_False;
477 
478         m_nCurrentDropAction= getFilteredActions( grfKeyState, *pdwEffect);
479         m_currentDropContext= static_cast<XDropTargetDropContext*>( new TargetDropContext( static_cast<DropTarget*>(this ))  );
480         if( m_nCurrentDropAction)
481         {
482             DropTargetDropEvent e;
483             e.DropAction= m_nCurrentDropAction;
484             e.Source= Reference<XInterface>( static_cast<XDropTarget*>(this), UNO_QUERY);
485             e.Context= m_currentDropContext;
486             POINT point={ pt.x, pt.y};
487             ScreenToClient( m_hWnd, &point);
488             e.LocationX= point.x;
489             e.LocationY= point.y;
490             e.SourceActions= dndOleDropEffectsToActions( *pdwEffect);
491             e.Transferable= m_currentData;
492             fire_drop( e);
493 
494             //if fire_drop returns than a listener might have modified m_nCurrentDropAction
495             if( m_bDropComplete == sal_True)
496             {
497                 sal_Int8 allowedActions= dndOleDropEffectsToActions( *pdwEffect);
498                 *pdwEffect= dndActionsToSingleDropEffect( m_nCurrentDropAction & allowedActions);
499             }
500             else
501                 *pdwEffect= DROPEFFECT_NONE;
502         }
503         else
504             *pdwEffect= DROPEFFECT_NONE;
505 
506         m_currentData= 0;
507         m_currentDragContext= 0;
508         m_currentDropContext= 0;
509         m_nLastDropAction= 0;
510     }
511     return S_OK;
512 }
513 
514 
515 
516 void DropTarget::fire_drop( const DropTargetDropEvent& dte)
517 {
518     OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (Reference<XDropTargetListener>* )0 ) );
519     if( pContainer)
520     {
521         OInterfaceIteratorHelper iter( *pContainer);
522         while( iter.hasMoreElements())
523         {
524             Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next()));
525             listener->drop( dte);
526         }
527     }
528 }
529 
530 void DropTarget::fire_dragEnter( const DropTargetDragEnterEvent& e )
531 {
532     OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (Reference<XDropTargetListener>* )0 ) );
533     if( pContainer)
534     {
535         OInterfaceIteratorHelper iter( *pContainer);
536         while( iter.hasMoreElements())
537         {
538             Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next()));
539             listener->dragEnter( e);
540         }
541     }
542 }
543 
544 void DropTarget::fire_dragExit( const DropTargetEvent& dte )
545 {
546     OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (Reference<XDropTargetListener>* )0 ) );
547 
548     if( pContainer)
549     {
550         OInterfaceIteratorHelper iter( *pContainer);
551         while( iter.hasMoreElements())
552         {
553             Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next()));
554             listener->dragExit( dte);
555         }
556     }
557 }
558 
559 void DropTarget::fire_dragOver( const DropTargetDragEvent& dtde )
560 {
561     OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (Reference<XDropTargetListener>* )0 ) );
562     if( pContainer)
563     {
564         OInterfaceIteratorHelper iter( *pContainer );
565         while( iter.hasMoreElements())
566         {
567             Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next()));
568             listener->dragOver( dtde);
569         }
570     }
571 }
572 
573 void DropTarget::fire_dropActionChanged( const DropTargetDragEvent& dtde )
574 {
575     OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (Reference<XDropTargetListener>* )0 ) );
576     if( pContainer)
577     {
578         OInterfaceIteratorHelper iter( *pContainer);
579         while( iter.hasMoreElements())
580         {
581             Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next()));
582             listener->dropActionChanged( dtde);
583         }
584     }
585 }
586 
587 // Non - interface functions ============================================================
588 // DropTarget fires events to XDropTargetListeners. The event object contains an
589 // XDropTargetDropContext implementaion. When the listener calls on that interface
590 // then the calls are delegated from DropContext (XDropTargetDropContext) to these
591 // functions.
592 // Only one listener which visible area is affected is allowed to call on
593 // XDropTargetDropContext
594 // Returning sal_False would cause the XDropTargetDropContext or ..DragContext implementation
595 // to throw an InvalidDNDOperationException, meaning that a Drag is not currently performed.
596 // return sal_False results in throwing a InvalidDNDOperationException in the caller.
597 
598 void DropTarget::_acceptDrop(sal_Int8 dropOperation, const Reference<XDropTargetDropContext>& context)
599 {
600     if( context == m_currentDropContext)
601     {
602         m_nCurrentDropAction= dropOperation;
603     }
604 }
605 
606 void DropTarget::_rejectDrop( const Reference<XDropTargetDropContext>& context)
607 {
608     if( context == m_currentDropContext)
609     {
610         m_nCurrentDropAction= ACTION_NONE;
611     }
612 }
613 
614 void DropTarget::_dropComplete(sal_Bool success, const Reference<XDropTargetDropContext>& context)
615 {
616     if(context == m_currentDropContext)
617     {
618         m_bDropComplete= success;
619     }
620 }
621 // --------------------------------------------------------------------------------------
622 // DropTarget fires events to XDropTargetListeners. The event object can contains an
623 // XDropTargetDragContext implementaion. When the listener calls on that interface
624 // then the calls are delegated from DragContext (XDropTargetDragContext) to these
625 // functions.
626 // Only one listener which visible area is affected is allowed to call on
627 // XDropTargetDragContext
628 void DropTarget::_acceptDrag( sal_Int8 dragOperation, const Reference<XDropTargetDragContext>& context)
629 {
630     if( context == m_currentDragContext)
631     {
632         m_nLastDropAction= dragOperation;
633     }
634 }
635 
636 void DropTarget::_rejectDrag( const Reference<XDropTargetDragContext>& context)
637 {
638     if(context == m_currentDragContext)
639     {
640         m_nLastDropAction= ACTION_NONE;
641     }
642 }
643 
644 
645 //--------------------------------------------------------------------------------------
646 
647 
648 // This function determines the action dependend on the pressed
649 // key modifiers ( CTRL, SHIFT, ALT, Right Mouse Button). The result
650 // is then checked against the allowed actions which can be set through
651 // XDropTarget::setDefaultActions. Only those values which are also
652 // default actions are returned. If setDefaultActions has not been called
653 // beforehand the the default actions comprise all possible actions.
654 // params: grfKeyState - the modifier keys and mouse buttons currently pressed
655 inline sal_Int8 DropTarget::getFilteredActions( DWORD grfKeyState, DWORD dwEffect)
656 {
657     sal_Int8 actions= dndOleKeysToAction( grfKeyState, dndOleDropEffectsToActions( dwEffect));
658     return actions &  m_nDefaultActions;
659 }
660 
661 
662