update credits
[LibreOffice.git] / vcl / source / window / dndevdis.cxx
blob74101c60744723d0b3e795b8ef2034e79d7f7220
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <dndevdis.hxx>
22 #include <dndlcon.hxx>
23 #include <window.h>
24 #include <svdata.hxx>
26 #include <osl/mutex.hxx>
27 #include <vcl/svapp.hxx>
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;
35 //==================================================================================================
36 // DNDEventDispatcher::DNDEventDispatcher
37 //==================================================================================================
39 DNDEventDispatcher::DNDEventDispatcher( Window * pTopWindow ):
40 m_pTopWindow( pTopWindow ),
41 m_pCurrentWindow( NULL )
45 //==================================================================================================
46 // DNDEventDispatcher::~DNDEventDispatcher
47 //==================================================================================================
49 DNDEventDispatcher::~DNDEventDispatcher()
53 Window* DNDEventDispatcher::findTopLevelWindow(Point location)
55 SolarMutexGuard aSolarGuard;
57 // find the window that is toplevel for this coordinates
58 // because those coordinates come from outside, they must be mirrored if RTL layout is active
59 if( Application::GetSettings().GetLayoutRTL() )
60 m_pTopWindow->ImplMirrorFramePos( location );
61 Window * pChildWindow = m_pTopWindow->ImplFindWindow( location );
63 if( NULL == pChildWindow )
64 pChildWindow = m_pTopWindow;
66 while( pChildWindow->ImplGetClientWindow() )
67 pChildWindow = pChildWindow->ImplGetClientWindow();
69 if( pChildWindow->ImplIsAntiparallel() )
70 pChildWindow->ImplReMirror( location );
72 return pChildWindow;
75 //==================================================================================================
76 // DNDEventDispatcher::drop
77 //==================================================================================================
79 void SAL_CALL DNDEventDispatcher::drop( const DropTargetDropEvent& dtde )
80 throw(RuntimeException)
82 osl::MutexGuard aImplGuard( m_aMutex );
84 Point location( dtde.LocationX, dtde.LocationY );
86 Window* pChildWindow = findTopLevelWindow(location);
88 // handle the case that drop is in an other vcl window than the last dragOver
89 if( pChildWindow != m_pCurrentWindow )
91 // fire dragExit on listeners of previous window
92 fireDragExitEvent( m_pCurrentWindow );
94 fireDragEnterEvent( pChildWindow, static_cast < XDropTargetDragContext * > (this),
95 dtde.DropAction, location, dtde.SourceActions, m_aDataFlavorList );
98 sal_Int32 nListeners = 0;
100 // send drop event to the child window
101 nListeners = fireDropEvent( pChildWindow, dtde.Context, dtde.DropAction,
102 location, dtde.SourceActions, dtde.Transferable );
104 // reject drop if no listeners found
105 if( nListeners == 0 ) {
106 OSL_TRACE( "rejecting drop due to missing listeners." );
107 dtde.Context->rejectDrop();
110 // this is a drop -> no further drag overs
111 m_pCurrentWindow = NULL;
112 m_aDataFlavorList.realloc( 0 );
115 //==================================================================================================
116 // DNDEventDispatcher::dragEnter
117 //==================================================================================================
119 void SAL_CALL DNDEventDispatcher::dragEnter( const DropTargetDragEnterEvent& dtdee )
120 throw(RuntimeException)
122 osl::MutexGuard aImplGuard( m_aMutex );
123 Point location( dtdee.LocationX, dtdee.LocationY );
125 Window * pChildWindow = findTopLevelWindow(location);
127 // assume pointer write operation to be atomic
128 m_pCurrentWindow = pChildWindow;
129 m_aDataFlavorList = dtdee.SupportedDataFlavors;
131 // fire dragEnter on listeners of current window
132 sal_Int32 nListeners = fireDragEnterEvent( pChildWindow, dtdee.Context, dtdee.DropAction, location,
133 dtdee.SourceActions, dtdee.SupportedDataFlavors );
135 // reject drag if no listener found
136 if( nListeners == 0 ) {
137 OSL_TRACE( "rejecting drag enter due to missing listeners." );
138 dtdee.Context->rejectDrag();
143 //==================================================================================================
144 // DNDEventDispatcher::dragExit
145 //==================================================================================================
147 void SAL_CALL DNDEventDispatcher::dragExit( const DropTargetEvent& /*dte*/ )
148 throw(RuntimeException)
150 osl::MutexGuard aImplGuard( m_aMutex );
152 fireDragExitEvent( m_pCurrentWindow );
154 // reset member values
155 m_pCurrentWindow = NULL;
156 m_aDataFlavorList.realloc( 0 );
159 //==================================================================================================
160 // DNDEventDispatcher::dragOver
161 //==================================================================================================
163 void SAL_CALL DNDEventDispatcher::dragOver( const DropTargetDragEvent& dtde )
164 throw(RuntimeException)
166 osl::MutexGuard aImplGuard( m_aMutex );
168 Point location( dtde.LocationX, dtde.LocationY );
169 sal_Int32 nListeners;
171 Window * pChildWindow = findTopLevelWindow(location);
173 if( pChildWindow != m_pCurrentWindow )
175 // fire dragExit on listeners of previous window
176 fireDragExitEvent( m_pCurrentWindow );
178 // remember new window
179 m_pCurrentWindow = pChildWindow;
181 // fire dragEnter on listeners of current window
182 nListeners = fireDragEnterEvent( pChildWindow, dtde.Context, dtde.DropAction, location,
183 dtde.SourceActions, m_aDataFlavorList );
185 else
187 // fire dragOver on listeners of current window
188 nListeners = fireDragOverEvent( pChildWindow, dtde.Context, dtde.DropAction, location,
189 dtde.SourceActions );
192 // reject drag if no listener found
193 if( nListeners == 0 )
195 OSL_TRACE( "rejecting drag over due to missing listeners." );
196 dtde.Context->rejectDrag();
200 //==================================================================================================
201 // DNDEventDispatcher::dropActionChanged
202 //==================================================================================================
204 void SAL_CALL DNDEventDispatcher::dropActionChanged( const DropTargetDragEvent& dtde )
205 throw(RuntimeException)
207 osl::MutexGuard aImplGuard( m_aMutex );
209 Point location( dtde.LocationX, dtde.LocationY );
210 sal_Int32 nListeners;
212 Window* pChildWindow = findTopLevelWindow(location);
214 if( pChildWindow != m_pCurrentWindow )
216 // fire dragExit on listeners of previous window
217 fireDragExitEvent( m_pCurrentWindow );
219 // remember new window
220 m_pCurrentWindow = pChildWindow;
222 // fire dragEnter on listeners of current window
223 nListeners = fireDragEnterEvent( pChildWindow, dtde.Context, dtde.DropAction, location,
224 dtde.SourceActions, m_aDataFlavorList );
226 else
228 // fire dropActionChanged on listeners of current window
229 nListeners = fireDropActionChangedEvent( pChildWindow, dtde.Context, dtde.DropAction, location,
230 dtde.SourceActions );
233 // reject drag if no listener found
234 if( nListeners == 0 )
236 OSL_TRACE( "rejecting dropActionChanged due to missing listeners." );
237 dtde.Context->rejectDrag();
242 //==================================================================================================
243 // DNDEventDispatcher::dragGestureRecognized
244 //==================================================================================================
246 void SAL_CALL DNDEventDispatcher::dragGestureRecognized( const DragGestureEvent& dge )
247 throw(RuntimeException)
249 osl::MutexGuard aImplGuard( m_aMutex );
251 Point origin( dge.DragOriginX, dge.DragOriginY );
253 Window* pChildWindow = findTopLevelWindow(origin);
255 fireDragGestureEvent( pChildWindow, dge.DragSource, dge.Event, origin, dge.DragAction );
258 //==================================================================================================
259 // DNDEventDispatcher::disposing
260 //==================================================================================================
262 void SAL_CALL DNDEventDispatcher::disposing( const EventObject& )
263 throw(RuntimeException)
267 //==================================================================================================
268 // DNDEventDispatcher::acceptDrag
269 //==================================================================================================
271 void SAL_CALL DNDEventDispatcher::acceptDrag( sal_Int8 /*dropAction*/ ) throw(RuntimeException)
275 //==================================================================================================
276 // DNDEventDispatcher::rejectDrag
277 //==================================================================================================
279 void SAL_CALL DNDEventDispatcher::rejectDrag() throw(RuntimeException)
283 //==================================================================================================
284 // DNDEventDispatcher::fireDragEnterEvent
285 //==================================================================================================
287 sal_Int32 DNDEventDispatcher::fireDragEnterEvent( Window *pWindow,
288 const Reference< XDropTargetDragContext >& xContext, const sal_Int8 nDropAction,
289 const Point& rLocation, const sal_Int8 nSourceActions, const Sequence< DataFlavor >& aFlavorList
291 throw(RuntimeException)
293 sal_Int32 n = 0;
295 if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
297 SolarMutexClearableGuard aSolarGuard;
299 // set an UI lock
300 pWindow->IncrementLockCount();
302 // query DropTarget from window
303 Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();
305 if( xDropTarget.is() )
307 // retrieve relative mouse position
308 Point relLoc = pWindow->ImplFrameToOutput( rLocation );
309 aSolarGuard.clear();
311 n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDragEnterEvent(
312 xContext, nDropAction, relLoc.X(), relLoc.Y(), nSourceActions, aFlavorList );
316 return n;
319 //==================================================================================================
320 // DNDEventDispatcher::fireDragOverEvent
321 //==================================================================================================
323 sal_Int32 DNDEventDispatcher::fireDragOverEvent( Window *pWindow,
324 const Reference< XDropTargetDragContext >& xContext, const sal_Int8 nDropAction,
325 const Point& rLocation, const sal_Int8 nSourceActions
327 throw(RuntimeException)
329 sal_Int32 n = 0;
331 if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
333 SolarMutexClearableGuard aSolarGuard;
335 // query DropTarget from window
336 Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();
338 if( xDropTarget.is() )
340 // retrieve relative mouse position
341 Point relLoc = pWindow->ImplFrameToOutput( rLocation );
342 aSolarGuard.clear();
344 n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDragOverEvent(
345 xContext, nDropAction, relLoc.X(), relLoc.Y(), nSourceActions );
349 return n;
352 //==================================================================================================
353 // DNDEventDispatcher::fireDragExitEvent
354 //==================================================================================================
356 sal_Int32 DNDEventDispatcher::fireDragExitEvent( Window *pWindow ) throw(RuntimeException)
358 sal_Int32 n = 0;
360 if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
362 SolarMutexClearableGuard aGuard;
364 // query DropTarget from window
365 Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();
367 aGuard.clear();
369 if( xDropTarget.is() )
370 n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDragExitEvent();
372 // release UI lock
373 pWindow->DecrementLockCount();
376 return n;
379 //==================================================================================================
380 // DNDEventDispatcher::fireDropActionChangedEvent
381 //==================================================================================================
383 sal_Int32 DNDEventDispatcher::fireDropActionChangedEvent( Window *pWindow,
384 const Reference< XDropTargetDragContext >& xContext, const sal_Int8 nDropAction,
385 const Point& rLocation, const sal_Int8 nSourceActions
387 throw(RuntimeException)
389 sal_Int32 n = 0;
391 if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
393 SolarMutexClearableGuard aGuard;
395 // query DropTarget from window
396 Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();
398 if( xDropTarget.is() )
400 // retrieve relative mouse position
401 Point relLoc = pWindow->ImplFrameToOutput( rLocation );
402 aGuard.clear();
404 n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDropActionChangedEvent(
405 xContext, nDropAction, relLoc.X(), relLoc.Y(), nSourceActions );
409 return n;
412 //==================================================================================================
413 // DNDEventDispatcher::fireDropEvent
414 //==================================================================================================
416 sal_Int32 DNDEventDispatcher::fireDropEvent( Window *pWindow,
417 const Reference< XDropTargetDropContext >& xContext, const sal_Int8 nDropAction, const Point& rLocation,
418 const sal_Int8 nSourceActions, const Reference< XTransferable >& xTransferable
420 throw(RuntimeException)
422 sal_Int32 n = 0;
424 if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
426 SolarMutexClearableGuard aGuard;
428 // query DropTarget from window
429 Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();
431 // window may be destroyed in drop event handler
432 ImplDelData aDelData;
433 pWindow->ImplAddDel( &aDelData );
435 if( xDropTarget.is() )
437 // retrieve relative mouse position
438 Point relLoc = pWindow->ImplFrameToOutput( rLocation );
439 aGuard.clear();
441 n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDropEvent(
442 xContext, nDropAction, relLoc.X(), relLoc.Y(), nSourceActions, xTransferable );
445 if ( !aDelData.IsDead() )
447 pWindow->ImplRemoveDel( &aDelData );
448 // release UI lock
449 pWindow->DecrementLockCount();
454 return n;
457 //==================================================================================================
458 // DNDEventDispatcher::fireDragGestureRecognized
459 //==================================================================================================
461 sal_Int32 DNDEventDispatcher::fireDragGestureEvent( Window *pWindow,
462 const Reference< XDragSource >& xSource, const Any event,
463 const Point& rOrigin, const sal_Int8 nDragAction
465 throw(::com::sun::star::uno::RuntimeException)
467 sal_Int32 n = 0;
469 if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
471 SolarMutexClearableGuard aGuard;
473 // query DropTarget from window
474 Reference< XDragGestureRecognizer > xDragGestureRecognizer = pWindow->GetDragGestureRecognizer();
476 if( xDragGestureRecognizer.is() )
478 // retrieve relative mouse position
479 Point relLoc = pWindow->ImplFrameToOutput( rOrigin );
480 aGuard.clear();
482 n = static_cast < DNDListenerContainer * > ( xDragGestureRecognizer.get() )->fireDragGestureEvent(
483 nDragAction, relLoc.X(), relLoc.Y(), xSource, event );
486 // release UI lock
487 pWindow->DecrementLockCount();
490 return n;
493 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */