1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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
);
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
);
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
);
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
)
295 if( pWindow
&& pWindow
->IsInputEnabled() && ! pWindow
->IsInModalMode() )
297 SolarMutexClearableGuard aSolarGuard
;
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
);
311 n
= static_cast < DNDListenerContainer
* > ( xDropTarget
.get() )->fireDragEnterEvent(
312 xContext
, nDropAction
, relLoc
.X(), relLoc
.Y(), nSourceActions
, aFlavorList
);
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
)
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
);
344 n
= static_cast < DNDListenerContainer
* > ( xDropTarget
.get() )->fireDragOverEvent(
345 xContext
, nDropAction
, relLoc
.X(), relLoc
.Y(), nSourceActions
);
352 //==================================================================================================
353 // DNDEventDispatcher::fireDragExitEvent
354 //==================================================================================================
356 sal_Int32
DNDEventDispatcher::fireDragExitEvent( Window
*pWindow
) throw(RuntimeException
)
360 if( pWindow
&& pWindow
->IsInputEnabled() && ! pWindow
->IsInModalMode() )
362 SolarMutexClearableGuard aGuard
;
364 // query DropTarget from window
365 Reference
< XDropTarget
> xDropTarget
= pWindow
->GetDropTarget();
369 if( xDropTarget
.is() )
370 n
= static_cast < DNDListenerContainer
* > ( xDropTarget
.get() )->fireDragExitEvent();
373 pWindow
->DecrementLockCount();
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
)
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
);
404 n
= static_cast < DNDListenerContainer
* > ( xDropTarget
.get() )->fireDropActionChangedEvent(
405 xContext
, nDropAction
, relLoc
.X(), relLoc
.Y(), nSourceActions
);
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
)
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
);
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
);
449 pWindow
->DecrementLockCount();
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
)
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
);
482 n
= static_cast < DNDListenerContainer
* > ( xDragGestureRecognizer
.get() )->fireDragGestureEvent(
483 nDragAction
, relLoc
.X(), relLoc
.Y(), xSource
, event
);
487 pWindow
->DecrementLockCount();
493 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */