update credits
[LibreOffice.git] / vcl / source / window / dndevdis.cxx
blob94d6ae75b1dd408757fa31105f8beeaf8820f35b
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 .
20 #include <dndevdis.hxx>
21 #include <dndlcon.hxx>
22 #include <window.h>
23 #include <svdata.hxx>
25 #include <osl/mutex.hxx>
26 #include <vcl/svapp.hxx>
27 #include <vcl/settings.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 // DNDEventDispatcher::DNDEventDispatcher
36 DNDEventDispatcher::DNDEventDispatcher( vcl::Window * pTopWindow ):
37 m_pTopWindow( pTopWindow ),
38 m_pCurrentWindow( NULL )
42 // DNDEventDispatcher::~DNDEventDispatcher
43 DNDEventDispatcher::~DNDEventDispatcher()
45 designate_currentwindow(NULL);
48 vcl::Window* DNDEventDispatcher::findTopLevelWindow(Point location)
50 SolarMutexGuard aSolarGuard;
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 if( AllSettings::GetLayoutRTL() )
55 m_pTopWindow->ImplMirrorFramePos( location );
56 vcl::Window * pChildWindow = m_pTopWindow->ImplFindWindow( location );
58 if( NULL == pChildWindow )
59 pChildWindow = m_pTopWindow;
61 while( pChildWindow->ImplGetClientWindow() )
62 pChildWindow = pChildWindow->ImplGetClientWindow();
64 if( pChildWindow->ImplIsAntiparallel() )
66 const OutputDevice *pChildWinOutDev = pChildWindow->GetOutDev();
67 pChildWinOutDev->ReMirror( location );
70 return pChildWindow;
73 IMPL_LINK(DNDEventDispatcher, WindowEventListener, VclSimpleEvent*, pEvent)
75 if (pEvent && pEvent->GetId() == VCLEVENT_OBJECT_DYING)
77 designate_currentwindow(NULL);
79 return 0;
82 void DNDEventDispatcher::designate_currentwindow(vcl::Window *pWindow)
84 if (m_pCurrentWindow)
85 m_pCurrentWindow->RemoveEventListener(LINK(this, DNDEventDispatcher, WindowEventListener));
86 m_pCurrentWindow = pWindow;
87 if (m_pCurrentWindow)
88 m_pCurrentWindow->AddEventListener(LINK(this, DNDEventDispatcher, WindowEventListener));
91 // DNDEventDispatcher::drop
92 void SAL_CALL DNDEventDispatcher::drop( const DropTargetDropEvent& dtde )
93 throw(RuntimeException, std::exception)
95 osl::MutexGuard aImplGuard( m_aMutex );
97 Point location( dtde.LocationX, dtde.LocationY );
99 vcl::Window* pChildWindow = findTopLevelWindow(location);
101 // handle the case that drop is in an other vcl window than the last dragOver
102 if( pChildWindow != m_pCurrentWindow.get() )
104 // fire dragExit on listeners of previous window
105 fireDragExitEvent( m_pCurrentWindow );
107 fireDragEnterEvent( pChildWindow, static_cast < XDropTargetDragContext * > (this),
108 dtde.DropAction, location, dtde.SourceActions, m_aDataFlavorList );
111 sal_Int32 nListeners = 0;
113 // send drop event to the child window
114 nListeners = fireDropEvent( pChildWindow, dtde.Context, dtde.DropAction,
115 location, dtde.SourceActions, dtde.Transferable );
117 // reject drop if no listeners found
118 if( nListeners == 0 ) {
119 OSL_TRACE( "rejecting drop due to missing listeners." );
120 dtde.Context->rejectDrop();
123 // this is a drop -> no further drag overs
124 designate_currentwindow(NULL);
125 m_aDataFlavorList.realloc( 0 );
128 // DNDEventDispatcher::dragEnter
130 void SAL_CALL DNDEventDispatcher::dragEnter( const DropTargetDragEnterEvent& dtdee )
131 throw(RuntimeException, std::exception)
133 osl::MutexGuard aImplGuard( m_aMutex );
134 Point location( dtdee.LocationX, dtdee.LocationY );
136 vcl::Window * pChildWindow = findTopLevelWindow(location);
138 // assume pointer write operation to be atomic
139 designate_currentwindow(pChildWindow);
140 m_aDataFlavorList = dtdee.SupportedDataFlavors;
142 // fire dragEnter on listeners of current window
143 sal_Int32 nListeners = fireDragEnterEvent( pChildWindow, dtdee.Context, dtdee.DropAction, location,
144 dtdee.SourceActions, dtdee.SupportedDataFlavors );
146 // reject drag if no listener found
147 if( nListeners == 0 ) {
148 OSL_TRACE( "rejecting drag enter due to missing listeners." );
149 dtdee.Context->rejectDrag();
154 // DNDEventDispatcher::dragExit
156 void SAL_CALL DNDEventDispatcher::dragExit( const DropTargetEvent& /*dte*/ )
157 throw(RuntimeException, std::exception)
159 osl::MutexGuard aImplGuard( m_aMutex );
161 fireDragExitEvent( m_pCurrentWindow );
163 // reset member values
164 designate_currentwindow(NULL);
165 m_aDataFlavorList.realloc( 0 );
168 // DNDEventDispatcher::dragOver
170 void SAL_CALL DNDEventDispatcher::dragOver( const DropTargetDragEvent& dtde )
171 throw(RuntimeException, std::exception)
173 osl::MutexGuard aImplGuard( m_aMutex );
175 Point location( dtde.LocationX, dtde.LocationY );
176 sal_Int32 nListeners;
178 vcl::Window * pChildWindow = findTopLevelWindow(location);
180 if( pChildWindow != m_pCurrentWindow.get() )
182 // fire dragExit on listeners of previous window
183 fireDragExitEvent( m_pCurrentWindow );
185 // remember new window
186 designate_currentwindow(pChildWindow);
188 // fire dragEnter on listeners of current window
189 nListeners = fireDragEnterEvent( pChildWindow, dtde.Context, dtde.DropAction, location,
190 dtde.SourceActions, m_aDataFlavorList );
192 else
194 // fire dragOver on listeners of current window
195 nListeners = fireDragOverEvent( pChildWindow, dtde.Context, dtde.DropAction, location,
196 dtde.SourceActions );
199 // reject drag if no listener found
200 if( nListeners == 0 )
202 OSL_TRACE( "rejecting drag over due to missing listeners." );
203 dtde.Context->rejectDrag();
207 // DNDEventDispatcher::dropActionChanged
208 void SAL_CALL DNDEventDispatcher::dropActionChanged( const DropTargetDragEvent& dtde )
209 throw(RuntimeException, std::exception)
211 osl::MutexGuard aImplGuard( m_aMutex );
213 Point location( dtde.LocationX, dtde.LocationY );
214 sal_Int32 nListeners;
216 vcl::Window* pChildWindow = findTopLevelWindow(location);
218 if( pChildWindow != m_pCurrentWindow.get() )
220 // fire dragExit on listeners of previous window
221 fireDragExitEvent( m_pCurrentWindow );
223 // remember new window
224 designate_currentwindow(pChildWindow);
226 // fire dragEnter on listeners of current window
227 nListeners = fireDragEnterEvent( pChildWindow, dtde.Context, dtde.DropAction, location,
228 dtde.SourceActions, m_aDataFlavorList );
230 else
232 // fire dropActionChanged on listeners of current window
233 nListeners = fireDropActionChangedEvent( pChildWindow, dtde.Context, dtde.DropAction, location,
234 dtde.SourceActions );
237 // reject drag if no listener found
238 if( nListeners == 0 )
240 OSL_TRACE( "rejecting dropActionChanged due to missing listeners." );
241 dtde.Context->rejectDrag();
245 // DNDEventDispatcher::dragGestureRecognized
247 void SAL_CALL DNDEventDispatcher::dragGestureRecognized( const DragGestureEvent& dge )
248 throw(RuntimeException, std::exception)
250 osl::MutexGuard aImplGuard( m_aMutex );
252 Point origin( dge.DragOriginX, dge.DragOriginY );
254 vcl::Window* pChildWindow = findTopLevelWindow(origin);
256 fireDragGestureEvent( pChildWindow, dge.DragSource, dge.Event, origin, dge.DragAction );
259 // DNDEventDispatcher::disposing
261 void SAL_CALL DNDEventDispatcher::disposing( const EventObject& )
262 throw(RuntimeException, std::exception)
266 // DNDEventDispatcher::acceptDrag
268 void SAL_CALL DNDEventDispatcher::acceptDrag( sal_Int8 /*dropAction*/ ) throw(RuntimeException, std::exception)
272 // DNDEventDispatcher::rejectDrag
274 void SAL_CALL DNDEventDispatcher::rejectDrag() throw(RuntimeException, std::exception)
278 // DNDEventDispatcher::fireDragEnterEvent
280 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
284 throw(RuntimeException)
286 sal_Int32 n = 0;
288 if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
290 SolarMutexClearableGuard aSolarGuard;
292 // set an UI lock
293 pWindow->IncrementLockCount();
295 // query DropTarget from window
296 Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();
298 if( xDropTarget.is() )
300 // retrieve relative mouse position
301 Point relLoc = pWindow->ImplFrameToOutput( rLocation );
302 aSolarGuard.clear();
304 n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDragEnterEvent(
305 xContext, nDropAction, relLoc.X(), relLoc.Y(), nSourceActions, aFlavorList );
309 return n;
312 // DNDEventDispatcher::fireDragOverEvent
314 sal_Int32 DNDEventDispatcher::fireDragOverEvent( vcl::Window *pWindow,
315 const Reference< XDropTargetDragContext >& xContext, const sal_Int8 nDropAction,
316 const Point& rLocation, const sal_Int8 nSourceActions
318 throw(RuntimeException)
320 sal_Int32 n = 0;
322 if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
324 SolarMutexClearableGuard aSolarGuard;
326 // query DropTarget from window
327 Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();
329 if( xDropTarget.is() )
331 // retrieve relative mouse position
332 Point relLoc = pWindow->ImplFrameToOutput( rLocation );
333 aSolarGuard.clear();
335 n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDragOverEvent(
336 xContext, nDropAction, relLoc.X(), relLoc.Y(), nSourceActions );
340 return n;
343 // DNDEventDispatcher::fireDragExitEvent
345 sal_Int32 DNDEventDispatcher::fireDragExitEvent( vcl::Window *pWindow ) throw(RuntimeException)
347 sal_Int32 n = 0;
349 if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
351 SolarMutexClearableGuard aGuard;
353 // query DropTarget from window
354 Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();
356 aGuard.clear();
358 if( xDropTarget.is() )
359 n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDragExitEvent();
361 // release UI lock
362 pWindow->DecrementLockCount();
365 return n;
368 // DNDEventDispatcher::fireDropActionChangedEvent
370 sal_Int32 DNDEventDispatcher::fireDropActionChangedEvent( vcl::Window *pWindow,
371 const Reference< XDropTargetDragContext >& xContext, const sal_Int8 nDropAction,
372 const Point& rLocation, const sal_Int8 nSourceActions
374 throw(RuntimeException)
376 sal_Int32 n = 0;
378 if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
380 SolarMutexClearableGuard aGuard;
382 // query DropTarget from window
383 Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();
385 if( xDropTarget.is() )
387 // retrieve relative mouse position
388 Point relLoc = pWindow->ImplFrameToOutput( rLocation );
389 aGuard.clear();
391 n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDropActionChangedEvent(
392 xContext, nDropAction, relLoc.X(), relLoc.Y(), nSourceActions );
396 return n;
399 // DNDEventDispatcher::fireDropEvent
401 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
405 throw(RuntimeException)
407 sal_Int32 n = 0;
409 if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
411 SolarMutexClearableGuard aGuard;
413 // query DropTarget from window
414 Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();
416 // window may be destroyed in drop event handler
417 ImplDelData aDelData;
418 pWindow->ImplAddDel( &aDelData );
420 if( xDropTarget.is() )
422 // retrieve relative mouse position
423 Point relLoc = pWindow->ImplFrameToOutput( rLocation );
424 aGuard.clear();
426 n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDropEvent(
427 xContext, nDropAction, relLoc.X(), relLoc.Y(), nSourceActions, xTransferable );
430 if ( !aDelData.IsDead() )
432 pWindow->ImplRemoveDel( &aDelData );
433 // release UI lock
434 pWindow->DecrementLockCount();
439 return n;
442 // DNDEventDispatcher::fireDragGestureRecognized
444 sal_Int32 DNDEventDispatcher::fireDragGestureEvent( vcl::Window *pWindow,
445 const Reference< XDragSource >& xSource, const Any& event,
446 const Point& rOrigin, const sal_Int8 nDragAction
448 throw(::com::sun::star::uno::RuntimeException)
450 sal_Int32 n = 0;
452 if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
454 SolarMutexClearableGuard aGuard;
456 // query DropTarget from window
457 Reference< XDragGestureRecognizer > xDragGestureRecognizer = pWindow->GetDragGestureRecognizer();
459 if( xDragGestureRecognizer.is() )
461 // retrieve relative mouse position
462 Point relLoc = pWindow->ImplFrameToOutput( rOrigin );
463 aGuard.clear();
465 n = static_cast < DNDListenerContainer * > ( xDragGestureRecognizer.get() )->fireDragGestureEvent(
466 nDragAction, relLoc.X(), relLoc.Y(), xSource, event );
469 // release UI lock
470 pWindow->DecrementLockCount();
473 return n;
476 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */