dtrans/Library_dnd_os2.mk | 56 +++ dtrans/Library_sysdtrans_os2.mk | 7 dtrans/Module_dtrans.mk | 1 dtrans/source/os2/clipb/Os2Clipboard.hxx | 3 dtrans/source/os2/clipb/Os2Transferable.hxx | 4 dtrans/source/os2/dnd/DragSource.cxx | 404 ++++++++++++++++++++++ dtrans/source/os2/dnd/DragSource.hxx | 108 +++++ dtrans/source/os2/dnd/DropTarget.cxx | 511 ++++++++++++++++++++++++++++ dtrans/source/os2/dnd/DropTarget.hxx | 137 +++++++ dtrans/source/os2/dnd/OTransferable.cxx | 452 ++++++++++++++++++++++++ dtrans/source/os2/dnd/OTransferable.hxx | 98 +++++ dtrans/source/os2/dnd/dndentry.cxx | 117 ++++++ dtrans/source/os2/dnd/globals.cxx | 200 ++++++++++ dtrans/source/os2/dnd/globals.hxx | 63 +++ postprocess/packcomponents/makefile.mk | 1 scp2/source/ooo/file_library_ooo.scp | 2 vcl/inc/os2/saldata.hxx | 11 vcl/source/window/syschild.cxx | 2 vcl/source/window/window.cxx | 2 19 files changed, 2169 insertions(+), 10 deletions(-)
New commits: commit ad88c94f4ecb7e5876ff481164276403000993e6 Author: Yuri Dario <yda...@apache.org> Date: Wed Mar 28 17:00:13 2018 +0000 #i127729# Add full drag&drop support for the OS/2 platform. diff --git a/dtrans/Library_dnd_os2.mk b/dtrans/Library_dnd_os2.mk new file mode 100644 index 000000000000..4aa30f541c38 --- /dev/null +++ b/dtrans/Library_dnd_os2.mk @@ -0,0 +1,56 @@ +#************************************************************** +# +# 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. +# +#************************************************************** + + + +$(eval $(call gb_Library_Library,dnd)) + +$(eval $(call gb_Library_add_precompiled_header,dnd,$(SRCDIR)/dtrans/inc/pch/precompiled_dtrans)) + +$(eval $(call gb_Library_set_componentfile,dnd,dtrans/util/dnd)) + +$(eval $(call gb_Library_set_include,dnd,\ + $$(INCLUDE) \ + -I$(SRCDIR)/dtrans/inc/pch \ +)) + +$(eval $(call gb_Library_add_api,dnd,\ + offapi \ + udkapi \ +)) + +$(eval $(call gb_Library_add_linked_libs,dnd,\ + cppuhelper \ + cppu \ + sal \ + stl \ + $(gb_STDLIBS) \ +)) + +$(eval $(call gb_Library_add_exception_objects,dnd,\ + dtrans/source/os2/dnd/dndentry \ + dtrans/source/os2/dnd/globals \ + dtrans/source/os2/dnd/OTransferable \ + dtrans/source/os2/dnd/DragSource \ + dtrans/source/os2/dnd/DropTarget \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/dtrans/Module_dtrans.mk b/dtrans/Module_dtrans.mk index e2826ac331f1..bf1820b4ac88 100644 --- a/dtrans/Module_dtrans.mk +++ b/dtrans/Module_dtrans.mk @@ -39,6 +39,7 @@ endif ifeq ($(OS),OS2) $(eval $(call gb_Module_add_targets,dtrans,\ + Library_dnd_os2 \ Library_sysdtrans_os2 \ )) endif diff --git a/dtrans/source/os2/dnd/DragSource.cxx b/dtrans/source/os2/dnd/DragSource.cxx new file mode 100644 index 000000000000..9a6cfc5bb626 --- /dev/null +++ b/dtrans/source/os2/dnd/DragSource.cxx @@ -0,0 +1,404 @@ +/************************************************************** +* +* 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 <com/sun/star/datatransfer/dnd/DNDConstants.hpp> +#include <com/sun/star/datatransfer/XTransferable.hpp> +#include <com/sun/star/awt/MouseButton.hpp> +#include <com/sun/star/awt/MouseEvent.hpp> + +#include <vcl/window.hxx> + +#include "DragSource.hxx" +#include "globals.hxx" + +using namespace com::sun::star::datatransfer::dnd::DNDConstants; + +// for AOO internal D&D we provide the Transferable +Reference<XTransferable> DragSource::g_XTransferable; +// the handle of the window starting the drag +HWND DragSource::g_DragSourceHwnd = NULLHANDLE; + + +DragSource::DragSource( const Reference<XMultiServiceFactory>& 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<OWeakObject*>(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<XTransferable >& trans, + const Reference<XDragSourceListener >& 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<DataFlavor> seq = g_XTransferable->getTransferDataFlavors(); + for( int i=0; i<seq.getLength(); i++) { + DataFlavor df = seq[i]; + debug_printf("DragSource::startDrag mimetype %s", + ::rtl::OUStringToOString( df.MimeType, RTL_TEXTENCODING_UTF8 ).getStr()); + } +#endif + + dragSourceListener = listener; + debug_printf("DragSource::startDrag dragSourceListener 0x%x", dragSourceListener.get()); + + // allocate OS/2 specific resources + pSourceDraginfo = DrgAllocDraginfo(1); + pSourceDraginfo->hwndSource = m_hWnd; + + hstrType = DrgAddStrHandle( DRT_TEXT); + hstrRMF = DrgAddStrHandle( "<DRM_DTSHARE,DRF_TEXT>,<DRM_SHAREDMEM,DRF_TEXT>,<DRM_OS2FILE,DRF_TEXT>"); + + 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<OUString>(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, "<DRM_DTSHARE") != 0) { + + char DTShareName[CCHMAXPATH]; + + DataFlavor df; + df.MimeType = OUString::createFromAscii( "text/plain;charset=utf-16" ); + df.DataType = getCppuType( static_cast<OUString*>(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, "<DRM_SHAREDMEM") != 0) { + + PID pid; + TID tid; + DataFlavor df; + df.MimeType = OUString::createFromAscii( "text/plain;charset=utf-16" ); + df.DataType = getCppuType( static_cast<OUString*>(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, "<DRM_OS2FILE") != 0) { + + char fileName[CCHMAXPATH]; + + DataFlavor df; + df.MimeType = OUString::createFromAscii( "text/plain;charset=utf-16" ); + df.DataType = getCppuType( static_cast<OUString*>(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<OWeakObject*>(this), + static_cast<XDragSourceContext*>(this), + static_cast<XDragSource*>(this), + effect, + success); + dragSourceListener->dragDropEnd( de); + + // clear globals + g_XTransferable = Reference<XTransferable>(); + g_DragSourceHwnd = NULLHANDLE; + dragSourceListener = Reference<XDragSourceListener>(); + + // Reserved value, should be 0 + return 0; +} diff --git a/dtrans/source/os2/dnd/DragSource.hxx b/dtrans/source/os2/dnd/DragSource.hxx new file mode 100644 index 000000000000..887b7f1e9af5 --- /dev/null +++ b/dtrans/source/os2/dnd/DragSource.hxx @@ -0,0 +1,108 @@ +/************************************************************** +* +* 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. +* +*************************************************************/ + + +#ifndef _DRAGSOURCE_HXX_ +#define _DRAGSOURCE_HXX_ + +#include <svpm.h> + +#include <com/sun/star/datatransfer/dnd/XDragSource.hpp> +#include <com/sun/star/datatransfer/dnd/XDragSourceContext.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> + +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/compbase4.hxx> +#include <osl/mutex.hxx> + +#include "globals.hxx" + +using namespace cppu; +using namespace osl; +using namespace rtl; +using namespace com::sun::star::datatransfer; +using namespace com::sun::star::datatransfer::dnd; +using namespace com::sun::star::lang; +using namespace com::sun::star::uno; + + +class DragSource: + public cppu::BaseMutex, + public WeakComponentImplHelper4<XDragSource, + XInitialization, + XDragSourceContext, + XServiceInfo> +{ +public: + // used also in DropTarget in AOO internal d&d + static Reference<XTransferable> g_XTransferable; + // the handle of the window starting the drag + static HWND g_DragSourceHwnd; + +private: + Reference<XMultiServiceFactory> m_serviceFactory; + // The native window which acts as source. + HWND m_hWnd; + PDRAGINFO pSourceDraginfo; + char *pSharedMem; + char *pDTShareMem; + + Reference<XDragSourceListener> dragSourceListener; + +public: + DragSource( const Reference<XMultiServiceFactory>& sf); + virtual ~DragSource(); + + // XInitialization + virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) + throw(Exception, RuntimeException); + virtual void SAL_CALL disposing(); + + // XDragSource + virtual sal_Bool SAL_CALL isDragImageSupported( ) throw(RuntimeException); + virtual sal_Int32 SAL_CALL getDefaultCursor(sal_Int8 dragAction) + throw(IllegalArgumentException, RuntimeException); + virtual void SAL_CALL startDrag( const DragGestureEvent& trigger, + sal_Int8 sourceActions, + sal_Int32 cursor, + sal_Int32 image, + const Reference< XTransferable>& transferable, + const Reference< XDragSourceListener>& listener) + throw(RuntimeException); + + // XDragSourceContext + virtual sal_Int32 SAL_CALL getCurrentCursor() throw( RuntimeException); + virtual void SAL_CALL setCursor( sal_Int32) throw( RuntimeException); + virtual void SAL_CALL setImage( sal_Int32) throw( RuntimeException); + virtual void SAL_CALL transferablesFlavorsChanged() throw( RuntimeException); + + // XServiceInfo + virtual rtl::OUString SAL_CALL getImplementationName() throw (RuntimeException); + virtual sal_Bool SAL_CALL supportsService(const rtl::OUString& ServiceName) throw (RuntimeException); + virtual Sequence< rtl::OUString > SAL_CALL getSupportedServiceNames() throw (RuntimeException); + + // OS/2 window messaging handlers + MRESULT render( PDRAGTRANSFER); + MRESULT endConversation( ULONG, ULONG); + +}; +#endif // _DRAGSOURCE_HXX_ diff --git a/dtrans/source/os2/dnd/DropTarget.cxx b/dtrans/source/os2/dnd/DropTarget.cxx new file mode 100644 index 000000000000..53ba4a8f4fa3 --- /dev/null +++ b/dtrans/source/os2/dnd/DropTarget.cxx @@ -0,0 +1,511 @@ +/************************************************************** +* +* 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 <com/sun/star/datatransfer/dnd/DNDConstants.hpp> +#include <com/sun/star/datatransfer/XTransferable.hpp> +#include <rtl/ustring.h> +#include <cppuhelper/implbase1.hxx> + +#include <vcl/window.hxx> + +#include "globals.hxx" +#include "DropTarget.hxx" +#include "DragSource.hxx" +#include "OTransferable.hxx" + + +using namespace com::sun::star; +using namespace com::sun::star::io; +using namespace com::sun::star::datatransfer::dnd::DNDConstants; + + +DropTarget::DropTarget( const Reference<XMultiServiceFactory>& sf): + WeakComponentImplHelper5< XInitialization, + XDropTarget, + XDropTargetDragContext, + XDropTargetDropContext, + XServiceInfo>(m_aMutex), + m_serviceFactory( sf), + dragEnterEmulation( true), + mbActive(false), + mDragSourceSupportedActions(ACTION_NONE), + mSelectedDropAction(ACTION_NONE), + mDefaultActions(ACTION_COPY_OR_MOVE | ACTION_LINK | ACTION_DEFAULT) +{ + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); +} + +DropTarget::~DropTarget() +{ + debug_printf("DropTarget::~DropTarget"); + + // This will free the previous instance if present, + // so it removes the tmp file + mXTransferable = Reference<XTransferable>(); + + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} + +void SAL_CALL DropTarget::initialize(const Sequence< Any >& aArguments) +throw(Exception) +{ + if (aArguments.getLength() < 2) { + throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM("DropTarget::initialize: Cannot install window event handler")), + static_cast<OWeakObject*>(this)); + } + + m_hWnd = *(HWND*) aArguments[0].getValue(); + debug_printf("DropTarget::initialize hwnd %x", m_hWnd); + + // subclass window to allow intercepting D&D messages + defWndProc = WinSubclassWindow( m_hWnd, dndFrameProc); + SetWindowDropTargetPtr( m_hWnd, this); +} + +// called from WeakComponentImplHelperX::dispose +// WeakComponentImplHelper calls disposing before it destroys +// itself. +void SAL_CALL DropTarget::disposing() +{ + debug_printf("DropTarget::disposing hwnd %x", m_hWnd); + + // revert window subclassing + WinSubclassWindow( m_hWnd, defWndProc); + defWndProc = NULL; + SetWindowDropTargetPtr( m_hWnd, 0); +} + +void SAL_CALL DropTarget::addDropTargetListener(const uno::Reference<XDropTargetListener>& dtl) +throw(RuntimeException) +{ + debug_printf("DropTarget::addDropTargetListener hwnd %x", m_hWnd); + rBHelper.addListener(::getCppuType(&dtl), dtl); +} + +void SAL_CALL DropTarget::removeDropTargetListener(const uno::Reference<XDropTargetListener>& dtl) +throw(RuntimeException) +{ + debug_printf("DropTarget::removeDropTargetListener hwnd %x", m_hWnd); + rBHelper.removeListener(::getCppuType(&dtl), dtl); +} + +sal_Bool SAL_CALL DropTarget::isActive( ) throw(RuntimeException) +{ + debug_printf("DropTarget::isActive %d", mbActive); + return mbActive; +} + +void SAL_CALL DropTarget::setActive(sal_Bool active) throw(RuntimeException) +{ + debug_printf("DropTarget::setActive %d", active); + mbActive = active; +} + +sal_Int8 SAL_CALL DropTarget::getDefaultActions() throw(RuntimeException) +{ + debug_printf("DropTarget::getDefaultActions %d", mDefaultActions); + return mDefaultActions; +} + +void SAL_CALL DropTarget::setDefaultActions(sal_Int8 actions) throw(RuntimeException) +{ + OSL_ENSURE( actions < 8, "No valid default actions"); + mDefaultActions= actions; +} + +// +// XDropTargetDragContext +// +// Non - interface functions ============================================================ +// DropTarget fires events to XDropTargetListeners. The event object can contains an +// XDropTargetDragContext implementaion. When the listener calls on that interface +// then the calls are delegated from DragContext (XDropTargetDragContext) to these +// functions. +// Only one listener which visible area is affected is allowed to call on +// XDropTargetDragContext + +void SAL_CALL DropTarget::acceptDrag(sal_Int8 dragOperation) throw (RuntimeException) +{ + debug_printf("DropTarget::acceptDrag hwnd %x, dragOperation %d", m_hWnd, dragOperation); + mSelectedDropAction = dragOperation; +} + +void SAL_CALL DropTarget::rejectDrag() throw (RuntimeException) +{ + debug_printf("DropTarget::rejectDrag hwnd %x", m_hWnd); + mSelectedDropAction = ACTION_NONE; +} + +// +// XDropTargetDropContext +// +// Non - interface functions ============================================================ +// DropTarget fires events to XDropTargetListeners. The event object contains an +// XDropTargetDropContext implementaion. When the listener calls on that interface +// then the calls are delegated from DropContext (XDropTargetDropContext) to these +// functions. +// Only one listener which visible area is affected is allowed to call on +// XDropTargetDropContext +// Returning sal_False would cause the XDropTargetDropContext or ..DragContext implementation +// to throw an InvalidDNDOperationException, meaning that a Drag is not currently performed. +// return sal_False results in throwing a InvalidDNDOperationException in the caller. +// +void SAL_CALL DropTarget::acceptDrop(sal_Int8 dropOperation) throw( RuntimeException) +{ + debug_printf("DropTarget::acceptDrop hwnd %x, dragOperation %d", m_hWnd, dropOperation); + mSelectedDropAction = dropOperation; +} + +void SAL_CALL DropTarget::rejectDrop() throw (RuntimeException) +{ + debug_printf("DropTarget::rejectDrop hwnd %x", m_hWnd); + mSelectedDropAction = ACTION_NONE; +} + +void SAL_CALL DropTarget::dropComplete(sal_Bool success) throw (RuntimeException) +{ + debug_printf("DropTarget::dropComplete hwnd %x", m_hWnd); + + // reset action flags + mDragSourceSupportedActions = ACTION_NONE; + mSelectedDropAction = ACTION_NONE; + // enable drag enter emulation again + dragEnterEmulation = true; + // free local transferable list on next d&d or destruction + + // post a dummy message to source window to allow DragSource + // release resources and close internal d&d + if (DragSource::g_DragSourceHwnd != NULLHANDLE) { + debug_printf("DropTarget::renderComplete post DM_AOO_ENDCONVERSATION to source"); + WinPostMsg( DragSource::g_DragSourceHwnd, DM_AOO_ENDCONVERSATION, 0, + MPFROMSHORT(success ? DMFL_TARGETSUCCESSFUL : DMFL_TARGETFAIL)); + } + +} + +// +// XServiceInfo +// +OUString SAL_CALL DropTarget::getImplementationName() throw (RuntimeException) +{ + return OUString(RTL_CONSTASCII_USTRINGPARAM(OS2_DNDTARGET_IMPL_NAME));; +} + +sal_Bool SAL_CALL DropTarget::supportsService( const OUString& ServiceName ) throw (RuntimeException) +{ + return ServiceName.equals(OUString(RTL_CONSTASCII_USTRINGPARAM( OS2_DNDTARGET_SERVICE_NAME))); +} + +Sequence< OUString > SAL_CALL DropTarget::getSupportedServiceNames( ) throw (RuntimeException) +{ + OUString names[1]= {OUString(RTL_CONSTASCII_USTRINGPARAM( OS2_DNDTARGET_SERVICE_NAME))}; + return Sequence<OUString>(names, 1); +} + +// +// AOO private interface events +// +void DropTarget::fire_drop( const DropTargetDropEvent& dte) +{ + OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (uno::Reference<XDropTargetListener>* )0 ) ); + if( pContainer) + { + OInterfaceIteratorHelper iter( *pContainer); + while( iter.hasMoreElements()) + { + uno::Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next())); + + try { listener->drop( dte); } + catch(RuntimeException&) {} + } + } + debug_printf("DropTarget::fire_drop fired"); +} + +void DropTarget::fire_dragEnter(const DropTargetDragEnterEvent& e) +{ + OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (uno::Reference<XDropTargetListener>* )0 ) ); + if( pContainer) + { + OInterfaceIteratorHelper iter( *pContainer); + while( iter.hasMoreElements()) + { + uno::Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next())); + + try { listener->dragEnter( e); } + catch (RuntimeException&) {} + } + } + debug_printf("DropTarget::fire_dragEnter fired"); +} + +void DropTarget::fire_dragExit(const DropTargetEvent& dte) +{ + OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (uno::Reference<XDropTargetListener>* )0 ) ); + + if( pContainer) + { + OInterfaceIteratorHelper iter( *pContainer); + while( iter.hasMoreElements()) + { + uno::Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next())); + + try { listener->dragExit( dte); } + catch (RuntimeException&) {} + } + } + debug_printf("DropTarget::fire_dragExit fired"); +} + +void DropTarget::fire_dragOver(const DropTargetDragEvent& dtde) +{ + OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (uno::Reference<XDropTargetListener>* )0 ) ); + if( pContainer) + { + OInterfaceIteratorHelper iter( *pContainer ); + while( iter.hasMoreElements()) + { + uno::Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next())); + + try { listener->dragOver( dtde); } + catch (RuntimeException&) {} + } + } + debug_printf("DropTarget::fire_dragOver fired"); +} + +void DropTarget::fire_dropActionChanged(const DropTargetDragEvent& dtde) +{ + OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (uno::Reference<XDropTargetListener>* )0 ) ); + if( pContainer) + { + OInterfaceIteratorHelper iter( *pContainer); + while( iter.hasMoreElements()) + { + uno::Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next())); + + try { listener->dropActionChanged( dtde); } + catch (RuntimeException&) {} + } + } + debug_printf("DropTarget::fire_dropActionChanged fired"); +} + +// +// OS/2 specific platform code +// + +MRESULT DropTarget::dragEnter( PDRAGINFO dragInfo) +{ + debug_printf("DropTarget::dragEnter start hwnd 0x%x", m_hWnd); + + // disable drag enter emulation until next DM_DRAGLEAVE + dragEnterEmulation = false; + + // Get access to the DRAGINFO data structure + DrgAccessDraginfo( dragInfo); + + // Initially when DnD will be started no modifier key can be pressed yet + // thus we are getting all actions that the drag source supports, we save + // this value because later the system masks the drag source actions if + // a modifier key will be pressed + mDragSourceSupportedActions = + SystemToOfficeDragActions( dragInfo->usOperation); + + // Only if the drop target is really interested in the drag actions + // supported by the source + if (mDragSourceSupportedActions & mDefaultActions) { + + //sal_Int8 currentAction = determineDropAction(mDragSourceSupportedActions, sender); + sal_Int8 currentAction = mDragSourceSupportedActions; + + // map from desktop to client window + MapWindowPoint( m_hWnd, dragInfo, &ptlMouse); + + // This will free the previous instance if present, + // so it removes the tmp file + mXTransferable = Reference<XTransferable>(); + + // if g_XTransferable is empty this is an external drop operation, + // create a new transferable set + mXTransferable = DragSource::g_XTransferable; + if (!mXTransferable.is()) { + mXTransferable = + //new OTransferable( OUString::createFromAscii( "TestString" ) ); + new OTransferable( m_hWnd, dragInfo); + } + +#if 1 + // dump data flavours + Sequence<DataFlavor> seq = mXTransferable->getTransferDataFlavors(); + for( int i=0; i<seq.getLength(); i++) { + DataFlavor df = seq[i]; + debug_printf("DropTarget::dragEnter mimetype %s", + ::rtl::OUStringToOString( df.MimeType, RTL_TEXTENCODING_UTF8 ).getStr()); + } +#endif + + debug_printf("DropTarget::dragEnter (%dx%d) mDragSourceSupportedActions %d", + ptlMouse.x, ptlMouse.y, + mDragSourceSupportedActions); + + DropTargetDragEnterEvent dtdee(static_cast<OWeakObject*>(this), + 0, this, currentAction, + ptlMouse.x, ptlMouse.y, + mDragSourceSupportedActions, + mXTransferable->getTransferDataFlavors()); + fire_dragEnter(dtdee); + } + + // Release the draginfo data structure + DrgFreeDraginfo(dragInfo); + + return OfficeToSystemDragActions( mSelectedDropAction); +} + +MRESULT DropTarget::dragOver( PDRAGINFO dragInfo) +{ + MRESULT dragOp = MRFROM2SHORT( DOR_NODROPOP, 0); + + if (dragEnterEmulation) + return dragEnter( dragInfo); + + // Get access to the DRAGINFO data structure + DrgAccessDraginfo( dragInfo); + + sal_Int8 currentDragSourceActions = + SystemToOfficeDragActions( dragInfo->usOperation); + + // Only if the drop target is really interessted in the drag actions + // supported by the source + if (currentDragSourceActions & mDefaultActions) { + //sal_Int8 currentAction = determineDropAction(mDragSourceSupportedActions, sender); + sal_Int8 currentAction = currentDragSourceActions; + + // map from desktop to client window + MapWindowPoint( m_hWnd, dragInfo, &ptlMouse); + + DropTargetDragEvent dtde(static_cast<OWeakObject*>(this), + 0, this, currentAction, + ptlMouse.x, ptlMouse.y, + mDragSourceSupportedActions); + // firing the event will result in a XDropTargetDragContext event + fire_dragOver(dtde); + + dragOp = OfficeToSystemDragActions(mSelectedDropAction); + } + + // Release the draginfo data structure + DrgFreeDraginfo(dragInfo); + return dragOp; +} + +MRESULT DropTarget::dragLeave( PDRAGINFO /* dragInfo */) +{ + debug_printf("DropTarget::dragLeave"); + + DropTargetEvent dte(static_cast<OWeakObject*>(this), 0); + fire_dragExit(dte); + + // reset action flags + mDragSourceSupportedActions = ACTION_NONE; + mSelectedDropAction = ACTION_NONE; + // enable drag enter emulation again + dragEnterEmulation = true; + // free local transferable list on next d&d or destruction + + return 0; +} + +MRESULT DropTarget::drop( PDRAGINFO dragInfo) +{ + debug_printf("DropTarget::drop"); + + // Get access to the DRAGINFO data structure + DrgAccessDraginfo( dragInfo); + + MRESULT dropOp = MRFROM2SHORT( DOR_NODROPOP, 0); + + if (mSelectedDropAction != ACTION_NONE) { + + bool rr = false; + + // map from desktop to client window + MapWindowPoint( m_hWnd, dragInfo, &ptlMouse); + + // if external d&d, request rendering + OTransferable* ot = dynamic_cast<OTransferable*>(mXTransferable.get()); + if (ot != NULL) { + // request rendering, if operation is already possible it + // will return false + rr = ot->requestRendering(); + debug_printf("DropTarget::drop requestRendering=%d", rr); + } + + // no rendering requested, post a DM_RENDERCOMPLETE to ourselves + // to fire AOO drop event + if (rr == false) + WinPostMsg( m_hWnd, DM_RENDERCOMPLETE, 0, 0); + + dropOp = OfficeToSystemDragActions(mSelectedDropAction); + } + + // Release the draginfo data structure + DrgFreeDraginfo(dragInfo); + + return dropOp; + +} + +MRESULT DropTarget::renderComplete( PDRAGTRANSFER dragTransfer) +{ + debug_printf("DropTarget::renderComplete dragTransfer 0x%x", dragTransfer); + + if (dragTransfer != NULL) { + OTransferable* ot = dynamic_cast<OTransferable*>(mXTransferable.get()); + // DM_RENDERCOMPLETE cannot be received in internal AOO d&d + if (ot == NULL) { + debug_printf("DropTarget::renderComplete INTERNAL ERROR null dragtransfer"); + return 0; + } + + // set rendered data + ot->renderComplete( dragTransfer); + } + + debug_printf("DropTarget::renderComplete mXTransferable.is() %d", mXTransferable.is()); + + // complete AOO drop event, this will make AOO call + // XTransferable::getTransferData() for external ops, + // then acceptDrop(), dropComplete() are called from listeners + DropTargetDropEvent dtde( static_cast<OWeakObject*>(this), + 0, this, mSelectedDropAction, + ptlMouse.x, ptlMouse.y, + mDragSourceSupportedActions, + mXTransferable); + fire_drop(dtde); + + // Reserved value, should be 0 + return 0; +} diff --git a/dtrans/source/os2/dnd/DropTarget.hxx b/dtrans/source/os2/dnd/DropTarget.hxx new file mode 100644 index 000000000000..f155e6ac2620 --- /dev/null +++ b/dtrans/source/os2/dnd/DropTarget.hxx @@ -0,0 +1,137 @@ +/************************************************************** +* +* 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. +* +*************************************************************/ + + +#ifndef _DROPTARGET_HXX_ +#define _DROPTARGET_HXX_ + +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/datatransfer/dnd/XDropTarget.hpp> +#include <com/sun/star/datatransfer/dnd/XDropTargetDragContext.hpp> +#include <com/sun/star/datatransfer/dnd/XDropTargetDropContext.hpp> +#include <com/sun/star/datatransfer/dnd/DropTargetDragEnterEvent.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> + +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/compbase5.hxx> +#include <cppuhelper/interfacecontainer.hxx> +#include <osl/mutex.hxx> + +#include "globals.hxx" + + +using namespace cppu; +using namespace osl; +using namespace rtl; +using namespace com::sun::star::datatransfer; +using namespace com::sun::star::datatransfer::dnd; +using namespace com::sun::star::lang; +using namespace com::sun::star::uno; + + +// The client +// has to call XComponent::dispose. The thread that calls initialize +// must also execute the destruction of the instance. This is because +// initialize calls OleInitialize and the destructor calls OleUninitialize. +// If the service calls OleInitialize then it also calls OleUnitialize when +// it is destroyed. Therefore no second instance may exist which was +// created in the same thread and still needs OLE. +class DropTarget: public cppu::BaseMutex, + public WeakComponentImplHelper5< XInitialization, + XDropTarget, + XDropTargetDragContext, + XDropTargetDropContext, + XServiceInfo> +{ +private: + Reference<XMultiServiceFactory> m_serviceFactory; + // The native window which acts as drop target. + HWND m_hWnd; + POINTL ptlMouse; + // OS/2 does not provide a DM_DRAGENTER message, provide emulation + bool dragEnterEmulation; + // If mbActive == sal_True then events are fired to XDropTargetListener s, + // none otherwise. The default value is sal_True. + bool mbActive; + sal_Int8 mDragSourceSupportedActions; + sal_Int8 mSelectedDropAction; + sal_Int8 mDefaultActions; + Reference<XTransferable> mXTransferable; + +public: + DropTarget( const Reference<XMultiServiceFactory>& sf); + virtual ~DropTarget(); + + // Overrides WeakComponentImplHelper::disposing which is called by + // WeakComponentImplHelper::dispose + // Must be called. + virtual void SAL_CALL disposing(); + + // XInitialization + virtual void SAL_CALL initialize( const Sequence< Any >& aArguments) + throw(Exception); + + // XDropTarget + virtual void SAL_CALL addDropTargetListener( const Reference< XDropTargetListener >& dtl ) + throw(RuntimeException); + virtual void SAL_CALL removeDropTargetListener( const Reference< XDropTargetListener >& dtl ) + throw(RuntimeException); + + // Default is not active + virtual sal_Bool SAL_CALL isActive() throw(RuntimeException); + virtual void SAL_CALL setActive(sal_Bool) throw(RuntimeException); + virtual sal_Int8 SAL_CALL getDefaultActions() throw(RuntimeException); + virtual void SAL_CALL setDefaultActions(sal_Int8) throw(RuntimeException); + + // XDropTargetDragContext + virtual void SAL_CALL acceptDrag( sal_Int8) throw(RuntimeException); + virtual void SAL_CALL rejectDrag() throw(RuntimeException); + + // XDropTargetDropContext + virtual void SAL_CALL acceptDrop(sal_Int8) throw (RuntimeException); + virtual void SAL_CALL rejectDrop() throw (RuntimeException); + virtual void SAL_CALL dropComplete(sal_Bool) throw (RuntimeException); + + // XServiceInfo + virtual rtl::OUString SAL_CALL getImplementationName() throw (RuntimeException); + virtual sal_Bool SAL_CALL supportsService(const rtl::OUString& ServiceName) throw (RuntimeException); + virtual Sequence< rtl::OUString > SAL_CALL getSupportedServiceNames() throw (RuntimeException); + + // OS/2 window messaging handlers + MRESULT dragEnter( PDRAGINFO dragInfo); + MRESULT dragOver( PDRAGINFO dragInfo); + MRESULT dragLeave( PDRAGINFO dragInfo); + MRESULT drop( PDRAGINFO dragInfo); + MRESULT renderComplete( PDRAGTRANSFER); + +public: + // default window frame procedure + PFNWP defWndProc; + +private: + void fire_drop(const DropTargetDropEvent& dte); + void fire_dragEnter(const DropTargetDragEnterEvent& dtdee); + void fire_dragExit(const DropTargetEvent& dte); + void fire_dragOver(const DropTargetDragEvent& dtde); + void fire_dropActionChanged(const DropTargetDragEvent& dtde); + +}; +#endif // _DROPTARGET_HXX_ diff --git a/dtrans/source/os2/dnd/OTransferable.cxx b/dtrans/source/os2/dnd/OTransferable.cxx new file mode 100644 index 000000000000..b5c5fb20bccd --- /dev/null +++ b/dtrans/source/os2/dnd/OTransferable.cxx @@ -0,0 +1,452 @@ +/************************************************************** +* +* 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" + +#define INCL_DOSERRORS + +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include <rtl/string.hxx> + +#include "OTransferable.hxx" +#include "globals.hxx" + + +OTransferable::OTransferable( HWND hwndTarget, PDRAGINFO dragInfo) + : m_aFlavorList( 1), + mHwndTarget( hwndTarget), + mDragInfo( dragInfo), + removeOnExit( false), + pDTShare( NULL), + renderDRM( DRM_NULL), + mimeType( MIMETYPE_NULL) +{ + USHORT cItems; + PDRAGITEM dragItem; + PSZ pNativeRMF; + + strcpy( fullpath, ""); + + cItems = DrgQueryDragitemCount(dragInfo); + if (cItems > 1) { + debug_printf("OTransferable::OTransferable multiple drop not supported"); + return; + } + + ULONG ulLength; + PSZ pBuffer; + + // get 1st item + dragItem = DrgQueryDragitemPtr(dragInfo, 0); + + // dump true type + ulLength = DrgQueryTrueTypeLen( dragItem) + 1; + pBuffer = (PSZ) malloc( ulLength); + DrgQueryTrueType( dragItem, ulLength, pBuffer); + debug_printf("DrgQueryTrueType %s", pBuffer); + free( pBuffer); + + // get native RMF format + ulLength = DrgQueryNativeRMFLen( dragItem) + 1; + pNativeRMF = (PSZ) malloc( ulLength); + DrgQueryNativeRMF( dragItem, ulLength, pNativeRMF); + debug_printf("OTransferable::OTransferable DrgQueryNativeRMF %s", pNativeRMF); + + debug_printf("OTransferable::OTransferable DrgVerifyRMF DRM_ATOM %d", DrgVerifyRMF( dragItem, "DRM_ATOM", NULL)); + debug_printf("OTransferable::OTransferable DrgVerifyRMF DRM_OS2FILE %d", DrgVerifyRMF( dragItem, "DRM_OS2FILE", NULL)); + debug_printf("OTransferable::OTransferable DrgVerifyRMF DRM_PRINTOBJECT %d", DrgVerifyRMF( dragItem, "DRM_PRINTOBJECT", NULL)); + debug_printf("OTransferable::OTransferable DrgVerifyRMF DRM_SHAREDMEM %d", DrgVerifyRMF( dragItem, "DRM_SHAREDMEM", NULL)); + debug_printf("OTransferable::OTransferable DrgVerifyRMF DRM_DTSHARE %d", DrgVerifyRMF( dragItem, "DRM_DTSHARE", NULL)); + + DataFlavor df; + + if (strstr( pNativeRMF, "<DRM_ATOM") != 0 + || strstr( pNativeRMF, "<DRM_DTSHARE") != 0 + || strstr( pNativeRMF, "<DRM_SHAREDMEM") != 0) { + + df.MimeType = OUString::createFromAscii( "text/plain;charset=utf-16" ); + df.DataType = getCppuType( static_cast<rtl::OUString*>(0)); + m_aFlavorList[0] = df; + mimeType = MIMETYPE_TEXT; + + } else if (strstr( pNativeRMF, "<DRM_OS2FILE") != 0) { + + df.MimeType = OUString::createFromAscii( + "application/x-openoffice-file;windows_formatname=\"FileName\""); + df.DataType = getCppuType( static_cast<OUString*>(0)); + m_aFlavorList[0] = df; + mimeType = MIMETYPE_FILE; + + } else { + + mimeType = MIMETYPE_NULL; + debug_printf("OTransferable::OTransferable UNKNOWN native RMF"); + + } + + free( pNativeRMF); + +} + +OTransferable::~OTransferable() +{ + if (removeOnExit) { + int rc; + rc = unlink( fullpath); + debug_printf( "OTransferable::~OTransferable unlink rc=%d", rc); + } +} + + +// +// a generic request dispatcher +// +bool OTransferable::RequestFileRendering( PDRAGITEM pditem, HWND hwnd, + PCSZ pRMF, PCSZ pName) +{ + PDRAGTRANSFER pdxfer; + + pdxfer = DrgAllocDragtransfer( 1); + if (!pdxfer) + return true; + + pdxfer->cb = sizeof(DRAGTRANSFER); + pdxfer->hwndClient = hwnd; + pdxfer->pditem = pditem; + pdxfer->hstrSelectedRMF = DrgAddStrHandle( pRMF); + pdxfer->hstrRenderToName = 0; + pdxfer->ulTargetInfo = pditem->ulItemID; + pdxfer->usOperation = (USHORT)DO_COPY; + pdxfer->fsReply = 0; + + // send the msg before setting a render-to name + if (pditem->fsControl & DC_PREPAREITEM) + DrgSendTransferMsg( pditem->hwndItem, DM_RENDERPREPARE, (MPARAM)pdxfer, 0); + + if (pName) + pdxfer->hstrRenderToName = DrgAddStrHandle( pName); + else + pdxfer->hstrRenderToName = 0; + + // send the msg after setting a render-to name + if ((pditem->fsControl & (DC_PREPARE | DC_PREPAREITEM)) == DC_PREPARE) + DrgSendTransferMsg( pditem->hwndItem, DM_RENDERPREPARE, (MPARAM)pdxfer, 0); + + // ask the source to render the selected item + if (!DrgSendTransferMsg( pditem->hwndItem, DM_RENDER, (MPARAM)pdxfer, 0)) + return true; + + return false; +} + +// currently, the same filename is used for every render request; +// it is deleted when the drag session ends +// +bool OTransferable::RenderToOS2File( PDRAGITEM pditem, HWND hwnd) +{ + bool rv = true; + + const char * pszRMF; + if (DrgVerifyRMF(pditem, "DRM_OS2FILE", "DRF_TEXT")) + pszRMF = OS2FILE_TXTRMF; + else + pszRMF = OS2FILE_UNKRMF; + + // create temp name + strcpy( fullpath, tempnam( NULL, "AOO")); + debug_printf("OTransferable::RenderToOS2File to %s", fullpath); + + rv = RequestFileRendering( pditem, hwnd, pszRMF, fullpath); + + return rv; +} + +// DTShare uses 1mb of uncommitted named-shared memory +// (next time I'll do it differently - rw) +// +bool OTransferable::RenderToDTShare( PDRAGITEM pditem, HWND hwnd) +{ + bool rv; + + APIRET rc = DosAllocSharedMem( &pDTShare, DTSHARE_NAME, 0x100000, + PAG_WRITE | PAG_READ | OBJ_ANY); + if (rc != NO_ERROR && + rc != ERROR_ALREADY_EXISTS) { // Did the kernel handle OBJ_ANY? + // Try again without OBJ_ANY and if the first failure was not caused + // by OBJ_ANY then we will get the same failure, else we have taken + // care of pre-FP13 systems where the kernel couldn't handle it. + rc = DosAllocSharedMem( &pDTShare, DTSHARE_NAME, 0x100000, + PAG_WRITE | PAG_READ); + } + + if (rc == ERROR_ALREADY_EXISTS) + rc = DosGetNamedSharedMem( &pDTShare, DTSHARE_NAME, + PAG_WRITE | PAG_READ); + if (rc) + rv = true; // error + else + rv = RequestFileRendering( pditem, hwnd, DTSHARE_RMF, DTSHARE_NAME); + + return rv; +} + +// SharedMem rendering, memory is allocated by source window +// +bool OTransferable::RenderToSharedMem( PDRAGITEM pditem, HWND hwnd) +{ + bool rv; + + rv = RequestFileRendering( pditem, hwnd, SHAREDMEM_RMF, NULL); + + return rv; +} + +bool OTransferable::requestRendering( void) +{ + char path[CCHMAXPATH]; + char file[CCHMAXPATH]; + PDRAGITEM dragItem; + + // unknown rendering + renderDRM = DRM_NULL; + + // only 1st item supported + dragItem = DrgQueryDragitemPtr( mDragInfo, 0); + + // check if we already have all necessary fields or a rendering + // request must be sent to source window + + switch( mimeType) { + case MIMETYPE_NULL: + debug_printf("OTransferable::requestRendering INTERNAL ERROR, mimetype undef"); + break; + + case MIMETYPE_FILE: + if (DrgVerifyRMF( dragItem, "DRM_OS2FILE", NULL) + && dragItem->hstrSourceName == NULLHANDLE) { + + // if hstrSourceName is NULL we need to ask source for rendering + bool rv; + debug_printf("OTransferable::requestRendering request rendering"); + rv = RenderToOS2File( dragItem, mHwndTarget); + debug_printf("OTransferable::requestRendering requested rendering rv=%d", rv); + renderDRM = DRM_OS2FILE; + + // notify rendering request ongoing + return true; + + } else if (DrgVerifyRMF( dragItem, "DRM_OS2FILE", NULL)) { + + // we have hstrSourceName, no need for rendering, + // we already have enough data for rendering path now + + // get full path + DrgQueryStrName(dragItem->hstrContainerName, sizeof(path), path); + debug_printf("OTransferable::getTransferData hstrSourceName %x", dragItem->hstrSourceName); + debug_printf("OTransferable::getTransferData hstrTargetName %x", dragItem->hstrTargetName); + DrgQueryStrName(dragItem->hstrSourceName, sizeof(file), file); + sprintf( fullpath, "%s%s", path, file); + debug_printf("OTransferable::getTransferData fullpath %s", fullpath); + renderDRM = DRM_OS2FILE; + + } else { + debug_printf("OTransferable::requestRendering UNKNOWN request for FILE mimetype"); + } + break; + + case MIMETYPE_TEXT: + if (DrgVerifyRMF( dragItem, "DRM_ATOM", NULL)) { + + DrgQueryStrName(dragItem->ulItemID, sizeof(fullpath), fullpath); + debug_printf("OTransferable::requestRendering DRM_ATOM '%s'", fullpath); + renderDRM = DRM_ATOM; + + // no request rendering necessary + return false; + + } else if (DrgVerifyRMF( dragItem, "DRM_DTSHARE", NULL)) { + + bool rv; + debug_printf("OTransferable::requestRendering request DRM_DTSHARE rendering"); + rv = RenderToDTShare( dragItem, mHwndTarget); + debug_printf("OTransferable::requestRendering requested DRM_DTSHARE rendering rv=%d", rv); + renderDRM = DRM_DTSHARE; + + // notify rendering request ongoing + return true; + + } else if (DrgVerifyRMF( dragItem, "DRM_SHAREDMEM", NULL)) { + + bool rv; + debug_printf("OTransferable::requestRendering request DRM_SHAREDMEM rendering"); + rv = RenderToSharedMem( dragItem, mHwndTarget); + debug_printf("OTransferable::requestRendering requested DRM_SHAREDMEM rendering rv=%d", rv); + renderDRM = DRM_SHAREDMEM; + + // notify rendering request ongoing + return true; + + } else { + debug_printf("OTransferable::requestRendering UNKNOWN request for TEXT mimetype"); + } + break; + } + + // request rendering not necessary + return false; + +} + +// +// AOO window received DM_RENDERCOMPLETE message +// +bool OTransferable::renderComplete( PDRAGTRANSFER pdxfer) +{ + switch( renderDRM) { + case DRM_NULL: + // already handled in requestRendering() + break; + case DRM_ATOM: + // set full path from source rendered name string + DrgQueryStrName( pdxfer->hstrRenderToName, sizeof(fullpath), fullpath); + debug_printf("OTransferable::setDragTransfer fullpath %s", fullpath); + break; + case DRM_DTSHARE: + // handled in getTransferData() + break; + case DRM_SHAREDMEM: + // save pointer + pSharedMem = (char *) pdxfer->hstrRenderToName; + // extraction handled in getTransferData() + break; + case DRM_OS2FILE: + // we already know the path, no need to use hstrRenderToName + debug_printf("OTransferable::setDragTransfer fullpath %s", fullpath); + // remove tmp file on destruction + removeOnExit = true; + break; + } + + // send success to source window + DrgSendTransferMsg( pdxfer->hwndClient, DM_ENDCONVERSATION, + (MPARAM) pdxfer->ulTargetInfo, + (MPARAM) DMFL_TARGETSUCCESSFUL); + + // free resources + DrgDeleteStrHandle( pdxfer->hstrSelectedRMF); + DrgDeleteStrHandle( pdxfer->hstrRenderToName); + DrgFreeDragtransfer( pdxfer); + + return false; +} + +Any SAL_CALL OTransferable::getTransferData( const DataFlavor& df) +throw(UnsupportedFlavorException, IOException, RuntimeException) +{ + OUString m_aData; + char * pszText = 0; + int pszLen; + ULONG size = ~0; + ULONG flags = 0; + APIRET rc; + bool renderOk = false; + + debug_printf("OTransferable::getTransferData MimeType %s", + ::rtl::OUStringToOString( df.MimeType, RTL_TEXTENCODING_UTF8 ).getStr()); + + // handle shared memory cases + switch( renderDRM) { + case DRM_DTSHARE: + + pszLen = ((ULONG*)pDTShare)[0]; + pszText = (char*) malloc( pszLen + 1); + if (pszText) { + strcpy(pszText, &((char*)pDTShare)[sizeof(ULONG)] ); + } + // using DosGetNamedSharedMem() on memory we allocated appears + // to increment its usage ctr, so we have to free it 2x + DosFreeMem(pDTShare); + DosFreeMem(pDTShare); + // reset pointer + pDTShare = NULL; + + // prepare data for AOO + m_aData = OUString( pszText, pszLen, RTL_TEXTENCODING_UTF8); + break; + + case DRM_SHAREDMEM: + rc = DosQueryMem((PVOID) pSharedMem, &size, &flags); + renderOk = rc == 0; + if (renderOk) { + renderOk = (flags & (PAG_COMMIT | PAG_READ | PAG_BASE)) == + (PAG_COMMIT | PAG_READ | PAG_BASE); + } + if (renderOk) { + ULONG realSize = *(ULONG *) pSharedMem; + renderOk = realSize <= size; + if (renderOk) { + // prepare data for AOO + m_aData = OUString( pSharedMem + sizeof(ULONG), realSize, RTL_TEXTENCODING_UTF8); + } + } + // free memory only if it is given by another process, + // otherwise DefaultDragWorker will free it + if (flags & PAG_SHARED) + DosFreeMem((PVOID) pSharedMem); + break; + + case DRM_ATOM: + case DRM_OS2FILE: + // data is in fullpath string + // prepare data for AOO + m_aData = OUString( fullpath, strlen(fullpath), RTL_TEXTENCODING_UTF8); + break; + + default: + debug_printf( "OTransferable::getTransferData unsupported DRM_* type %d", + renderDRM); + break; + } + + // return data + return makeAny( m_aData ); +} + +// ----------------------------------------------------------------------- + +Sequence< DataFlavor > SAL_CALL OTransferable::getTransferDataFlavors( ) +throw(RuntimeException) +{ + return m_aFlavorList; +} + +// ----------------------------------------------------------------------- + +sal_Bool SAL_CALL OTransferable::isDataFlavorSupported( const DataFlavor& ) +throw(RuntimeException) +{ + return sal_True; +} diff --git a/dtrans/source/os2/dnd/OTransferable.hxx b/dtrans/source/os2/dnd/OTransferable.hxx new file mode 100644 index 000000000000..ba377114b1c5 --- /dev/null +++ b/dtrans/source/os2/dnd/OTransferable.hxx @@ -0,0 +1,98 @@ +/************************************************************** + * + * 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. + * + *************************************************************/ + + +#ifndef _OTRANSFERABLE_HXX_ +#define _OTRANSFERABLE_HXX_ + +#include <svpm.h> + +#include <cppuhelper/implbase1.hxx> +#include <rtl/ustring.hxx> +#include <rtl/unload.h> +#include <com/sun/star/datatransfer/DataFlavor.hpp> +#include <com/sun/star/datatransfer/XTransferable.hpp> + +using namespace cppu; +using namespace osl; +using namespace rtl; +using namespace com::sun::star::io; +using namespace com::sun::star::uno; +using namespace com::sun::star::datatransfer; + + +// undocumented(?) +#ifndef DC_PREPAREITEM +#define DC_PREPAREITEM 0x0040 +#endif + +// rendering mechanism +#define DTSHARE_NAME "\\SHAREMEM\\AOO_DND" +#define DTSHARE_RMF "<DRM_DTSHARE,DRF_TEXT>" + +#define SHAREDMEM_RMF "<DRM_SHAREDMEM,DRF_TEXT>" + +#define OS2FILE_NAME "AOO_TGT.TMP" +#define OS2FILE_TXTRMF "<DRM_OS2FILE,DRF_TEXT>" +#define OS2FILE_UNKRMF "<DRM_OS2FILE,DRF_UNKNOWN>" + + +class OTransferable: public ::cppu::WeakImplHelper1<XTransferable> +{ + com::sun::star::uno::Sequence<DataFlavor> m_aFlavorList; + +private: + HWND mHwndTarget; + PDRAGINFO mDragInfo; + bool removeOnExit; + char fullpath[CCHMAXPATH]; + void *pDTShare; + char *pSharedMem; + enum _DRM { DRM_NULL, DRM_ATOM, DRM_DTSHARE, DRM_OS2FILE, DRM_SHAREDMEM}; + _DRM renderDRM; + enum _MIMETYPE { MIMETYPE_NULL, MIMETYPE_TEXT, MIMETYPE_FILE}; + _MIMETYPE mimeType; + +public: + +public: + OTransferable( HWND hwnd, PDRAGINFO dragInfo); + ~OTransferable(); + + virtual Any SAL_CALL getTransferData( const DataFlavor& aFlavor) + throw(UnsupportedFlavorException, IOException, RuntimeException); + virtual Sequence< DataFlavor > SAL_CALL getTransferDataFlavors() + throw(RuntimeException); + virtual sal_Bool SAL_CALL isDataFlavorSupported( const DataFlavor& aFlavor) + throw(RuntimeException); + + bool renderComplete( PDRAGTRANSFER pdxfer); + bool requestRendering( void); + +private: + bool RequestFileRendering( PDRAGITEM pditem, HWND hwnd, PCSZ pRMF, PCSZ pName); + bool RenderToOS2File( PDRAGITEM pditem, HWND hwnd); + bool RenderToDTShare( PDRAGITEM pditem, HWND hwnd); + bool RenderToSharedMem( PDRAGITEM pditem, HWND hwnd); + +}; + +#endif // _OTRANSFERABLE_HXX_ diff --git a/dtrans/source/os2/dnd/dndentry.cxx b/dtrans/source/os2/dnd/dndentry.cxx new file mode 100644 index 000000000000..0dca6e5a34e9 --- /dev/null +++ b/dtrans/source/os2/dnd/dndentry.cxx @@ -0,0 +1,117 @@ +/************************************************************** +* +* 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 <cppuhelper/factory.hxx> +#include <com/sun/star/container/XSet.hpp> +#include <osl/diagnose.h> + +#include "DragSource.hxx" +#include "DropTarget.hxx" + +using namespace rtl; +using namespace cppu; +using namespace com::sun::star::lang; +using namespace com::sun::star::registry; +using namespace com::sun::star::uno; + +rtl_StandardModuleCount g_moduleCount = MODULE_COUNT_INIT; + +// ----------------------------------------------------------------------- + +Reference< XInterface > SAL_CALL createDragSource( const Reference< XMultiServiceFactory >& rServiceManager ) +{ + DragSource* pSource = new DragSource( rServiceManager); + return Reference<XInterface>( static_cast<XInitialization*>(pSource), UNO_QUERY); +} + +Reference< XInterface > SAL_CALL createDropTarget( const Reference< XMultiServiceFactory >& rServiceManager ) +{ + DropTarget* pTarget = new DropTarget( rServiceManager); + return Reference<XInterface>( static_cast<XInitialization*>(pTarget), UNO_QUERY); +} + +extern "C" { + +SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL component_canUnload( TimeValue *pTime) +{ + return g_moduleCount.canUnload( &g_moduleCount, pTime); +} + +//---------------------------------------------------------------------- +// component_getImplementationEnvironment +//---------------------------------------------------------------------- +SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** /*ppEnv*/ ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +//---------------------------------------------------------------------- +// component_getFactory +// returns a factory to create XFilePicker-Services +//---------------------------------------------------------------------- +SAL_DLLPUBLIC_EXPORT void* SAL_CALL component_getFactory( const sal_Char* pImplName, uno_Interface* pSrvManager, uno_Interface* /*pRegistryKey*/ ) +{ + void* pRet = 0; + Reference< XSingleServiceFactory > xFactory; + + debug_printf("dnd component_getFactory %s", pImplName); + + if ( pSrvManager && ( 0 == rtl_str_compare( pImplName, OS2_DNDSOURCE_IMPL_NAME ) ) ) + { + Sequence< OUString > aSNS( 1 ); + aSNS.getArray( )[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( OS2_DNDSOURCE_SERVICE_NAME ) ); + + xFactory = createSingleFactory( + reinterpret_cast< XMultiServiceFactory* > ( pSrvManager ), + OUString::createFromAscii( pImplName ), + createDragSource, + aSNS, + &g_moduleCount.modCnt); + + } + else if( pSrvManager && ( 0 == rtl_str_compare( pImplName, OS2_DNDTARGET_IMPL_NAME ) ) ) + { + Sequence< OUString > aSNS( 1 ); + aSNS.getArray( )[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( OS2_DNDTARGET_SERVICE_NAME ) ); + + xFactory = createSingleFactory( + reinterpret_cast< XMultiServiceFactory* > ( pSrvManager ), + OUString::createFromAscii( pImplName ), + createDropTarget, + aSNS); + + } + + if ( xFactory.is() ) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + + return pRet; +} + +} // extern "C" diff --git a/dtrans/source/os2/dnd/globals.cxx b/dtrans/source/os2/dnd/globals.cxx new file mode 100644 index 000000000000..bf1bc93777f2 --- /dev/null +++ b/dtrans/source/os2/dnd/globals.cxx @@ -0,0 +1,200 @@ +/************************************************************** +* +* 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 <com/sun/star/datatransfer/dnd/DNDConstants.hpp> + +#include "globals.hxx" +#include "DragSource.hxx" +#include "DropTarget.hxx" + +using namespace com::sun::star::datatransfer::dnd::DNDConstants; + +// +// Convert office drag actions as defined in +// <type>com::sun::star::datatransfer::dnd::DNDConstants</type> +// into system conform drag actions. +// +MRESULT OfficeToSystemDragActions( sal_Int8 dragActions) +{ + MRESULT actions = MRFROM2SHORT( DOR_NODROP, 0); + + if (dragActions & ACTION_COPY) + { + actions = MRFROM2SHORT( DOR_DROP, DO_COPY); + } + + if (dragActions & ACTION_MOVE) + { + actions = MRFROM2SHORT( DOR_DROP, DO_MOVE); + } + + if (dragActions & ACTION_LINK) + { + actions = MRFROM2SHORT( DOR_DROP, DO_LINK); + } + + debug_printf("OfficeToSystemDragActions %d->0x%x", dragActions, actions); + return actions; +} + +// +// Convert system conform drag actions into office conform +// drag actions as defined in +// <type>com::sun::star::datatransfer::dnd::DNDConstants</type>. +// +sal_Int8 SystemToOfficeDragActions( USHORT usOperation) +{ + sal_Int8 actions = ACTION_NONE; + + switch( usOperation) { + case DO_UNKNOWN: + break; + case DO_DEFAULT: + actions |= ACTION_MOVE; + break; + case DO_MOVE: + actions |= ACTION_MOVE; + break; + case DO_COPY: + actions |= ACTION_COPY; + break; + case DO_LINK: + actions |= ACTION_LINK; + break; + } + + debug_printf("SystemToOfficeDragActions 0x%x->%d", usOperation, actions); + return actions; +} + + +// +// functions used by dnd.dll to get access to Window class data fields +// in the subclassed window procedure +// + +// Store DropTarget object reference +void SetWindowDropTargetPtr( HWND hWnd, void* dropTarget ) +{ + WinSetWindowULong( hWnd, SAL_FRAME_DROPTARGET, (ULONG)dropTarget); +} + +// Get DropTarget object reference +void* GetWindowDropTargetPtr( HWND hWnd ) +{ + return (void*)WinQueryWindowULong( hWnd, SAL_FRAME_DROPTARGET); +} + +// Store DragSource object reference +void SetWindowDragSourcePtr( HWND hWnd, void* dragSource ) +{ + WinSetWindowULong( hWnd, SAL_FRAME_DRAGSOURCE, (ULONG)dragSource); +} + +// Get DropTarget object reference +void* GetWindowDragSourcePtr( HWND hWnd ) +{ + return (void*)WinQueryWindowULong( hWnd, SAL_FRAME_DRAGSOURCE); +} + +// map desktop coordinates of mouse pointer to local window +// inverting also the y axis +void MapWindowPoint( HWND hwnd, PDRAGINFO dragInfo, PPOINTL ptlMouse) +{ + RECTL rclClient; + ptlMouse->x = dragInfo->xDrop; + ptlMouse->y = dragInfo->yDrop; + WinMapWindowPoints( HWND_DESKTOP, hwnd, ptlMouse, 1); + // invert y-coordinate + WinQueryWindowRect( hwnd, &rclClient); + ptlMouse->y = rclClient.yTop - ptlMouse->y; +} + + +// +// subclassed frame window procedure: used to intercept DM_* messages +// without accessing default window procedure inside VCL private code +// +extern "C" MRESULT EXPENTRY dndFrameProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) +{ +#if 0 + debug_printf("dndFrameProc hwnd %x, msg %x", hwnd, msg); +#endif + DropTarget* dt = (DropTarget*) GetWindowDropTargetPtr( hwnd); + DragSource* ds = NULL; + MRESULT mr; + + switch( msg) { + + case DM_DRAGOVER: + debug_printf("dndFrameProc hwnd %x, dt %x, DM_DRAGOVER", hwnd, dt); + return dt->dragOver( (PDRAGINFO) mp1); + break; + + case DM_DRAGLEAVE: + debug_printf("dndFrameProc hwnd %x, dt %x, DM_DRAGLEAVE", hwnd, dt); + return dt->dragLeave( (PDRAGINFO) mp1); + break; + + case DM_DROP: + debug_printf("dndFrameProc hwnd %x, dt %x, DM_DROP", hwnd, dt); + mr = dt->drop( (PDRAGINFO) mp1); + debug_printf("dndFrameProc hwnd %x, dt %x, DM_DROP mr=%x", hwnd, dt, mr); + return mr; + break; + + case DM_RENDERCOMPLETE: + debug_printf("dndFrameProc hwnd %x, dt %x, DM_RENDERCOMPLETE", hwnd, dt); + mr = dt->renderComplete( (PDRAGTRANSFER) mp1); + debug_printf("dndFrameProc hwnd %x, dt %x, DM_RENDERCOMPLETE mr=0x%x", hwnd, dt, mr); + return mr; + break; + + case DM_RENDERPREPARE: + debug_printf("dndFrameProc hwnd %x, dt %x, DM_RENDERPREPARE", hwnd, dt); + break; + + case DM_RENDER: + ds = (DragSource*) GetWindowDragSourcePtr( hwnd); + debug_printf("dndFrameProc hwnd %x, dt %x, DM_RENDER", hwnd, ds); + mr = ds->render( (PDRAGTRANSFER) mp1); + return mr; + break; + + // sent from target window to source window after rendering + case DM_ENDCONVERSATION: + // sent from AOO to DropSource to notify end of dragging + case DM_AOO_ENDCONVERSATION: + ds = (DragSource*) GetWindowDragSourcePtr( hwnd); + debug_printf("dndFrameProc hwnd %x, dt %x, DM_ENDCONVERSATION", hwnd, ds); + mr = ds->endConversation( (ULONG) mp1, (ULONG) mp2); + return mr; + break; + + } + + // forward to VCL frame proc + return dt->defWndProc(hwnd, msg, mp1, mp2); +} diff --git a/dtrans/source/os2/dnd/globals.hxx b/dtrans/source/os2/dnd/globals.hxx new file mode 100644 index 000000000000..16d36863d935 --- /dev/null +++ b/dtrans/source/os2/dnd/globals.hxx @@ -0,0 +1,63 @@ +/************************************************************** + * + * 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. + * + *************************************************************/ + + +#ifndef _GLOBALS_HXX_ +#define _GLOBALS_HXX_ + +#include <svpm.h> + +#include <rtl/unload.h> + +#define OS2_DNDSOURCE_SERVICE_NAME "com.sun.star.datatransfer.dnd.OleDragSource" +#define OS2_DNDSOURCE_IMPL_NAME "com.sun.star.comp.datatransfer.dnd.OleDragSource_V1" + +#define OS2_DNDTARGET_SERVICE_NAME "com.sun.star.datatransfer.dnd.OleDropTarget" +#define OS2_DNDTARGET_IMPL_NAME "com.sun.star.comp.datatransfer.dnd.OleDropTarget_V1" + +// from saldata.hxx: these offsets are hardcoded in dnd/globals.hxx too to avoid vcl dependancies +#define SAL_FRAME_DROPTARGET sizeof(ULONG) +#define SAL_FRAME_DRAGSOURCE (sizeof(ULONG)*2) +// from saldata.hxx: drag&drop internal messages (see dnd/globals.hxx) +#define DM_AOO_ENDCONVERSATION (WM_USER+170) + +extern rtl_StandardModuleCount g_moduleCount; + +#if OSL_DEBUG_LEVEL>0 +extern "C" int debug_printf(const char *f, ...); +#else +#define debug_printf( ...) +#endif + +MRESULT OfficeToSystemDragActions( sal_Int8 dragActions); +sal_Int8 SystemToOfficeDragActions( USHORT usOperation); + +extern "C" MRESULT EXPENTRY dndFrameProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2); + +// private exports from saldata.hxx +void SetWindowDropTargetPtr( HWND hWnd, void* dt); +void* GetWindowDropTargetPtr( HWND hWnd); +void SetWindowDragSourcePtr( HWND hWnd, void* ds); +void* GetWindowDragSourcePtr( HWND hWnd); + +void MapWindowPoint( HWND, PDRAGINFO, PPOINTL); + +#endif diff --git a/postprocess/packcomponents/makefile.mk b/postprocess/packcomponents/makefile.mk index 98be0a54e500..cd4836eefd8a 100644 --- a/postprocess/packcomponents/makefile.mk +++ b/postprocess/packcomponents/makefile.mk @@ -339,6 +339,7 @@ my_components += \ .IF "$(OS)" == "OS2" my_components += \ component/dtrans/source/generic/dtrans \ + component/dtrans/util/dnd \ component/dtrans/util/sysdtrans .END diff --git a/scp2/source/ooo/file_library_ooo.scp b/scp2/source/ooo/file_library_ooo.scp index e367fb3d9723..378e640dd265 100644 --- a/scp2/source/ooo/file_library_ooo.scp +++ b/scp2/source/ooo/file_library_ooo.scp @@ -408,7 +408,7 @@ File gid_File_Lib_Vbahelper End -#ifdef WNT +#if defined WNT || defined OS2 File gid_File_Lib_Dnd TXT_FILE_BODY; diff --git a/vcl/inc/os2/saldata.hxx b/vcl/inc/os2/saldata.hxx index daf546f5616b..43bdc86cbd0c 100644 --- a/vcl/inc/os2/saldata.hxx +++ b/vcl/inc/os2/saldata.hxx @@ -204,8 +204,12 @@ void ImplReleaseSALIMEData(); #define SAL_PROFILE_PRINTDJP ((PSZ)"PrintDJP") #define SAL_PROFILE_PRINTRAW ((PSZ)"PrintRAW") -#define SAL_FRAME_WNDEXTRA sizeof(ULONG) -#define SAL_FRAME_THIS 0 +#define SAL_FRAME_WNDEXTRA (sizeof(ULONG)*3) +#define SAL_FRAME_THIS 0 +// these offsets are hardcoded in dnd/globals.hxx too to avoid vcl dependancies +#define SAL_FRAME_DROPTARGET sizeof(ULONG) +#define SAL_FRAME_DRAGSOURCE (sizeof(ULONG)*2) + #define SAL_FRAME_CLASSNAME "SALFRAME" #define SAL_SUBFRAME_CLASSNAME "SALSUBFRAME" #define SAL_OBJECT_WNDEXTRA sizeof(ULONG) @@ -275,6 +279,9 @@ void ImplReleaseSALIMEData(); // POSTTIMER-Message; wparam = 0, lParam == time #define SAL_MSG_POSTTIMER (WM_USER+169) +// drag&drop internal messages (see dnd/globals.hxx) +#define DM_AOO_ENDCONVERSATION (WM_USER+170) + // ----------------- // - Helpfunctions - // ----------------- diff --git a/vcl/source/window/syschild.cxx b/vcl/source/window/syschild.cxx index cbdba7d35751..6bbe5805fd70 100644 --- a/vcl/source/window/syschild.cxx +++ b/vcl/source/window/syschild.cxx @@ -242,6 +242,8 @@ sal_IntPtr SystemChildWindow::GetParentWindowHandle( sal_Bool bUseJava ) (void)bUseJava; #if defined WNT nRet = reinterpret_cast< sal_IntPtr >( GetSystemData()->hWnd ); +#elif defined OS2 + nRet = reinterpret_cast< sal_IntPtr >( (long)GetSystemData()->hWnd ); #elif defined QUARTZ // FIXME: this is wrong nRet = reinterpret_cast< sal_IntPtr >( GetSystemData()->mpNSView ); diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx index 5cc3819bbe9d..7269794766d8 100644 --- a/vcl/source/window/window.cxx +++ b/vcl/source/window/window.cxx @@ -8611,7 +8611,7 @@ uno::Reference< XDragSource > Window::GetDragSource() { Sequence< Any > aDragSourceAL( 2 ), aDropTargetAL( 2 ); OUString aDragSourceSN, aDropTargetSN; -#if defined WNT +#if defined WNT || defined OS2 aDragSourceSN = OUString::createFromAscii( "com.sun.star.datatransfer.dnd.OleDragSource" ); aDropTargetSN = OUString::createFromAscii( "com.sun.star.datatransfer.dnd.OleDropTarget" ); aDragSourceAL[ 1 ] = makeAny( (sal_uInt32) pEnvData->hWnd ); commit 6065985d440bb38020fb0551fd044a2d95592eaa Author: Yuri Dario <yda...@apache.org> Date: Wed Mar 28 16:54:09 2018 +0000 #i126518# adjust building of sysdtrans module for OS/2. diff --git a/dtrans/Library_sysdtrans_os2.mk b/dtrans/Library_sysdtrans_os2.mk index 53bec2542775..60bc6fa78adb 100644 --- a/dtrans/Library_sysdtrans_os2.mk +++ b/dtrans/Library_sysdtrans_os2.mk @@ -42,10 +42,15 @@ $(eval $(call gb_Library_add_linked_libs,sysdtrans,\ cppu \ sal \ stl \ - UClip \ + uclip \ $(gb_STDLIBS) \ )) +# YD FIXME this is not working... needs ldflags hack... +$(eval $(call gb_Library_add_libs,sysdtrans,\ + -luclip \ +)) + $(eval $(call gb_Library_add_exception_objects,sysdtrans,\ dtrans/source/os2/clipb/Os2Clipboard \ dtrans/source/os2/clipb/Os2Bitmap \ diff --git a/dtrans/source/os2/clipb/Os2Clipboard.hxx b/dtrans/source/os2/clipb/Os2Clipboard.hxx index ca8f29c1446c..ba09bbedf8a3 100644 --- a/dtrans/source/os2/clipb/Os2Clipboard.hxx +++ b/dtrans/source/os2/clipb/Os2Clipboard.hxx @@ -42,9 +42,6 @@ // the implementation names #define OS2_CLIPBOARD_IMPL_NAME "com.sun.star.datatransfer.clipboard.ClipboardW32" -// the registry key names -#define OS2_CLIPBOARD_REGKEY_NAME "/com.sun.star.datatransfer.clipboard.Os2Clipboard/UNO/SERVICES/com.sun.star.datatransfer.clipboard.SystemClipboard" - namespace os2 { class Os2Clipboard : diff --git a/dtrans/source/os2/clipb/Os2Transferable.hxx b/dtrans/source/os2/clipb/Os2Transferable.hxx index 261709cc6985..e5eef8f8b100 100644 --- a/dtrans/source/os2/clipb/Os2Transferable.hxx +++ b/dtrans/source/os2/clipb/Os2Transferable.hxx @@ -38,10 +38,10 @@ #define CHAR_POINTER(THE_OUSTRING) ::rtl::OUStringToOString (THE_OUSTRING, RTL_TEXTENCODING_UTF8).pData->buffer -#if OSL_DEBUG_LEVEL>10 +#if OSL_DEBUG_LEVEL>0 extern "C" int debug_printf(const char *f, ...); #else -#define debug_printf( ...) { 1; } +#define debug_printf( ...) #endif #define CPPUTYPE_SEQSALINT8 getCppuType( (const Sequence< sal_Int8 >*) 0 ) _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits