1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: dndevdis.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
34 #include <dndevdis.hxx>
35 #include <dndlcon.hxx>
36 #include <vcl/window.h>
38 #include <vos/mutex.hxx>
39 #include <vcl/svapp.hxx>
40 #include <vcl/svdata.hxx>
41 using namespace ::osl
;
42 using namespace ::vos
;
43 using namespace ::cppu
;
44 using namespace ::com::sun::star::uno
;
45 using namespace ::com::sun::star::lang
;
46 using namespace ::com::sun::star::datatransfer
;
47 using namespace ::com::sun::star::datatransfer::dnd
;
49 //==================================================================================================
50 // DNDEventDispatcher::DNDEventDispatcher
51 //==================================================================================================
53 DNDEventDispatcher::DNDEventDispatcher( Window
* pTopWindow
):
54 m_pTopWindow( pTopWindow
),
55 m_pCurrentWindow( NULL
)
59 //==================================================================================================
60 // DNDEventDispatcher::~DNDEventDispatcher
61 //==================================================================================================
63 DNDEventDispatcher::~DNDEventDispatcher()
67 //==================================================================================================
68 // DNDEventDispatcher::drop
69 //==================================================================================================
71 void SAL_CALL
DNDEventDispatcher::drop( const DropTargetDropEvent
& dtde
)
72 throw(RuntimeException
)
74 MutexGuard
aImplGuard( m_aMutex
);
76 Point
location( dtde
.LocationX
, dtde
.LocationY
);
78 // find the window that is toplevel for this coordinates
79 OClearableGuard
aSolarGuard( Application::GetSolarMutex() );
81 // because those coordinates come from outside, they must be mirrored if RTL layout is active
82 if( Application::GetSettings().GetLayoutRTL() )
83 m_pTopWindow
->ImplMirrorFramePos( location
);
84 Window
* pChildWindow
= m_pTopWindow
->ImplFindWindow( location
);
86 if( NULL
== pChildWindow
)
87 pChildWindow
= m_pTopWindow
;
89 while( pChildWindow
->ImplGetClientWindow() )
90 pChildWindow
= pChildWindow
->ImplGetClientWindow();
92 if( pChildWindow
->ImplIsAntiparallel() )
93 pChildWindow
->ImplReMirror( location
);
97 // handle the case that drop is in an other vcl window than the last dragOver
98 if( pChildWindow
!= m_pCurrentWindow
)
100 // fire dragExit on listeners of previous window
101 fireDragExitEvent( m_pCurrentWindow
);
103 fireDragEnterEvent( pChildWindow
, static_cast < XDropTargetDragContext
* > (this),
104 dtde
.DropAction
, location
, dtde
.SourceActions
, m_aDataFlavorList
);
107 sal_Int32 nListeners
= 0;
109 // send drop event to the child window
110 nListeners
= fireDropEvent( pChildWindow
, dtde
.Context
, dtde
.DropAction
,
111 location
, dtde
.SourceActions
, dtde
.Transferable
);
113 // reject drop if no listeners found
114 if( nListeners
== 0 ) {
115 OSL_TRACE( "rejecting drop due to missing listeners." );
116 dtde
.Context
->rejectDrop();
119 // this is a drop -> no further drag overs
120 m_pCurrentWindow
= NULL
;
121 m_aDataFlavorList
.realloc( 0 );
124 //==================================================================================================
125 // DNDEventDispatcher::dragEnter
126 //==================================================================================================
128 void SAL_CALL
DNDEventDispatcher::dragEnter( const DropTargetDragEnterEvent
& dtdee
)
129 throw(RuntimeException
)
131 MutexGuard
aImplGuard( m_aMutex
);
132 Point
location( dtdee
.LocationX
, dtdee
.LocationY
);
134 // find the window that is toplevel for this coordinates
135 OClearableGuard
aSolarGuard( Application::GetSolarMutex() );
137 // because those coordinates come from outside, they must be mirrored if RTL layout is active
138 if( Application::GetSettings().GetLayoutRTL() )
139 m_pTopWindow
->ImplMirrorFramePos( location
);
140 Window
* pChildWindow
= m_pTopWindow
->ImplFindWindow( location
);
142 if( NULL
== pChildWindow
)
143 pChildWindow
= m_pTopWindow
;
145 while( pChildWindow
->ImplGetClientWindow() )
146 pChildWindow
= pChildWindow
->ImplGetClientWindow();
148 if( pChildWindow
->ImplIsAntiparallel() )
149 pChildWindow
->ImplReMirror( location
);
153 // assume pointer write operation to be atomic
154 m_pCurrentWindow
= pChildWindow
;
155 m_aDataFlavorList
= dtdee
.SupportedDataFlavors
;
157 // fire dragEnter on listeners of current window
158 sal_Int32 nListeners
= fireDragEnterEvent( pChildWindow
, dtdee
.Context
, dtdee
.DropAction
, location
,
159 dtdee
.SourceActions
, dtdee
.SupportedDataFlavors
);
161 // reject drag if no listener found
162 if( nListeners
== 0 ) {
163 OSL_TRACE( "rejecting drag enter due to missing listeners." );
164 dtdee
.Context
->rejectDrag();
169 //==================================================================================================
170 // DNDEventDispatcher::dragExit
171 //==================================================================================================
173 void SAL_CALL
DNDEventDispatcher::dragExit( const DropTargetEvent
& /*dte*/ )
174 throw(RuntimeException
)
176 MutexGuard
aImplGuard( m_aMutex
);
178 fireDragExitEvent( m_pCurrentWindow
);
180 // reset member values
181 m_pCurrentWindow
= NULL
;
182 m_aDataFlavorList
.realloc( 0 );
185 //==================================================================================================
186 // DNDEventDispatcher::dragOver
187 //==================================================================================================
189 void SAL_CALL
DNDEventDispatcher::dragOver( const DropTargetDragEvent
& dtde
)
190 throw(RuntimeException
)
192 MutexGuard
aImplGuard( m_aMutex
);
194 Point
location( dtde
.LocationX
, dtde
.LocationY
);
195 sal_Int32 nListeners
;
197 // find the window that is toplevel for this coordinates
198 OClearableGuard
aSolarGuard( Application::GetSolarMutex() );
200 // because those coordinates come from outside, they must be mirrored if RTL layout is active
201 if( Application::GetSettings().GetLayoutRTL() )
202 m_pTopWindow
->ImplMirrorFramePos( location
);
203 Window
* pChildWindow
= m_pTopWindow
->ImplFindWindow( location
);
205 if( NULL
== pChildWindow
)
206 pChildWindow
= m_pTopWindow
;
208 while( pChildWindow
->ImplGetClientWindow() )
209 pChildWindow
= pChildWindow
->ImplGetClientWindow();
211 if( pChildWindow
->ImplIsAntiparallel() )
212 pChildWindow
->ImplReMirror( location
);
216 if( pChildWindow
!= m_pCurrentWindow
)
218 // fire dragExit on listeners of previous window
219 fireDragExitEvent( m_pCurrentWindow
);
221 // remember new window
222 m_pCurrentWindow
= pChildWindow
;
224 // fire dragEnter on listeners of current window
225 nListeners
= fireDragEnterEvent( pChildWindow
, dtde
.Context
, dtde
.DropAction
, location
,
226 dtde
.SourceActions
, m_aDataFlavorList
);
230 // fire dragOver on listeners of current window
231 nListeners
= fireDragOverEvent( pChildWindow
, dtde
.Context
, dtde
.DropAction
, location
,
232 dtde
.SourceActions
);
235 // reject drag if no listener found
236 if( nListeners
== 0 )
238 OSL_TRACE( "rejecting drag over due to missing listeners." );
239 dtde
.Context
->rejectDrag();
243 //==================================================================================================
244 // DNDEventDispatcher::dropActionChanged
245 //==================================================================================================
247 void SAL_CALL
DNDEventDispatcher::dropActionChanged( const DropTargetDragEvent
& dtde
)
248 throw(RuntimeException
)
250 MutexGuard
aImplGuard( m_aMutex
);
252 Point
location( dtde
.LocationX
, dtde
.LocationY
);
253 sal_Int32 nListeners
;
255 // find the window that is toplevel for this coordinates
256 OClearableGuard
aSolarGuard( Application::GetSolarMutex() );
258 // because those coordinates come from outside, they must be mirrored if RTL layout is active
259 if( Application::GetSettings().GetLayoutRTL() )
260 m_pTopWindow
->ImplMirrorFramePos( location
);
261 Window
* pChildWindow
= m_pTopWindow
->ImplFindWindow( location
);
263 if( NULL
== pChildWindow
)
264 pChildWindow
= m_pTopWindow
;
266 while( pChildWindow
->ImplGetClientWindow() )
267 pChildWindow
= pChildWindow
->ImplGetClientWindow();
269 if( pChildWindow
->ImplIsAntiparallel() )
270 pChildWindow
->ImplReMirror( location
);
274 if( pChildWindow
!= m_pCurrentWindow
)
276 // fire dragExit on listeners of previous window
277 fireDragExitEvent( m_pCurrentWindow
);
279 // remember new window
280 m_pCurrentWindow
= pChildWindow
;
282 // fire dragEnter on listeners of current window
283 nListeners
= fireDragEnterEvent( pChildWindow
, dtde
.Context
, dtde
.DropAction
, location
,
284 dtde
.SourceActions
, m_aDataFlavorList
);
288 // fire dropActionChanged on listeners of current window
289 nListeners
= fireDropActionChangedEvent( pChildWindow
, dtde
.Context
, dtde
.DropAction
, location
,
290 dtde
.SourceActions
);
293 // reject drag if no listener found
294 if( nListeners
== 0 )
296 OSL_TRACE( "rejecting dropActionChanged due to missing listeners." );
297 dtde
.Context
->rejectDrag();
302 //==================================================================================================
303 // DNDEventDispatcher::dragGestureRecognized
304 //==================================================================================================
306 void SAL_CALL
DNDEventDispatcher::dragGestureRecognized( const DragGestureEvent
& dge
)
307 throw(RuntimeException
)
308 { MutexGuard
aImplGuard( m_aMutex
);
310 Point
origin( dge
.DragOriginX
, dge
.DragOriginY
);
312 // find the window that is toplevel for this coordinates
313 OClearableGuard
aSolarGuard( Application::GetSolarMutex() );
315 // because those coordinates come from outside, they must be mirrored if RTL layout is active
316 if( Application::GetSettings().GetLayoutRTL() )
317 m_pTopWindow
->ImplMirrorFramePos( origin
);
318 Window
* pChildWindow
= m_pTopWindow
->ImplFindWindow( origin
);
320 if( NULL
== pChildWindow
)
321 pChildWindow
= m_pTopWindow
;
323 while( pChildWindow
->ImplGetClientWindow() )
324 pChildWindow
= pChildWindow
->ImplGetClientWindow();
326 if( pChildWindow
->ImplIsAntiparallel() )
327 pChildWindow
->ImplReMirror( origin
);
331 fireDragGestureEvent( pChildWindow
, dge
.DragSource
, dge
.Event
, origin
, dge
.DragAction
);
334 //==================================================================================================
335 // DNDEventDispatcher::disposing
336 //==================================================================================================
338 void SAL_CALL
DNDEventDispatcher::disposing( const EventObject
& )
339 throw(RuntimeException
)
343 //==================================================================================================
344 // DNDEventDispatcher::acceptDrag
345 //==================================================================================================
347 void SAL_CALL
DNDEventDispatcher::acceptDrag( sal_Int8
/*dropAction*/ ) throw(RuntimeException
)
351 //==================================================================================================
352 // DNDEventDispatcher::rejectDrag
353 //==================================================================================================
355 void SAL_CALL
DNDEventDispatcher::rejectDrag() throw(RuntimeException
)
359 //==================================================================================================
360 // DNDEventDispatcher::fireDragEnterEvent
361 //==================================================================================================
363 sal_Int32
DNDEventDispatcher::fireDragEnterEvent( Window
*pWindow
,
364 const Reference
< XDropTargetDragContext
>& xContext
, const sal_Int8 nDropAction
,
365 const Point
& rLocation
, const sal_Int8 nSourceActions
, const Sequence
< DataFlavor
>& aFlavorList
367 throw(RuntimeException
)
371 if( pWindow
&& pWindow
->IsInputEnabled() && ! pWindow
->IsInModalMode() )
373 OClearableGuard
aGuard( Application::GetSolarMutex() );
376 pWindow
->IncrementLockCount();
378 // query DropTarget from window
379 Reference
< XDropTarget
> xDropTarget
= pWindow
->GetDropTarget();
381 if( xDropTarget
.is() )
383 // retrieve relative mouse position
384 Point relLoc
= pWindow
->ImplFrameToOutput( rLocation
);
387 n
= static_cast < DNDListenerContainer
* > ( xDropTarget
.get() )->fireDragEnterEvent(
388 xContext
, nDropAction
, relLoc
.X(), relLoc
.Y(), nSourceActions
, aFlavorList
);
395 //==================================================================================================
396 // DNDEventDispatcher::fireDragOverEvent
397 //==================================================================================================
399 sal_Int32
DNDEventDispatcher::fireDragOverEvent( Window
*pWindow
,
400 const Reference
< XDropTargetDragContext
>& xContext
, const sal_Int8 nDropAction
,
401 const Point
& rLocation
, const sal_Int8 nSourceActions
403 throw(RuntimeException
)
407 if( pWindow
&& pWindow
->IsInputEnabled() && ! pWindow
->IsInModalMode() )
409 OClearableGuard
aGuard( Application::GetSolarMutex() );
411 // query DropTarget from window
412 Reference
< XDropTarget
> xDropTarget
= pWindow
->GetDropTarget();
414 if( xDropTarget
.is() )
416 // retrieve relative mouse position
417 Point relLoc
= pWindow
->ImplFrameToOutput( rLocation
);
420 n
= static_cast < DNDListenerContainer
* > ( xDropTarget
.get() )->fireDragOverEvent(
421 xContext
, nDropAction
, relLoc
.X(), relLoc
.Y(), nSourceActions
);
428 //==================================================================================================
429 // DNDEventDispatcher::fireDragExitEvent
430 //==================================================================================================
432 sal_Int32
DNDEventDispatcher::fireDragExitEvent( Window
*pWindow
) throw(RuntimeException
)
436 if( pWindow
&& pWindow
->IsInputEnabled() && ! pWindow
->IsInModalMode() )
438 OClearableGuard
aGuard( Application::GetSolarMutex() );
440 // query DropTarget from window
441 Reference
< XDropTarget
> xDropTarget
= pWindow
->GetDropTarget();
445 if( xDropTarget
.is() )
446 n
= static_cast < DNDListenerContainer
* > ( xDropTarget
.get() )->fireDragExitEvent();
449 pWindow
->DecrementLockCount();
455 //==================================================================================================
456 // DNDEventDispatcher::fireDropActionChangedEvent
457 //==================================================================================================
459 sal_Int32
DNDEventDispatcher::fireDropActionChangedEvent( Window
*pWindow
,
460 const Reference
< XDropTargetDragContext
>& xContext
, const sal_Int8 nDropAction
,
461 const Point
& rLocation
, const sal_Int8 nSourceActions
463 throw(RuntimeException
)
467 if( pWindow
&& pWindow
->IsInputEnabled() && ! pWindow
->IsInModalMode() )
469 OClearableGuard
aGuard( Application::GetSolarMutex() );
471 // query DropTarget from window
472 Reference
< XDropTarget
> xDropTarget
= pWindow
->GetDropTarget();
474 if( xDropTarget
.is() )
476 // retrieve relative mouse position
477 Point relLoc
= pWindow
->ImplFrameToOutput( rLocation
);
480 n
= static_cast < DNDListenerContainer
* > ( xDropTarget
.get() )->fireDropActionChangedEvent(
481 xContext
, nDropAction
, relLoc
.X(), relLoc
.Y(), nSourceActions
);
488 //==================================================================================================
489 // DNDEventDispatcher::fireDropEvent
490 //==================================================================================================
492 sal_Int32
DNDEventDispatcher::fireDropEvent( Window
*pWindow
,
493 const Reference
< XDropTargetDropContext
>& xContext
, const sal_Int8 nDropAction
, const Point
& rLocation
,
494 const sal_Int8 nSourceActions
, const Reference
< XTransferable
>& xTransferable
496 throw(RuntimeException
)
500 if( pWindow
&& pWindow
->IsInputEnabled() && ! pWindow
->IsInModalMode() )
502 OClearableGuard
aGuard( Application::GetSolarMutex() );
504 // query DropTarget from window
505 Reference
< XDropTarget
> xDropTarget
= pWindow
->GetDropTarget();
507 // window may be destroyed in drop event handler
508 ImplDelData aDelData
;
509 pWindow
->ImplAddDel( &aDelData
);
511 if( xDropTarget
.is() )
513 // retrieve relative mouse position
514 Point relLoc
= pWindow
->ImplFrameToOutput( rLocation
);
517 n
= static_cast < DNDListenerContainer
* > ( xDropTarget
.get() )->fireDropEvent(
518 xContext
, nDropAction
, relLoc
.X(), relLoc
.Y(), nSourceActions
, xTransferable
);
521 if ( !aDelData
.IsDelete() )
523 pWindow
->ImplRemoveDel( &aDelData
);
525 pWindow
->DecrementLockCount();
533 //==================================================================================================
534 // DNDEventDispatcher::fireDragGestureRecognized
535 //==================================================================================================
537 sal_Int32
DNDEventDispatcher::fireDragGestureEvent( Window
*pWindow
,
538 const Reference
< XDragSource
>& xSource
, const Any event
,
539 const Point
& rOrigin
, const sal_Int8 nDragAction
541 throw(::com::sun::star::uno::RuntimeException
)
545 if( pWindow
&& pWindow
->IsInputEnabled() && ! pWindow
->IsInModalMode() )
547 OClearableGuard
aGuard( Application::GetSolarMutex() );
549 // query DropTarget from window
550 Reference
< XDragGestureRecognizer
> xDragGestureRecognizer
= pWindow
->GetDragGestureRecognizer();
552 if( xDragGestureRecognizer
.is() )
554 // retrieve relative mouse position
555 Point relLoc
= pWindow
->ImplFrameToOutput( rOrigin
);
558 n
= static_cast < DNDListenerContainer
* > ( xDragGestureRecognizer
.get() )->fireDragGestureEvent(
559 nDragAction
, relLoc
.X(), relLoc
.Y(), xSource
, event
);
563 pWindow
->DecrementLockCount();