xref: /aoo42x/main/dtrans/source/win32/dnd/target.cxx (revision cdf0e10c)
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