xref: /trunk/main/dtrans/source/os2/dnd/DragSource.cxx (revision cc13e73e)
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 // MARKER(update_precomp.py): autogen include statement, do not remove
24 #include "precompiled_dtrans.hxx"
25 #include <com/sun/star/datatransfer/dnd/DNDConstants.hpp>
26 #include <com/sun/star/datatransfer/XTransferable.hpp>
27 #include <com/sun/star/awt/MouseButton.hpp>
28 #include <com/sun/star/awt/MouseEvent.hpp>
29 
30 #include <vcl/window.hxx>
31 
32 #include "DragSource.hxx"
33 #include "globals.hxx"
34 
35 using namespace com::sun::star::datatransfer::dnd::DNDConstants;
36 
37 // for AOO internal D&D we provide the Transferable
38 Reference<XTransferable> DragSource::g_XTransferable;
39 // the handle of the window starting the drag
40 HWND DragSource::g_DragSourceHwnd = NULLHANDLE;
41 
42 
DragSource(const Reference<XMultiServiceFactory> & sf)43 DragSource::DragSource( const Reference<XMultiServiceFactory>& sf):
44     WeakComponentImplHelper4< XDragSource,
45             XInitialization,
46             XDragSourceContext,
47             XServiceInfo >(m_aMutex),
48     m_serviceFactory(sf),
49     pSourceDraginfo(NULL),
50     pSharedMem(NULL),
51     pDTShareMem(NULL)
52 {
53     g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt);
54     debug_printf("DragSource::DragSource");
55 }
56 
~DragSource()57 DragSource::~DragSource()
58 {
59     g_moduleCount.modCnt.release( &g_moduleCount.modCnt);
60     debug_printf("DragSource::~DragSource");
61 }
62 
63 // XInitialization
64 
65 //
66 // aArguments contains a machine id
67 //
initialize(const Sequence<Any> & aArguments)68 void SAL_CALL DragSource::initialize( const Sequence< Any >& aArguments )
69 throw(Exception, RuntimeException)
70 {
71     if (aArguments.getLength() < 2) {
72         throw Exception(OUString(RTL_CONSTASCII_USTRINGPARAM("DragSource::initialize: Not enough parameter.")),
73                         static_cast<OWeakObject*>(this));
74     }
75 
76     m_hWnd = *(HWND*)aArguments[1].getValue();
77     debug_printf("DragSource::initialize hwnd %x", m_hWnd);
78     // init done in DropTarget, window is already subclassed
79     SetWindowDragSourcePtr( m_hWnd, this);
80 }
81 
disposing()82 void SAL_CALL DragSource::disposing()
83 {
84     debug_printf("DragSource::disposing hwnd %x", m_hWnd);
85     SetWindowDragSourcePtr( m_hWnd, 0);
86 }
87 
88 // XDragSource
isDragImageSupported()89 sal_Bool SAL_CALL DragSource::isDragImageSupported(  )
90 throw(RuntimeException)
91 {
92     return 0;
93 }
94 
getDefaultCursor(sal_Int8)95 sal_Int32 SAL_CALL DragSource::getDefaultCursor( sal_Int8 /*dragAction*/ )
96 throw( IllegalArgumentException, RuntimeException)
97 {
98     return 0;
99 }
100 
101 //
102 // Notifies the XDragSourceListener by calling dragDropEnd
103 //
startDrag(const DragGestureEvent &,sal_Int8 sourceActions,sal_Int32,sal_Int32,const Reference<XTransferable> & trans,const Reference<XDragSourceListener> & listener)104 void SAL_CALL DragSource::startDrag(
105     const DragGestureEvent& /* trigger */,
106     sal_Int8 sourceActions,
107     sal_Int32 /* cursor */,
108     sal_Int32 /* image */,
109     const Reference<XTransferable >& trans,
110     const Reference<XDragSourceListener >& listener ) throw( RuntimeException)
111 {
112     debug_printf("DragSource::startDrag hwnd %x, sourceActions %d",
113                  m_hWnd, sourceActions);
114 
115     DRAGITEM    dragItem;
116     DRAGIMAGE   dimg;
117     HSTR        hstrType, hstrRMF;
118     HWND        hwndTarget;
119 
120     // store transferable for internal AOO d&d operations
121     g_XTransferable = trans;
122     // store drag source window handle in a global field since we can
123     // start only one drag operation at time
124     g_DragSourceHwnd = m_hWnd;
125 
126 #if 1
127     // dump data flavours
128     Sequence<DataFlavor> seq = g_XTransferable->getTransferDataFlavors();
129     for( int i=0; i<seq.getLength(); i++) {
130         DataFlavor df = seq[i];
131         debug_printf("DragSource::startDrag mimetype %s",
132                      ::rtl::OUStringToOString( df.MimeType, RTL_TEXTENCODING_UTF8 ).getStr());
133     }
134 #endif
135 
136     dragSourceListener = listener;
137     debug_printf("DragSource::startDrag dragSourceListener 0x%x", dragSourceListener.get());
138 
139     // allocate OS/2 specific resources
140     pSourceDraginfo = DrgAllocDraginfo(1);
141     pSourceDraginfo->hwndSource = m_hWnd;
142 
143     hstrType = DrgAddStrHandle( DRT_TEXT);
144     hstrRMF = DrgAddStrHandle( "<DRM_DTSHARE,DRF_TEXT>,<DRM_SHAREDMEM,DRF_TEXT>,<DRM_OS2FILE,DRF_TEXT>");
145 
146     dragItem.hwndItem          = m_hWnd;
147     dragItem.ulItemID          = 1;
148     dragItem.hstrType          = hstrType;
149     dragItem.hstrRMF           = hstrRMF;
150     dragItem.hstrContainerName = NULL; // force rendering
151     dragItem.hstrSourceName    = NULL;
152     dragItem.hstrTargetName    = NULL;
153     dragItem.fsControl         = 0;
154     dragItem.fsSupportedOps    = DO_COPYABLE | DO_MOVEABLE | DO_LINKABLE;
155 
156     dimg.cb       = sizeof(dimg);
157     dimg.hImage   = WinQuerySysPointer( HWND_DESKTOP, SPTR_FILE, FALSE);
158     dimg.fl       = DRG_ICON | DRG_TRANSPARENT;
159     dimg.cxOffset = 0;
160     dimg.cyOffset = 0;
161 
162     DrgSetDragitem( pSourceDraginfo, &dragItem, sizeof(dragItem), 0);
163 
164     // start PM dragging
165     hwndTarget = DrgDrag( m_hWnd, pSourceDraginfo, &dimg, 1L, VK_BUTTON2, NULL);
166     if (hwndTarget == NULLHANDLE) {
167         // post a dummy message to ourselves to allow freeing resources
168         // (yes, we could call endConversation() directly)
169         WinPostMsg( m_hWnd, DM_AOO_ENDCONVERSATION,
170                     0, MPFROMSHORT(DMFL_TARGETFAIL));
171     }
172 
173     debug_printf("DragSource::startDrag hwndTarget %x", hwndTarget);
174 
175 }
176 
177 // XDragSourceContext
getCurrentCursor()178 sal_Int32 SAL_CALL DragSource::getCurrentCursor(  )
179 throw( RuntimeException)
180 {
181     return 0;
182 }
183 
setCursor(sal_Int32)184 void SAL_CALL DragSource::setCursor( sal_Int32 /*cursorId*/ )
185 throw( RuntimeException)
186 {
187 }
188 
setImage(sal_Int32)189 void SAL_CALL DragSource::setImage( sal_Int32 /*imageId*/ )
190 throw( RuntimeException)
191 {
192 }
193 
transferablesFlavorsChanged()194 void SAL_CALL DragSource::transferablesFlavorsChanged(  )
195 throw( RuntimeException)
196 {
197 }
198 
199 
200 //
201 // XServiceInfo
202 //
getImplementationName()203 OUString SAL_CALL DragSource::getImplementationName(  ) throw (RuntimeException)
204 {
205     return OUString(RTL_CONSTASCII_USTRINGPARAM(OS2_DNDSOURCE_IMPL_NAME));;
206 }
207 
supportsService(const OUString & ServiceName)208 sal_Bool SAL_CALL DragSource::supportsService( const OUString& ServiceName ) throw (RuntimeException)
209 {
210     if( ServiceName.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(OS2_DNDSOURCE_SERVICE_NAME ))))
211         return sal_True;
212     return sal_False;
213 }
214 
getSupportedServiceNames()215 Sequence< OUString > SAL_CALL DragSource::getSupportedServiceNames(  ) throw (RuntimeException)
216 {
217     OUString names[1]= {OUString(RTL_CONSTASCII_USTRINGPARAM(OS2_DNDSOURCE_SERVICE_NAME))};
218     return Sequence<OUString>(names, 1);
219 }
220 
221 
222 //
223 // OS/2 specific platform code
224 //
225 
226 
227 //
228 // AOO as source window vs external drop target.
229 //
230 // this is sent when drop target requests the render
231 //
render(PDRAGTRANSFER pdxfer)232 MRESULT DragSource::render( PDRAGTRANSFER pdxfer)
233 {
234     APIRET rc;
235     ULONG ulLength;
236     PSZ pRMF;
237     bool rv = false;
238 
239     ulLength = DrgQueryStrNameLen( pdxfer->hstrSelectedRMF) + 1;
240     pRMF = (PSZ) malloc( ulLength);
241     DrgQueryStrName( pdxfer->hstrSelectedRMF, ulLength, pRMF);
242     debug_printf("DragSource::render RMF:%s", pRMF);
243     debug_printf("DragSource::render hstrRenderToName:%x", pdxfer->hstrRenderToName);
244 
245     if (strstr( pRMF, "<DRM_DTSHARE") != 0) {
246 
247         char DTShareName[CCHMAXPATH];
248 
249         DataFlavor df;
250         df.MimeType = OUString::createFromAscii( "text/plain;charset=utf-16" );
251         df.DataType = getCppuType( static_cast<OUString*>(0));
252 
253         Any aAny = DragSource::g_XTransferable->getTransferData(df);
254         OUString utext;
255         aAny >>= utext;
256         OString text = ::rtl::OUStringToOString( utext, RTL_TEXTENCODING_UTF8).getStr();
257         debug_printf("DragSource::render text:%s", text.getStr());
258         debug_printf("DragSource::render text.getLength():%d", text.getLength());
259 
260         DrgQueryStrName( pdxfer->hstrRenderToName, sizeof(DTShareName),
261                          DTShareName);
262         debug_printf("DragSource::render hstrRenderToName:%s", DTShareName);
263 
264         rc = DosGetNamedSharedMem( (PPVOID) &pDTShareMem, DTShareName,
265                                    PAG_WRITE | PAG_READ);
266         debug_printf("DragSource::render DosGetNamedSharedMem rc:%d", rc);
267         debug_printf("DragSource::render DosGetNamedSharedMem pSharedMem:%x", pSharedMem);
268 
269         // the memory is still not committed
270         rc = DosSetMem( pDTShareMem, text.getLength()+1, PAG_DEFAULT | PAG_COMMIT);
271         debug_printf("DragSource::render DosSetMem rc:%d", rc);
272 
273         // first ULONG is text length
274         *(ULONG*) pDTShareMem = text.getLength();
275         // text data from 2nd ULONG
276         memcpy( pDTShareMem + sizeof(ULONG), text.getStr(),
277                 text.getLength()+1);
278 
279         // return success
280         rv = true;
281 
282     } else if (strstr( pRMF, "<DRM_SHAREDMEM") != 0) {
283 
284         PID pid;
285         TID tid;
286         DataFlavor df;
287         df.MimeType = OUString::createFromAscii( "text/plain;charset=utf-16" );
288         df.DataType = getCppuType( static_cast<OUString*>(0));
289 
290         Any aAny = DragSource::g_XTransferable->getTransferData(df);
291         OUString utext;
292         aAny >>= utext;
293         OString text = ::rtl::OUStringToOString( utext, RTL_TEXTENCODING_UTF8).getStr();
294         debug_printf("DragSource::render text:%s", text.getStr());
295         debug_printf("DragSource::render text.getLength():%d", text.getLength());
296 
297         rc = DosAllocSharedMem( (PPVOID) &pSharedMem, NULL,
298                                        text.getLength()+sizeof(ULONG)+1,
299                                        OBJ_GIVEABLE | PAG_COMMIT |
300                                        PAG_WRITE | PAG_READ /*| OBJ_ANY*/);
301 
302         rc = WinQueryWindowProcess( pdxfer->hwndClient, &pid, &tid);
303         rc = DosGiveSharedMem( pSharedMem, pid, PAG_READ);
304 
305         debug_printf("DragSource::render rc:%d", rc);
306         *(ULONG *) pSharedMem = text.getLength();
307         memcpy( pSharedMem + sizeof(ULONG), text.getStr(), text.getLength()+1);
308         pdxfer->hstrRenderToName = (HSTR) pSharedMem;
309 
310         // return success
311         rv = true;
312 
313     } else if (strstr( pRMF, "<DRM_OS2FILE") != 0) {
314 
315         char fileName[CCHMAXPATH];
316 
317         DataFlavor df;
318         df.MimeType = OUString::createFromAscii( "text/plain;charset=utf-16" );
319         df.DataType = getCppuType( static_cast<OUString*>(0));
320 
321         Any aAny = DragSource::g_XTransferable->getTransferData(df);
322         OUString utext;
323         aAny >>= utext;
324         OString text = ::rtl::OUStringToOString( utext, RTL_TEXTENCODING_UTF8).getStr();
325         debug_printf("DragSource::render text:%s", text.getStr());
326         debug_printf("DragSource::render text.getLength():%d", text.getLength());
327 
328         DrgQueryStrName( pdxfer->hstrRenderToName, sizeof(fileName), fileName);
329         debug_printf("DragSource::render hstrRenderToName:%s", fileName);
330 
331         // write data to target file
332         FILE* tmp = fopen( fileName, "wb");
333         if (tmp) {
334             fwrite( text.getStr(), 1, text.getLength(), tmp);
335             fclose( tmp);
336             rv = true;
337         }
338 
339     } else {
340 
341         debug_printf("DragSource::render INTERNAL ERROR unknown type");
342 
343     }
344 
345     free( pRMF);
346 
347     // post rendered data
348     int renderOK = (rv==true) ? DMFL_RENDEROK : DMFL_RENDERFAIL;
349     debug_printf("DragSource::render render:%d", renderOK);
350     rc = DrgPostTransferMsg( pdxfer->hwndClient, DM_RENDERCOMPLETE, pdxfer,
351                         renderOK, 0, FALSE);
352     debug_printf("DragSource::render DrgPostTransferMsg:%d", rc);
353 
354     // free resources
355     DrgFreeDragtransfer(pdxfer);
356 
357     return (MRESULT) rv;
358 }
359 
360 //
361 // AOO as source window vs external drop target.
362 //
363 // this is sent when external drop target requests the render
364 //
endConversation(ULONG itemID,ULONG flags)365 MRESULT DragSource::endConversation( ULONG itemID, ULONG flags)
366 {
367     sal_Bool success = ((flags==DMFL_TARGETSUCCESSFUL) ? true : false);
368     sal_Int8 effect = ACTION_NONE;
369 
370     debug_printf("DragSource::endConversation itemID %d, flags %d", itemID, flags);
371 
372     if (pDTShareMem)
373         DosFreeMem( pDTShareMem);
374     pDTShareMem = NULL;
375     if (pSharedMem)
376         DosFreeMem( pSharedMem);
377     pSharedMem = NULL;
378 
379     if (pSourceDraginfo) {
380         // query which kind of operation the target did with our data
381         if (success == true)
382             effect = SystemToOfficeDragActions( pSourceDraginfo->usOperation);
383         debug_printf("DragSource::endConversation usOperation 0x%x", pSourceDraginfo->usOperation);
384         DrgDeleteDraginfoStrHandles( pSourceDraginfo);
385         DrgFreeDraginfo( pSourceDraginfo);
386     }
387     pSourceDraginfo = NULL;
388 
389     // terminate AOO drag
390     DragSourceDropEvent de(static_cast<OWeakObject*>(this),
391                            static_cast<XDragSourceContext*>(this),
392                            static_cast<XDragSource*>(this),
393                            effect,
394                            success);
395     dragSourceListener->dragDropEnd( de);
396 
397     // clear globals
398     g_XTransferable = Reference<XTransferable>();
399     g_DragSourceHwnd = NULLHANDLE;
400     dragSourceListener = Reference<XDragSourceListener>();
401 
402     // Reserved value, should be 0
403     return 0;
404 }
405