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