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