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 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 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 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 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 meesages 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. 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 262 OUString SAL_CALL DropTarget::getImplementationName( ) throw (RuntimeException) 263 { 264 return OUString(RTL_CONSTASCII_USTRINGPARAM(DNDTARGET_IMPL_NAME));; 265 } 266 // XServiceInfo 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 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 ---------------------------------------------------------------- 282 void SAL_CALL DropTarget::addDropTargetListener( const Reference< XDropTargetListener >& dtl ) 283 throw(RuntimeException) 284 { 285 rBHelper.addListener( ::getCppuType( &dtl ), dtl ); 286 } 287 288 void SAL_CALL DropTarget::removeDropTargetListener( const Reference< XDropTargetListener >& dtl ) 289 throw(RuntimeException) 290 { 291 rBHelper.removeListener( ::getCppuType( &dtl ), dtl ); 292 } 293 294 sal_Bool SAL_CALL DropTarget::isActive( ) throw(RuntimeException) 295 { 296 return m_bActive; //m_bDropTargetRegistered; 297 } 298 299 300 void SAL_CALL DropTarget::setActive( sal_Bool _b ) throw(RuntimeException) 301 { 302 MutexGuard g(m_mutex); 303 m_bActive= _b; 304 } 305 306 307 sal_Int8 SAL_CALL DropTarget::getDefaultActions( ) throw(RuntimeException) 308 { 309 return m_nDefaultActions; 310 } 311 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 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 asynchron, that is we cannot expext 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 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 asynchron, that is we cannot expext 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 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 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 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 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 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 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 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 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 602 void DropTarget::_rejectDrop( const Reference<XDropTargetDropContext>& context) 603 { 604 if( context == m_currentDropContext) 605 { 606 m_nCurrentDropAction= ACTION_NONE; 607 } 608 } 609 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 implementaion. 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 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 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 dependend 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 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 658