Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <dndevdis.hxx>
31 : : #include <dndlcon.hxx>
32 : : #include <window.h>
33 : : #include <svdata.hxx>
34 : :
35 : : #include <osl/mutex.hxx>
36 : : #include <vcl/svapp.hxx>
37 : :
38 : : using namespace ::cppu;
39 : : using namespace ::com::sun::star::uno;
40 : : using namespace ::com::sun::star::lang;
41 : : using namespace ::com::sun::star::datatransfer;
42 : : using namespace ::com::sun::star::datatransfer::dnd;
43 : :
44 : : //==================================================================================================
45 : : // DNDEventDispatcher::DNDEventDispatcher
46 : : //==================================================================================================
47 : :
48 : 2741 : DNDEventDispatcher::DNDEventDispatcher( Window * pTopWindow ):
49 : : m_pTopWindow( pTopWindow ),
50 [ + - ][ + - ]: 2741 : m_pCurrentWindow( NULL )
51 : : {
52 : 2741 : }
53 : :
54 : : //==================================================================================================
55 : : // DNDEventDispatcher::~DNDEventDispatcher
56 : : //==================================================================================================
57 : :
58 [ + - ][ + - ]: 2741 : DNDEventDispatcher::~DNDEventDispatcher()
59 : : {
60 [ - + ]: 5482 : }
61 : :
62 : 0 : Window* DNDEventDispatcher::findTopLevelWindow(Point location)
63 : : {
64 [ # # ]: 0 : SolarMutexGuard aSolarGuard;
65 : :
66 : : // find the window that is toplevel for this coordinates
67 : : // because those coordinates come from outside, they must be mirrored if RTL layout is active
68 [ # # ][ # # ]: 0 : if( Application::GetSettings().GetLayoutRTL() )
[ # # ]
69 [ # # ]: 0 : m_pTopWindow->ImplMirrorFramePos( location );
70 [ # # ]: 0 : Window * pChildWindow = m_pTopWindow->ImplFindWindow( location );
71 : :
72 [ # # ]: 0 : if( NULL == pChildWindow )
73 : 0 : pChildWindow = m_pTopWindow;
74 : :
75 [ # # ][ # # ]: 0 : while( pChildWindow->ImplGetClientWindow() )
76 [ # # ]: 0 : pChildWindow = pChildWindow->ImplGetClientWindow();
77 : :
78 [ # # ][ # # ]: 0 : if( pChildWindow->ImplIsAntiparallel() )
79 [ # # ]: 0 : pChildWindow->ImplReMirror( location );
80 : :
81 [ # # ]: 0 : return pChildWindow;
82 : : }
83 : :
84 : : //==================================================================================================
85 : : // DNDEventDispatcher::drop
86 : : //==================================================================================================
87 : :
88 : 0 : void SAL_CALL DNDEventDispatcher::drop( const DropTargetDropEvent& dtde )
89 : : throw(RuntimeException)
90 : : {
91 [ # # ]: 0 : osl::MutexGuard aImplGuard( m_aMutex );
92 : :
93 : 0 : Point location( dtde.LocationX, dtde.LocationY );
94 : :
95 [ # # ]: 0 : Window* pChildWindow = findTopLevelWindow(location);
96 : :
97 : : // handle the case that drop is in an other vcl window than the last dragOver
98 [ # # ]: 0 : if( pChildWindow != m_pCurrentWindow )
99 : : {
100 : : // fire dragExit on listeners of previous window
101 [ # # ]: 0 : fireDragExitEvent( m_pCurrentWindow );
102 : :
103 : : fireDragEnterEvent( pChildWindow, static_cast < XDropTargetDragContext * > (this),
104 [ # # ][ # # ]: 0 : dtde.DropAction, location, dtde.SourceActions, m_aDataFlavorList );
105 : : }
106 : :
107 : 0 : sal_Int32 nListeners = 0;
108 : :
109 : : // send drop event to the child window
110 : : nListeners = fireDropEvent( pChildWindow, dtde.Context, dtde.DropAction,
111 [ # # ]: 0 : location, dtde.SourceActions, dtde.Transferable );
112 : :
113 : : // reject drop if no listeners found
114 [ # # ]: 0 : if( nListeners == 0 ) {
115 : : OSL_TRACE( "rejecting drop due to missing listeners." );
116 [ # # ][ # # ]: 0 : dtde.Context->rejectDrop();
117 : : }
118 : :
119 : : // this is a drop -> no further drag overs
120 : 0 : m_pCurrentWindow = NULL;
121 [ # # ][ # # ]: 0 : m_aDataFlavorList.realloc( 0 );
122 : 0 : }
123 : :
124 : : //==================================================================================================
125 : : // DNDEventDispatcher::dragEnter
126 : : //==================================================================================================
127 : :
128 : 0 : void SAL_CALL DNDEventDispatcher::dragEnter( const DropTargetDragEnterEvent& dtdee )
129 : : throw(RuntimeException)
130 : : {
131 [ # # ]: 0 : osl::MutexGuard aImplGuard( m_aMutex );
132 : 0 : Point location( dtdee.LocationX, dtdee.LocationY );
133 : :
134 [ # # ]: 0 : Window * pChildWindow = findTopLevelWindow(location);
135 : :
136 : : // assume pointer write operation to be atomic
137 : 0 : m_pCurrentWindow = pChildWindow;
138 [ # # ]: 0 : m_aDataFlavorList = dtdee.SupportedDataFlavors;
139 : :
140 : : // fire dragEnter on listeners of current window
141 : : sal_Int32 nListeners = fireDragEnterEvent( pChildWindow, dtdee.Context, dtdee.DropAction, location,
142 [ # # ]: 0 : dtdee.SourceActions, dtdee.SupportedDataFlavors );
143 : :
144 : : // reject drag if no listener found
145 [ # # ]: 0 : if( nListeners == 0 ) {
146 : : OSL_TRACE( "rejecting drag enter due to missing listeners." );
147 [ # # ][ # # ]: 0 : dtdee.Context->rejectDrag();
148 [ # # ]: 0 : }
149 : :
150 : 0 : }
151 : :
152 : : //==================================================================================================
153 : : // DNDEventDispatcher::dragExit
154 : : //==================================================================================================
155 : :
156 : 0 : void SAL_CALL DNDEventDispatcher::dragExit( const DropTargetEvent& /*dte*/ )
157 : : throw(RuntimeException)
158 : : {
159 [ # # ]: 0 : osl::MutexGuard aImplGuard( m_aMutex );
160 : :
161 [ # # ]: 0 : fireDragExitEvent( m_pCurrentWindow );
162 : :
163 : : // reset member values
164 : 0 : m_pCurrentWindow = NULL;
165 [ # # ][ # # ]: 0 : m_aDataFlavorList.realloc( 0 );
166 : 0 : }
167 : :
168 : : //==================================================================================================
169 : : // DNDEventDispatcher::dragOver
170 : : //==================================================================================================
171 : :
172 : 0 : void SAL_CALL DNDEventDispatcher::dragOver( const DropTargetDragEvent& dtde )
173 : : throw(RuntimeException)
174 : : {
175 [ # # ]: 0 : osl::MutexGuard aImplGuard( m_aMutex );
176 : :
177 : 0 : Point location( dtde.LocationX, dtde.LocationY );
178 : : sal_Int32 nListeners;
179 : :
180 [ # # ]: 0 : Window * pChildWindow = findTopLevelWindow(location);
181 : :
182 [ # # ]: 0 : if( pChildWindow != m_pCurrentWindow )
183 : : {
184 : : // fire dragExit on listeners of previous window
185 [ # # ]: 0 : fireDragExitEvent( m_pCurrentWindow );
186 : :
187 : : // remember new window
188 : 0 : m_pCurrentWindow = pChildWindow;
189 : :
190 : : // fire dragEnter on listeners of current window
191 : : nListeners = fireDragEnterEvent( pChildWindow, dtde.Context, dtde.DropAction, location,
192 [ # # ]: 0 : dtde.SourceActions, m_aDataFlavorList );
193 : : }
194 : : else
195 : : {
196 : : // fire dragOver on listeners of current window
197 : : nListeners = fireDragOverEvent( pChildWindow, dtde.Context, dtde.DropAction, location,
198 [ # # ]: 0 : dtde.SourceActions );
199 : : }
200 : :
201 : : // reject drag if no listener found
202 [ # # ]: 0 : if( nListeners == 0 )
203 : : {
204 : : OSL_TRACE( "rejecting drag over due to missing listeners." );
205 [ # # ][ # # ]: 0 : dtde.Context->rejectDrag();
206 [ # # ]: 0 : }
207 : 0 : }
208 : :
209 : : //==================================================================================================
210 : : // DNDEventDispatcher::dropActionChanged
211 : : //==================================================================================================
212 : :
213 : 0 : void SAL_CALL DNDEventDispatcher::dropActionChanged( const DropTargetDragEvent& dtde )
214 : : throw(RuntimeException)
215 : : {
216 [ # # ]: 0 : osl::MutexGuard aImplGuard( m_aMutex );
217 : :
218 : 0 : Point location( dtde.LocationX, dtde.LocationY );
219 : : sal_Int32 nListeners;
220 : :
221 [ # # ]: 0 : Window* pChildWindow = findTopLevelWindow(location);
222 : :
223 [ # # ]: 0 : if( pChildWindow != m_pCurrentWindow )
224 : : {
225 : : // fire dragExit on listeners of previous window
226 [ # # ]: 0 : fireDragExitEvent( m_pCurrentWindow );
227 : :
228 : : // remember new window
229 : 0 : m_pCurrentWindow = pChildWindow;
230 : :
231 : : // fire dragEnter on listeners of current window
232 : : nListeners = fireDragEnterEvent( pChildWindow, dtde.Context, dtde.DropAction, location,
233 [ # # ]: 0 : dtde.SourceActions, m_aDataFlavorList );
234 : : }
235 : : else
236 : : {
237 : : // fire dropActionChanged on listeners of current window
238 : : nListeners = fireDropActionChangedEvent( pChildWindow, dtde.Context, dtde.DropAction, location,
239 [ # # ]: 0 : dtde.SourceActions );
240 : : }
241 : :
242 : : // reject drag if no listener found
243 [ # # ]: 0 : if( nListeners == 0 )
244 : : {
245 : : OSL_TRACE( "rejecting dropActionChanged due to missing listeners." );
246 [ # # ][ # # ]: 0 : dtde.Context->rejectDrag();
247 [ # # ]: 0 : }
248 : 0 : }
249 : :
250 : :
251 : : //==================================================================================================
252 : : // DNDEventDispatcher::dragGestureRecognized
253 : : //==================================================================================================
254 : :
255 : 0 : void SAL_CALL DNDEventDispatcher::dragGestureRecognized( const DragGestureEvent& dge )
256 : : throw(RuntimeException)
257 : : {
258 [ # # ]: 0 : osl::MutexGuard aImplGuard( m_aMutex );
259 : :
260 : 0 : Point origin( dge.DragOriginX, dge.DragOriginY );
261 : :
262 [ # # ]: 0 : Window* pChildWindow = findTopLevelWindow(origin);
263 : :
264 [ # # ][ # # ]: 0 : fireDragGestureEvent( pChildWindow, dge.DragSource, dge.Event, origin, dge.DragAction );
265 : 0 : }
266 : :
267 : : //==================================================================================================
268 : : // DNDEventDispatcher::disposing
269 : : //==================================================================================================
270 : :
271 : 2754 : void SAL_CALL DNDEventDispatcher::disposing( const EventObject& )
272 : : throw(RuntimeException)
273 : : {
274 : 2754 : }
275 : :
276 : : //==================================================================================================
277 : : // DNDEventDispatcher::acceptDrag
278 : : //==================================================================================================
279 : :
280 : 0 : void SAL_CALL DNDEventDispatcher::acceptDrag( sal_Int8 /*dropAction*/ ) throw(RuntimeException)
281 : : {
282 : 0 : }
283 : :
284 : : //==================================================================================================
285 : : // DNDEventDispatcher::rejectDrag
286 : : //==================================================================================================
287 : :
288 : 0 : void SAL_CALL DNDEventDispatcher::rejectDrag() throw(RuntimeException)
289 : : {
290 : 0 : }
291 : :
292 : : //==================================================================================================
293 : : // DNDEventDispatcher::fireDragEnterEvent
294 : : //==================================================================================================
295 : :
296 : 0 : sal_Int32 DNDEventDispatcher::fireDragEnterEvent( Window *pWindow,
297 : : const Reference< XDropTargetDragContext >& xContext, const sal_Int8 nDropAction,
298 : : const Point& rLocation, const sal_Int8 nSourceActions, const Sequence< DataFlavor >& aFlavorList
299 : : )
300 : : throw(RuntimeException)
301 : : {
302 : 0 : sal_Int32 n = 0;
303 : :
304 [ # # ][ # # ]: 0 : if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
[ # # ][ # # ]
305 : : {
306 [ # # ]: 0 : SolarMutexClearableGuard aSolarGuard;
307 : :
308 : : // set an UI lock
309 [ # # ]: 0 : pWindow->IncrementLockCount();
310 : :
311 : : // query DropTarget from window
312 [ # # ]: 0 : Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();
313 : :
314 [ # # ]: 0 : if( xDropTarget.is() )
315 : : {
316 : : // retrieve relative mouse position
317 [ # # ]: 0 : Point relLoc = pWindow->ImplFrameToOutput( rLocation );
318 [ # # ]: 0 : aSolarGuard.clear();
319 : :
320 [ # # ]: 0 : n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDragEnterEvent(
321 [ # # ][ # # ]: 0 : xContext, nDropAction, relLoc.X(), relLoc.Y(), nSourceActions, aFlavorList );
322 [ # # ]: 0 : }
323 : : }
324 : :
325 : 0 : return n;
326 : : }
327 : :
328 : : //==================================================================================================
329 : : // DNDEventDispatcher::fireDragOverEvent
330 : : //==================================================================================================
331 : :
332 : 0 : sal_Int32 DNDEventDispatcher::fireDragOverEvent( Window *pWindow,
333 : : const Reference< XDropTargetDragContext >& xContext, const sal_Int8 nDropAction,
334 : : const Point& rLocation, const sal_Int8 nSourceActions
335 : : )
336 : : throw(RuntimeException)
337 : : {
338 : 0 : sal_Int32 n = 0;
339 : :
340 [ # # ][ # # ]: 0 : if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
[ # # ][ # # ]
341 : : {
342 [ # # ]: 0 : SolarMutexClearableGuard aSolarGuard;
343 : :
344 : : // query DropTarget from window
345 [ # # ]: 0 : Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();
346 : :
347 [ # # ]: 0 : if( xDropTarget.is() )
348 : : {
349 : : // retrieve relative mouse position
350 [ # # ]: 0 : Point relLoc = pWindow->ImplFrameToOutput( rLocation );
351 [ # # ]: 0 : aSolarGuard.clear();
352 : :
353 [ # # ]: 0 : n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDragOverEvent(
354 [ # # ][ # # ]: 0 : xContext, nDropAction, relLoc.X(), relLoc.Y(), nSourceActions );
355 [ # # ]: 0 : }
356 : : }
357 : :
358 : 0 : return n;
359 : : }
360 : :
361 : : //==================================================================================================
362 : : // DNDEventDispatcher::fireDragExitEvent
363 : : //==================================================================================================
364 : :
365 : 0 : sal_Int32 DNDEventDispatcher::fireDragExitEvent( Window *pWindow ) throw(RuntimeException)
366 : : {
367 : 0 : sal_Int32 n = 0;
368 : :
369 [ # # ][ # # ]: 0 : if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
[ # # ][ # # ]
370 : : {
371 [ # # ]: 0 : SolarMutexClearableGuard aGuard;
372 : :
373 : : // query DropTarget from window
374 [ # # ]: 0 : Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();
375 : :
376 [ # # ]: 0 : aGuard.clear();
377 : :
378 [ # # ]: 0 : if( xDropTarget.is() )
379 [ # # ][ # # ]: 0 : n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDragExitEvent();
[ # # ]
380 : :
381 : : // release UI lock
382 [ # # ][ # # ]: 0 : pWindow->DecrementLockCount();
383 : : }
384 : :
385 : 0 : return n;
386 : : }
387 : :
388 : : //==================================================================================================
389 : : // DNDEventDispatcher::fireDropActionChangedEvent
390 : : //==================================================================================================
391 : :
392 : 0 : sal_Int32 DNDEventDispatcher::fireDropActionChangedEvent( Window *pWindow,
393 : : const Reference< XDropTargetDragContext >& xContext, const sal_Int8 nDropAction,
394 : : const Point& rLocation, const sal_Int8 nSourceActions
395 : : )
396 : : throw(RuntimeException)
397 : : {
398 : 0 : sal_Int32 n = 0;
399 : :
400 [ # # ][ # # ]: 0 : if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
[ # # ][ # # ]
401 : : {
402 [ # # ]: 0 : SolarMutexClearableGuard aGuard;
403 : :
404 : : // query DropTarget from window
405 [ # # ]: 0 : Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();
406 : :
407 [ # # ]: 0 : if( xDropTarget.is() )
408 : : {
409 : : // retrieve relative mouse position
410 [ # # ]: 0 : Point relLoc = pWindow->ImplFrameToOutput( rLocation );
411 [ # # ]: 0 : aGuard.clear();
412 : :
413 [ # # ]: 0 : n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDropActionChangedEvent(
414 [ # # ][ # # ]: 0 : xContext, nDropAction, relLoc.X(), relLoc.Y(), nSourceActions );
415 [ # # ]: 0 : }
416 : : }
417 : :
418 : 0 : return n;
419 : : }
420 : :
421 : : //==================================================================================================
422 : : // DNDEventDispatcher::fireDropEvent
423 : : //==================================================================================================
424 : :
425 : 0 : sal_Int32 DNDEventDispatcher::fireDropEvent( Window *pWindow,
426 : : const Reference< XDropTargetDropContext >& xContext, const sal_Int8 nDropAction, const Point& rLocation,
427 : : const sal_Int8 nSourceActions, const Reference< XTransferable >& xTransferable
428 : : )
429 : : throw(RuntimeException)
430 : : {
431 : 0 : sal_Int32 n = 0;
432 : :
433 [ # # ][ # # ]: 0 : if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
[ # # ][ # # ]
434 : : {
435 [ # # ]: 0 : SolarMutexClearableGuard aGuard;
436 : :
437 : : // query DropTarget from window
438 [ # # ]: 0 : Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();
439 : :
440 : : // window may be destroyed in drop event handler
441 [ # # ]: 0 : ImplDelData aDelData;
442 [ # # ]: 0 : pWindow->ImplAddDel( &aDelData );
443 : :
444 [ # # ]: 0 : if( xDropTarget.is() )
445 : : {
446 : : // retrieve relative mouse position
447 [ # # ]: 0 : Point relLoc = pWindow->ImplFrameToOutput( rLocation );
448 [ # # ]: 0 : aGuard.clear();
449 : :
450 [ # # ]: 0 : n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDropEvent(
451 [ # # ][ # # ]: 0 : xContext, nDropAction, relLoc.X(), relLoc.Y(), nSourceActions, xTransferable );
452 : : }
453 : :
454 [ # # ]: 0 : if ( !aDelData.IsDead() )
455 : : {
456 [ # # ]: 0 : pWindow->ImplRemoveDel( &aDelData );
457 : : // release UI lock
458 [ # # ]: 0 : pWindow->DecrementLockCount();
459 [ # # ][ # # ]: 0 : }
460 : :
461 : : }
462 : :
463 : 0 : return n;
464 : : }
465 : :
466 : : //==================================================================================================
467 : : // DNDEventDispatcher::fireDragGestureRecognized
468 : : //==================================================================================================
469 : :
470 : 0 : sal_Int32 DNDEventDispatcher::fireDragGestureEvent( Window *pWindow,
471 : : const Reference< XDragSource >& xSource, const Any event,
472 : : const Point& rOrigin, const sal_Int8 nDragAction
473 : : )
474 : : throw(::com::sun::star::uno::RuntimeException)
475 : : {
476 : 0 : sal_Int32 n = 0;
477 : :
478 [ # # ][ # # ]: 0 : if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
[ # # ][ # # ]
479 : : {
480 [ # # ]: 0 : SolarMutexClearableGuard aGuard;
481 : :
482 : : // query DropTarget from window
483 [ # # ]: 0 : Reference< XDragGestureRecognizer > xDragGestureRecognizer = pWindow->GetDragGestureRecognizer();
484 : :
485 [ # # ]: 0 : if( xDragGestureRecognizer.is() )
486 : : {
487 : : // retrieve relative mouse position
488 [ # # ]: 0 : Point relLoc = pWindow->ImplFrameToOutput( rOrigin );
489 [ # # ]: 0 : aGuard.clear();
490 : :
491 [ # # ]: 0 : n = static_cast < DNDListenerContainer * > ( xDragGestureRecognizer.get() )->fireDragGestureEvent(
492 [ # # ][ # # ]: 0 : nDragAction, relLoc.X(), relLoc.Y(), xSource, event );
493 : : }
494 : :
495 : : // release UI lock
496 [ # # ][ # # ]: 0 : pWindow->DecrementLockCount();
497 : : }
498 : :
499 : 0 : return n;
500 : : }
501 : :
502 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|