bump product version to 6.4.0.3
[LibreOffice.git] / vcl / source / window / dndeventdispatcher.cxx
blob9af6ab6e76c3cb7d5a5f1de09f5a7d547716c033
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
20 #include <dndeventdispatcher.hxx>
21 #include <dndlistenercontainer.hxx>
22 #include <sal/log.hxx>
24 #include <osl/mutex.hxx>
25 #include <vcl/svapp.hxx>
26 #include <vcl/settings.hxx>
28 using namespace ::cppu;
29 using namespace ::com::sun::star::uno;
30 using namespace ::com::sun::star::lang;
31 using namespace ::com::sun::star::datatransfer;
32 using namespace ::com::sun::star::datatransfer::dnd;
34 DNDEventDispatcher::DNDEventDispatcher( vcl::Window * pTopWindow ):
35 m_pTopWindow( pTopWindow ),
36 m_pCurrentWindow( nullptr )
40 DNDEventDispatcher::~DNDEventDispatcher()
42 designate_currentwindow(nullptr);
45 vcl::Window* DNDEventDispatcher::findTopLevelWindow(Point location)
47 SolarMutexGuard aSolarGuard;
49 // find the window that is toplevel for this coordinates
50 // because those coordinates come from outside, they must be mirrored if RTL layout is active
51 if( AllSettings::GetLayoutRTL() )
52 m_pTopWindow->ImplMirrorFramePos( location );
53 vcl::Window * pChildWindow = m_pTopWindow->ImplFindWindow( location );
55 if( nullptr == pChildWindow )
56 pChildWindow = m_pTopWindow;
58 while( pChildWindow->ImplGetClientWindow() )
59 pChildWindow = pChildWindow->ImplGetClientWindow();
61 if( pChildWindow->ImplIsAntiparallel() )
63 const OutputDevice *pChildWinOutDev = pChildWindow->GetOutDev();
64 pChildWinOutDev->ReMirror( location );
67 return pChildWindow;
70 IMPL_LINK(DNDEventDispatcher, WindowEventListener, VclWindowEvent&, rEvent, void)
72 if (rEvent.GetId() == VclEventId::ObjectDying)
74 designate_currentwindow(nullptr);
78 void DNDEventDispatcher::designate_currentwindow(vcl::Window *pWindow)
80 if (m_pCurrentWindow)
81 m_pCurrentWindow->RemoveEventListener(LINK(this, DNDEventDispatcher, WindowEventListener));
82 m_pCurrentWindow = pWindow;
83 if (m_pCurrentWindow)
84 m_pCurrentWindow->AddEventListener(LINK(this, DNDEventDispatcher, WindowEventListener));
87 void SAL_CALL DNDEventDispatcher::drop( const DropTargetDropEvent& dtde )
89 osl::MutexGuard aImplGuard( m_aMutex );
91 Point location( dtde.LocationX, dtde.LocationY );
93 vcl::Window* pChildWindow = findTopLevelWindow(location);
95 // handle the case that drop is in another vcl window than the last dragOver
96 if( pChildWindow != m_pCurrentWindow.get() )
98 // fire dragExit on listeners of previous window
99 fireDragExitEvent( m_pCurrentWindow );
101 fireDragEnterEvent( pChildWindow, static_cast < XDropTargetDragContext * > (this),
102 dtde.DropAction, location, dtde.SourceActions, m_aDataFlavorList );
105 // send drop event to the child window
106 sal_Int32 nListeners = fireDropEvent( pChildWindow, dtde.Context, dtde.DropAction,
107 location, dtde.SourceActions, dtde.Transferable );
109 // reject drop if no listeners found
110 if( nListeners == 0 ) {
111 SAL_WARN( "vcl", "rejecting drop due to missing listeners." );
112 dtde.Context->rejectDrop();
115 // this is a drop -> no further drag overs
116 designate_currentwindow(nullptr);
117 m_aDataFlavorList.realloc( 0 );
120 void SAL_CALL DNDEventDispatcher::dragEnter( const DropTargetDragEnterEvent& dtdee )
122 osl::MutexGuard aImplGuard( m_aMutex );
123 Point location( dtdee.LocationX, dtdee.LocationY );
125 vcl::Window * pChildWindow = findTopLevelWindow(location);
127 // assume pointer write operation to be atomic
128 designate_currentwindow(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 SAL_WARN( "vcl", "rejecting drag enter due to missing listeners." );
138 dtdee.Context->rejectDrag();
143 void SAL_CALL DNDEventDispatcher::dragExit( const DropTargetEvent& /*dte*/ )
145 osl::MutexGuard aImplGuard( m_aMutex );
147 fireDragExitEvent( m_pCurrentWindow );
149 // reset member values
150 designate_currentwindow(nullptr);
151 m_aDataFlavorList.realloc( 0 );
154 void SAL_CALL DNDEventDispatcher::dragOver( const DropTargetDragEvent& dtde )
156 osl::MutexGuard aImplGuard( m_aMutex );
158 Point location( dtde.LocationX, dtde.LocationY );
159 sal_Int32 nListeners;
161 vcl::Window * pChildWindow = findTopLevelWindow(location);
163 if( pChildWindow != m_pCurrentWindow.get() )
165 // fire dragExit on listeners of previous window
166 fireDragExitEvent( m_pCurrentWindow );
168 // remember new window
169 designate_currentwindow(pChildWindow);
171 // fire dragEnter on listeners of current window
172 nListeners = fireDragEnterEvent( pChildWindow, dtde.Context, dtde.DropAction, location,
173 dtde.SourceActions, m_aDataFlavorList );
175 else
177 // fire dragOver on listeners of current window
178 nListeners = fireDragOverEvent( pChildWindow, dtde.Context, dtde.DropAction, location,
179 dtde.SourceActions );
182 // reject drag if no listener found
183 if( nListeners == 0 )
185 SAL_WARN( "vcl", "rejecting drag over due to missing listeners." );
186 dtde.Context->rejectDrag();
190 void SAL_CALL DNDEventDispatcher::dropActionChanged( const DropTargetDragEvent& dtde )
192 osl::MutexGuard aImplGuard( m_aMutex );
194 Point location( dtde.LocationX, dtde.LocationY );
195 sal_Int32 nListeners;
197 vcl::Window* pChildWindow = findTopLevelWindow(location);
199 if( pChildWindow != m_pCurrentWindow.get() )
201 // fire dragExit on listeners of previous window
202 fireDragExitEvent( m_pCurrentWindow );
204 // remember new window
205 designate_currentwindow(pChildWindow);
207 // fire dragEnter on listeners of current window
208 nListeners = fireDragEnterEvent( pChildWindow, dtde.Context, dtde.DropAction, location,
209 dtde.SourceActions, m_aDataFlavorList );
211 else
213 // fire dropActionChanged on listeners of current window
214 nListeners = fireDropActionChangedEvent( pChildWindow, dtde.Context, dtde.DropAction, location,
215 dtde.SourceActions );
218 // reject drag if no listener found
219 if( nListeners == 0 )
221 SAL_WARN( "vcl", "rejecting dropActionChanged due to missing listeners." );
222 dtde.Context->rejectDrag();
226 void SAL_CALL DNDEventDispatcher::dragGestureRecognized( const DragGestureEvent& dge )
228 osl::MutexGuard aImplGuard( m_aMutex );
230 Point origin( dge.DragOriginX, dge.DragOriginY );
232 vcl::Window* pChildWindow = findTopLevelWindow(origin);
234 fireDragGestureEvent( pChildWindow, dge.DragSource, dge.Event, origin, dge.DragAction );
237 void SAL_CALL DNDEventDispatcher::disposing( const EventObject& )
241 void SAL_CALL DNDEventDispatcher::acceptDrag( sal_Int8 /*dropAction*/ )
245 void SAL_CALL DNDEventDispatcher::rejectDrag()
249 sal_Int32 DNDEventDispatcher::fireDragEnterEvent( vcl::Window *pWindow,
250 const Reference< XDropTargetDragContext >& xContext, const sal_Int8 nDropAction,
251 const Point& rLocation, const sal_Int8 nSourceActions, const Sequence< DataFlavor >& aFlavorList
254 sal_Int32 n = 0;
256 if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
258 SolarMutexClearableGuard aSolarGuard;
260 // query DropTarget from window
261 Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();
263 if( xDropTarget.is() )
265 // retrieve relative mouse position
266 Point relLoc = pWindow->ImplFrameToOutput( rLocation );
267 aSolarGuard.clear();
269 n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDragEnterEvent(
270 xContext, nDropAction, relLoc.X(), relLoc.Y(), nSourceActions, aFlavorList );
274 return n;
277 sal_Int32 DNDEventDispatcher::fireDragOverEvent( vcl::Window *pWindow,
278 const Reference< XDropTargetDragContext >& xContext, const sal_Int8 nDropAction,
279 const Point& rLocation, const sal_Int8 nSourceActions
282 sal_Int32 n = 0;
284 if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
286 SolarMutexClearableGuard aSolarGuard;
288 // query DropTarget from window
289 Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();
291 if( xDropTarget.is() )
293 // retrieve relative mouse position
294 Point relLoc = pWindow->ImplFrameToOutput( rLocation );
295 aSolarGuard.clear();
297 n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDragOverEvent(
298 xContext, nDropAction, relLoc.X(), relLoc.Y(), nSourceActions );
302 return n;
305 sal_Int32 DNDEventDispatcher::fireDragExitEvent( vcl::Window *pWindow )
307 sal_Int32 n = 0;
309 if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
311 SolarMutexClearableGuard aGuard;
313 // query DropTarget from window
314 Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();
316 aGuard.clear();
318 if( xDropTarget.is() )
319 n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDragExitEvent();
322 return n;
325 sal_Int32 DNDEventDispatcher::fireDropActionChangedEvent( vcl::Window *pWindow,
326 const Reference< XDropTargetDragContext >& xContext, const sal_Int8 nDropAction,
327 const Point& rLocation, const sal_Int8 nSourceActions
330 sal_Int32 n = 0;
332 if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
334 SolarMutexClearableGuard aGuard;
336 // query DropTarget from window
337 Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();
339 if( xDropTarget.is() )
341 // retrieve relative mouse position
342 Point relLoc = pWindow->ImplFrameToOutput( rLocation );
343 aGuard.clear();
345 n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDropActionChangedEvent(
346 xContext, nDropAction, relLoc.X(), relLoc.Y(), nSourceActions );
350 return n;
353 sal_Int32 DNDEventDispatcher::fireDropEvent( vcl::Window *pWindow,
354 const Reference< XDropTargetDropContext >& xContext, const sal_Int8 nDropAction, const Point& rLocation,
355 const sal_Int8 nSourceActions, const Reference< XTransferable >& xTransferable
358 sal_Int32 n = 0;
360 if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
362 SolarMutexClearableGuard aGuard;
364 // query DropTarget from window
365 Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();
367 // window may be destroyed in drop event handler
368 VclPtr<vcl::Window> xWindow = pWindow;
370 if( xDropTarget.is() )
372 // retrieve relative mouse position
373 Point relLoc = pWindow->ImplFrameToOutput( rLocation );
374 aGuard.clear();
376 n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDropEvent(
377 xContext, nDropAction, relLoc.X(), relLoc.Y(), nSourceActions, xTransferable );
381 return n;
384 sal_Int32 DNDEventDispatcher::fireDragGestureEvent( vcl::Window *pWindow,
385 const Reference< XDragSource >& xSource, const Any& event,
386 const Point& rOrigin, const sal_Int8 nDragAction
389 sal_Int32 n = 0;
391 if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
393 SolarMutexClearableGuard aGuard;
395 // query DropTarget from window
396 Reference< XDragGestureRecognizer > xDragGestureRecognizer = pWindow->GetDragGestureRecognizer();
398 if( xDragGestureRecognizer.is() )
400 // retrieve relative mouse position
401 Point relLoc = pWindow->ImplFrameToOutput( rOrigin );
402 aGuard.clear();
404 n = static_cast < DNDListenerContainer * > ( xDragGestureRecognizer.get() )->fireDragGestureEvent(
405 nDragAction, relLoc.X(), relLoc.Y(), xSource, event );
409 return n;
412 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */