xref: /trunk/main/dtrans/source/win32/dnd/target.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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 {
118     // The window must be registered for Dnd by RegisterDragDrop. We must ensure
119     // that RegisterDragDrop is called from an STA ( OleInitialize) thread.
120     // As long as the window is registered we need to receive OLE messages in
121     // an OLE thread. That is to say, if DropTarget::initialize was called from an
122     // MTA thread then we create an OLE thread in which the window is registered.
123     // The thread will stay alive until aver RevokeDragDrop has been called.
124 
125     // Additionally even if RegisterDragDrop is called from an STA thread we have
126     // to ensure that it is called from the same thread that created the Window
127     // otherwise messages sent during DND won't reach the windows message queue.
128     // Calling AttachThreadInput first would resolve this problem but would block
129     // the message queue of the calling thread. So if the current thread
130     // (even if it's an STA thread) and the thread that created the window are not
131     // identical we need to create a new thread as we do when the calling thread is
132     // an MTA thread.
133 
134     if( aArguments.getLength() > 0)
135     {
136         // Get the window handle from aArgument. It is needed for RegisterDragDrop.
137         sal_uInt64 nWindowHandle= 0;
138         aArguments[0] >>= nWindowHandle;
139         m_hWnd= (HWND)(sal_uIntPtr) nWindowHandle;
140         OSL_ASSERT( IsWindow( m_hWnd) );
141 
142         // Obtain the id of the thread that created the window
143         m_threadIdWindow= GetWindowThreadProcessId( m_hWnd, NULL);
144 
145         HRESULT hr= OleInitialize( NULL);
146 
147         // Current thread is MTA or Current thread and Window thread are not identical
148         if( hr == RPC_E_CHANGED_MODE || GetCurrentThreadId() != m_threadIdWindow )
149         {
150             OSL_ENSURE( ! m_threadIdTarget,"initialize was called twice");
151             // create the IDropTargetImplementation
152             m_pDropTarget= new IDropTargetImpl( *static_cast<DropTarget*>( this) );
153             m_pDropTarget->AddRef();
154 
155 
156             // Obtain the id of the thread that created the window
157             m_threadIdWindow= GetWindowThreadProcessId( m_hWnd, NULL);
158             // The event is set by the thread that we will create momentarily.
159             // It indicates that the thread is ready to receive messages.
160             HANDLE m_evtThreadReady= CreateEvent( NULL, FALSE, FALSE, NULL);
161 
162             m_hOleThread= CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)DndTargetOleSTAFunc,
163                                             &m_evtThreadReady, 0, &m_threadIdTarget);
164             WaitForSingleObject( m_evtThreadReady, INFINITE);
165             CloseHandle( m_evtThreadReady);
166             PostThreadMessage( m_threadIdTarget, WM_REGISTERDRAGDROP, (WPARAM)static_cast<DropTarget*>(this), 0);
167         }
168         else if( hr == S_OK || hr == S_FALSE)
169         {
170             // current thread is STA
171             // If OleInitialize has been called by the caller then we must not call
172             // OleUninitialize
173             if( hr == S_OK)
174             {
175                 // caller did not call OleInitialize, so we call OleUninitialize
176                 // remember the thread that will call OleUninitialize
177                 m_oleThreadId= CoGetCurrentProcess(); // get a unique thread id
178             }
179 
180             // Get the window handle from aArgument. It is needed for RegisterDragDrop.
181             // create the IDropTargetImplementation
182             m_pDropTarget= new IDropTargetImpl( *static_cast<DropTarget*>( this) );
183             m_pDropTarget->AddRef();
184             // CoLockObjectExternal is prescribed by the protocol. It bumps up the ref count
185             if( SUCCEEDED( CoLockObjectExternal( m_pDropTarget, TRUE, FALSE)))
186             {
187                 if( FAILED( RegisterDragDrop( m_hWnd, m_pDropTarget) ) )
188                 {
189                     // do clean up if drag and drop is not possible
190                     CoLockObjectExternal( m_pDropTarget, FALSE, FALSE);
191                     m_pDropTarget->Release();
192                     m_hWnd= NULL;
193                 }
194             }
195         }
196         else
197             throw Exception();
198 
199     }
200 }
201 
202 // This function is called as extra thread from DragSource::startDrag.
203 // The function carries out a drag and drop operation by calling
204 // DoDragDrop. The thread also notifies all XSourceListener.
DndTargetOleSTAFunc(LPVOID pParams)205 DWORD WINAPI DndTargetOleSTAFunc(LPVOID pParams)
206 {
207     HRESULT hr= OleInitialize( NULL);
208     if( SUCCEEDED( hr) )
209     {
210         MSG msg;
211         // force the creation of a message queue
212         PeekMessage( &msg, (HWND)NULL, 0, 0, PM_NOREMOVE);
213         // Signal the creator ( DropTarget::initialize) that the thread is
214         // ready to receive messages.
215         SetEvent( *(HANDLE*) pParams);
216         // Thread id is needed for attaching this message queue to the one of the
217         // thread where the window was created.
218         DWORD threadId= GetCurrentThreadId();
219         // We force the creation of a thread message queue. This is necessary
220         // for a later call to AttachThreadInput
221         while( GetMessage(&msg, (HWND)NULL, 0, 0) )
222         {
223             if( msg.message == WM_REGISTERDRAGDROP)
224             {
225                 DropTarget *pTarget= (DropTarget*)msg.wParam;
226                 // This thread is attached to the thread that created the window. Hence
227                 // this thread also receives all mouse and keyboard messages which are
228                 // needed
229                 AttachThreadInput( threadId , pTarget->m_threadIdWindow, TRUE );
230 
231                 if( SUCCEEDED( CoLockObjectExternal(pTarget-> m_pDropTarget, TRUE, FALSE)))
232                 {
233                     if( FAILED( RegisterDragDrop( pTarget-> m_hWnd, pTarget-> m_pDropTarget) ) )
234                     {
235                         // do clean up if drag and drop is not possible
236                         CoLockObjectExternal( pTarget->m_pDropTarget, FALSE, FALSE);
237                         pTarget->m_pDropTarget->Release();
238                         pTarget->m_hWnd= NULL;
239                     }
240                 }
241             }
242             else if( msg.message == WM_REVOKEDRAGDROP)
243             {
244                 DropTarget *pTarget= (DropTarget*)msg.wParam;
245                 RevokeDragDrop( pTarget-> m_hWnd);
246                 // Detach this thread from the window thread
247                 AttachThreadInput( threadId, pTarget->m_threadIdWindow, FALSE);
248                 pTarget->m_hWnd= 0;
249                 break;
250             }
251             TranslateMessage( &msg);
252             DispatchMessage( &msg);
253         }
254         OleUninitialize();
255     }
256     return 0;
257 }
258 
259 
260 
261 
262 // XServiceInfo
getImplementationName()263 OUString SAL_CALL DropTarget::getImplementationName(  )
264 {
265     return OUString(RTL_CONSTASCII_USTRINGPARAM(DNDTARGET_IMPL_NAME));
266 }
267 // XServiceInfo
supportsService(const OUString & ServiceName)268 sal_Bool SAL_CALL DropTarget::supportsService( const OUString& ServiceName )
269 {
270     if( ServiceName.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(DNDTARGET_SERVICE_NAME ))))
271         return sal_True;
272     return sal_False;
273 }
274 
getSupportedServiceNames()275 Sequence< OUString > SAL_CALL DropTarget::getSupportedServiceNames(  )
276 {
277     OUString names[1]= {OUString(RTL_CONSTASCII_USTRINGPARAM(DNDTARGET_SERVICE_NAME))};
278     return Sequence<OUString>(names, 1);
279 }
280 
281 
282 // XDropTarget ----------------------------------------------------------------
addDropTargetListener(const Reference<XDropTargetListener> & dtl)283 void SAL_CALL DropTarget::addDropTargetListener( const Reference< XDropTargetListener >& dtl )
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 {
290     rBHelper.removeListener( ::getCppuType( &dtl ), dtl );
291 }
292 
isActive()293 sal_Bool SAL_CALL DropTarget::isActive(  )
294 {
295     return m_bActive; //m_bDropTargetRegistered;
296 }
297 
298 
setActive(sal_Bool _b)299 void SAL_CALL DropTarget::setActive( sal_Bool _b )
300 {
301     MutexGuard g(m_mutex);
302     m_bActive= _b;
303 }
304 
305 
getDefaultActions()306 sal_Int8 SAL_CALL DropTarget::getDefaultActions(  )
307 {
308     return m_nDefaultActions;
309 }
310 
setDefaultActions(sal_Int8 actions)311 void SAL_CALL DropTarget::setDefaultActions( sal_Int8 actions )
312 {
313     OSL_ENSURE( actions < 8, "No valid default actions");
314     m_nDefaultActions= actions;
315 }
316 
317 
DragEnter(IDataObject * pDataObj,DWORD grfKeyState,POINTL pt,DWORD * pdwEffect)318 HRESULT DropTarget::DragEnter( IDataObject *pDataObj,
319                                     DWORD grfKeyState,
320                                     POINTL pt,
321                                     DWORD *pdwEffect)
322 {
323 #if defined DBG_CONSOLE_OUT
324     printf("\nDropTarget::DragEnter state: %x effect %d", grfKeyState, *pdwEffect);
325 #endif
326     if( m_bActive )
327     {
328         // Intersection of pdwEffect and the allowed actions ( setDefaultActions)
329         m_nCurrentDropAction= getFilteredActions( grfKeyState, *pdwEffect);
330         // m_nLastDropAction has to be set by a listener. If no listener calls
331         //XDropTargetDragContext::acceptDrag and specifies an action then pdwEffect
332         // will be DROPEFFECT_NONE throughout
333         m_nLastDropAction= ACTION_DEFAULT | ACTION_MOVE;
334 
335         m_currentDragContext= static_cast<XDropTargetDragContext*>( new TargetDragContext(
336             static_cast<DropTarget*>(this) ) );
337 
338         //--> TRA
339 
340         // shortcut
341         if ( g_XTransferable.is( ) )
342             m_currentData = g_XTransferable;
343         else
344         {
345             // Convert the IDataObject to a XTransferable
346             m_currentData= m_aDataConverter.createTransferableFromDataObj(
347                                             m_serviceFactory, IDataObjectPtr(pDataObj));
348         }
349 
350         //<-- TRA
351 
352         if( m_nCurrentDropAction != ACTION_NONE)
353         {
354             DropTargetDragEnterEvent e;
355             e.SupportedDataFlavors= m_currentData->getTransferDataFlavors();
356             e.DropAction= m_nCurrentDropAction;
357             e.Source= Reference<XInterface>( static_cast<XDropTarget*>(this),UNO_QUERY);
358             e.Context= m_currentDragContext;
359             POINT point={ pt.x, pt.y};
360             ScreenToClient( m_hWnd, &point);
361             e.LocationX= point.x;
362             e.LocationY= point.y;
363             e.SourceActions= dndOleDropEffectsToActions( *pdwEffect);
364 
365             fire_dragEnter( e);
366             // Check if the action derived from grfKeyState (m_nCurrentDropAction) or the action set
367             // by the listener (m_nCurrentDropAction) is allowed by the source. Only a allowed action is set
368             // in pdwEffect. The listener notification is asynchronous, that is we cannot expect that the listener
369             // has already reacted to the notification.
370             // If there is more then one valid action which is the case when ALT or RIGHT MOUSE BUTTON is pressed
371             // then getDropEffect returns DROPEFFECT_MOVE which is the default value if no other modifier is pressed.
372             // On drop the target should present the user a dialog from which the user may change the action.
373             sal_Int8 allowedActions= dndOleDropEffectsToActions( *pdwEffect);
374             *pdwEffect= dndActionsToSingleDropEffect( m_nLastDropAction & allowedActions);
375         }
376         else
377         {
378             *pdwEffect= DROPEFFECT_NONE;
379         }
380     }
381     return S_OK;
382 }
383 
DragOver(DWORD grfKeyState,POINTL pt,DWORD * pdwEffect)384 HRESULT DropTarget::DragOver( DWORD grfKeyState,
385                                    POINTL pt,
386                                    DWORD *pdwEffect)
387 {
388     if( m_bActive)
389     {
390         m_nCurrentDropAction= getFilteredActions( grfKeyState, *pdwEffect);
391 
392         if( m_nCurrentDropAction)
393         {
394             DropTargetDragEvent e;
395             e.DropAction= m_nCurrentDropAction;
396             e.Source= Reference<XInterface>(static_cast<XDropTarget*>(this),UNO_QUERY);
397             e.Context= m_currentDragContext;
398             POINT point={ pt.x, pt.y};
399             ScreenToClient( m_hWnd, &point);
400             e.LocationX= point.x;
401             e.LocationY= point.y;
402             e.SourceActions= dndOleDropEffectsToActions( *pdwEffect);
403 
404             // if grfKeyState has changed since the last DragOver then fire events.
405             // A listener might change m_nCurrentDropAction by calling the
406             // XDropTargetDragContext::acceptDrag function. But this is not important
407             // because in the afterwards fired dragOver event the action reflects
408             // grgKeyState again.
409             if( m_nLastDropAction != m_nCurrentDropAction)
410                 fire_dropActionChanged( e);
411 
412             // The Event contains a XDropTargetDragContext implementation.
413             fire_dragOver( e);
414             // Check if the action derived from grfKeyState (m_nCurrentDropAction) or the action set
415             // by the listener (m_nCurrentDropAction) is allowed by the source. Only a allowed action is set
416             // in pdwEffect. The listener notification is asynchronous, that is we cannot expect that the listener
417             // has already reacted to the notification.
418             // If there is more then one valid action which is the case when ALT or RIGHT MOUSE BUTTON is pressed
419             // then getDropEffect returns DROPEFFECT_MOVE which is the default value if no other modifier is pressed.
420             // On drop the target should present the user a dialog from which the user may change the action.
421             sal_Int8 allowedActions= dndOleDropEffectsToActions( *pdwEffect);
422             // set the last action to the current if listener has not changed the value yet
423             *pdwEffect= dndActionsToSingleDropEffect( m_nLastDropAction & allowedActions);
424         }
425         else
426         {
427             *pdwEffect= DROPEFFECT_NONE;
428         }
429     }
430 #if defined DBG_CONSOLE_OUT
431     printf("\nDropTarget::DragOver %d", *pdwEffect );
432 #endif
433     return S_OK;
434 }
435 
DragLeave(void)436 HRESULT DropTarget::DragLeave( void)
437 {
438 #if defined DBG_CONSOLE_OUT
439     printf("\nDropTarget::DragLeave");
440 #endif
441     if( m_bActive)
442     {
443 
444         m_currentData=0;
445         m_currentDragContext= 0;
446         m_currentDropContext= 0;
447         m_nLastDropAction= 0;
448 
449         if( m_nDefaultActions != ACTION_NONE)
450         {
451             DropTargetEvent e;
452             e.Source= static_cast<XDropTarget*>(this);
453 
454             fire_dragExit( e);
455         }
456     }
457     return S_OK;
458 }
459 
Drop(IDataObject *,DWORD grfKeyState,POINTL pt,DWORD * pdwEffect)460 HRESULT DropTarget::Drop( IDataObject * /*pDataObj*/,
461                    DWORD grfKeyState,
462                    POINTL pt,
463                    DWORD *pdwEffect)
464 {
465 #if defined DBG_CONSOLE_OUT
466     printf("\nDropTarget::Drop");
467 #endif
468     if( m_bActive)
469     {
470 
471         m_bDropComplete= sal_False;
472 
473         m_nCurrentDropAction= getFilteredActions( grfKeyState, *pdwEffect);
474         m_currentDropContext= static_cast<XDropTargetDropContext*>( new TargetDropContext( static_cast<DropTarget*>(this )) );
475         if( m_nCurrentDropAction)
476         {
477             DropTargetDropEvent e;
478             e.DropAction= m_nCurrentDropAction;
479             e.Source= Reference<XInterface>( static_cast<XDropTarget*>(this), UNO_QUERY);
480             e.Context= m_currentDropContext;
481             POINT point={ pt.x, pt.y};
482             ScreenToClient( m_hWnd, &point);
483             e.LocationX= point.x;
484             e.LocationY= point.y;
485             e.SourceActions= dndOleDropEffectsToActions( *pdwEffect);
486             e.Transferable= m_currentData;
487             fire_drop( e);
488 
489             // if fire_drop returns than a listener might have modified m_nCurrentDropAction
490             if( m_bDropComplete == sal_True)
491             {
492                 sal_Int8 allowedActions= dndOleDropEffectsToActions( *pdwEffect);
493                 *pdwEffect= dndActionsToSingleDropEffect( m_nCurrentDropAction & allowedActions);
494             }
495             else
496                 *pdwEffect= DROPEFFECT_NONE;
497         }
498         else
499             *pdwEffect= DROPEFFECT_NONE;
500 
501         m_currentData= 0;
502         m_currentDragContext= 0;
503         m_currentDropContext= 0;
504         m_nLastDropAction= 0;
505     }
506     return S_OK;
507 }
508 
509 
510 
fire_drop(const DropTargetDropEvent & dte)511 void DropTarget::fire_drop( const DropTargetDropEvent& dte)
512 {
513     OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (Reference<XDropTargetListener>* )0 ) );
514     if( pContainer)
515     {
516         OInterfaceIteratorHelper iter( *pContainer);
517         while( iter.hasMoreElements())
518         {
519             Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next()));
520             listener->drop( dte);
521         }
522     }
523 }
524 
fire_dragEnter(const DropTargetDragEnterEvent & e)525 void DropTarget::fire_dragEnter( const DropTargetDragEnterEvent& e )
526 {
527     OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (Reference<XDropTargetListener>* )0 ) );
528     if( pContainer)
529     {
530         OInterfaceIteratorHelper iter( *pContainer);
531         while( iter.hasMoreElements())
532         {
533             Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next()));
534             listener->dragEnter( e);
535         }
536     }
537 }
538 
fire_dragExit(const DropTargetEvent & dte)539 void DropTarget::fire_dragExit( const DropTargetEvent& dte )
540 {
541     OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (Reference<XDropTargetListener>* )0 ) );
542 
543     if( pContainer)
544     {
545         OInterfaceIteratorHelper iter( *pContainer);
546         while( iter.hasMoreElements())
547         {
548             Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next()));
549             listener->dragExit( dte);
550         }
551     }
552 }
553 
fire_dragOver(const DropTargetDragEvent & dtde)554 void DropTarget::fire_dragOver( const DropTargetDragEvent& dtde )
555 {
556     OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (Reference<XDropTargetListener>* )0 ) );
557     if( pContainer)
558     {
559         OInterfaceIteratorHelper iter( *pContainer );
560         while( iter.hasMoreElements())
561         {
562             Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next()));
563             listener->dragOver( dtde);
564         }
565     }
566 }
567 
fire_dropActionChanged(const DropTargetDragEvent & dtde)568 void DropTarget::fire_dropActionChanged( const DropTargetDragEvent& dtde )
569 {
570     OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (Reference<XDropTargetListener>* )0 ) );
571     if( pContainer)
572     {
573         OInterfaceIteratorHelper iter( *pContainer);
574         while( iter.hasMoreElements())
575         {
576             Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next()));
577             listener->dropActionChanged( dtde);
578         }
579     }
580 }
581 
582 // Non - interface functions ============================================================
583 // DropTarget fires events to XDropTargetListeners. The event object contains an
584 // XDropTargetDropContext implementation. When the listener calls on that interface
585 // then the calls are delegated from DropContext (XDropTargetDropContext) to these
586 // functions.
587 // Only one listener which visible area is affected is allowed to call on
588 // XDropTargetDropContext
589 // Returning sal_False would cause the XDropTargetDropContext or ..DragContext implementation
590 // to throw an InvalidDNDOperationException, meaning that a Drag is not currently performed.
591 // return sal_False results in throwing a InvalidDNDOperationException in the caller.
592 
_acceptDrop(sal_Int8 dropOperation,const Reference<XDropTargetDropContext> & context)593 void DropTarget::_acceptDrop(sal_Int8 dropOperation, const Reference<XDropTargetDropContext>& context)
594 {
595     if( context == m_currentDropContext)
596     {
597         m_nCurrentDropAction= dropOperation;
598     }
599 }
600 
_rejectDrop(const Reference<XDropTargetDropContext> & context)601 void DropTarget::_rejectDrop( const Reference<XDropTargetDropContext>& context)
602 {
603     if( context == m_currentDropContext)
604     {
605         m_nCurrentDropAction= ACTION_NONE;
606     }
607 }
608 
_dropComplete(sal_Bool success,const Reference<XDropTargetDropContext> & context)609 void DropTarget::_dropComplete(sal_Bool success, const Reference<XDropTargetDropContext>& context)
610 {
611     if(context == m_currentDropContext)
612     {
613         m_bDropComplete= success;
614     }
615 }
616 // --------------------------------------------------------------------------------------
617 // DropTarget fires events to XDropTargetListeners. The event object can contains an
618 // XDropTargetDragContext implementation. When the listener calls on that interface
619 // then the calls are delegated from DragContext (XDropTargetDragContext) to these
620 // functions.
621 // Only one listener which visible area is affected is allowed to call on
622 // XDropTargetDragContext
_acceptDrag(sal_Int8 dragOperation,const Reference<XDropTargetDragContext> & context)623 void DropTarget::_acceptDrag( sal_Int8 dragOperation, const Reference<XDropTargetDragContext>& context)
624 {
625     if( context == m_currentDragContext)
626     {
627         m_nLastDropAction= dragOperation;
628     }
629 }
630 
_rejectDrag(const Reference<XDropTargetDragContext> & context)631 void DropTarget::_rejectDrag( const Reference<XDropTargetDragContext>& context)
632 {
633     if(context == m_currentDragContext)
634     {
635         m_nLastDropAction= ACTION_NONE;
636     }
637 }
638 
639 
640 //--------------------------------------------------------------------------------------
641 
642 
643 // This function determines the action dependent on the pressed
644 // key modifiers ( CTRL, SHIFT, ALT, Right Mouse Button). The result
645 // is then checked against the allowed actions which can be set through
646 // XDropTarget::setDefaultActions. Only those values which are also
647 // default actions are returned. If setDefaultActions has not been called
648 // beforehand the default actions comprise all possible actions.
649 // params: grfKeyState - the modifier keys and mouse buttons currently pressed
getFilteredActions(DWORD grfKeyState,DWORD dwEffect)650 inline sal_Int8 DropTarget::getFilteredActions( DWORD grfKeyState, DWORD dwEffect)
651 {
652     sal_Int8 actions= dndOleKeysToAction( grfKeyState, dndOleDropEffectsToActions( dwEffect));
653     return actions & m_nDefaultActions;
654 }
655