xref: /trunk/main/dtrans/source/win32/dnd/target.cxx (revision 41e09fa9)
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 messages 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 asynchronous, that is we cannot expect 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 asynchronous, that is we cannot expect 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 implementation. 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 dependent 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 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