/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_dtrans.hxx" #include #include #include #include #include #include "DragSource.hxx" #include "globals.hxx" using namespace com::sun::star::datatransfer::dnd::DNDConstants; // for AOO internal D&D we provide the Transferable Reference DragSource::g_XTransferable; // the handle of the window starting the drag HWND DragSource::g_DragSourceHwnd = NULLHANDLE; DragSource::DragSource( const Reference& sf): WeakComponentImplHelper4< XDragSource, XInitialization, XDragSourceContext, XServiceInfo >(m_aMutex), m_serviceFactory(sf), pSourceDraginfo(NULL), pSharedMem(NULL), pDTShareMem(NULL) { g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt); debug_printf("DragSource::DragSource"); } DragSource::~DragSource() { g_moduleCount.modCnt.release( &g_moduleCount.modCnt); debug_printf("DragSource::~DragSource"); } // XInitialization // // aArguments contains a machine id // void SAL_CALL DragSource::initialize( const Sequence< Any >& aArguments ) throw(Exception, RuntimeException) { if (aArguments.getLength() < 2) { throw Exception(OUString(RTL_CONSTASCII_USTRINGPARAM("DragSource::initialize: Not enough parameter.")), static_cast(this)); } m_hWnd = *(HWND*)aArguments[1].getValue(); debug_printf("DragSource::initialize hwnd %x", m_hWnd); // init done in DropTarget, window is already subclassed SetWindowDragSourcePtr( m_hWnd, this); } void SAL_CALL DragSource::disposing() { debug_printf("DragSource::disposing hwnd %x", m_hWnd); SetWindowDragSourcePtr( m_hWnd, 0); } // XDragSource sal_Bool SAL_CALL DragSource::isDragImageSupported( ) throw(RuntimeException) { return 0; } sal_Int32 SAL_CALL DragSource::getDefaultCursor( sal_Int8 /*dragAction*/ ) throw( IllegalArgumentException, RuntimeException) { return 0; } // // Notifies the XDragSourceListener by calling dragDropEnd // void SAL_CALL DragSource::startDrag( const DragGestureEvent& /* trigger */, sal_Int8 sourceActions, sal_Int32 /* cursor */, sal_Int32 /* image */, const Reference& trans, const Reference& listener ) throw( RuntimeException) { debug_printf("DragSource::startDrag hwnd %x, sourceActions %d", m_hWnd, sourceActions); DRAGITEM dragItem; DRAGIMAGE dimg; HSTR hstrType, hstrRMF; HWND hwndTarget; // store transferable for internal AOO d&d operations g_XTransferable = trans; // store drag source window handle in a global field since we can // start only one drag operation at time g_DragSourceHwnd = m_hWnd; #if 1 // dump data flavours Sequence seq = g_XTransferable->getTransferDataFlavors(); for( int i=0; ihwndSource = m_hWnd; hstrType = DrgAddStrHandle( DRT_TEXT); hstrRMF = DrgAddStrHandle( ",,"); dragItem.hwndItem = m_hWnd; dragItem.ulItemID = 1; dragItem.hstrType = hstrType; dragItem.hstrRMF = hstrRMF; dragItem.hstrContainerName = NULL; // force rendering dragItem.hstrSourceName = NULL; dragItem.hstrTargetName = NULL; dragItem.fsControl = 0; dragItem.fsSupportedOps = DO_COPYABLE | DO_MOVEABLE | DO_LINKABLE; dimg.cb = sizeof(dimg); dimg.hImage = WinQuerySysPointer( HWND_DESKTOP, SPTR_FILE, FALSE); dimg.fl = DRG_ICON | DRG_TRANSPARENT; dimg.cxOffset = 0; dimg.cyOffset = 0; DrgSetDragitem( pSourceDraginfo, &dragItem, sizeof(dragItem), 0); // start PM dragging hwndTarget = DrgDrag( m_hWnd, pSourceDraginfo, &dimg, 1L, VK_BUTTON2, NULL); if (hwndTarget == NULLHANDLE) { // post a dummy message to ourselves to allow freeing resources // (yes, we could call endConversation() directly) WinPostMsg( m_hWnd, DM_AOO_ENDCONVERSATION, 0, MPFROMSHORT(DMFL_TARGETFAIL)); } debug_printf("DragSource::startDrag hwndTarget %x", hwndTarget); } // XDragSourceContext sal_Int32 SAL_CALL DragSource::getCurrentCursor( ) throw( RuntimeException) { return 0; } void SAL_CALL DragSource::setCursor( sal_Int32 /*cursorId*/ ) throw( RuntimeException) { } void SAL_CALL DragSource::setImage( sal_Int32 /*imageId*/ ) throw( RuntimeException) { } void SAL_CALL DragSource::transferablesFlavorsChanged( ) throw( RuntimeException) { } // // XServiceInfo // OUString SAL_CALL DragSource::getImplementationName( ) throw (RuntimeException) { return OUString(RTL_CONSTASCII_USTRINGPARAM(OS2_DNDSOURCE_IMPL_NAME));; } sal_Bool SAL_CALL DragSource::supportsService( const OUString& ServiceName ) throw (RuntimeException) { if( ServiceName.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(OS2_DNDSOURCE_SERVICE_NAME )))) return sal_True; return sal_False; } Sequence< OUString > SAL_CALL DragSource::getSupportedServiceNames( ) throw (RuntimeException) { OUString names[1]= {OUString(RTL_CONSTASCII_USTRINGPARAM(OS2_DNDSOURCE_SERVICE_NAME))}; return Sequence(names, 1); } // // OS/2 specific platform code // // // AOO as source window vs external drop target. // // this is sent when drop target requests the render // MRESULT DragSource::render( PDRAGTRANSFER pdxfer) { APIRET rc; ULONG ulLength; PSZ pRMF; bool rv = false; ulLength = DrgQueryStrNameLen( pdxfer->hstrSelectedRMF) + 1; pRMF = (PSZ) malloc( ulLength); DrgQueryStrName( pdxfer->hstrSelectedRMF, ulLength, pRMF); debug_printf("DragSource::render RMF:%s", pRMF); debug_printf("DragSource::render hstrRenderToName:%x", pdxfer->hstrRenderToName); if (strstr( pRMF, "(0)); Any aAny = DragSource::g_XTransferable->getTransferData(df); OUString utext; aAny >>= utext; OString text = ::rtl::OUStringToOString( utext, RTL_TEXTENCODING_UTF8).getStr(); debug_printf("DragSource::render text:%s", text.getStr()); debug_printf("DragSource::render text.getLength():%d", text.getLength()); DrgQueryStrName( pdxfer->hstrRenderToName, sizeof(DTShareName), DTShareName); debug_printf("DragSource::render hstrRenderToName:%s", DTShareName); rc = DosGetNamedSharedMem( (PPVOID) &pDTShareMem, DTShareName, PAG_WRITE | PAG_READ); debug_printf("DragSource::render DosGetNamedSharedMem rc:%d", rc); debug_printf("DragSource::render DosGetNamedSharedMem pSharedMem:%x", pSharedMem); // the memory is still not committed rc = DosSetMem( pDTShareMem, text.getLength()+1, PAG_DEFAULT | PAG_COMMIT); debug_printf("DragSource::render DosSetMem rc:%d", rc); // first ULONG is text length *(ULONG*) pDTShareMem = text.getLength(); // text data from 2nd ULONG memcpy( pDTShareMem + sizeof(ULONG), text.getStr(), text.getLength()+1); // return success rv = true; } else if (strstr( pRMF, "(0)); Any aAny = DragSource::g_XTransferable->getTransferData(df); OUString utext; aAny >>= utext; OString text = ::rtl::OUStringToOString( utext, RTL_TEXTENCODING_UTF8).getStr(); debug_printf("DragSource::render text:%s", text.getStr()); debug_printf("DragSource::render text.getLength():%d", text.getLength()); rc = DosAllocSharedMem( (PPVOID) &pSharedMem, NULL, text.getLength()+sizeof(ULONG)+1, OBJ_GIVEABLE | PAG_COMMIT | PAG_WRITE | PAG_READ /*| OBJ_ANY*/); rc = WinQueryWindowProcess( pdxfer->hwndClient, &pid, &tid); rc = DosGiveSharedMem( pSharedMem, pid, PAG_READ); debug_printf("DragSource::render rc:%d", rc); *(ULONG *) pSharedMem = text.getLength(); memcpy( pSharedMem + sizeof(ULONG), text.getStr(), text.getLength()+1); pdxfer->hstrRenderToName = (HSTR) pSharedMem; // return success rv = true; } else if (strstr( pRMF, "(0)); Any aAny = DragSource::g_XTransferable->getTransferData(df); OUString utext; aAny >>= utext; OString text = ::rtl::OUStringToOString( utext, RTL_TEXTENCODING_UTF8).getStr(); debug_printf("DragSource::render text:%s", text.getStr()); debug_printf("DragSource::render text.getLength():%d", text.getLength()); DrgQueryStrName( pdxfer->hstrRenderToName, sizeof(fileName), fileName); debug_printf("DragSource::render hstrRenderToName:%s", fileName); // write data to target file FILE* tmp = fopen( fileName, "wb"); if (tmp) { fwrite( text.getStr(), 1, text.getLength(), tmp); fclose( tmp); rv = true; } } else { debug_printf("DragSource::render INTERNAL ERROR unknown type"); } free( pRMF); // post rendered data int renderOK = (rv==true) ? DMFL_RENDEROK : DMFL_RENDERFAIL; debug_printf("DragSource::render render:%d", renderOK); rc = DrgPostTransferMsg( pdxfer->hwndClient, DM_RENDERCOMPLETE, pdxfer, renderOK, 0, FALSE); debug_printf("DragSource::render DrgPostTransferMsg:%d", rc); // free resources DrgFreeDragtransfer(pdxfer); return (MRESULT) rv; } // // AOO as source window vs external drop target. // // this is sent when external drop target requests the render // MRESULT DragSource::endConversation( ULONG itemID, ULONG flags) { sal_Bool success = ((flags==DMFL_TARGETSUCCESSFUL) ? true : false); sal_Int8 effect = ACTION_NONE; debug_printf("DragSource::endConversation itemID %d, flags %d", itemID, flags); if (pDTShareMem) DosFreeMem( pDTShareMem); pDTShareMem = NULL; if (pSharedMem) DosFreeMem( pSharedMem); pSharedMem = NULL; if (pSourceDraginfo) { // query which kind of operation the target did with our data if (success == true) effect = SystemToOfficeDragActions( pSourceDraginfo->usOperation); debug_printf("DragSource::endConversation usOperation 0x%x", pSourceDraginfo->usOperation); DrgDeleteDraginfoStrHandles( pSourceDraginfo); DrgFreeDraginfo( pSourceDraginfo); } pSourceDraginfo = NULL; // terminate AOO drag DragSourceDropEvent de(static_cast(this), static_cast(this), static_cast(this), effect, success); dragSourceListener->dragDropEnd( de); // clear globals g_XTransferable = Reference(); g_DragSourceHwnd = NULLHANDLE; dragSourceListener = Reference(); // Reserved value, should be 0 return 0; }