xref: /AOO41X/main/vcl/source/window/dndevdis.cxx (revision 9f62ea84a806e17e6f2bbff75724a7257a0eb5d9)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_vcl.hxx"
26 
27 #include <dndevdis.hxx>
28 #include <dndlcon.hxx>
29 #include <window.h>
30 #include <svdata.hxx>
31 
32 #include <vos/mutex.hxx>
33 #include <vcl/svapp.hxx>
34 
35 using namespace ::osl;
36 using namespace ::vos;
37 using namespace ::cppu;
38 using namespace ::com::sun::star::uno;
39 using namespace ::com::sun::star::lang;
40 using namespace ::com::sun::star::datatransfer;
41 using namespace ::com::sun::star::datatransfer::dnd;
42 
43 //==================================================================================================
44 // DNDEventDispatcher::DNDEventDispatcher
45 //==================================================================================================
46 
DNDEventDispatcher(Window * pTopWindow)47 DNDEventDispatcher::DNDEventDispatcher( Window * pTopWindow ):
48     m_pTopWindow( pTopWindow ),
49     m_pCurrentWindow( NULL )
50 {
51 }
52 
53 //==================================================================================================
54 // DNDEventDispatcher::~DNDEventDispatcher
55 //==================================================================================================
56 
~DNDEventDispatcher()57 DNDEventDispatcher::~DNDEventDispatcher()
58 {
59 }
60 
61 //==================================================================================================
62 // DNDEventDispatcher::drop
63 //==================================================================================================
64 
drop(const DropTargetDropEvent & dtde)65 void SAL_CALL DNDEventDispatcher::drop( const DropTargetDropEvent& dtde )
66     throw(RuntimeException)
67 {
68     MutexGuard aImplGuard( m_aMutex );
69 
70     Point location( dtde.LocationX, dtde.LocationY );
71 
72     // find the window that is toplevel for this coordinates
73     OClearableGuard aSolarGuard( Application::GetSolarMutex() );
74 
75     // because those coordinates come from outside, they must be mirrored if RTL layout is active
76     if( Application::GetSettings().GetLayoutRTL() )
77         m_pTopWindow->ImplMirrorFramePos( location );
78     Window * pChildWindow = m_pTopWindow->ImplFindWindow( location );
79 
80     if( NULL == pChildWindow )
81         pChildWindow = m_pTopWindow;
82 
83     while( pChildWindow->ImplGetClientWindow() )
84         pChildWindow = pChildWindow->ImplGetClientWindow();
85 
86     if( pChildWindow->ImplIsAntiparallel() )
87         pChildWindow->ImplReMirror( location );
88 
89     aSolarGuard.clear();
90 
91     // handle the case that drop is in an other vcl window than the last dragOver
92     if( pChildWindow != m_pCurrentWindow )
93     {
94         // fire dragExit on listeners of previous window
95         fireDragExitEvent( m_pCurrentWindow );
96 
97         fireDragEnterEvent( pChildWindow, static_cast < XDropTargetDragContext * > (this),
98             dtde.DropAction, location, dtde.SourceActions, m_aDataFlavorList );
99     }
100 
101     sal_Int32 nListeners = 0;
102 
103     // send drop event to the child window
104     nListeners = fireDropEvent( pChildWindow, dtde.Context, dtde.DropAction,
105         location, dtde.SourceActions, dtde.Transferable );
106 
107     // reject drop if no listeners found
108     if( nListeners == 0 ) {
109         OSL_TRACE( "rejecting drop due to missing listeners." );
110         dtde.Context->rejectDrop();
111     }
112 
113     // this is a drop -> no further drag overs
114     m_pCurrentWindow = NULL;
115     m_aDataFlavorList.realloc( 0 );
116 }
117 
118 //==================================================================================================
119 // DNDEventDispatcher::dragEnter
120 //==================================================================================================
121 
dragEnter(const DropTargetDragEnterEvent & dtdee)122 void SAL_CALL DNDEventDispatcher::dragEnter( const DropTargetDragEnterEvent& dtdee )
123     throw(RuntimeException)
124 {
125     MutexGuard aImplGuard( m_aMutex );
126     Point location( dtdee.LocationX, dtdee.LocationY );
127 
128     // find the window that is toplevel for this coordinates
129     OClearableGuard aSolarGuard( Application::GetSolarMutex() );
130 
131     // because those coordinates come from outside, they must be mirrored if RTL layout is active
132     if( Application::GetSettings().GetLayoutRTL() )
133         m_pTopWindow->ImplMirrorFramePos( location );
134     Window * pChildWindow = m_pTopWindow->ImplFindWindow( location );
135 
136     if( NULL == pChildWindow )
137         pChildWindow = m_pTopWindow;
138 
139     while( pChildWindow->ImplGetClientWindow() )
140         pChildWindow = pChildWindow->ImplGetClientWindow();
141 
142     if( pChildWindow->ImplIsAntiparallel() )
143         pChildWindow->ImplReMirror( location );
144 
145     aSolarGuard.clear();
146 
147     // assume pointer write operation to be atomic
148     m_pCurrentWindow = pChildWindow;
149     m_aDataFlavorList = dtdee.SupportedDataFlavors;
150 
151     // fire dragEnter on listeners of current window
152     sal_Int32 nListeners = fireDragEnterEvent( pChildWindow, dtdee.Context, dtdee.DropAction, location,
153         dtdee.SourceActions, dtdee.SupportedDataFlavors );
154 
155     // reject drag if no listener found
156     if( nListeners == 0 ) {
157         OSL_TRACE( "rejecting drag enter due to missing listeners." );
158         dtdee.Context->rejectDrag();
159     }
160 
161 }
162 
163 //==================================================================================================
164 // DNDEventDispatcher::dragExit
165 //==================================================================================================
166 
dragExit(const DropTargetEvent &)167 void SAL_CALL DNDEventDispatcher::dragExit( const DropTargetEvent& /*dte*/ )
168     throw(RuntimeException)
169 {
170     MutexGuard aImplGuard( m_aMutex );
171 
172     fireDragExitEvent( m_pCurrentWindow );
173 
174     // reset member values
175     m_pCurrentWindow = NULL;
176     m_aDataFlavorList.realloc( 0 );
177 }
178 
179 //==================================================================================================
180 // DNDEventDispatcher::dragOver
181 //==================================================================================================
182 
dragOver(const DropTargetDragEvent & dtde)183 void SAL_CALL DNDEventDispatcher::dragOver( const DropTargetDragEvent& dtde )
184     throw(RuntimeException)
185 {
186     MutexGuard aImplGuard( m_aMutex );
187 
188     Point location( dtde.LocationX, dtde.LocationY );
189     sal_Int32 nListeners;
190 
191     // find the window that is toplevel for this coordinates
192     OClearableGuard aSolarGuard( Application::GetSolarMutex() );
193 
194     // because those coordinates come from outside, they must be mirrored if RTL layout is active
195     if( Application::GetSettings().GetLayoutRTL() )
196         m_pTopWindow->ImplMirrorFramePos( location );
197     Window * pChildWindow = m_pTopWindow->ImplFindWindow( location );
198 
199     if( NULL == pChildWindow )
200         pChildWindow = m_pTopWindow;
201 
202     while( pChildWindow->ImplGetClientWindow() )
203         pChildWindow = pChildWindow->ImplGetClientWindow();
204 
205     if( pChildWindow->ImplIsAntiparallel() )
206         pChildWindow->ImplReMirror( location );
207 
208     aSolarGuard.clear();
209 
210     if( pChildWindow != m_pCurrentWindow )
211     {
212         // fire dragExit on listeners of previous window
213         fireDragExitEvent( m_pCurrentWindow );
214 
215         // remember new window
216         m_pCurrentWindow = pChildWindow;
217 
218         // fire dragEnter on listeners of current window
219         nListeners = fireDragEnterEvent( pChildWindow, dtde.Context, dtde.DropAction, location,
220             dtde.SourceActions, m_aDataFlavorList );
221     }
222     else
223     {
224         // fire dragOver on listeners of current window
225         nListeners = fireDragOverEvent( pChildWindow, dtde.Context, dtde.DropAction, location,
226             dtde.SourceActions );
227     }
228 
229     // reject drag if no listener found
230     if( nListeners == 0 )
231     {
232         OSL_TRACE( "rejecting drag over due to missing listeners." );
233         dtde.Context->rejectDrag();
234     }
235 }
236 
237 //==================================================================================================
238 // DNDEventDispatcher::dropActionChanged
239 //==================================================================================================
240 
dropActionChanged(const DropTargetDragEvent & dtde)241 void SAL_CALL DNDEventDispatcher::dropActionChanged( const DropTargetDragEvent& dtde )
242     throw(RuntimeException)
243 {
244     MutexGuard aImplGuard( m_aMutex );
245 
246     Point location( dtde.LocationX, dtde.LocationY );
247     sal_Int32 nListeners;
248 
249     // find the window that is toplevel for this coordinates
250     OClearableGuard aSolarGuard( Application::GetSolarMutex() );
251 
252     // because those coordinates come from outside, they must be mirrored if RTL layout is active
253     if( Application::GetSettings().GetLayoutRTL() )
254         m_pTopWindow->ImplMirrorFramePos( location );
255     Window * pChildWindow = m_pTopWindow->ImplFindWindow( location );
256 
257     if( NULL == pChildWindow )
258         pChildWindow = m_pTopWindow;
259 
260     while( pChildWindow->ImplGetClientWindow() )
261         pChildWindow = pChildWindow->ImplGetClientWindow();
262 
263     if( pChildWindow->ImplIsAntiparallel() )
264         pChildWindow->ImplReMirror( location );
265 
266     aSolarGuard.clear();
267 
268     if( pChildWindow != m_pCurrentWindow )
269     {
270         // fire dragExit on listeners of previous window
271         fireDragExitEvent( m_pCurrentWindow );
272 
273         // remember new window
274         m_pCurrentWindow = pChildWindow;
275 
276         // fire dragEnter on listeners of current window
277         nListeners = fireDragEnterEvent( pChildWindow, dtde.Context, dtde.DropAction, location,
278             dtde.SourceActions, m_aDataFlavorList );
279     }
280     else
281     {
282         // fire dropActionChanged on listeners of current window
283         nListeners = fireDropActionChangedEvent( pChildWindow, dtde.Context, dtde.DropAction, location,
284             dtde.SourceActions );
285     }
286 
287     // reject drag if no listener found
288     if( nListeners == 0 )
289     {
290         OSL_TRACE( "rejecting dropActionChanged due to missing listeners." );
291         dtde.Context->rejectDrag();
292     }
293 }
294 
295 
296 //==================================================================================================
297 // DNDEventDispatcher::dragGestureRecognized
298 //==================================================================================================
299 
dragGestureRecognized(const DragGestureEvent & dge)300 void SAL_CALL DNDEventDispatcher::dragGestureRecognized( const DragGestureEvent& dge )
301     throw(RuntimeException)
302 {   MutexGuard aImplGuard( m_aMutex );
303 
304     Point origin( dge.DragOriginX, dge.DragOriginY );
305 
306     // find the window that is toplevel for this coordinates
307     OClearableGuard aSolarGuard( Application::GetSolarMutex() );
308 
309     // because those coordinates come from outside, they must be mirrored if RTL layout is active
310     if( Application::GetSettings().GetLayoutRTL() )
311         m_pTopWindow->ImplMirrorFramePos( origin );
312     Window * pChildWindow = m_pTopWindow->ImplFindWindow( origin );
313 
314     if( NULL == pChildWindow )
315         pChildWindow = m_pTopWindow;
316 
317     while( pChildWindow->ImplGetClientWindow() )
318         pChildWindow = pChildWindow->ImplGetClientWindow();
319 
320     if( pChildWindow->ImplIsAntiparallel() )
321         pChildWindow->ImplReMirror( origin );
322 
323     aSolarGuard.clear();
324 
325     fireDragGestureEvent( pChildWindow, dge.DragSource, dge.Event, origin, dge.DragAction );
326 }
327 
328 //==================================================================================================
329 // DNDEventDispatcher::disposing
330 //==================================================================================================
331 
disposing(const EventObject &)332 void SAL_CALL DNDEventDispatcher::disposing( const EventObject& )
333     throw(RuntimeException)
334 {
335 }
336 
337 //==================================================================================================
338 // DNDEventDispatcher::acceptDrag
339 //==================================================================================================
340 
acceptDrag(sal_Int8)341 void SAL_CALL DNDEventDispatcher::acceptDrag( sal_Int8 /*dropAction*/ ) throw(RuntimeException)
342 {
343 }
344 
345 //==================================================================================================
346 // DNDEventDispatcher::rejectDrag
347 //==================================================================================================
348 
rejectDrag()349 void SAL_CALL DNDEventDispatcher::rejectDrag() throw(RuntimeException)
350 {
351 }
352 
353 //==================================================================================================
354 // DNDEventDispatcher::fireDragEnterEvent
355 //==================================================================================================
356 
fireDragEnterEvent(Window * pWindow,const Reference<XDropTargetDragContext> & xContext,const sal_Int8 nDropAction,const Point & rLocation,const sal_Int8 nSourceActions,const Sequence<DataFlavor> & aFlavorList)357 sal_Int32 DNDEventDispatcher::fireDragEnterEvent( Window *pWindow,
358     const Reference< XDropTargetDragContext >& xContext, const sal_Int8 nDropAction,
359     const Point& rLocation, const sal_Int8 nSourceActions, const Sequence< DataFlavor >& aFlavorList
360 )
361     throw(RuntimeException)
362 {
363     sal_Int32 n = 0;
364 
365     if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
366     {
367         OClearableGuard aGuard( Application::GetSolarMutex() );
368 
369         // set an UI lock
370         pWindow->IncrementLockCount();
371 
372         // query DropTarget from window
373         Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();
374 
375         if( xDropTarget.is() )
376         {
377             // retrieve relative mouse position
378             Point relLoc = pWindow->ImplFrameToOutput( rLocation );
379             aGuard.clear();
380 
381             n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDragEnterEvent(
382                 xContext, nDropAction, relLoc.X(), relLoc.Y(), nSourceActions, aFlavorList );
383         }
384     }
385 
386     return n;
387 }
388 
389 //==================================================================================================
390 // DNDEventDispatcher::fireDragOverEvent
391 //==================================================================================================
392 
fireDragOverEvent(Window * pWindow,const Reference<XDropTargetDragContext> & xContext,const sal_Int8 nDropAction,const Point & rLocation,const sal_Int8 nSourceActions)393 sal_Int32 DNDEventDispatcher::fireDragOverEvent( Window *pWindow,
394     const Reference< XDropTargetDragContext >& xContext, const sal_Int8 nDropAction,
395     const Point& rLocation, const sal_Int8 nSourceActions
396 )
397     throw(RuntimeException)
398 {
399     sal_Int32 n = 0;
400 
401     if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
402     {
403         OClearableGuard aGuard( Application::GetSolarMutex() );
404 
405         // query DropTarget from window
406         Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();
407 
408         if( xDropTarget.is() )
409         {
410             // retrieve relative mouse position
411             Point relLoc = pWindow->ImplFrameToOutput( rLocation );
412             aGuard.clear();
413 
414             n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDragOverEvent(
415                 xContext, nDropAction, relLoc.X(), relLoc.Y(), nSourceActions );
416         }
417     }
418 
419     return n;
420 }
421 
422 //==================================================================================================
423 // DNDEventDispatcher::fireDragExitEvent
424 //==================================================================================================
425 
fireDragExitEvent(Window * pWindow)426 sal_Int32 DNDEventDispatcher::fireDragExitEvent( Window *pWindow ) throw(RuntimeException)
427 {
428     sal_Int32 n = 0;
429 
430     if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
431     {
432         OClearableGuard aGuard( Application::GetSolarMutex() );
433 
434         // query DropTarget from window
435         Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();
436 
437         aGuard.clear();
438 
439         if( xDropTarget.is() )
440             n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDragExitEvent();
441 
442         // release UI lock
443         pWindow->DecrementLockCount();
444     }
445 
446     return n;
447 }
448 
449 //==================================================================================================
450 // DNDEventDispatcher::fireDropActionChangedEvent
451 //==================================================================================================
452 
fireDropActionChangedEvent(Window * pWindow,const Reference<XDropTargetDragContext> & xContext,const sal_Int8 nDropAction,const Point & rLocation,const sal_Int8 nSourceActions)453 sal_Int32 DNDEventDispatcher::fireDropActionChangedEvent( Window *pWindow,
454     const Reference< XDropTargetDragContext >& xContext, const sal_Int8 nDropAction,
455     const Point& rLocation, const sal_Int8 nSourceActions
456 )
457     throw(RuntimeException)
458 {
459     sal_Int32 n = 0;
460 
461     if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
462     {
463         OClearableGuard aGuard( Application::GetSolarMutex() );
464 
465         // query DropTarget from window
466         Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();
467 
468         if( xDropTarget.is() )
469         {
470             // retrieve relative mouse position
471             Point relLoc = pWindow->ImplFrameToOutput( rLocation );
472             aGuard.clear();
473 
474             n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDropActionChangedEvent(
475                 xContext, nDropAction, relLoc.X(), relLoc.Y(), nSourceActions );
476         }
477     }
478 
479     return n;
480 }
481 
482 //==================================================================================================
483 // DNDEventDispatcher::fireDropEvent
484 //==================================================================================================
485 
fireDropEvent(Window * pWindow,const Reference<XDropTargetDropContext> & xContext,const sal_Int8 nDropAction,const Point & rLocation,const sal_Int8 nSourceActions,const Reference<XTransferable> & xTransferable)486 sal_Int32 DNDEventDispatcher::fireDropEvent( Window *pWindow,
487     const Reference< XDropTargetDropContext >& xContext, const sal_Int8 nDropAction, const Point& rLocation,
488     const sal_Int8 nSourceActions, const Reference< XTransferable >& xTransferable
489 )
490     throw(RuntimeException)
491 {
492     sal_Int32 n = 0;
493 
494     if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
495     {
496         OClearableGuard aGuard( Application::GetSolarMutex() );
497 
498         // query DropTarget from window
499         Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();
500 
501         // window may be destroyed in drop event handler
502         ImplDelData         aDelData;
503         pWindow->ImplAddDel( &aDelData );
504 
505         if( xDropTarget.is() )
506         {
507             // retrieve relative mouse position
508             Point relLoc = pWindow->ImplFrameToOutput( rLocation );
509             aGuard.clear();
510 
511             n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDropEvent(
512                 xContext, nDropAction, relLoc.X(), relLoc.Y(), nSourceActions, xTransferable );
513         }
514 
515         if ( !aDelData.IsDelete() )
516         {
517             pWindow->ImplRemoveDel( &aDelData );
518             // release UI lock
519             pWindow->DecrementLockCount();
520         }
521 
522     }
523 
524     return n;
525 }
526 
527 //==================================================================================================
528 // DNDEventDispatcher::fireDragGestureRecognized
529 //==================================================================================================
530 
fireDragGestureEvent(Window * pWindow,const Reference<XDragSource> & xSource,const Any event,const Point & rOrigin,const sal_Int8 nDragAction)531 sal_Int32 DNDEventDispatcher::fireDragGestureEvent( Window *pWindow,
532     const Reference< XDragSource >& xSource, const Any event,
533     const Point& rOrigin, const sal_Int8 nDragAction
534 )
535     throw(::com::sun::star::uno::RuntimeException)
536 {
537     sal_Int32 n = 0;
538 
539     if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
540     {
541         OClearableGuard aGuard( Application::GetSolarMutex() );
542 
543         // query DropTarget from window
544         Reference< XDragGestureRecognizer > xDragGestureRecognizer = pWindow->GetDragGestureRecognizer();
545 
546         if( xDragGestureRecognizer.is() )
547         {
548             // retrieve relative mouse position
549             Point relLoc = pWindow->ImplFrameToOutput( rOrigin );
550             aGuard.clear();
551 
552             n = static_cast < DNDListenerContainer * > ( xDragGestureRecognizer.get() )->fireDragGestureEvent(
553                 nDragAction, relLoc.X(), relLoc.Y(), xSource, event );
554         }
555 
556         // release UI lock
557         pWindow->DecrementLockCount();
558     }
559 
560     return n;
561 }
562