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