LCOV - code coverage report
Current view: top level - vcl/source/window - dndevdis.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 13 175 7.4 %
Date: 2015-06-13 12:38:46 Functions: 5 22 22.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <dndevdis.hxx>
      21             : #include <dndlcon.hxx>
      22             : #include <window.h>
      23             : #include <svdata.hxx>
      24             : 
      25             : #include <osl/mutex.hxx>
      26             : #include <vcl/svapp.hxx>
      27             : #include <vcl/settings.hxx>
      28             : 
      29             : using namespace ::cppu;
      30             : using namespace ::com::sun::star::uno;
      31             : using namespace ::com::sun::star::lang;
      32             : using namespace ::com::sun::star::datatransfer;
      33             : using namespace ::com::sun::star::datatransfer::dnd;
      34             : 
      35             : // DNDEventDispatcher::DNDEventDispatcher
      36        1897 : DNDEventDispatcher::DNDEventDispatcher( vcl::Window * pTopWindow ):
      37             :     m_pTopWindow( pTopWindow ),
      38        1897 :     m_pCurrentWindow( NULL )
      39             : {
      40        1897 : }
      41             : 
      42             : // DNDEventDispatcher::~DNDEventDispatcher
      43        5679 : DNDEventDispatcher::~DNDEventDispatcher()
      44             : {
      45        1893 :     designate_currentwindow(NULL);
      46        3786 : }
      47             : 
      48           0 : vcl::Window* DNDEventDispatcher::findTopLevelWindow(Point location)
      49             : {
      50           0 :     SolarMutexGuard aSolarGuard;
      51             : 
      52             :     // find the window that is toplevel for this coordinates
      53             :     // because those coordinates come from outside, they must be mirrored if RTL layout is active
      54           0 :     if( AllSettings::GetLayoutRTL() )
      55           0 :         m_pTopWindow->ImplMirrorFramePos( location );
      56           0 :     vcl::Window * pChildWindow = m_pTopWindow->ImplFindWindow( location );
      57             : 
      58           0 :     if( NULL == pChildWindow )
      59           0 :         pChildWindow = m_pTopWindow;
      60             : 
      61           0 :     while( pChildWindow->ImplGetClientWindow() )
      62           0 :         pChildWindow = pChildWindow->ImplGetClientWindow();
      63             : 
      64           0 :     if( pChildWindow->ImplIsAntiparallel() )
      65             :     {
      66           0 :         const OutputDevice *pChildWinOutDev = pChildWindow->GetOutDev();
      67           0 :         pChildWinOutDev->ReMirror( location );
      68             :     }
      69             : 
      70           0 :     return pChildWindow;
      71             : }
      72             : 
      73           0 : IMPL_LINK(DNDEventDispatcher, WindowEventListener, VclSimpleEvent*, pEvent)
      74             : {
      75           0 :     if (pEvent && pEvent->GetId() == VCLEVENT_OBJECT_DYING)
      76             :     {
      77           0 :         designate_currentwindow(NULL);
      78             :     }
      79           0 :     return 0;
      80             : }
      81             : 
      82        1893 : void DNDEventDispatcher::designate_currentwindow(vcl::Window *pWindow)
      83             : {
      84        1893 :     if (m_pCurrentWindow)
      85           0 :         m_pCurrentWindow->RemoveEventListener(LINK(this, DNDEventDispatcher, WindowEventListener));
      86        1893 :     m_pCurrentWindow = pWindow;
      87        1893 :     if (m_pCurrentWindow)
      88           0 :         m_pCurrentWindow->AddEventListener(LINK(this, DNDEventDispatcher, WindowEventListener));
      89        1893 : }
      90             : 
      91             : // DNDEventDispatcher::drop
      92           0 : void SAL_CALL DNDEventDispatcher::drop( const DropTargetDropEvent& dtde )
      93             :     throw(RuntimeException, std::exception)
      94             : {
      95           0 :     osl::MutexGuard aImplGuard( m_aMutex );
      96             : 
      97           0 :     Point location( dtde.LocationX, dtde.LocationY );
      98             : 
      99           0 :     vcl::Window* pChildWindow = findTopLevelWindow(location);
     100             : 
     101             :     // handle the case that drop is in an other vcl window than the last dragOver
     102           0 :     if( pChildWindow != m_pCurrentWindow.get() )
     103             :     {
     104             :         // fire dragExit on listeners of previous window
     105           0 :         fireDragExitEvent( m_pCurrentWindow );
     106             : 
     107             :         fireDragEnterEvent( pChildWindow, static_cast < XDropTargetDragContext * > (this),
     108           0 :             dtde.DropAction, location, dtde.SourceActions, m_aDataFlavorList );
     109             :     }
     110             : 
     111           0 :     sal_Int32 nListeners = 0;
     112             : 
     113             :     // send drop event to the child window
     114             :     nListeners = fireDropEvent( pChildWindow, dtde.Context, dtde.DropAction,
     115           0 :         location, dtde.SourceActions, dtde.Transferable );
     116             : 
     117             :     // reject drop if no listeners found
     118           0 :     if( nListeners == 0 ) {
     119             :         OSL_TRACE( "rejecting drop due to missing listeners." );
     120           0 :         dtde.Context->rejectDrop();
     121             :     }
     122             : 
     123             :     // this is a drop -> no further drag overs
     124           0 :     designate_currentwindow(NULL);
     125           0 :     m_aDataFlavorList.realloc( 0 );
     126           0 : }
     127             : 
     128             : // DNDEventDispatcher::dragEnter
     129             : 
     130           0 : void SAL_CALL DNDEventDispatcher::dragEnter( const DropTargetDragEnterEvent& dtdee )
     131             :     throw(RuntimeException, std::exception)
     132             : {
     133           0 :     osl::MutexGuard aImplGuard( m_aMutex );
     134           0 :     Point location( dtdee.LocationX, dtdee.LocationY );
     135             : 
     136           0 :     vcl::Window * pChildWindow = findTopLevelWindow(location);
     137             : 
     138             :     // assume pointer write operation to be atomic
     139           0 :     designate_currentwindow(pChildWindow);
     140           0 :     m_aDataFlavorList = dtdee.SupportedDataFlavors;
     141             : 
     142             :     // fire dragEnter on listeners of current window
     143             :     sal_Int32 nListeners = fireDragEnterEvent( pChildWindow, dtdee.Context, dtdee.DropAction, location,
     144           0 :         dtdee.SourceActions, dtdee.SupportedDataFlavors );
     145             : 
     146             :     // reject drag if no listener found
     147           0 :     if( nListeners == 0 ) {
     148             :         OSL_TRACE( "rejecting drag enter due to missing listeners." );
     149           0 :         dtdee.Context->rejectDrag();
     150           0 :     }
     151             : 
     152           0 : }
     153             : 
     154             : // DNDEventDispatcher::dragExit
     155             : 
     156           0 : void SAL_CALL DNDEventDispatcher::dragExit( const DropTargetEvent& /*dte*/ )
     157             :     throw(RuntimeException, std::exception)
     158             : {
     159           0 :     osl::MutexGuard aImplGuard( m_aMutex );
     160             : 
     161           0 :     fireDragExitEvent( m_pCurrentWindow );
     162             : 
     163             :     // reset member values
     164           0 :     designate_currentwindow(NULL);
     165           0 :     m_aDataFlavorList.realloc( 0 );
     166           0 : }
     167             : 
     168             : // DNDEventDispatcher::dragOver
     169             : 
     170           0 : void SAL_CALL DNDEventDispatcher::dragOver( const DropTargetDragEvent& dtde )
     171             :     throw(RuntimeException, std::exception)
     172             : {
     173           0 :     osl::MutexGuard aImplGuard( m_aMutex );
     174             : 
     175           0 :     Point location( dtde.LocationX, dtde.LocationY );
     176             :     sal_Int32 nListeners;
     177             : 
     178           0 :     vcl::Window * pChildWindow = findTopLevelWindow(location);
     179             : 
     180           0 :     if( pChildWindow != m_pCurrentWindow.get() )
     181             :     {
     182             :         // fire dragExit on listeners of previous window
     183           0 :         fireDragExitEvent( m_pCurrentWindow );
     184             : 
     185             :         // remember new window
     186           0 :         designate_currentwindow(pChildWindow);
     187             : 
     188             :         // fire dragEnter on listeners of current window
     189             :         nListeners = fireDragEnterEvent( pChildWindow, dtde.Context, dtde.DropAction, location,
     190           0 :             dtde.SourceActions, m_aDataFlavorList );
     191             :     }
     192             :     else
     193             :     {
     194             :         // fire dragOver on listeners of current window
     195             :         nListeners = fireDragOverEvent( pChildWindow, dtde.Context, dtde.DropAction, location,
     196           0 :             dtde.SourceActions );
     197             :     }
     198             : 
     199             :     // reject drag if no listener found
     200           0 :     if( nListeners == 0 )
     201             :     {
     202             :         OSL_TRACE( "rejecting drag over due to missing listeners." );
     203           0 :         dtde.Context->rejectDrag();
     204           0 :     }
     205           0 : }
     206             : 
     207             : // DNDEventDispatcher::dropActionChanged
     208           0 : void SAL_CALL DNDEventDispatcher::dropActionChanged( const DropTargetDragEvent& dtde )
     209             :     throw(RuntimeException, std::exception)
     210             : {
     211           0 :     osl::MutexGuard aImplGuard( m_aMutex );
     212             : 
     213           0 :     Point location( dtde.LocationX, dtde.LocationY );
     214             :     sal_Int32 nListeners;
     215             : 
     216           0 :     vcl::Window* pChildWindow = findTopLevelWindow(location);
     217             : 
     218           0 :     if( pChildWindow != m_pCurrentWindow.get() )
     219             :     {
     220             :         // fire dragExit on listeners of previous window
     221           0 :         fireDragExitEvent( m_pCurrentWindow );
     222             : 
     223             :         // remember new window
     224           0 :         designate_currentwindow(pChildWindow);
     225             : 
     226             :         // fire dragEnter on listeners of current window
     227             :         nListeners = fireDragEnterEvent( pChildWindow, dtde.Context, dtde.DropAction, location,
     228           0 :             dtde.SourceActions, m_aDataFlavorList );
     229             :     }
     230             :     else
     231             :     {
     232             :         // fire dropActionChanged on listeners of current window
     233             :         nListeners = fireDropActionChangedEvent( pChildWindow, dtde.Context, dtde.DropAction, location,
     234           0 :             dtde.SourceActions );
     235             :     }
     236             : 
     237             :     // reject drag if no listener found
     238           0 :     if( nListeners == 0 )
     239             :     {
     240             :         OSL_TRACE( "rejecting dropActionChanged due to missing listeners." );
     241           0 :         dtde.Context->rejectDrag();
     242           0 :     }
     243           0 : }
     244             : 
     245             : // DNDEventDispatcher::dragGestureRecognized
     246             : 
     247           0 : void SAL_CALL DNDEventDispatcher::dragGestureRecognized( const DragGestureEvent& dge )
     248             :     throw(RuntimeException, std::exception)
     249             : {
     250           0 :     osl::MutexGuard aImplGuard( m_aMutex );
     251             : 
     252           0 :     Point origin( dge.DragOriginX, dge.DragOriginY );
     253             : 
     254           0 :     vcl::Window* pChildWindow = findTopLevelWindow(origin);
     255             : 
     256           0 :     fireDragGestureEvent( pChildWindow, dge.DragSource, dge.Event, origin, dge.DragAction );
     257           0 : }
     258             : 
     259             : // DNDEventDispatcher::disposing
     260             : 
     261        1250 : void SAL_CALL DNDEventDispatcher::disposing( const EventObject& )
     262             :     throw(RuntimeException, std::exception)
     263             : {
     264        1250 : }
     265             : 
     266             : // DNDEventDispatcher::acceptDrag
     267             : 
     268           0 : void SAL_CALL DNDEventDispatcher::acceptDrag( sal_Int8 /*dropAction*/ ) throw(RuntimeException, std::exception)
     269             : {
     270           0 : }
     271             : 
     272             : // DNDEventDispatcher::rejectDrag
     273             : 
     274           0 : void SAL_CALL DNDEventDispatcher::rejectDrag() throw(RuntimeException, std::exception)
     275             : {
     276           0 : }
     277             : 
     278             : // DNDEventDispatcher::fireDragEnterEvent
     279             : 
     280           0 : sal_Int32 DNDEventDispatcher::fireDragEnterEvent( vcl::Window *pWindow,
     281             :     const Reference< XDropTargetDragContext >& xContext, const sal_Int8 nDropAction,
     282             :     const Point& rLocation, const sal_Int8 nSourceActions, const Sequence< DataFlavor >& aFlavorList
     283             : )
     284             :     throw(RuntimeException)
     285             : {
     286           0 :     sal_Int32 n = 0;
     287             : 
     288           0 :     if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
     289             :     {
     290           0 :         SolarMutexClearableGuard aSolarGuard;
     291             : 
     292             :         // set an UI lock
     293           0 :         pWindow->IncrementLockCount();
     294             : 
     295             :         // query DropTarget from window
     296           0 :         Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();
     297             : 
     298           0 :         if( xDropTarget.is() )
     299             :         {
     300             :             // retrieve relative mouse position
     301           0 :             Point relLoc = pWindow->ImplFrameToOutput( rLocation );
     302           0 :             aSolarGuard.clear();
     303             : 
     304           0 :             n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDragEnterEvent(
     305           0 :                 xContext, nDropAction, relLoc.X(), relLoc.Y(), nSourceActions, aFlavorList );
     306           0 :         }
     307             :     }
     308             : 
     309           0 :     return n;
     310             : }
     311             : 
     312             : // DNDEventDispatcher::fireDragOverEvent
     313             : 
     314           0 : sal_Int32 DNDEventDispatcher::fireDragOverEvent( vcl::Window *pWindow,
     315             :     const Reference< XDropTargetDragContext >& xContext, const sal_Int8 nDropAction,
     316             :     const Point& rLocation, const sal_Int8 nSourceActions
     317             : )
     318             :     throw(RuntimeException)
     319             : {
     320           0 :     sal_Int32 n = 0;
     321             : 
     322           0 :     if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
     323             :     {
     324           0 :         SolarMutexClearableGuard aSolarGuard;
     325             : 
     326             :         // query DropTarget from window
     327           0 :         Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();
     328             : 
     329           0 :         if( xDropTarget.is() )
     330             :         {
     331             :             // retrieve relative mouse position
     332           0 :             Point relLoc = pWindow->ImplFrameToOutput( rLocation );
     333           0 :             aSolarGuard.clear();
     334             : 
     335           0 :             n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDragOverEvent(
     336           0 :                 xContext, nDropAction, relLoc.X(), relLoc.Y(), nSourceActions );
     337           0 :         }
     338             :     }
     339             : 
     340           0 :     return n;
     341             : }
     342             : 
     343             : // DNDEventDispatcher::fireDragExitEvent
     344             : 
     345           0 : sal_Int32 DNDEventDispatcher::fireDragExitEvent( vcl::Window *pWindow ) throw(RuntimeException)
     346             : {
     347           0 :     sal_Int32 n = 0;
     348             : 
     349           0 :     if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
     350             :     {
     351           0 :         SolarMutexClearableGuard aGuard;
     352             : 
     353             :         // query DropTarget from window
     354           0 :         Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();
     355             : 
     356           0 :         aGuard.clear();
     357             : 
     358           0 :         if( xDropTarget.is() )
     359           0 :             n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDragExitEvent();
     360             : 
     361             :         // release UI lock
     362           0 :         pWindow->DecrementLockCount();
     363             :     }
     364             : 
     365           0 :     return n;
     366             : }
     367             : 
     368             : // DNDEventDispatcher::fireDropActionChangedEvent
     369             : 
     370           0 : sal_Int32 DNDEventDispatcher::fireDropActionChangedEvent( vcl::Window *pWindow,
     371             :     const Reference< XDropTargetDragContext >& xContext, const sal_Int8 nDropAction,
     372             :     const Point& rLocation, const sal_Int8 nSourceActions
     373             : )
     374             :     throw(RuntimeException)
     375             : {
     376           0 :     sal_Int32 n = 0;
     377             : 
     378           0 :     if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
     379             :     {
     380           0 :         SolarMutexClearableGuard aGuard;
     381             : 
     382             :         // query DropTarget from window
     383           0 :         Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();
     384             : 
     385           0 :         if( xDropTarget.is() )
     386             :         {
     387             :             // retrieve relative mouse position
     388           0 :             Point relLoc = pWindow->ImplFrameToOutput( rLocation );
     389           0 :             aGuard.clear();
     390             : 
     391           0 :             n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDropActionChangedEvent(
     392           0 :                 xContext, nDropAction, relLoc.X(), relLoc.Y(), nSourceActions );
     393           0 :         }
     394             :     }
     395             : 
     396           0 :     return n;
     397             : }
     398             : 
     399             : // DNDEventDispatcher::fireDropEvent
     400             : 
     401           0 : sal_Int32 DNDEventDispatcher::fireDropEvent( vcl::Window *pWindow,
     402             :     const Reference< XDropTargetDropContext >& xContext, const sal_Int8 nDropAction, const Point& rLocation,
     403             :     const sal_Int8 nSourceActions, const Reference< XTransferable >& xTransferable
     404             : )
     405             :     throw(RuntimeException)
     406             : {
     407           0 :     sal_Int32 n = 0;
     408             : 
     409           0 :     if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
     410             :     {
     411           0 :         SolarMutexClearableGuard aGuard;
     412             : 
     413             :         // query DropTarget from window
     414           0 :         Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();
     415             : 
     416             :         // window may be destroyed in drop event handler
     417           0 :         ImplDelData         aDelData;
     418           0 :         pWindow->ImplAddDel( &aDelData );
     419             : 
     420           0 :         if( xDropTarget.is() )
     421             :         {
     422             :             // retrieve relative mouse position
     423           0 :             Point relLoc = pWindow->ImplFrameToOutput( rLocation );
     424           0 :             aGuard.clear();
     425             : 
     426           0 :             n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDropEvent(
     427           0 :                 xContext, nDropAction, relLoc.X(), relLoc.Y(), nSourceActions, xTransferable );
     428             :         }
     429             : 
     430           0 :         if ( !aDelData.IsDead() )
     431             :         {
     432           0 :             pWindow->ImplRemoveDel( &aDelData );
     433             :             // release UI lock
     434           0 :             pWindow->DecrementLockCount();
     435           0 :         }
     436             : 
     437             :     }
     438             : 
     439           0 :     return n;
     440             : }
     441             : 
     442             : // DNDEventDispatcher::fireDragGestureRecognized
     443             : 
     444           0 : sal_Int32 DNDEventDispatcher::fireDragGestureEvent( vcl::Window *pWindow,
     445             :     const Reference< XDragSource >& xSource, const Any& event,
     446             :     const Point& rOrigin, const sal_Int8 nDragAction
     447             : )
     448             :     throw(::com::sun::star::uno::RuntimeException)
     449             : {
     450           0 :     sal_Int32 n = 0;
     451             : 
     452           0 :     if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
     453             :     {
     454           0 :         SolarMutexClearableGuard aGuard;
     455             : 
     456             :         // query DropTarget from window
     457           0 :         Reference< XDragGestureRecognizer > xDragGestureRecognizer = pWindow->GetDragGestureRecognizer();
     458             : 
     459           0 :         if( xDragGestureRecognizer.is() )
     460             :         {
     461             :             // retrieve relative mouse position
     462           0 :             Point relLoc = pWindow->ImplFrameToOutput( rOrigin );
     463           0 :             aGuard.clear();
     464             : 
     465           0 :             n = static_cast < DNDListenerContainer * > ( xDragGestureRecognizer.get() )->fireDragGestureEvent(
     466           0 :                 nDragAction, relLoc.X(), relLoc.Y(), xSource, event );
     467             :         }
     468             : 
     469             :         // release UI lock
     470           0 :         pWindow->DecrementLockCount();
     471             :     }
     472             : 
     473           0 :     return n;
     474             : }
     475             : 
     476             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11