1*48123e16SAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
3*48123e16SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
4*48123e16SAndrew Rist * or more contributor license agreements. See the NOTICE file
5*48123e16SAndrew Rist * distributed with this work for additional information
6*48123e16SAndrew Rist * regarding copyright ownership. The ASF licenses this file
7*48123e16SAndrew Rist * to you under the Apache License, Version 2.0 (the
8*48123e16SAndrew Rist * "License"); you may not use this file except in compliance
9*48123e16SAndrew Rist * with the License. You may obtain a copy of the License at
10*48123e16SAndrew Rist *
11*48123e16SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12*48123e16SAndrew Rist *
13*48123e16SAndrew Rist * Unless required by applicable law or agreed to in writing,
14*48123e16SAndrew Rist * software distributed under the License is distributed on an
15*48123e16SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*48123e16SAndrew Rist * KIND, either express or implied. See the License for the
17*48123e16SAndrew Rist * specific language governing permissions and limitations
18*48123e16SAndrew Rist * under the License.
19*48123e16SAndrew Rist *
20*48123e16SAndrew Rist *************************************************************/
21*48123e16SAndrew Rist
22*48123e16SAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_dtrans.hxx"
26cdf0e10cSrcweir #include <com/sun/star/datatransfer/dnd/DNDConstants.hpp>
27cdf0e10cSrcweir #include <com/sun/star/datatransfer/XTransferable.hpp>
28cdf0e10cSrcweir #include <rtl/unload.h>
29cdf0e10cSrcweir
30cdf0e10cSrcweir #include <stdio.h>
31cdf0e10cSrcweir #include "target.hxx"
32cdf0e10cSrcweir #include "idroptarget.hxx"
33cdf0e10cSrcweir #include "globals.hxx"
34cdf0e10cSrcweir #include "targetdropcontext.hxx"
35cdf0e10cSrcweir #include "targetdragcontext.hxx"
36cdf0e10cSrcweir #include <rtl/ustring.h>
37cdf0e10cSrcweir using namespace rtl;
38cdf0e10cSrcweir using namespace cppu;
39cdf0e10cSrcweir using namespace osl;
40cdf0e10cSrcweir using namespace com::sun::star::datatransfer;
41cdf0e10cSrcweir using namespace com::sun::star::datatransfer::dnd;
42cdf0e10cSrcweir using namespace com::sun::star::datatransfer::dnd::DNDConstants;
43cdf0e10cSrcweir
44cdf0e10cSrcweir #define WM_REGISTERDRAGDROP WM_USER + 1
45cdf0e10cSrcweir #define WM_REVOKEDRAGDROP WM_USER + 2
46cdf0e10cSrcweir //--> TRA
47cdf0e10cSrcweir extern Reference< XTransferable > g_XTransferable;
48cdf0e10cSrcweir
49cdf0e10cSrcweir //<-- TRA
50cdf0e10cSrcweir
51cdf0e10cSrcweir extern rtl_StandardModuleCount g_moduleCount;
52cdf0e10cSrcweir DWORD WINAPI DndTargetOleSTAFunc(LPVOID pParams);
53cdf0e10cSrcweir
DropTarget(const Reference<XMultiServiceFactory> & sf)54cdf0e10cSrcweir DropTarget::DropTarget( const Reference<XMultiServiceFactory>& sf):
55cdf0e10cSrcweir m_hWnd( NULL),
56cdf0e10cSrcweir m_serviceFactory( sf),
57cdf0e10cSrcweir WeakComponentImplHelper3<XInitialization,XDropTarget, XServiceInfo>(m_mutex),
58cdf0e10cSrcweir m_bActive(sal_True),
59cdf0e10cSrcweir m_nDefaultActions(ACTION_COPY|ACTION_MOVE|ACTION_LINK|ACTION_DEFAULT),
60cdf0e10cSrcweir m_nCurrentDropAction( ACTION_NONE),
61cdf0e10cSrcweir m_oleThreadId( 0),
62cdf0e10cSrcweir m_pDropTarget( NULL),
63cdf0e10cSrcweir m_threadIdWindow(0),
64cdf0e10cSrcweir m_threadIdTarget(0),
65cdf0e10cSrcweir m_hOleThread(0),
66cdf0e10cSrcweir m_nLastDropAction(0)
67cdf0e10cSrcweir
68cdf0e10cSrcweir
69cdf0e10cSrcweir {
70cdf0e10cSrcweir g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
71cdf0e10cSrcweir }
72cdf0e10cSrcweir
73cdf0e10cSrcweir
~DropTarget()74cdf0e10cSrcweir DropTarget::~DropTarget()
75cdf0e10cSrcweir {
76cdf0e10cSrcweir g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
77cdf0e10cSrcweir
78cdf0e10cSrcweir }
79cdf0e10cSrcweir // called from WeakComponentImplHelperX::dispose
80cdf0e10cSrcweir // WeakComponentImplHelper calls disposing before it destroys
81cdf0e10cSrcweir // itself.
82cdf0e10cSrcweir // NOTE: RevokeDragDrop decrements the ref count on the IDropTarget
83cdf0e10cSrcweir // interface. (m_pDropTarget)
84cdf0e10cSrcweir // If the HWND is invalid then it doesn't decrement and
85cdf0e10cSrcweir // the IDropTarget object will live on. MEMORY LEAK
disposing()86cdf0e10cSrcweir void SAL_CALL DropTarget::disposing()
87cdf0e10cSrcweir {
88cdf0e10cSrcweir HRESULT hr= S_OK;
89cdf0e10cSrcweir if( m_threadIdTarget)
90cdf0e10cSrcweir {
91cdf0e10cSrcweir // Call RevokeDragDrop and wait for the OLE thread to die;
92cdf0e10cSrcweir PostThreadMessage( m_threadIdTarget, WM_REVOKEDRAGDROP, (WPARAM)this, 0);
93cdf0e10cSrcweir WaitForSingleObject( m_hOleThread, INFINITE);
94cdf0e10cSrcweir CloseHandle( m_hOleThread);
95cdf0e10cSrcweir //OSL_ENSURE( SUCCEEDED( hr), "HWND not valid!" );
96cdf0e10cSrcweir }
97cdf0e10cSrcweir else
98cdf0e10cSrcweir {
99cdf0e10cSrcweir hr= RevokeDragDrop( m_hWnd);
100cdf0e10cSrcweir m_hWnd= 0;
101cdf0e10cSrcweir }
102cdf0e10cSrcweir if( m_pDropTarget)
103cdf0e10cSrcweir {
104cdf0e10cSrcweir CoLockObjectExternal( m_pDropTarget, FALSE, TRUE);
105cdf0e10cSrcweir m_pDropTarget->Release();
106cdf0e10cSrcweir }
107cdf0e10cSrcweir
108cdf0e10cSrcweir if( m_oleThreadId)
109cdf0e10cSrcweir {
110cdf0e10cSrcweir if( m_oleThreadId == CoGetCurrentProcess() )
111cdf0e10cSrcweir OleUninitialize();
112cdf0e10cSrcweir }
113cdf0e10cSrcweir
114cdf0e10cSrcweir }
115cdf0e10cSrcweir
initialize(const Sequence<Any> & aArguments)116cdf0e10cSrcweir void SAL_CALL DropTarget::initialize( const Sequence< Any >& aArguments )
117cdf0e10cSrcweir throw(Exception, RuntimeException)
118cdf0e10cSrcweir {
119cdf0e10cSrcweir // The window must be registered for Dnd by RegisterDragDrop. We must ensure
120cdf0e10cSrcweir // that RegisterDragDrop is called from an STA ( OleInitialize) thread.
121cdf0e10cSrcweir // As long as the window is registered we need to receive OLE messages in
122cdf0e10cSrcweir // an OLE thread. That is to say, if DropTarget::initialize was called from an
123cdf0e10cSrcweir // MTA thread then we create an OLE thread in which the window is registered.
124cdf0e10cSrcweir // The thread will stay alive until aver RevokeDragDrop has been called.
125cdf0e10cSrcweir
126cdf0e10cSrcweir // Additionally even if RegisterDragDrop is called from an STA thread we have
127cdf0e10cSrcweir // to ensure that it is called from the same thread that created the Window
128cdf0e10cSrcweir // otherwise meesages sent during DND won't reach the windows message queue.
129cdf0e10cSrcweir // Calling AttachThreadInput first would resolve this problem but would block
130cdf0e10cSrcweir // the message queue of the calling thread. So if the current thread
131cdf0e10cSrcweir // (even if it's an STA thread) and the thread that created the window are not
132cdf0e10cSrcweir // identical we need to create a new thread as we do when the calling thread is
133cdf0e10cSrcweir // an MTA thread.
134cdf0e10cSrcweir
135cdf0e10cSrcweir if( aArguments.getLength() > 0)
136cdf0e10cSrcweir {
137cdf0e10cSrcweir // Get the window handle from aArgument. It is needed for RegisterDragDrop.
138cdf0e10cSrcweir m_hWnd= *(HWND*)aArguments[0].getValue();
139cdf0e10cSrcweir OSL_ASSERT( IsWindow( m_hWnd) );
140cdf0e10cSrcweir
141cdf0e10cSrcweir // Obtain the id of the thread that created the window
142cdf0e10cSrcweir m_threadIdWindow= GetWindowThreadProcessId( m_hWnd, NULL);
143cdf0e10cSrcweir
144cdf0e10cSrcweir HRESULT hr= OleInitialize( NULL);
145cdf0e10cSrcweir
146cdf0e10cSrcweir // Current thread is MTA or Current thread and Window thread are not identical
147cdf0e10cSrcweir if( hr == RPC_E_CHANGED_MODE || GetCurrentThreadId() != m_threadIdWindow )
148cdf0e10cSrcweir {
149cdf0e10cSrcweir OSL_ENSURE( ! m_threadIdTarget,"initialize was called twice");
150cdf0e10cSrcweir // create the IDropTargetImplementation
151cdf0e10cSrcweir m_pDropTarget= new IDropTargetImpl( *static_cast<DropTarget*>( this) );
152cdf0e10cSrcweir m_pDropTarget->AddRef();
153cdf0e10cSrcweir
154cdf0e10cSrcweir
155cdf0e10cSrcweir // Obtain the id of the thread that created the window
156cdf0e10cSrcweir m_threadIdWindow= GetWindowThreadProcessId( m_hWnd, NULL);
157cdf0e10cSrcweir // The event is set by the thread that we will create momentarily.
158cdf0e10cSrcweir // It indicates that the thread is ready to receive messages.
159cdf0e10cSrcweir HANDLE m_evtThreadReady= CreateEvent( NULL, FALSE, FALSE, NULL);
160cdf0e10cSrcweir
161cdf0e10cSrcweir m_hOleThread= CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)DndTargetOleSTAFunc,
162cdf0e10cSrcweir &m_evtThreadReady, 0, &m_threadIdTarget);
163cdf0e10cSrcweir WaitForSingleObject( m_evtThreadReady, INFINITE);
164cdf0e10cSrcweir CloseHandle( m_evtThreadReady);
165cdf0e10cSrcweir PostThreadMessage( m_threadIdTarget, WM_REGISTERDRAGDROP, (WPARAM)static_cast<DropTarget*>(this), 0);
166cdf0e10cSrcweir }
167cdf0e10cSrcweir else if( hr == S_OK || hr == S_FALSE)
168cdf0e10cSrcweir {
169cdf0e10cSrcweir // current thread is STA
170cdf0e10cSrcweir // If OleInitialize has been called by the caller then we must not call
171cdf0e10cSrcweir // OleUninitialize
172cdf0e10cSrcweir if( hr == S_OK)
173cdf0e10cSrcweir {
174cdf0e10cSrcweir // caller did not call OleInitialize, so we call OleUninitialize
175cdf0e10cSrcweir // remember the thread that will call OleUninitialize
176cdf0e10cSrcweir m_oleThreadId= CoGetCurrentProcess(); // get a unique thread id
177cdf0e10cSrcweir }
178cdf0e10cSrcweir
179cdf0e10cSrcweir // Get the window handle from aArgument. It is needed for RegisterDragDrop.
180cdf0e10cSrcweir // create the IDropTargetImplementation
181cdf0e10cSrcweir m_pDropTarget= new IDropTargetImpl( *static_cast<DropTarget*>( this) );
182cdf0e10cSrcweir m_pDropTarget->AddRef();
183cdf0e10cSrcweir // CoLockObjectExternal is prescribed by the protocol. It bumps up the ref count
184cdf0e10cSrcweir if( SUCCEEDED( CoLockObjectExternal( m_pDropTarget, TRUE, FALSE)))
185cdf0e10cSrcweir {
186cdf0e10cSrcweir if( FAILED( RegisterDragDrop( m_hWnd, m_pDropTarget) ) )
187cdf0e10cSrcweir {
188cdf0e10cSrcweir // do clean up if drag and drop is not possible
189cdf0e10cSrcweir CoLockObjectExternal( m_pDropTarget, FALSE, FALSE);
190cdf0e10cSrcweir m_pDropTarget->Release();
191cdf0e10cSrcweir m_hWnd= NULL;
192cdf0e10cSrcweir }
193cdf0e10cSrcweir }
194cdf0e10cSrcweir }
195cdf0e10cSrcweir else
196cdf0e10cSrcweir throw Exception();
197cdf0e10cSrcweir
198cdf0e10cSrcweir }
199cdf0e10cSrcweir }
200cdf0e10cSrcweir
201cdf0e10cSrcweir // This function is called as extra thread from DragSource::startDrag.
202cdf0e10cSrcweir // The function carries out a drag and drop operation by calling
203cdf0e10cSrcweir // DoDragDrop. The thread also notifies all XSourceListener.
DndTargetOleSTAFunc(LPVOID pParams)204cdf0e10cSrcweir DWORD WINAPI DndTargetOleSTAFunc(LPVOID pParams)
205cdf0e10cSrcweir {
206cdf0e10cSrcweir HRESULT hr= OleInitialize( NULL);
207cdf0e10cSrcweir if( SUCCEEDED( hr) )
208cdf0e10cSrcweir {
209cdf0e10cSrcweir MSG msg;
210cdf0e10cSrcweir // force the creation of a message queue
211cdf0e10cSrcweir PeekMessage( &msg, (HWND)NULL, 0, 0, PM_NOREMOVE);
212cdf0e10cSrcweir // Signal the creator ( DropTarget::initialize) that the thread is
213cdf0e10cSrcweir // ready to receive messages.
214cdf0e10cSrcweir SetEvent( *(HANDLE*) pParams);
215cdf0e10cSrcweir // Thread id is needed for attaching this message queue to the one of the
216cdf0e10cSrcweir // thread where the window was created.
217cdf0e10cSrcweir DWORD threadId= GetCurrentThreadId();
218cdf0e10cSrcweir // We force the creation of a thread message queue. This is necessary
219cdf0e10cSrcweir // for a later call to AttachThreadInput
220cdf0e10cSrcweir while( GetMessage(&msg, (HWND)NULL, 0, 0) )
221cdf0e10cSrcweir {
222cdf0e10cSrcweir if( msg.message == WM_REGISTERDRAGDROP)
223cdf0e10cSrcweir {
224cdf0e10cSrcweir DropTarget *pTarget= (DropTarget*)msg.wParam;
225cdf0e10cSrcweir // This thread is attached to the thread that created the window. Hence
226cdf0e10cSrcweir // this thread also receives all mouse and keyboard messages which are
227cdf0e10cSrcweir // needed
228cdf0e10cSrcweir AttachThreadInput( threadId , pTarget->m_threadIdWindow, TRUE );
229cdf0e10cSrcweir
230cdf0e10cSrcweir if( SUCCEEDED( CoLockObjectExternal(pTarget-> m_pDropTarget, TRUE, FALSE)))
231cdf0e10cSrcweir {
232cdf0e10cSrcweir if( FAILED( RegisterDragDrop( pTarget-> m_hWnd, pTarget-> m_pDropTarget) ) )
233cdf0e10cSrcweir {
234cdf0e10cSrcweir // do clean up if drag and drop is not possible
235cdf0e10cSrcweir CoLockObjectExternal( pTarget->m_pDropTarget, FALSE, FALSE);
236cdf0e10cSrcweir pTarget->m_pDropTarget->Release();
237cdf0e10cSrcweir pTarget->m_hWnd= NULL;
238cdf0e10cSrcweir }
239cdf0e10cSrcweir }
240cdf0e10cSrcweir }
241cdf0e10cSrcweir else if( msg.message == WM_REVOKEDRAGDROP)
242cdf0e10cSrcweir {
243cdf0e10cSrcweir DropTarget *pTarget= (DropTarget*)msg.wParam;
244cdf0e10cSrcweir RevokeDragDrop( pTarget-> m_hWnd);
245cdf0e10cSrcweir // Detach this thread from the window thread
246cdf0e10cSrcweir AttachThreadInput( threadId, pTarget->m_threadIdWindow, FALSE);
247cdf0e10cSrcweir pTarget->m_hWnd= 0;
248cdf0e10cSrcweir break;
249cdf0e10cSrcweir }
250cdf0e10cSrcweir TranslateMessage( &msg);
251cdf0e10cSrcweir DispatchMessage( &msg);
252cdf0e10cSrcweir }
253cdf0e10cSrcweir OleUninitialize();
254cdf0e10cSrcweir }
255cdf0e10cSrcweir return 0;
256cdf0e10cSrcweir }
257cdf0e10cSrcweir
258cdf0e10cSrcweir
259cdf0e10cSrcweir
260cdf0e10cSrcweir
261cdf0e10cSrcweir // XServiceInfo
getImplementationName()262cdf0e10cSrcweir OUString SAL_CALL DropTarget::getImplementationName( ) throw (RuntimeException)
263cdf0e10cSrcweir {
264cdf0e10cSrcweir return OUString(RTL_CONSTASCII_USTRINGPARAM(DNDTARGET_IMPL_NAME));;
265cdf0e10cSrcweir }
266cdf0e10cSrcweir // XServiceInfo
supportsService(const OUString & ServiceName)267cdf0e10cSrcweir sal_Bool SAL_CALL DropTarget::supportsService( const OUString& ServiceName ) throw (RuntimeException)
268cdf0e10cSrcweir {
269cdf0e10cSrcweir if( ServiceName.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(DNDTARGET_SERVICE_NAME ))))
270cdf0e10cSrcweir return sal_True;
271cdf0e10cSrcweir return sal_False;
272cdf0e10cSrcweir }
273cdf0e10cSrcweir
getSupportedServiceNames()274cdf0e10cSrcweir Sequence< OUString > SAL_CALL DropTarget::getSupportedServiceNames( ) throw (RuntimeException)
275cdf0e10cSrcweir {
276cdf0e10cSrcweir OUString names[1]= {OUString(RTL_CONSTASCII_USTRINGPARAM(DNDTARGET_SERVICE_NAME))};
277cdf0e10cSrcweir return Sequence<OUString>(names, 1);
278cdf0e10cSrcweir }
279cdf0e10cSrcweir
280cdf0e10cSrcweir
281cdf0e10cSrcweir // XDropTarget ----------------------------------------------------------------
addDropTargetListener(const Reference<XDropTargetListener> & dtl)282cdf0e10cSrcweir void SAL_CALL DropTarget::addDropTargetListener( const Reference< XDropTargetListener >& dtl )
283cdf0e10cSrcweir throw(RuntimeException)
284cdf0e10cSrcweir {
285cdf0e10cSrcweir rBHelper.addListener( ::getCppuType( &dtl ), dtl );
286cdf0e10cSrcweir }
287cdf0e10cSrcweir
removeDropTargetListener(const Reference<XDropTargetListener> & dtl)288cdf0e10cSrcweir void SAL_CALL DropTarget::removeDropTargetListener( const Reference< XDropTargetListener >& dtl )
289cdf0e10cSrcweir throw(RuntimeException)
290cdf0e10cSrcweir {
291cdf0e10cSrcweir rBHelper.removeListener( ::getCppuType( &dtl ), dtl );
292cdf0e10cSrcweir }
293cdf0e10cSrcweir
isActive()294cdf0e10cSrcweir sal_Bool SAL_CALL DropTarget::isActive( ) throw(RuntimeException)
295cdf0e10cSrcweir {
296cdf0e10cSrcweir return m_bActive; //m_bDropTargetRegistered;
297cdf0e10cSrcweir }
298cdf0e10cSrcweir
299cdf0e10cSrcweir
setActive(sal_Bool _b)300cdf0e10cSrcweir void SAL_CALL DropTarget::setActive( sal_Bool _b ) throw(RuntimeException)
301cdf0e10cSrcweir {
302cdf0e10cSrcweir MutexGuard g(m_mutex);
303cdf0e10cSrcweir m_bActive= _b;
304cdf0e10cSrcweir }
305cdf0e10cSrcweir
306cdf0e10cSrcweir
getDefaultActions()307cdf0e10cSrcweir sal_Int8 SAL_CALL DropTarget::getDefaultActions( ) throw(RuntimeException)
308cdf0e10cSrcweir {
309cdf0e10cSrcweir return m_nDefaultActions;
310cdf0e10cSrcweir }
311cdf0e10cSrcweir
setDefaultActions(sal_Int8 actions)312cdf0e10cSrcweir void SAL_CALL DropTarget::setDefaultActions( sal_Int8 actions ) throw(RuntimeException)
313cdf0e10cSrcweir {
314cdf0e10cSrcweir OSL_ENSURE( actions < 8, "No valid default actions");
315cdf0e10cSrcweir m_nDefaultActions= actions;
316cdf0e10cSrcweir }
317cdf0e10cSrcweir
318cdf0e10cSrcweir
DragEnter(IDataObject * pDataObj,DWORD grfKeyState,POINTL pt,DWORD * pdwEffect)319cdf0e10cSrcweir HRESULT DropTarget::DragEnter( IDataObject *pDataObj,
320cdf0e10cSrcweir DWORD grfKeyState,
321cdf0e10cSrcweir POINTL pt,
322cdf0e10cSrcweir DWORD *pdwEffect)
323cdf0e10cSrcweir {
324cdf0e10cSrcweir #if defined DBG_CONSOLE_OUT
325cdf0e10cSrcweir printf("\nDropTarget::DragEnter state: %x effect %d", grfKeyState, *pdwEffect);
326cdf0e10cSrcweir #endif
327cdf0e10cSrcweir if( m_bActive )
328cdf0e10cSrcweir {
329cdf0e10cSrcweir // Intersection of pdwEffect and the allowed actions ( setDefaultActions)
330cdf0e10cSrcweir m_nCurrentDropAction= getFilteredActions( grfKeyState, *pdwEffect);
331cdf0e10cSrcweir // m_nLastDropAction has to be set by a listener. If no listener calls
332cdf0e10cSrcweir //XDropTargetDragContext::acceptDrag and specifies an action then pdwEffect
333cdf0e10cSrcweir // will be DROPEFFECT_NONE throughout
334cdf0e10cSrcweir m_nLastDropAction= ACTION_DEFAULT | ACTION_MOVE;
335cdf0e10cSrcweir
336cdf0e10cSrcweir m_currentDragContext= static_cast<XDropTargetDragContext*>( new TargetDragContext(
337cdf0e10cSrcweir static_cast<DropTarget*>(this) ) );
338cdf0e10cSrcweir
339cdf0e10cSrcweir //--> TRA
340cdf0e10cSrcweir
341cdf0e10cSrcweir // shortcut
342cdf0e10cSrcweir if ( g_XTransferable.is( ) )
343cdf0e10cSrcweir m_currentData = g_XTransferable;
344cdf0e10cSrcweir else
345cdf0e10cSrcweir {
346cdf0e10cSrcweir // Convert the IDataObject to a XTransferable
347cdf0e10cSrcweir m_currentData= m_aDataConverter.createTransferableFromDataObj(
348cdf0e10cSrcweir m_serviceFactory, IDataObjectPtr(pDataObj));
349cdf0e10cSrcweir }
350cdf0e10cSrcweir
351cdf0e10cSrcweir //<-- TRA
352cdf0e10cSrcweir
353cdf0e10cSrcweir if( m_nCurrentDropAction != ACTION_NONE)
354cdf0e10cSrcweir {
355cdf0e10cSrcweir DropTargetDragEnterEvent e;
356cdf0e10cSrcweir e.SupportedDataFlavors= m_currentData->getTransferDataFlavors();
357cdf0e10cSrcweir e.DropAction= m_nCurrentDropAction;
358cdf0e10cSrcweir e.Source= Reference<XInterface>( static_cast<XDropTarget*>(this),UNO_QUERY);
359cdf0e10cSrcweir e.Context= m_currentDragContext;
360cdf0e10cSrcweir POINT point={ pt.x, pt.y};
361cdf0e10cSrcweir ScreenToClient( m_hWnd, &point);
362cdf0e10cSrcweir e.LocationX= point.x;
363cdf0e10cSrcweir e.LocationY= point.y;
364cdf0e10cSrcweir e.SourceActions= dndOleDropEffectsToActions( *pdwEffect);
365cdf0e10cSrcweir
366cdf0e10cSrcweir fire_dragEnter( e);
367cdf0e10cSrcweir // Check if the action derived from grfKeyState (m_nCurrentDropAction) or the action set
368cdf0e10cSrcweir // by the listener (m_nCurrentDropAction) is allowed by the source. Only a allowed action is set
369cdf0e10cSrcweir // in pdwEffect. The listener notification is asynchron, that is we cannot expext that the listener
370cdf0e10cSrcweir // has already reacted to the notification.
371cdf0e10cSrcweir // If there is more then one valid action which is the case when ALT or RIGHT MOUSE BUTTON is pressed
372cdf0e10cSrcweir // then getDropEffect returns DROPEFFECT_MOVE which is the default value if no other modifier is pressed.
373cdf0e10cSrcweir // On drop the target should present the user a dialog from which the user may change the action.
374cdf0e10cSrcweir sal_Int8 allowedActions= dndOleDropEffectsToActions( *pdwEffect);
375cdf0e10cSrcweir *pdwEffect= dndActionsToSingleDropEffect( m_nLastDropAction & allowedActions);
376cdf0e10cSrcweir }
377cdf0e10cSrcweir else
378cdf0e10cSrcweir {
379cdf0e10cSrcweir *pdwEffect= DROPEFFECT_NONE;
380cdf0e10cSrcweir }
381cdf0e10cSrcweir }
382cdf0e10cSrcweir return S_OK;
383cdf0e10cSrcweir }
384cdf0e10cSrcweir
DragOver(DWORD grfKeyState,POINTL pt,DWORD * pdwEffect)385cdf0e10cSrcweir HRESULT DropTarget::DragOver( DWORD grfKeyState,
386cdf0e10cSrcweir POINTL pt,
387cdf0e10cSrcweir DWORD *pdwEffect)
388cdf0e10cSrcweir {
389cdf0e10cSrcweir if( m_bActive)
390cdf0e10cSrcweir {
391cdf0e10cSrcweir m_nCurrentDropAction= getFilteredActions( grfKeyState, *pdwEffect);
392cdf0e10cSrcweir
393cdf0e10cSrcweir if( m_nCurrentDropAction)
394cdf0e10cSrcweir {
395cdf0e10cSrcweir DropTargetDragEvent e;
396cdf0e10cSrcweir e.DropAction= m_nCurrentDropAction;
397cdf0e10cSrcweir e.Source= Reference<XInterface>(static_cast<XDropTarget*>(this),UNO_QUERY);
398cdf0e10cSrcweir e.Context= m_currentDragContext;
399cdf0e10cSrcweir POINT point={ pt.x, pt.y};
400cdf0e10cSrcweir ScreenToClient( m_hWnd, &point);
401cdf0e10cSrcweir e.LocationX= point.x;
402cdf0e10cSrcweir e.LocationY= point.y;
403cdf0e10cSrcweir e.SourceActions= dndOleDropEffectsToActions( *pdwEffect);
404cdf0e10cSrcweir
405cdf0e10cSrcweir // if grfKeyState has changed since the last DragOver then fire events.
406cdf0e10cSrcweir // A listener might change m_nCurrentDropAction by calling the
407cdf0e10cSrcweir // XDropTargetDragContext::acceptDrag function. But this is not important
408cdf0e10cSrcweir // because in the afterwards fired dragOver event the action reflects
409cdf0e10cSrcweir // grgKeyState again.
410cdf0e10cSrcweir if( m_nLastDropAction != m_nCurrentDropAction)
411cdf0e10cSrcweir fire_dropActionChanged( e);
412cdf0e10cSrcweir
413cdf0e10cSrcweir // The Event contains a XDropTargetDragContext implementation.
414cdf0e10cSrcweir fire_dragOver( e);
415cdf0e10cSrcweir // Check if the action derived from grfKeyState (m_nCurrentDropAction) or the action set
416cdf0e10cSrcweir // by the listener (m_nCurrentDropAction) is allowed by the source. Only a allowed action is set
417cdf0e10cSrcweir // in pdwEffect. The listener notification is asynchron, that is we cannot expext that the listener
418cdf0e10cSrcweir // has already reacted to the notification.
419cdf0e10cSrcweir // If there is more then one valid action which is the case when ALT or RIGHT MOUSE BUTTON is pressed
420cdf0e10cSrcweir // then getDropEffect returns DROPEFFECT_MOVE which is the default value if no other modifier is pressed.
421cdf0e10cSrcweir // On drop the target should present the user a dialog from which the user may change the action.
422cdf0e10cSrcweir sal_Int8 allowedActions= dndOleDropEffectsToActions( *pdwEffect);
423cdf0e10cSrcweir // set the last action to the current if listener has not changed the value yet
424cdf0e10cSrcweir *pdwEffect= dndActionsToSingleDropEffect( m_nLastDropAction & allowedActions);
425cdf0e10cSrcweir }
426cdf0e10cSrcweir else
427cdf0e10cSrcweir {
428cdf0e10cSrcweir *pdwEffect= DROPEFFECT_NONE;
429cdf0e10cSrcweir }
430cdf0e10cSrcweir }
431cdf0e10cSrcweir #if defined DBG_CONSOLE_OUT
432cdf0e10cSrcweir printf("\nDropTarget::DragOver %d", *pdwEffect );
433cdf0e10cSrcweir #endif
434cdf0e10cSrcweir return S_OK;
435cdf0e10cSrcweir }
436cdf0e10cSrcweir
DragLeave(void)437cdf0e10cSrcweir HRESULT DropTarget::DragLeave( void)
438cdf0e10cSrcweir {
439cdf0e10cSrcweir #if defined DBG_CONSOLE_OUT
440cdf0e10cSrcweir printf("\nDropTarget::DragLeave");
441cdf0e10cSrcweir #endif
442cdf0e10cSrcweir if( m_bActive)
443cdf0e10cSrcweir {
444cdf0e10cSrcweir
445cdf0e10cSrcweir m_currentData=0;
446cdf0e10cSrcweir m_currentDragContext= 0;
447cdf0e10cSrcweir m_currentDropContext= 0;
448cdf0e10cSrcweir m_nLastDropAction= 0;
449cdf0e10cSrcweir
450cdf0e10cSrcweir if( m_nDefaultActions != ACTION_NONE)
451cdf0e10cSrcweir {
452cdf0e10cSrcweir DropTargetEvent e;
453cdf0e10cSrcweir e.Source= static_cast<XDropTarget*>(this);
454cdf0e10cSrcweir
455cdf0e10cSrcweir fire_dragExit( e);
456cdf0e10cSrcweir }
457cdf0e10cSrcweir }
458cdf0e10cSrcweir return S_OK;
459cdf0e10cSrcweir }
460cdf0e10cSrcweir
Drop(IDataObject *,DWORD grfKeyState,POINTL pt,DWORD * pdwEffect)461cdf0e10cSrcweir HRESULT DropTarget::Drop( IDataObject * /*pDataObj*/,
462cdf0e10cSrcweir DWORD grfKeyState,
463cdf0e10cSrcweir POINTL pt,
464cdf0e10cSrcweir DWORD *pdwEffect)
465cdf0e10cSrcweir {
466cdf0e10cSrcweir #if defined DBG_CONSOLE_OUT
467cdf0e10cSrcweir printf("\nDropTarget::Drop");
468cdf0e10cSrcweir #endif
469cdf0e10cSrcweir if( m_bActive)
470cdf0e10cSrcweir {
471cdf0e10cSrcweir
472cdf0e10cSrcweir m_bDropComplete= sal_False;
473cdf0e10cSrcweir
474cdf0e10cSrcweir m_nCurrentDropAction= getFilteredActions( grfKeyState, *pdwEffect);
475cdf0e10cSrcweir m_currentDropContext= static_cast<XDropTargetDropContext*>( new TargetDropContext( static_cast<DropTarget*>(this )) );
476cdf0e10cSrcweir if( m_nCurrentDropAction)
477cdf0e10cSrcweir {
478cdf0e10cSrcweir DropTargetDropEvent e;
479cdf0e10cSrcweir e.DropAction= m_nCurrentDropAction;
480cdf0e10cSrcweir e.Source= Reference<XInterface>( static_cast<XDropTarget*>(this), UNO_QUERY);
481cdf0e10cSrcweir e.Context= m_currentDropContext;
482cdf0e10cSrcweir POINT point={ pt.x, pt.y};
483cdf0e10cSrcweir ScreenToClient( m_hWnd, &point);
484cdf0e10cSrcweir e.LocationX= point.x;
485cdf0e10cSrcweir e.LocationY= point.y;
486cdf0e10cSrcweir e.SourceActions= dndOleDropEffectsToActions( *pdwEffect);
487cdf0e10cSrcweir e.Transferable= m_currentData;
488cdf0e10cSrcweir fire_drop( e);
489cdf0e10cSrcweir
490cdf0e10cSrcweir //if fire_drop returns than a listener might have modified m_nCurrentDropAction
491cdf0e10cSrcweir if( m_bDropComplete == sal_True)
492cdf0e10cSrcweir {
493cdf0e10cSrcweir sal_Int8 allowedActions= dndOleDropEffectsToActions( *pdwEffect);
494cdf0e10cSrcweir *pdwEffect= dndActionsToSingleDropEffect( m_nCurrentDropAction & allowedActions);
495cdf0e10cSrcweir }
496cdf0e10cSrcweir else
497cdf0e10cSrcweir *pdwEffect= DROPEFFECT_NONE;
498cdf0e10cSrcweir }
499cdf0e10cSrcweir else
500cdf0e10cSrcweir *pdwEffect= DROPEFFECT_NONE;
501cdf0e10cSrcweir
502cdf0e10cSrcweir m_currentData= 0;
503cdf0e10cSrcweir m_currentDragContext= 0;
504cdf0e10cSrcweir m_currentDropContext= 0;
505cdf0e10cSrcweir m_nLastDropAction= 0;
506cdf0e10cSrcweir }
507cdf0e10cSrcweir return S_OK;
508cdf0e10cSrcweir }
509cdf0e10cSrcweir
510cdf0e10cSrcweir
511cdf0e10cSrcweir
fire_drop(const DropTargetDropEvent & dte)512cdf0e10cSrcweir void DropTarget::fire_drop( const DropTargetDropEvent& dte)
513cdf0e10cSrcweir {
514cdf0e10cSrcweir OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (Reference<XDropTargetListener>* )0 ) );
515cdf0e10cSrcweir if( pContainer)
516cdf0e10cSrcweir {
517cdf0e10cSrcweir OInterfaceIteratorHelper iter( *pContainer);
518cdf0e10cSrcweir while( iter.hasMoreElements())
519cdf0e10cSrcweir {
520cdf0e10cSrcweir Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next()));
521cdf0e10cSrcweir listener->drop( dte);
522cdf0e10cSrcweir }
523cdf0e10cSrcweir }
524cdf0e10cSrcweir }
525cdf0e10cSrcweir
fire_dragEnter(const DropTargetDragEnterEvent & e)526cdf0e10cSrcweir void DropTarget::fire_dragEnter( const DropTargetDragEnterEvent& e )
527cdf0e10cSrcweir {
528cdf0e10cSrcweir OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (Reference<XDropTargetListener>* )0 ) );
529cdf0e10cSrcweir if( pContainer)
530cdf0e10cSrcweir {
531cdf0e10cSrcweir OInterfaceIteratorHelper iter( *pContainer);
532cdf0e10cSrcweir while( iter.hasMoreElements())
533cdf0e10cSrcweir {
534cdf0e10cSrcweir Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next()));
535cdf0e10cSrcweir listener->dragEnter( e);
536cdf0e10cSrcweir }
537cdf0e10cSrcweir }
538cdf0e10cSrcweir }
539cdf0e10cSrcweir
fire_dragExit(const DropTargetEvent & dte)540cdf0e10cSrcweir void DropTarget::fire_dragExit( const DropTargetEvent& dte )
541cdf0e10cSrcweir {
542cdf0e10cSrcweir OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (Reference<XDropTargetListener>* )0 ) );
543cdf0e10cSrcweir
544cdf0e10cSrcweir if( pContainer)
545cdf0e10cSrcweir {
546cdf0e10cSrcweir OInterfaceIteratorHelper iter( *pContainer);
547cdf0e10cSrcweir while( iter.hasMoreElements())
548cdf0e10cSrcweir {
549cdf0e10cSrcweir Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next()));
550cdf0e10cSrcweir listener->dragExit( dte);
551cdf0e10cSrcweir }
552cdf0e10cSrcweir }
553cdf0e10cSrcweir }
554cdf0e10cSrcweir
fire_dragOver(const DropTargetDragEvent & dtde)555cdf0e10cSrcweir void DropTarget::fire_dragOver( const DropTargetDragEvent& dtde )
556cdf0e10cSrcweir {
557cdf0e10cSrcweir OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (Reference<XDropTargetListener>* )0 ) );
558cdf0e10cSrcweir if( pContainer)
559cdf0e10cSrcweir {
560cdf0e10cSrcweir OInterfaceIteratorHelper iter( *pContainer );
561cdf0e10cSrcweir while( iter.hasMoreElements())
562cdf0e10cSrcweir {
563cdf0e10cSrcweir Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next()));
564cdf0e10cSrcweir listener->dragOver( dtde);
565cdf0e10cSrcweir }
566cdf0e10cSrcweir }
567cdf0e10cSrcweir }
568cdf0e10cSrcweir
fire_dropActionChanged(const DropTargetDragEvent & dtde)569cdf0e10cSrcweir void DropTarget::fire_dropActionChanged( const DropTargetDragEvent& dtde )
570cdf0e10cSrcweir {
571cdf0e10cSrcweir OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (Reference<XDropTargetListener>* )0 ) );
572cdf0e10cSrcweir if( pContainer)
573cdf0e10cSrcweir {
574cdf0e10cSrcweir OInterfaceIteratorHelper iter( *pContainer);
575cdf0e10cSrcweir while( iter.hasMoreElements())
576cdf0e10cSrcweir {
577cdf0e10cSrcweir Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next()));
578cdf0e10cSrcweir listener->dropActionChanged( dtde);
579cdf0e10cSrcweir }
580cdf0e10cSrcweir }
581cdf0e10cSrcweir }
582cdf0e10cSrcweir
583cdf0e10cSrcweir // Non - interface functions ============================================================
584cdf0e10cSrcweir // DropTarget fires events to XDropTargetListeners. The event object contains an
585cdf0e10cSrcweir // XDropTargetDropContext implementaion. When the listener calls on that interface
586cdf0e10cSrcweir // then the calls are delegated from DropContext (XDropTargetDropContext) to these
587cdf0e10cSrcweir // functions.
588cdf0e10cSrcweir // Only one listener which visible area is affected is allowed to call on
589cdf0e10cSrcweir // XDropTargetDropContext
590cdf0e10cSrcweir // Returning sal_False would cause the XDropTargetDropContext or ..DragContext implementation
591cdf0e10cSrcweir // to throw an InvalidDNDOperationException, meaning that a Drag is not currently performed.
592cdf0e10cSrcweir // return sal_False results in throwing a InvalidDNDOperationException in the caller.
593cdf0e10cSrcweir
_acceptDrop(sal_Int8 dropOperation,const Reference<XDropTargetDropContext> & context)594cdf0e10cSrcweir void DropTarget::_acceptDrop(sal_Int8 dropOperation, const Reference<XDropTargetDropContext>& context)
595cdf0e10cSrcweir {
596cdf0e10cSrcweir if( context == m_currentDropContext)
597cdf0e10cSrcweir {
598cdf0e10cSrcweir m_nCurrentDropAction= dropOperation;
599cdf0e10cSrcweir }
600cdf0e10cSrcweir }
601cdf0e10cSrcweir
_rejectDrop(const Reference<XDropTargetDropContext> & context)602cdf0e10cSrcweir void DropTarget::_rejectDrop( const Reference<XDropTargetDropContext>& context)
603cdf0e10cSrcweir {
604cdf0e10cSrcweir if( context == m_currentDropContext)
605cdf0e10cSrcweir {
606cdf0e10cSrcweir m_nCurrentDropAction= ACTION_NONE;
607cdf0e10cSrcweir }
608cdf0e10cSrcweir }
609cdf0e10cSrcweir
_dropComplete(sal_Bool success,const Reference<XDropTargetDropContext> & context)610cdf0e10cSrcweir void DropTarget::_dropComplete(sal_Bool success, const Reference<XDropTargetDropContext>& context)
611cdf0e10cSrcweir {
612cdf0e10cSrcweir if(context == m_currentDropContext)
613cdf0e10cSrcweir {
614cdf0e10cSrcweir m_bDropComplete= success;
615cdf0e10cSrcweir }
616cdf0e10cSrcweir }
617cdf0e10cSrcweir // --------------------------------------------------------------------------------------
618cdf0e10cSrcweir // DropTarget fires events to XDropTargetListeners. The event object can contains an
619cdf0e10cSrcweir // XDropTargetDragContext implementaion. When the listener calls on that interface
620cdf0e10cSrcweir // then the calls are delegated from DragContext (XDropTargetDragContext) to these
621cdf0e10cSrcweir // functions.
622cdf0e10cSrcweir // Only one listener which visible area is affected is allowed to call on
623cdf0e10cSrcweir // XDropTargetDragContext
_acceptDrag(sal_Int8 dragOperation,const Reference<XDropTargetDragContext> & context)624cdf0e10cSrcweir void DropTarget::_acceptDrag( sal_Int8 dragOperation, const Reference<XDropTargetDragContext>& context)
625cdf0e10cSrcweir {
626cdf0e10cSrcweir if( context == m_currentDragContext)
627cdf0e10cSrcweir {
628cdf0e10cSrcweir m_nLastDropAction= dragOperation;
629cdf0e10cSrcweir }
630cdf0e10cSrcweir }
631cdf0e10cSrcweir
_rejectDrag(const Reference<XDropTargetDragContext> & context)632cdf0e10cSrcweir void DropTarget::_rejectDrag( const Reference<XDropTargetDragContext>& context)
633cdf0e10cSrcweir {
634cdf0e10cSrcweir if(context == m_currentDragContext)
635cdf0e10cSrcweir {
636cdf0e10cSrcweir m_nLastDropAction= ACTION_NONE;
637cdf0e10cSrcweir }
638cdf0e10cSrcweir }
639cdf0e10cSrcweir
640cdf0e10cSrcweir
641cdf0e10cSrcweir //--------------------------------------------------------------------------------------
642cdf0e10cSrcweir
643cdf0e10cSrcweir
644cdf0e10cSrcweir // This function determines the action dependend on the pressed
645cdf0e10cSrcweir // key modifiers ( CTRL, SHIFT, ALT, Right Mouse Button). The result
646cdf0e10cSrcweir // is then checked against the allowed actions which can be set through
647cdf0e10cSrcweir // XDropTarget::setDefaultActions. Only those values which are also
648cdf0e10cSrcweir // default actions are returned. If setDefaultActions has not been called
649cdf0e10cSrcweir // beforehand the the default actions comprise all possible actions.
650cdf0e10cSrcweir // params: grfKeyState - the modifier keys and mouse buttons currently pressed
getFilteredActions(DWORD grfKeyState,DWORD dwEffect)651cdf0e10cSrcweir inline sal_Int8 DropTarget::getFilteredActions( DWORD grfKeyState, DWORD dwEffect)
652cdf0e10cSrcweir {
653cdf0e10cSrcweir sal_Int8 actions= dndOleKeysToAction( grfKeyState, dndOleDropEffectsToActions( dwEffect));
654cdf0e10cSrcweir return actions & m_nDefaultActions;
655cdf0e10cSrcweir }
656cdf0e10cSrcweir
657cdf0e10cSrcweir
658