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