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