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_vcl.hxx" 30 31 #include <dndevdis.hxx> 32 #include <dndlcon.hxx> 33 #include <window.h> 34 #include <svdata.hxx> 35 36 #include <vos/mutex.hxx> 37 #include <vcl/svapp.hxx> 38 39 using namespace ::osl; 40 using namespace ::vos; 41 using namespace ::cppu; 42 using namespace ::com::sun::star::uno; 43 using namespace ::com::sun::star::lang; 44 using namespace ::com::sun::star::datatransfer; 45 using namespace ::com::sun::star::datatransfer::dnd; 46 47 //================================================================================================== 48 // DNDEventDispatcher::DNDEventDispatcher 49 //================================================================================================== 50 51 DNDEventDispatcher::DNDEventDispatcher( Window * pTopWindow ): 52 m_pTopWindow( pTopWindow ), 53 m_pCurrentWindow( NULL ) 54 { 55 } 56 57 //================================================================================================== 58 // DNDEventDispatcher::~DNDEventDispatcher 59 //================================================================================================== 60 61 DNDEventDispatcher::~DNDEventDispatcher() 62 { 63 } 64 65 //================================================================================================== 66 // DNDEventDispatcher::drop 67 //================================================================================================== 68 69 void SAL_CALL DNDEventDispatcher::drop( const DropTargetDropEvent& dtde ) 70 throw(RuntimeException) 71 { 72 MutexGuard aImplGuard( m_aMutex ); 73 74 Point location( dtde.LocationX, dtde.LocationY ); 75 76 // find the window that is toplevel for this coordinates 77 OClearableGuard aSolarGuard( Application::GetSolarMutex() ); 78 79 // because those coordinates come from outside, they must be mirrored if RTL layout is active 80 if( Application::GetSettings().GetLayoutRTL() ) 81 m_pTopWindow->ImplMirrorFramePos( location ); 82 Window * pChildWindow = m_pTopWindow->ImplFindWindow( location ); 83 84 if( NULL == pChildWindow ) 85 pChildWindow = m_pTopWindow; 86 87 while( pChildWindow->ImplGetClientWindow() ) 88 pChildWindow = pChildWindow->ImplGetClientWindow(); 89 90 if( pChildWindow->ImplIsAntiparallel() ) 91 pChildWindow->ImplReMirror( location ); 92 93 aSolarGuard.clear(); 94 95 // handle the case that drop is in an other vcl window than the last dragOver 96 if( pChildWindow != m_pCurrentWindow ) 97 { 98 // fire dragExit on listeners of previous window 99 fireDragExitEvent( m_pCurrentWindow ); 100 101 fireDragEnterEvent( pChildWindow, static_cast < XDropTargetDragContext * > (this), 102 dtde.DropAction, location, dtde.SourceActions, m_aDataFlavorList ); 103 } 104 105 sal_Int32 nListeners = 0; 106 107 // send drop event to the child window 108 nListeners = fireDropEvent( pChildWindow, dtde.Context, dtde.DropAction, 109 location, dtde.SourceActions, dtde.Transferable ); 110 111 // reject drop if no listeners found 112 if( nListeners == 0 ) { 113 OSL_TRACE( "rejecting drop due to missing listeners." ); 114 dtde.Context->rejectDrop(); 115 } 116 117 // this is a drop -> no further drag overs 118 m_pCurrentWindow = NULL; 119 m_aDataFlavorList.realloc( 0 ); 120 } 121 122 //================================================================================================== 123 // DNDEventDispatcher::dragEnter 124 //================================================================================================== 125 126 void SAL_CALL DNDEventDispatcher::dragEnter( const DropTargetDragEnterEvent& dtdee ) 127 throw(RuntimeException) 128 { 129 MutexGuard aImplGuard( m_aMutex ); 130 Point location( dtdee.LocationX, dtdee.LocationY ); 131 132 // find the window that is toplevel for this coordinates 133 OClearableGuard aSolarGuard( Application::GetSolarMutex() ); 134 135 // because those coordinates come from outside, they must be mirrored if RTL layout is active 136 if( Application::GetSettings().GetLayoutRTL() ) 137 m_pTopWindow->ImplMirrorFramePos( location ); 138 Window * pChildWindow = m_pTopWindow->ImplFindWindow( location ); 139 140 if( NULL == pChildWindow ) 141 pChildWindow = m_pTopWindow; 142 143 while( pChildWindow->ImplGetClientWindow() ) 144 pChildWindow = pChildWindow->ImplGetClientWindow(); 145 146 if( pChildWindow->ImplIsAntiparallel() ) 147 pChildWindow->ImplReMirror( location ); 148 149 aSolarGuard.clear(); 150 151 // assume pointer write operation to be atomic 152 m_pCurrentWindow = pChildWindow; 153 m_aDataFlavorList = dtdee.SupportedDataFlavors; 154 155 // fire dragEnter on listeners of current window 156 sal_Int32 nListeners = fireDragEnterEvent( pChildWindow, dtdee.Context, dtdee.DropAction, location, 157 dtdee.SourceActions, dtdee.SupportedDataFlavors ); 158 159 // reject drag if no listener found 160 if( nListeners == 0 ) { 161 OSL_TRACE( "rejecting drag enter due to missing listeners." ); 162 dtdee.Context->rejectDrag(); 163 } 164 165 } 166 167 //================================================================================================== 168 // DNDEventDispatcher::dragExit 169 //================================================================================================== 170 171 void SAL_CALL DNDEventDispatcher::dragExit( const DropTargetEvent& /*dte*/ ) 172 throw(RuntimeException) 173 { 174 MutexGuard aImplGuard( m_aMutex ); 175 176 fireDragExitEvent( m_pCurrentWindow ); 177 178 // reset member values 179 m_pCurrentWindow = NULL; 180 m_aDataFlavorList.realloc( 0 ); 181 } 182 183 //================================================================================================== 184 // DNDEventDispatcher::dragOver 185 //================================================================================================== 186 187 void SAL_CALL DNDEventDispatcher::dragOver( const DropTargetDragEvent& dtde ) 188 throw(RuntimeException) 189 { 190 MutexGuard aImplGuard( m_aMutex ); 191 192 Point location( dtde.LocationX, dtde.LocationY ); 193 sal_Int32 nListeners; 194 195 // find the window that is toplevel for this coordinates 196 OClearableGuard aSolarGuard( Application::GetSolarMutex() ); 197 198 // because those coordinates come from outside, they must be mirrored if RTL layout is active 199 if( Application::GetSettings().GetLayoutRTL() ) 200 m_pTopWindow->ImplMirrorFramePos( location ); 201 Window * pChildWindow = m_pTopWindow->ImplFindWindow( location ); 202 203 if( NULL == pChildWindow ) 204 pChildWindow = m_pTopWindow; 205 206 while( pChildWindow->ImplGetClientWindow() ) 207 pChildWindow = pChildWindow->ImplGetClientWindow(); 208 209 if( pChildWindow->ImplIsAntiparallel() ) 210 pChildWindow->ImplReMirror( location ); 211 212 aSolarGuard.clear(); 213 214 if( pChildWindow != m_pCurrentWindow ) 215 { 216 // fire dragExit on listeners of previous window 217 fireDragExitEvent( m_pCurrentWindow ); 218 219 // remember new window 220 m_pCurrentWindow = pChildWindow; 221 222 // fire dragEnter on listeners of current window 223 nListeners = fireDragEnterEvent( pChildWindow, dtde.Context, dtde.DropAction, location, 224 dtde.SourceActions, m_aDataFlavorList ); 225 } 226 else 227 { 228 // fire dragOver on listeners of current window 229 nListeners = fireDragOverEvent( pChildWindow, dtde.Context, dtde.DropAction, location, 230 dtde.SourceActions ); 231 } 232 233 // reject drag if no listener found 234 if( nListeners == 0 ) 235 { 236 OSL_TRACE( "rejecting drag over due to missing listeners." ); 237 dtde.Context->rejectDrag(); 238 } 239 } 240 241 //================================================================================================== 242 // DNDEventDispatcher::dropActionChanged 243 //================================================================================================== 244 245 void SAL_CALL DNDEventDispatcher::dropActionChanged( const DropTargetDragEvent& dtde ) 246 throw(RuntimeException) 247 { 248 MutexGuard aImplGuard( m_aMutex ); 249 250 Point location( dtde.LocationX, dtde.LocationY ); 251 sal_Int32 nListeners; 252 253 // find the window that is toplevel for this coordinates 254 OClearableGuard aSolarGuard( Application::GetSolarMutex() ); 255 256 // because those coordinates come from outside, they must be mirrored if RTL layout is active 257 if( Application::GetSettings().GetLayoutRTL() ) 258 m_pTopWindow->ImplMirrorFramePos( location ); 259 Window * pChildWindow = m_pTopWindow->ImplFindWindow( location ); 260 261 if( NULL == pChildWindow ) 262 pChildWindow = m_pTopWindow; 263 264 while( pChildWindow->ImplGetClientWindow() ) 265 pChildWindow = pChildWindow->ImplGetClientWindow(); 266 267 if( pChildWindow->ImplIsAntiparallel() ) 268 pChildWindow->ImplReMirror( location ); 269 270 aSolarGuard.clear(); 271 272 if( pChildWindow != m_pCurrentWindow ) 273 { 274 // fire dragExit on listeners of previous window 275 fireDragExitEvent( m_pCurrentWindow ); 276 277 // remember new window 278 m_pCurrentWindow = pChildWindow; 279 280 // fire dragEnter on listeners of current window 281 nListeners = fireDragEnterEvent( pChildWindow, dtde.Context, dtde.DropAction, location, 282 dtde.SourceActions, m_aDataFlavorList ); 283 } 284 else 285 { 286 // fire dropActionChanged on listeners of current window 287 nListeners = fireDropActionChangedEvent( pChildWindow, dtde.Context, dtde.DropAction, location, 288 dtde.SourceActions ); 289 } 290 291 // reject drag if no listener found 292 if( nListeners == 0 ) 293 { 294 OSL_TRACE( "rejecting dropActionChanged due to missing listeners." ); 295 dtde.Context->rejectDrag(); 296 } 297 } 298 299 300 //================================================================================================== 301 // DNDEventDispatcher::dragGestureRecognized 302 //================================================================================================== 303 304 void SAL_CALL DNDEventDispatcher::dragGestureRecognized( const DragGestureEvent& dge ) 305 throw(RuntimeException) 306 { MutexGuard aImplGuard( m_aMutex ); 307 308 Point origin( dge.DragOriginX, dge.DragOriginY ); 309 310 // find the window that is toplevel for this coordinates 311 OClearableGuard aSolarGuard( Application::GetSolarMutex() ); 312 313 // because those coordinates come from outside, they must be mirrored if RTL layout is active 314 if( Application::GetSettings().GetLayoutRTL() ) 315 m_pTopWindow->ImplMirrorFramePos( origin ); 316 Window * pChildWindow = m_pTopWindow->ImplFindWindow( origin ); 317 318 if( NULL == pChildWindow ) 319 pChildWindow = m_pTopWindow; 320 321 while( pChildWindow->ImplGetClientWindow() ) 322 pChildWindow = pChildWindow->ImplGetClientWindow(); 323 324 if( pChildWindow->ImplIsAntiparallel() ) 325 pChildWindow->ImplReMirror( origin ); 326 327 aSolarGuard.clear(); 328 329 fireDragGestureEvent( pChildWindow, dge.DragSource, dge.Event, origin, dge.DragAction ); 330 } 331 332 //================================================================================================== 333 // DNDEventDispatcher::disposing 334 //================================================================================================== 335 336 void SAL_CALL DNDEventDispatcher::disposing( const EventObject& ) 337 throw(RuntimeException) 338 { 339 } 340 341 //================================================================================================== 342 // DNDEventDispatcher::acceptDrag 343 //================================================================================================== 344 345 void SAL_CALL DNDEventDispatcher::acceptDrag( sal_Int8 /*dropAction*/ ) throw(RuntimeException) 346 { 347 } 348 349 //================================================================================================== 350 // DNDEventDispatcher::rejectDrag 351 //================================================================================================== 352 353 void SAL_CALL DNDEventDispatcher::rejectDrag() throw(RuntimeException) 354 { 355 } 356 357 //================================================================================================== 358 // DNDEventDispatcher::fireDragEnterEvent 359 //================================================================================================== 360 361 sal_Int32 DNDEventDispatcher::fireDragEnterEvent( Window *pWindow, 362 const Reference< XDropTargetDragContext >& xContext, const sal_Int8 nDropAction, 363 const Point& rLocation, const sal_Int8 nSourceActions, const Sequence< DataFlavor >& aFlavorList 364 ) 365 throw(RuntimeException) 366 { 367 sal_Int32 n = 0; 368 369 if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() ) 370 { 371 OClearableGuard aGuard( Application::GetSolarMutex() ); 372 373 // set an UI lock 374 pWindow->IncrementLockCount(); 375 376 // query DropTarget from window 377 Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget(); 378 379 if( xDropTarget.is() ) 380 { 381 // retrieve relative mouse position 382 Point relLoc = pWindow->ImplFrameToOutput( rLocation ); 383 aGuard.clear(); 384 385 n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDragEnterEvent( 386 xContext, nDropAction, relLoc.X(), relLoc.Y(), nSourceActions, aFlavorList ); 387 } 388 } 389 390 return n; 391 } 392 393 //================================================================================================== 394 // DNDEventDispatcher::fireDragOverEvent 395 //================================================================================================== 396 397 sal_Int32 DNDEventDispatcher::fireDragOverEvent( Window *pWindow, 398 const Reference< XDropTargetDragContext >& xContext, const sal_Int8 nDropAction, 399 const Point& rLocation, const sal_Int8 nSourceActions 400 ) 401 throw(RuntimeException) 402 { 403 sal_Int32 n = 0; 404 405 if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() ) 406 { 407 OClearableGuard aGuard( Application::GetSolarMutex() ); 408 409 // query DropTarget from window 410 Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget(); 411 412 if( xDropTarget.is() ) 413 { 414 // retrieve relative mouse position 415 Point relLoc = pWindow->ImplFrameToOutput( rLocation ); 416 aGuard.clear(); 417 418 n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDragOverEvent( 419 xContext, nDropAction, relLoc.X(), relLoc.Y(), nSourceActions ); 420 } 421 } 422 423 return n; 424 } 425 426 //================================================================================================== 427 // DNDEventDispatcher::fireDragExitEvent 428 //================================================================================================== 429 430 sal_Int32 DNDEventDispatcher::fireDragExitEvent( Window *pWindow ) throw(RuntimeException) 431 { 432 sal_Int32 n = 0; 433 434 if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() ) 435 { 436 OClearableGuard aGuard( Application::GetSolarMutex() ); 437 438 // query DropTarget from window 439 Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget(); 440 441 aGuard.clear(); 442 443 if( xDropTarget.is() ) 444 n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDragExitEvent(); 445 446 // release UI lock 447 pWindow->DecrementLockCount(); 448 } 449 450 return n; 451 } 452 453 //================================================================================================== 454 // DNDEventDispatcher::fireDropActionChangedEvent 455 //================================================================================================== 456 457 sal_Int32 DNDEventDispatcher::fireDropActionChangedEvent( Window *pWindow, 458 const Reference< XDropTargetDragContext >& xContext, const sal_Int8 nDropAction, 459 const Point& rLocation, const sal_Int8 nSourceActions 460 ) 461 throw(RuntimeException) 462 { 463 sal_Int32 n = 0; 464 465 if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() ) 466 { 467 OClearableGuard aGuard( Application::GetSolarMutex() ); 468 469 // query DropTarget from window 470 Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget(); 471 472 if( xDropTarget.is() ) 473 { 474 // retrieve relative mouse position 475 Point relLoc = pWindow->ImplFrameToOutput( rLocation ); 476 aGuard.clear(); 477 478 n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDropActionChangedEvent( 479 xContext, nDropAction, relLoc.X(), relLoc.Y(), nSourceActions ); 480 } 481 } 482 483 return n; 484 } 485 486 //================================================================================================== 487 // DNDEventDispatcher::fireDropEvent 488 //================================================================================================== 489 490 sal_Int32 DNDEventDispatcher::fireDropEvent( Window *pWindow, 491 const Reference< XDropTargetDropContext >& xContext, const sal_Int8 nDropAction, const Point& rLocation, 492 const sal_Int8 nSourceActions, const Reference< XTransferable >& xTransferable 493 ) 494 throw(RuntimeException) 495 { 496 sal_Int32 n = 0; 497 498 if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() ) 499 { 500 OClearableGuard aGuard( Application::GetSolarMutex() ); 501 502 // query DropTarget from window 503 Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget(); 504 505 // window may be destroyed in drop event handler 506 ImplDelData aDelData; 507 pWindow->ImplAddDel( &aDelData ); 508 509 if( xDropTarget.is() ) 510 { 511 // retrieve relative mouse position 512 Point relLoc = pWindow->ImplFrameToOutput( rLocation ); 513 aGuard.clear(); 514 515 n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDropEvent( 516 xContext, nDropAction, relLoc.X(), relLoc.Y(), nSourceActions, xTransferable ); 517 } 518 519 if ( !aDelData.IsDelete() ) 520 { 521 pWindow->ImplRemoveDel( &aDelData ); 522 // release UI lock 523 pWindow->DecrementLockCount(); 524 } 525 526 } 527 528 return n; 529 } 530 531 //================================================================================================== 532 // DNDEventDispatcher::fireDragGestureRecognized 533 //================================================================================================== 534 535 sal_Int32 DNDEventDispatcher::fireDragGestureEvent( Window *pWindow, 536 const Reference< XDragSource >& xSource, const Any event, 537 const Point& rOrigin, const sal_Int8 nDragAction 538 ) 539 throw(::com::sun::star::uno::RuntimeException) 540 { 541 sal_Int32 n = 0; 542 543 if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() ) 544 { 545 OClearableGuard aGuard( Application::GetSolarMutex() ); 546 547 // query DropTarget from window 548 Reference< XDragGestureRecognizer > xDragGestureRecognizer = pWindow->GetDragGestureRecognizer(); 549 550 if( xDragGestureRecognizer.is() ) 551 { 552 // retrieve relative mouse position 553 Point relLoc = pWindow->ImplFrameToOutput( rOrigin ); 554 aGuard.clear(); 555 556 n = static_cast < DNDListenerContainer * > ( xDragGestureRecognizer.get() )->fireDragGestureEvent( 557 nDragAction, relLoc.X(), relLoc.Y(), xSource, event ); 558 } 559 560 // release UI lock 561 pWindow->DecrementLockCount(); 562 } 563 564 return n; 565 } 566