From b25f8d8f9bd5d77ab3f4181e41e8be003c5bf6a2 Mon Sep 17 00:00:00 2001 From: "mkaply%us.ibm.com" Date: Mon, 15 Apr 2002 22:56:31 +0000 Subject: [PATCH] #59403 r=pedemont, sr=blizzard, a=asa OS/2 only - beginning of drag/drop --- widget/src/os2/Makefile.in | 10 +- widget/src/os2/nsDragService.cpp | 1247 +++++++--------------------- widget/src/os2/nsDragService.h | 111 +-- widget/src/os2/nsWidgetFactory.cpp | 8 +- widget/src/os2/nsWindow.cpp | 89 +- 5 files changed, 423 insertions(+), 1042 deletions(-) diff --git a/widget/src/os2/Makefile.in b/widget/src/os2/Makefile.in index 6b4804e6d977..3579bab6cbeb 100644 --- a/widget/src/os2/Makefile.in +++ b/widget/src/os2/Makefile.in @@ -60,17 +60,9 @@ CPPSRCS = \ nsToolkit.cpp \ nsWidgetFactory.cpp \ nsWindow.cpp \ + nsDragService.cpp \ $(NULL) -# XXX FILES temporarily removed -# nsDragService.cpp \ - -# XXX OS2TODO -# nsNativeDragTarget.cpp \ -# nsNativeDragSource.cpp \ -# nsDataObj.cpp \ -# nsDataObjCollection.cpp \ - SHARED_LIBRARY_LIBS = \ $(DIST)/lib/$(LIB_PREFIX)xpwidgets_s.$(LIB_SUFFIX) \ $(NULL) diff --git a/widget/src/os2/nsDragService.cpp b/widget/src/os2/nsDragService.cpp index 1317ad91a176..f7ba06528e87 100644 --- a/widget/src/os2/nsDragService.cpp +++ b/widget/src/os2/nsDragService.cpp @@ -1,990 +1,377 @@ -/* - * The contents of this file are subject to the Mozilla Public License +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License * Version 1.1 (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.mozilla.org/MPL/ * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the - * License for the specific language governing rights and limitations - * under the License. + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. * - * The Original Code is the Mozilla OS/2 libraries. + * The Original Code is mozilla.org code. * - * The Initial Developer of the Original Code is John Fairhurst, - * . Portions created by John Fairhurst are - * Copyright (C) 1999 John Fairhurst. All Rights Reserved. + * The Initial Developer of the Original Code is + * IBM Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. * - * Contributor(s): + * Contributor(s): * - */ + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ -// Drag'n'drop manager - -#include "nsWidgetDefs.h" #include "nsDragService.h" -#include "nsITransferable.h" -#include "nsVoidArray.h" +#include "nsISupportsPrimitives.h" +#include "nsString.h" +#include "nsXPIDLString.h" +#include "nsReadableUtils.h" -#include "nsFileSpec.h" -#include "nsFileStream.h" -#include "nsSpecialSystemDirectory.h" -#include "resid.h" +void WriteTypeEA(const char* filename, const char* type); +BOOL GetURLObjectContents(PDRAGITEM pDragItem); -#include // for sscanf -#include // realloc/free - -// -// There are three major cases to consider: -// -// 1. Drag from xptoolkit to non-xptoolkit -// -// Use DRM_OS2FILE. Source render to get right rf used. -// -// 2. Drag from xptoolkit to xptoolkit -// -// Use a custom shared-memory RM; special-case same process -// -// 3. Drag from non-xptoolkit to xptoolkit -// -// Use DRM_OS2FILE and create nsFileListTransferable's -// Problem: we need to copy the file because we have no way of knowing -// when client has done with it & we can DM_ENDCONVERSATION -// -// Plus: xptoolkit will eventually acquire text/URL (or text/URI or something) -// which we can handle. -// -// Apart from this, the major thing not implemented is the initiation of -// post-drop conversations for DRM_OS2FILE. This is because of various reasons, -// see comment in nsDragService::DoPushedOS2FILE() below. -// - -// Quick utility class to clean up files we create at some later point... -class nsGCFileSpec : public nsFileSpec +nsDragService::nsDragService() { - public: - nsGCFileSpec(nsFileSpec &fs) : nsFileSpec(fs) {} - ~nsGCFileSpec() - { - Delete( FALSE); - } -}; - -static char *DecodeStrHandle( HSTR hstr); -static const char *MimeTypeToRF( const char *pcsz); -static const char *RFToMimeType( const char *pcsz); -static BOOL FindFile( PDRAGITEM pItem, nsFileSpec &aFileSpec); -static void GetTempFile( nsFileSpec &tempfile); - -// convert between pm & xptoolkit drag operation types -#define DragOperation(at) \ - (at == nsIDragService::DRAGDROP_ACTION_NONE ? DO_DEFAULT : \ - (at == nsIDragService::DRAGDROP_ACTION_COPY ? DO_COPY : \ - (at == nsIDragService::DRAGDROP_ACTION_MOVE ? DO_MOVE : DO_LINK))) - -#define DragDropAction(do) \ - (do == DO_LINK ? nsIDragService::DRAGDROP_ACTION_LINK : \ - (do == DO_COPY ? nsIDragService::DRAGDROP_ACTION_COPY : \ - nsIDragService::DRAGDROP_ACTION_MOVE)) - -nsDragService::nsDragService() : mDragInfo(0), mDragItems(0) -{ - // XXX temporary icon until xptoolkit realises it needs to give us one - mIcon = WinLoadPointer( HWND_DESKTOP, gWidgetModuleData->hModResources, - ID_ICO_DRAGITEM); - - // Window for doing things + /* member initializers and constructor code */ mDragWnd = WinCreateWindow( HWND_DESKTOP, WC_STATIC, 0, 0, 0, 0, 0, 0, HWND_DESKTOP, HWND_BOTTOM, 0, 0, 0); - mWndProc = WinSubclassWindow( mDragWnd, fnwpDragSource); + WinSubclassWindow( mDragWnd, nsDragWindowProc); +} + +MRESULT EXPENTRY nsDragWindowProc(HWND hWnd, ULONG msg, MPARAM mp1, + MPARAM mp2) +{ + PDRAGTRANSFER pdragtransfer; + PDRAGITEM pdragitem; + FILE *fp; + ULONG ulLength; + PSZ pszURL; + CHAR chPath[CCHMAXPATH]; + switch (msg) { + case DM_RENDER: + pdragtransfer = (PDRAGTRANSFER)mp1; + DrgQueryStrName(pdragtransfer->hstrRenderToName, CCHMAXPATH, chPath); + ulLength = DrgQueryStrNameLen(pdragtransfer->pditem->hstrSourceName); + pszURL = (PSZ)nsMemory::Alloc(ulLength+1); + DrgQueryStrName(pdragtransfer->pditem->hstrSourceName, ulLength+1, pszURL); + fp = fopen(chPath, "wb+"); + fwrite(pszURL, ulLength+1, 1, fp); + fclose(fp); + WriteTypeEA(chPath, "UniformResourceLocator"); + nsMemory::Free(pszURL); + DrgPostTransferMsg(pdragtransfer->hwndClient, DM_RENDERCOMPLETE, pdragtransfer, DMFL_RENDEROK,0,TRUE); + DrgFreeDragtransfer(pdragtransfer); + return (MRESULT)TRUE; + break; + default: + break; + } + return ::WinDefWindowProc(hWnd, msg, mp1, mp2); } nsDragService::~nsDragService() { - WinDestroyPointer( mIcon); - WinDestroyWindow( mDragWnd); + /* destructor code */ + WinDestroyWindow(mDragWnd); } -nsresult nsDragService::InvokeDragSession( nsIDOMNode *aDOMNode, - nsISupportsArray *aTransArray, - nsIRegion *aRegion, - PRUint32 aActionType) +NS_IMETHODIMP nsDragService::InvokeDragSession(nsIDOMNode *aDOMNode, nsISupportsArray *aTransferables, nsIScriptableRegion *aRegion, PRUint32 aActionType) { - nsBaseDragService::InvokeDragSession ( aDOMNode, aTransArray, aRegion, aActionType ); + nsBaseDragService::InvokeDragSession ( aDOMNode, aTransferables, aRegion, aActionType ); + + // set our reference to the transferables. this will also addref + // the transferables since we're going to hang onto this beyond the + // length of this call + mSourceDataItems = aTransferables; + + WinSetCapture(HWND_DESKTOP, NULLHANDLE); + + PDRAGINFO pDragInfo = DrgAllocDraginfo(1); /* Assume we are only dragging one thing for now */ + APIRET rc; + + if(pDragInfo) + { + pDragInfo->usOperation = DO_DEFAULT; + DRAGITEM dragitem; + dragitem.hwndItem = mDragWnd; + dragitem.ulItemID = (ULONG)0; + dragitem.hstrType = DrgAddStrHandle("UniformResourceLocator"); + dragitem.hstrRMF = DrgAddStrHandle(""); + dragitem.hstrContainerName = DrgAddStrHandle(""); + dragitem.hstrSourceName = NULLHANDLE; + dragitem.hstrTargetName = NULLHANDLE; + nsCOMPtr genericItem; + mSourceDataItems->GetElementAt(0, getter_AddRefs(genericItem)); + nsCOMPtr item (do_QueryInterface(genericItem)); + PRUint32 len = 0; + nsCOMPtr genericURL; + if ( NS_SUCCEEDED(item->GetTransferData(kURLMime, getter_AddRefs(genericURL), &len)) ) + { + nsCOMPtr urlObject ( do_QueryInterface(genericURL) ); + if( urlObject ) + { + nsXPIDLString urlInfo; + nsAutoString linkName, url; + urlObject->GetData ( getter_Copies(urlInfo) ); + PRInt32 lineIndex = urlInfo.FindChar ('\n'); + if ( lineIndex != -1 ) + { + urlInfo.Left(url, lineIndex); + urlInfo.Mid ( linkName, lineIndex + 1, (len/2) - (lineIndex + 1) ); + dragitem.hstrTargetName = DrgAddStrHandle(ToNewCString(linkName)); + dragitem.hstrSourceName = DrgAddStrHandle(ToNewCString(url)); + } + } + } + if (dragitem.hstrSourceName && dragitem.hstrTargetName) { + dragitem.hstrRMF = DrgAddStrHandle(""); + } else { + dragitem.hstrRMF = DrgAddStrHandle(""); /* Moz only drag */ + } + dragitem.fsControl = DC_OPEN; + dragitem.cxOffset = 2; + dragitem.cyOffset = 2; + dragitem.fsSupportedOps = DO_COPYABLE|DO_MOVEABLE|DO_LINKABLE; + rc = DrgSetDragitem(pDragInfo, &dragitem, sizeof(DRAGITEM), 0); + DRAGIMAGE dragimage; + memset(&dragimage, 0, sizeof(DRAGIMAGE)); + dragimage.cb = sizeof(DRAGIMAGE); + dragimage.hImage = WinQuerySysPointer(HWND_DESKTOP, SPTR_FILE, FALSE); + dragimage.fl = DRG_ICON; + + mDoingDrag = PR_TRUE; + HWND hwndDest = DrgDrag(mDragWnd, pDragInfo, &dragimage, 1, VK_BUTTON1, + (void*)0x80000000L); // Don't lock the desktop PS + mDoingDrag = PR_FALSE; +#ifdef DEBUG + if (!hwndDest) { + ERRORID eid = WinGetLastError((HAB)0); + printf("Drag did not finish - error = %x error=%x\n", eid); + } +#endif + + // Clean up everything here; no async. case to consider. + DrgDeleteDraginfoStrHandles(pDragInfo); + DrgFreeDraginfo(pDragInfo); + } + + return NS_OK; +} + +NS_IMETHODIMP nsDragService::GetNumDropItems(PRUint32 *aNumDropItems) +{ + mSourceDataItems->Count(aNumDropItems); + return NS_OK; +} + +NS_IMETHODIMP nsDragService::GetData(nsITransferable *aTransferable, PRUint32 aItemIndex) +{ + // make sure that we have a transferable + if (!aTransferable) + return NS_ERROR_INVALID_ARG; + + // get flavor list that includes all acceptable flavors (including + // ones obtained through conversion). Flavors are nsISupportsStrings + // so that they can be seen from JS. + nsresult rv = NS_ERROR_FAILURE; + nsCOMPtr flavorList; + rv = aTransferable->FlavorsTransferableCanImport(getter_AddRefs(flavorList)); + if (NS_FAILED(rv)) + return rv; + + // count the number of flavors + PRUint32 cnt; + flavorList->Count (&cnt); + + for (unsigned int i= 0; i < cnt; ++i ) { + nsCOMPtr genericWrapper; + flavorList->GetElementAt(i, getter_AddRefs(genericWrapper)); + nsCOMPtr currentFlavor; + currentFlavor = do_QueryInterface(genericWrapper); + if (currentFlavor) { + nsXPIDLCString flavorStr; + currentFlavor->ToString(getter_Copies(flavorStr)); - // This is horribly multidimensional -- we have an array of dragitems, fine. - // But -- each dragitem may be a file list, which itself is several dragitems. - PDRAGITEM pDragItems = 0; - ULONG cDragItems = 0; - - PRUint32 cItems; - aTransArray->Count( &cItems); - for( PRUint32 i = 0; i < cItems; i++) - { - nsCOMPtr pThing; - pThing = dont_AddRef( aTransArray->ElementAt(i)); // XXX check this doesn't leak - if( pThing) - { - // Get dragitems for this array element - nsCOMPtr pXfer = do_QueryInterface(pThing); - PDRAGITEM pDItems = 0; - ULONG cDItems = 0; - - CreateDragItems( &cDItems, &pDItems, pXfer); - - // Now extend & copy up into the local array - pDragItems = (PDRAGITEM) - realloc( pDragItems, cDragItems + cDItems * sizeof(DRAGITEM)); - memcpy( pDragItems + cDragItems, pDItems, cDItems * sizeof(DRAGITEM)); - cDragItems += cDItems; - - // free local data - delete [] pDItems; + nsCOMPtr genericItem; + + mSourceDataItems->GetElementAt(aItemIndex, getter_AddRefs(genericItem)); + nsCOMPtr item (do_QueryInterface(genericItem)); + if (item) { + nsCOMPtr data; + PRUint32 tmpDataLen = 0; + rv = item->GetTransferData(flavorStr, getter_AddRefs(data), &tmpDataLen); + if (NS_SUCCEEDED(rv)) { + rv = aTransferable->SetTransferData(flavorStr, data, tmpDataLen); + break; + } } - } - - nsresult rc = NS_ERROR_FAILURE; - - if( cDragItems) - { - rc = InvokeDrag( pDragItems, cDragItems, aActionType); - free( pDragItems); - } - - return rc; + } + } + return rv; } - -nsresult nsDragService::GetData( nsITransferable *aTransferable, - PRUint32 aItemIndex) +NS_IMETHODIMP nsDragService::IsDataFlavorSupported(const char *aDataFlavor, PRBool *_retval) { - // Fill the transferable with data from the given dragitem. - if( !aTransferable || aItemIndex >= mDragInfo->cditem) - return NS_ERROR_FAILURE; + if (!_retval) + return NS_ERROR_INVALID_ARG; - PDRAGITEM pItem = DrgQueryDragitemPtr( mDragInfo, aItemIndex); + // set this to no by default + *_retval = PR_FALSE; - // Problem here. Unless we're xptoolkit<->xptoolkit we can only - // get data in *one* flavour. - // - // Oh well; do our best. - - nsVoidArray *pFormats = nsnull; - aTransferable->FlavorsTransferableCanImport( &pFormats); - PRUint32 cFormats = pFormats->Count(); - - for( PRUint32 i = 0; i < cFormats; i++) - { - nsString *pFlavour = (nsString*) pFormats->ElementAt( i); - char buff[40]; - gWidgetModuleData->ConvertFromUcs( *pFlavour, buff, 40); - const char *rf = MimeTypeToRF( buff); - if( rf && DrgVerifyRMF( pItem, 0, rf)) - { - // Okay, have something to do. Now pick a rendering mechanism: - void *pData = 0; - PRUint32 cData = 0; - - BOOL source_dry_p = FALSE; // can only get single flavour - - // 1. Some xptoolkit - use DRM_MOZILLA - if( DrgVerifyRMF( pItem, "DRM_MOZILLA", 0)) - { - DoMozillaXfer( pItem, buff, &pData, &cData); - } - // 2. Some random process - use DRM_OS2FILE - else if( DrgVerifyRMF( pItem, "DRM_OS2FILE", 0)) - { - // 2a. `normal' rendering - load it, break out - if( pItem->hstrSourceName && pItem->hstrContainerName) - { - nsFileSpec file; - - if( FindFile( pItem, file)) - { - cData = file.GetFileSize(); - pData = new char [ cData ]; - nsInputFileStream istream( file); - istream.read( pData, (PRInt32) cData); - istream.close(); - - source_dry_p = TRUE; - } -#ifdef DEBUG - else - printf( "Can't find dropped file\n"); -#endif + PRUint32 numDragItems = 0; + // if we don't have mDataItems we didn't start this drag so it's + // an external client trying to fool us. + if (!mSourceDataItems) + return NS_OK; + mSourceDataItems->Count(&numDragItems); + for (PRUint32 itemIndex = 0; itemIndex < numDragItems; ++itemIndex) { + nsCOMPtr genericItem; + mSourceDataItems->GetElementAt(itemIndex, getter_AddRefs(genericItem)); + nsCOMPtr currItem (do_QueryInterface(genericItem)); + if (currItem) { + nsCOMPtr flavorList; + currItem->FlavorsTransferableCanExport(getter_AddRefs(flavorList)); + if (flavorList) { + PRUint32 numFlavors; + flavorList->Count( &numFlavors ); + for ( PRUint32 flavorIndex = 0; flavorIndex < numFlavors ; ++flavorIndex ) { + nsCOMPtr genericWrapper; + flavorList->GetElementAt (flavorIndex, getter_AddRefs(genericWrapper)); + nsCOMPtr currentFlavor; + currentFlavor = do_QueryInterface(genericWrapper); + if (currentFlavor) { + nsXPIDLCString flavorStr; + currentFlavor->ToString ( getter_Copies(flavorStr) ); + if (strcmp(flavorStr, aDataFlavor) == 0) { + *_retval = PR_TRUE; } - // 2b. DRM_OS2FILE push - faff around endlessly, break out - // This is a bit tricky 'cos this method needs to be synchronous. - else - { - DoPushedOS2FILE( pItem, rf, &pData, &cData); - source_dry_p = TRUE; - } - } -#ifdef DEBUG - else - { - const char *rmf = DecodeStrHandle( pItem->hstrRMF); - printf( "Incomprehensible DRM (%s)\n", rmf); - } -#endif - - if( pData && cData) - aTransferable->SetTransferData( pFlavour, pData, cData); - - if( source_dry_p) - break; + } + } } - else if( pFlavour->Equals( kDropFilesMime)) - { - // Moan if this isn't a filelisttransferable. - nsCOMPtr pFileList = do_QueryInterface(aTransferable); - - if(pFileList) - { - // Need a file. - nsFileSpec *pFileSpec = 0; - - if( DrgVerifyRMF( pItem, "DRM_MOZILLA", 0)) - { - void *pData = 0; - PRUint32 cData; - DoMozillaXfer( pItem, buff, &pData, &cData); - - if( pData) - { - nsFileSpec tempfile; - GetTempFile( tempfile); - - nsOutputFileStream stream(tempfile); - stream.write( pData, (PRInt32)cData); - stream.close(); - - // Make sure this temp file is erased eventually. - pFileSpec = new nsGCFileSpec( tempfile); - } - } - // 2. Some random process - use DRM_OS2FILE - else if( DrgVerifyRMF( pItem, "DRM_OS2FILE", 0)) - { - if( pItem->hstrSourceName && pItem->hstrContainerName) - { - nsFileSpec file; - - if( !FindFile( pItem, file)) - printf( "Can't find dropped file\n"); - else - pFileSpec = new nsFileSpec(file); - } - else - { - // (can't actually do source rendering yet) - DoPushedOS2FILE(0,0,0,0); - } - } - else - { - const char *rmf = DecodeStrHandle( pItem->hstrRMF); - printf( "Incomprehensible DRM -> file (%s)\n", rmf); - } - - // Did we get one? - if( pFileSpec) - { - nsVoidArray array; - array.AppendElement(pFileSpec); - pFileList->SetFileList(&array); - } - } -#ifdef DEBUG - else - printf( "kDropFilesMime requested but no filelisttransferable!\n"); -#endif - } - } - - return NS_OK; + } + } + return NS_OK; } -nsresult nsDragService::GetNumDropItems( PRUint32 *aNumItems) +/* Helper functions */ +void WriteTypeEA(const char* filename, const char* type) { - if( !aNumItems) - return NS_ERROR_NULL_POINTER; + const unsigned fea2listsize = 6000; + const char TYPE[] = ".TYPE"; + EAOP2 eaop2; + eaop2.fpGEA2List = 0; + eaop2.fpFEA2List = PFEA2LIST(new char[fea2listsize]); + PFEA2 pFEA2 = &eaop2.fpFEA2List->list[0]; - *aNumItems = mDragInfo->cditem; + // create .TYPE EA + pFEA2->fEA = 0; // .LONGNAME is not needed + pFEA2->cbName = sizeof(TYPE)-1; // skip \0 terminator - return NS_OK; -} - -nsresult nsDragService::IsDataFlavorSupported( nsString *aDataFlavour) -{ - // The idea here is to return NS_OK if any of the dragitems supports - // this flavour (yeah, hmm...) - // - // Maybe we should change it so they all have to be (which is what CUA - // says we should do...) - - nsresult rc = NS_ERROR_FAILURE; - - char buff[40]; - gWidgetModuleData->ConvertFromUcs( *aDataFlavour, buff, 40); - - const char *rf = MimeTypeToRF( buff); - -#ifdef DEBUG - printf( "IsDataFlavorSupported %s\n", buff); - printf( "RF for that is %s\n", rf); -#endif - - if( rf) - { - for( PRUint32 i = 0; i < mDragInfo->cditem; i++) - { - PDRAGITEM pItem = DrgQueryDragitemPtr( mDragInfo, i); - // this checks for ANY rm, which is a bit dubious. - if( DrgVerifyRMF( pItem, 0, rf)) - { - rc = NS_OK; - break; - } - } - } - -#ifdef DEBUG - printf( "Flavor is %ssupported.\n", rc == NS_OK ? "" : "not "); -#endif - - return rc; -} - -// Starting drag-over event block. -void nsDragService::InitDragOver( PDRAGINFO aDragInfo) -{ - // If the drag's from another process, grab it - if( !mDragInfo) - { - DrgAccessDraginfo( aDragInfo); - mDragInfo = aDragInfo; - } - - // Set xp flags - SetCanDrop( PR_FALSE); - SetDragAction( DragDropAction(mDragInfo->usOperation)); - StartDragSession(); -} - -// end of drag-over event block; get xp settings & convert. -MRESULT nsDragService::TermDragOver() -{ - MRESULT rc; - PRBool bCanDrop; - PRUint32 action; - - EndDragSession(); - GetCanDrop( &bCanDrop); - GetDragAction( &action); - - rc = MPFROM2SHORT( bCanDrop ? DOR_DROP : DOR_NODROP, DragOperation(action)); - - // ...factor code... - TermDragExit(); - - return rc; -} - -void nsDragService::InitDragExit( PDRAGINFO aDragInfo) -{ - // Nothing else to do - InitDragOver( aDragInfo); -} - -void nsDragService::TermDragExit() -{ - // release draginfo if appropriate. Note we use the slightly icky way - // of looking at the value of mDragItems to see if we started the drag. - if( !mDragItems) - { - DrgFreeDraginfo( mDragInfo); - mDragInfo = 0; - } -} - -void nsDragService::InitDrop( PDRAGINFO aDragInfo) -{ - // again, doesn't look like there's anything else to do - InitDragOver( aDragInfo); -} - -void nsDragService::TermDrop() -{ - // do an end-conversation for each dragitem. - // Any actual rendering is done in response to the GetData method above. - for( PRUint32 i = 0; i < mDragInfo->cditem; i++) - { - PDRAGITEM pItem = DrgQueryDragitemPtr( mDragInfo, i); - DrgSendTransferMsg( pItem->hwndItem, - DM_ENDCONVERSATION, - MPFROMLONG(pItem->ulItemID), - MPFROMSHORT(DMFL_TARGETSUCCESSFUL)); // I suppose - } - - TermDragExit(); -} - -// access the singleton -nsresult NS_GetDragService( nsISupports **aDragService) -{ - if( !aDragService) - return NS_ERROR_NULL_POINTER; - - *aDragService = (nsIDragService*)gWidgetModuleData->dragService; - NS_ADDREF(*aDragService); - - return NS_OK; -} - -// Examine a transferable and allocate & fill in appropriate DRAGITEMs -void nsDragService::CreateDragItems( PULONG pCount, PDRAGITEM *ppItems, - nsITransferable *aTransferable) -{ - nsCOMPtr pFileList = do_QueryInterface(aTransferable); - - if( pFileList) - { - nsVoidArray aFiles; - pFileList->GetFileList( &aFiles); - *pCount = aFiles.Count(); - if( *pCount) - { - // Create a dragitem for each filespec - *ppItems = new DRAGITEM [*pCount]; - for( PRUint32 i = 0; i < *pCount; i++) - { - nsFileSpec *pFile = (nsFileSpec*) aFiles.ElementAt(i); - FillDragItem( *ppItems + i, pFile); - } - } - } - else - { - *ppItems = new DRAGITEM [1]; // alloc w' new [] for uniform deletion - *pCount = 1; - FillDragItem( *ppItems, aTransferable); - } -} - -void nsDragService::FillDragItem( PDRAGITEM aItem, nsFileSpec *aFilespec) -{ - // We don't have to source-render these, 'cos they're unique files which - // already exist (we hope). - // - // On the down side, I have to trust nsFileSpec... + pFEA2->cbValue = strlen(type)+2*sizeof(USHORT); + // ^ + // space for the type and length field. // - aItem->hwndItem = mDragWnd; // just for completeness - aItem->ulItemID = 0; - aItem->hstrType = DrgAddStrHandle( DRT_UNKNOWN); - // XXX print & discard to come ? Maybe not, actually. - aItem->hstrRMF = DrgAddStrHandle( ""); + strcpy(pFEA2->szName, TYPE); + char* pData = pFEA2->szName+pFEA2->cbName+1; // data begins at + // first byte after + // the name + *(USHORT*)pData = EAT_ASCII; // type + *((USHORT*)pData+1) = strlen(type); // length + strcpy(pData+2*sizeof(USHORT), type);// content - // (this is a really messy, unwieldy api) - nsFileSpec parentDir; - aFilespec->GetParent( parentDir); - aItem->hstrContainerName = DrgAddStrHandle( nsNSPRPath(parentDir)); - char *pszLeaf = aFilespec->GetLeafName(); - aItem->hstrSourceName = DrgAddStrHandle( pszLeaf); - aItem->hstrTargetName = DrgAddStrHandle( pszLeaf); - nsCRT::free( pszLeaf); + pFEA2->oNextEntryOffset = 0; // no more EAs to write. - aItem->cxOffset = aItem->cyOffset = 0; - aItem->fsControl = 0; - aItem->fsSupportedOps = DO_COPYABLE | DO_MOVEABLE | DO_LINKABLE; + eaop2.fpFEA2List->cbList = PCHAR(pData+2*sizeof(USHORT)+ + pFEA2->cbValue)-PCHAR(eaop2.fpFEA2List); + APIRET rc = DosSetPathInfo(filename, + FIL_QUERYEASIZE, + &eaop2, + sizeof(eaop2), + 0); } - -// Transferables passed in here are guaranteed not to be nsIFileListTransferables -// -void nsDragService::FillDragItem( PDRAGITEM aItem, nsITransferable *aTransferable) +/* GetURLObjectContents -- This method gets the contents of a WPSH URL + * object by reading the file name specified in the dragitem and + * replacing it with the URL contained in the file. This is necessary + * so that dropping URL objects onto the browser displays the page at + * the URL, rather than displaying the URL itself. + */ +BOOL GetURLObjectContents(PDRAGITEM pDragItem) { - aItem->hwndItem = mDragWnd; + char szURLFileName[CCHMAXPATH] = {0}; + char szURL[CCHMAXPATH] = {0}; + char szTemp[CCHMAXPATH] = {0}; + char szProtocol[15] = {0}; + char szResource[CCHMAXPATH-15]= {0}; + BOOL rc = FALSE; - // ref the transferable to write out the data when we know which is needed - aItem->ulItemID = (ULONG) aTransferable; - NS_ADDREF(aTransferable); - - // Now go through transferable building things - nsVoidArray *pFormats = nsnull; - aTransferable->FlavorsTransferableCanExport( &pFormats); - - // XXX DRM_DISCARD and DRM_PRINTFILE to come when xptoolkit decides how - // (whether...) to handle them - - char rmf[200] = "(DRM_OS2FILE,DRM_MOZILLA) X (DRF_UNKNOWN"; - char buff[40]; - - PRUint32 cFormats = pFormats->Count(); - - for( PRUint32 i = 0; i < cFormats; i++) + // Get Drive and subdirectory name from hstrContainerName. + if (!DrgQueryStrName(pDragItem->hstrContainerName, + CCHMAXPATH, + szURLFileName)) { - nsString *pFlavour = (nsString*) pFormats->ElementAt( i); - gWidgetModuleData->ConvertFromUcs( *pFlavour, buff, 40); - const char *rf = MimeTypeToRF( buff); - if( rf) - { - strcat( rmf, ","); - strcat( rmf, rf); - } -#if 0 - else if( pFlavour->Equals( kURLMime)) - { - // Abort any processing already done; the idea here is to provide - // the URL format so the WPS can do the Right Thing; we also need to - // provide some kind of text format for insertion into a program. - aItem->hstrType = DrgAddStrHandle( DRT_URL","DRT_TEXT); - aItem->hstrRMF = DrgAddStrHandle( ","); - aItem->hstrContainerName = 0; - aItem->hstrSourceName = DrgAddStrHandle( full url ); - aItem->hstrTargetName = DrgAddStrHandle( title for object ); - aItem->cxOffset = aItem->cyOffset = 0; - aItem->fsControl = 0; - aItem->fsSupportedOps = DO_COPYABLE | DO_MOVEABLE | DO_LINKABLE; - - return; - } -#endif - // Not sure what to do about 'Type'. Setting everything is wrong, - // but picking an arbitary one is also bad. - // - // So leave it as unknown for now. + return(FALSE); } - delete pFormats; - - strcat( rmf, ")"); - - aItem->hstrType = DrgAddStrHandle( DRT_UNKNOWN); - aItem->hstrRMF = DrgAddStrHandle( rmf); - - // For source-rendering, don't supply `source name' - nsSpecialSystemDirectory tmpDir(nsSpecialSystemDirectory::OS_TemporaryDirectory); - aItem->hstrContainerName = DrgAddStrHandle( nsNSPRPath(tmpDir)); - aItem->hstrSourceName = 0; - aItem->hstrTargetName = DrgAddStrHandle( "ATempFile"); - aItem->cxOffset = aItem->cyOffset = 0; // DrgDrag() sets these - aItem->fsControl = 0; - aItem->fsSupportedOps = DO_COPYABLE | DO_MOVEABLE | DO_LINKABLE; -} - - -// Actually do the drag -nsresult nsDragService::InvokeDrag( PDRAGITEM aItems, ULONG aCItems, - PRUint32 aActionType) -{ - // keep track of allocated draginfos - NS_ASSERTION(!mDragInfo,"Drag info leaked"); - - nsresult rc = NS_ERROR_FAILURE; - PDRAGINFO pDragInfo = DrgAllocDraginfo( aCItems); - - if( pDragInfo) + // Get file name from hstrSourceName. + if (!DrgQueryStrName(pDragItem->hstrSourceName, + CCHMAXPATH, + szTemp)) { - pDragInfo->usOperation = DragOperation(aActionType); - pDragInfo->hwndSource = mDragWnd; - for( PRUint32 i = 0; i < aCItems; i++) - DrgSetDragitem( pDragInfo, aItems + i, sizeof(DRAGITEM), i); - - // XXX Need to make a dragimage from somewhere. There ought to be an - // nsIImage passed in here, but let's just make something up for now. - // - // XXX also need to handle the multiple-dragitem case correctly - // - DRAGIMAGE dimage = { sizeof(DRAGIMAGE), 0, mIcon, - { 0, 0 }, DRG_ICON, 0, 0 }; - - // Set draginfo pointer for reentrancy - mDragInfo = pDragInfo; - mDragItems = aCItems; - - HWND hwndDest = DrgDrag( mDragWnd, pDragInfo, &dimage, 1, VK_ENDDRAG, -#ifdef DEBUG - (void*) 0x80000000L // makes IPMD happier -#else - 0 -#endif - ); - rc = NS_OK; // hwndDest == 0 may be error or just cancelled; shrug. - - if( !hwndDest) - { - // Clean up everything here; no async. case to consider. - DrgDeleteDraginfoStrHandles( pDragInfo); - DrgFreeDraginfo( pDragInfo); - mDragInfo = 0; - mDragItems = 0; - } - - // We don't DrgFreeDragInfo() here if there is a transfer of some sort; - // instead this is done when we get the appropriate DM_ENDCONVERSATION. + return(FALSE); } - return rc; -} + // Concatenate hstrContainerName and hstrSourceName to get fully + // qualified name of the URL file. + strcat(szURLFileName, szTemp); -// Window-proc. for the drag-source window -MRESULT EXPENTRY fnwpDragSource( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) -{ - MRESULT mr; - - if( gWidgetModuleData->dragService) - mr = gWidgetModuleData->dragService->HandleMessage( msg, mp1, mp2); - else - mr = WinDefWindowProc( hwnd, msg, mp1, mp2); - - return mr; -} - -MRESULT nsDragService::HandleMessage( ULONG msg, MPARAM mp1, MPARAM mp2) -{ - switch(msg) + // Open the file specified by szURLFileName and read its contents + // into buffer szURL. + FILE *fp = fopen(szURLFileName, "r"); + if (fp) { - case DM_RENDER: + size_t bytes_read = fread((void *)szURL, 1, CCHMAXPATH, fp); + if (bytes_read > 0) { - NS_ASSERTION(mDragItems && mDragInfo, "Spurious DM_RENDER"); - - // The target wants us to put some data somewhere. - PDRAGTRANSFER pXFer = (PDRAGTRANSFER) mp1; - BOOL rc = FALSE; - - // This is vitally important, apparently. - pXFer->pditem->hstrSourceName = DrgAddStrHandle( "Dummy.fil"); - - if( !pXFer->pditem->ulItemID) + // Delete the container name and source name hstrs. + DrgDeleteStrHandle(pDragItem->hstrContainerName); + DrgDeleteStrHandle(pDragItem->hstrSourceName); + // Replace container name with protocol part of URL. + char *pStart = szURL; + char *pProtocol = strchr(szURL, ':'); + if (pProtocol) { - // the target (silly boy) has asked us to source-render something - // it's completely capable of rendering all by itself. - pXFer->fsReply = DMFL_NATIVERENDER; - DrgFreeDragtransfer( pXFer); - } - else - { - // Need to actually return from this call before we can render the - // thing... - WinPostMsg( mDragWnd, WM_USER, mp1, mp2); - rc = TRUE; + // Bump the pointer to the end of the protocol spec. (ie. '//') + pProtocol += 3; } + strncpy(szProtocol, szURL, pProtocol- pStart); + HSTR hstrContainerName = DrgAddStrHandle(szProtocol); + // Replace source name with resource part of the URL. + char *pResource = pProtocol; + strcpy(szResource, pResource); + HSTR hstrSourceName = DrgAddStrHandle(szResource); + // Add the new hstr's to the dragitem. + pDragItem->hstrContainerName = hstrContainerName; + pDragItem->hstrSourceName = hstrSourceName; - return MRFROMLONG(rc); - } + fclose(fp); - // - // Very possibly this should be in a fresh thread. - // - // This rather large block is the source-side of the source-render - // protocol; the target picks which format (from those provided by - // the transferable) it would like & where we should put it. - // - case WM_USER: - { - // Posted to ourselves in order to carry out a target's desired - // rendering. - PDRAGTRANSFER pXFer = (PDRAGTRANSFER) mp1; - nsITransferable *pTrans = (nsITransferable*) pXFer->pditem->ulItemID; - USHORT usFlags = DMFL_RENDERFAIL; - - NS_ASSERTION(pTrans, "No transferable to source-render"); - -#ifdef DEBUG - char *target = DecodeStrHandle( pXFer->hstrRenderToName); - printf( "Source-rendering to %s\n", target); - nsFileSpec dest( target); -#else - nsFileSpec dest( DecodeStrHandle( pXFer->hstrRenderToName)); -#endif - // Now, the fun bit is working out what format to use. - char *rmf = DecodeStrHandle( pXFer->hstrSelectedRMF); - char rm[50], rf[50]; - int tokens = sscanf( rmf, "<%s,%s>", rm, rf); - - NS_ASSERTION(tokens == 2, "Couldn't parse hstrSelectedRMF"); -#ifdef DEBUG - printf( "%d - %s %s\n", tokens, rm, rf); -#endif - if( !strcmp( rm, "DRM_OS2FILE")) - { - // Go through the transferable's flavours looking for one which - // matches the requested rf. - nsVoidArray *pFormats = nsnull; - char buff[40]; - pTrans->FlavorsTransferableCanExport( &pFormats); - PRUint32 cFormats = pFormats->Count(), i; - - for( i = 0; i < cFormats; i++) - { - nsString *pFlavour = (nsString*) pFormats->ElementAt( i); - gWidgetModuleData->ConvertFromUcs( *pFlavour, buff, 40); - const char *this_rf = MimeTypeToRF( buff); - if( this_rf && !strcmp( this_rf, rf)) - { - // Found it! - void *pData; - PRUint32 cData; - pTrans->GetTransferData( pFlavour, &pData, &cData); - - // (uh-oh) - nsOutputFileStream stream(dest); - stream.write( pData, (PRInt32)cData); - stream.close(); - usFlags = DMFL_RENDEROK; - break; - } - } - - delete pFormats; - if( i == cFormats) -#ifdef DEBUG - printf( "Target asked for format %s which we can't do.\n", rf); -#endif - } -#ifdef DEBUG - else - { - printf( "Unexpected rendering mechanism\n"); - } -#endif - - // Tell the target we're done. - DrgPostTransferMsg( pXFer->hwndClient, - DM_RENDERCOMPLETE, - pXFer, - usFlags, - 0, - TRUE); - - DrgFreeDragtransfer( pXFer); - - // Note that the transferable we have here will be release'd in - // the DM_ENDCONVERSATION for the dragitem in question. - - return 0; - } - - // DRM_MOZILLA messages; see nsWidgetDefs.h for details - case WMU_GETFLAVOURLEN: - case WMU_GETFLAVOURDATA: - { - char buffer[40] = ""; - PRUint32 cData = 0; - void *pData; - - nsITransferable *pTrans = (nsITransferable*) mp1; - - if( pTrans) - { - PWZDROPXFER pXFer = (PWZDROPXFER) mp2; - ATOM atom; - - if( msg == WMU_GETFLAVOURLEN) atom = LONGFROMMP(mp2); - else atom = pXFer->hAtomFlavour; - - WinQueryAtomName( WinQuerySystemAtomTable(), atom, buffer, 40); - nsAutoString str(buffer); - if( NS_SUCCEEDED(pTrans->GetTransferData( &str, &pData, &cData))) - { - if( msg == WMU_GETFLAVOURDATA) - { - memcpy( &pXFer->data[0], pData, cData); - DosFreeMem( pXFer); - return MPFROMLONG(TRUE); - } - } - } - - return MRFROMLONG(cData); - } - - case DM_ENDCONVERSATION: - { - NS_ASSERTION(mDragItems && mDragInfo, "Unexpected DM_ENDCONVERSATION"); - - // If it was necessary (for source-rendering), we kept a reference - // to the transferable in the dragitem. Now it's safe to release. - nsITransferable *pTransferable = (nsITransferable*) mp1; - NS_IF_RELEASE(pTransferable); - - mDragItems--; - if( mDragItems == 0) - { - // the last of the dragitems has been ack'ed, so free the draginfo - DrgFreeDraginfo( mDragInfo); - mDragInfo = 0; - } -#ifdef DEBUG - printf( "DM_ENDCONVERSATION, mDragItems = %d\n", (int)mDragItems); -#endif - return 0; + rc = TRUE; } } - - return (*mWndProc)( mDragWnd, msg, mp1, mp2); -} - -// Various forms of source-rendering, DRM_MOZILLA and "pushed-file" ------------- -// -// Custom shared-memory rendering mechanism -// -// Probably ought to just get creative with DRAGTRANSFER as is, but that (a) -// confuses the DRM_OS2FILE source-rendering & (b) imposes unhelpful constraints - -void nsDragService::DoMozillaXfer( PDRAGITEM pItem, char *szFlavour, - void **ppData, PRUint32 *cData) -{ - // First check if this is an intra-process transfer! - if( mDragItems) - { - // Yes. - nsITransferable *pSource = (nsITransferable*) pItem->ulItemID; - if( pSource) - { - nsAutoString flavour(szFlavour); - if( NS_SUCCEEDED(pSource->GetTransferData( &flavour, ppData, cData))) - { - // need to make a copy... - char *tmp = new char [ *cData ]; - memcpy( tmp, *ppData, *cData); - *ppData = tmp; - } - } -#ifdef DEBUG - else - printf( "intra-process xfer fails due to null ulItemID\n"); -#endif - return; - } - - HATOMTBL hAtomTbl = WinQuerySystemAtomTable(); - ATOM hAtom = WinAddAtom( hAtomTbl, szFlavour); - - ULONG ulLen = (ULONG) WinSendMsg( pItem->hwndItem, WMU_GETFLAVOURLEN, - MPFROMLONG(pItem->ulItemID), - MPFROMLONG(hAtom)); - if( ulLen) - { - void *shmem = 0; - if( !DosAllocSharedMem( &shmem, 0, ulLen + sizeof(ATOM), - PAG_COMMIT | OBJ_GIVEABLE | PAG_WRITE)) - { - // Find the tid of the source so we can give it the memory - PID pid; - TID tid; - WinQueryWindowProcess( pItem->hwndItem, &pid, &tid); - DosGiveSharedMem( shmem, pid, PAG_WRITE); - - PWZDROPXFER pWzData = (PWZDROPXFER) shmem; - pWzData->hAtomFlavour = hAtom; - - BOOL ok = (BOOL) WinSendMsg( pItem->hwndItem, WMU_GETFLAVOURDATA, - MPFROMLONG(pItem->ulItemID), - MPFROMP(pWzData)); - if( ok) - { - // now allocate (too many copies I know, but transferable has - // restrictions...) - char *buf = new char [ ulLen ]; - memcpy( buf, &pWzData->data[0], ulLen); - *cData = ulLen; - *ppData = buf; - } - - // free shared memory - DosFreeMem( shmem); - } - } - - WinDeleteAtom( hAtomTbl, hAtom); -} - -void nsDragService::DoPushedOS2FILE( PDRAGITEM pItem, const char *szRf, - void **pData, PRUint32 *cData) -{ - // Unfortunately there's no way we can do this: we must return from DM_DROP - // before having a "post-drop conversation" involving DM_RENDER. - // - // BUT we need to fill the transferable NOW, before we return from DM_DROP - // so that gecko (or whoever's underneath us). - // - // So we're stuck until there's some asynch. way of proceeding. - // - // But it's not all bad: not many people use source rendering; mozilla - // does, but we can use DRM_MOZILLA to do that. - -#ifdef DEBUG - printf( "\n\nSorry, source-rendering of DRM_OS2FILE not working.\n"); - printf( "(see mozilla/widget/src/os2/nsDragService::DoPushedOS2FILE)\n\n"); -#endif -} - -// Quick utility functions ------------------------------------------------------ - -static char *DecodeStrHandle( HSTR hstr) -{ - static char buf[CCHMAXPATH]; - DrgQueryStrName( hstr, CCHMAXPATH, buf); - return buf; -} - -// Table to map mozilla "mimetypes" to PM "rendering formats" -// Could optimize I guess, but not really important. - -static const char *gFormatMap[][2] = -{ - { "DRF_TEXT", kTextMime }, - { "DRF_UNICODE", kUnicodeMime }, - { "DRF_HTML", kHTMLMime }, - { "DRF_PNG", kPNGImageMime }, - { "DRF_GIF", kGIFImageMime }, - { "DRF_JPEG", kJPEGImageMime }, - { "DRF_AOLMAIL", kAOLMailMime }, - { 0, 0 } -}; - -static const char *MimeTypeToRF( const char *pcsz) -{ - int i = 0; - while( gFormatMap[i][0]) - if( !strcmp( pcsz, gFormatMap[i][1])) break; - return gFormatMap[i][0]; -} - -static const char *RFToMimeType( const char *pcsz) -{ - int i = 0; - while( gFormatMap[i][0]) - if( !strcmp( pcsz, gFormatMap[i][0])) break; - return gFormatMap[i][1]; -} - -static BOOL FindFile( PDRAGITEM pItem, nsFileSpec &aFileSpec) -{ - const char *str = DecodeStrHandle( pItem->hstrContainerName); -#ifdef DEBUG - printf( "Getting drag data from `%s'", str); -#endif - aFileSpec = str; - str = DecodeStrHandle( pItem->hstrSourceName); -#ifdef DEBUG - printf( "`%s'\n", str); -#endif - aFileSpec += str; - - return aFileSpec.Exists(); -} - -static void GetTempFile( nsFileSpec &tempfile) -{ - nsSpecialSystemDirectory tmpDir(nsSpecialSystemDirectory::OS_TemporaryDirectory); - tmpDir += "tmpfile"; - tmpDir.MakeUnique(); - tempfile = tmpDir; + return(rc); } diff --git a/widget/src/os2/nsDragService.h b/widget/src/os2/nsDragService.h index fd08345a5f3f..c780d4263156 100644 --- a/widget/src/os2/nsDragService.h +++ b/widget/src/os2/nsDragService.h @@ -1,90 +1,69 @@ -/* - * The contents of this file are subject to the Mozilla Public License +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License * Version 1.1 (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.mozilla.org/MPL/ * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the - * License for the specific language governing rights and limitations - * under the License. + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. * - * The Original Code is the Mozilla OS/2 libraries. + * The Original Code is mozilla.org code. * - * The Initial Developer of the Original Code is John Fairhurst, - * . Portions created by John Fairhurst are - * Copyright (C) 1999 John Fairhurst. All Rights Reserved. + * The Initial Developer of the Original Code is + * IBM Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. * - * Contributor(s): + * Contributor(s): * - */ + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ -#ifndef _nsdragservice_h -#define _nsdragservice_h - -// Drag service. Manages drag & drop events, converts between OS/2 and -// mozilla-style databuffers. -// -// This exists as a singleton in the nsModule; it's created at creation of the -// primaeval appshell and destroyed at DLL unload-time. -// +#ifndef nsDragService_h__ +#define nsDragService_h__ #include "nsBaseDragService.h" -class nsFileSpec; - -// This implements nsIDragSession and nsIDragService. +#define INCL_PM +#include class nsDragService : public nsBaseDragService { - public: - nsDragService(); - virtual ~nsDragService(); - // nsIDragService - NS_IMETHOD InvokeDragSession( nsIDOMNode *aDOMNode, - nsISupportsArray *anArrayTransferables, - nsIRegion *aRegion, PRUint32 aActionType); +public: + nsDragService(); + virtual ~nsDragService(); - // nsIDragSession - NS_IMETHOD GetData( nsITransferable *aTransferable, PRUint32 aItemIndex); - NS_IMETHOD GetNumDropItems( PRUint32 *aNumItems); - NS_IMETHOD IsDataFlavorSupported( nsString *aDataFlavour); + // nsIDragService + NS_IMETHOD InvokeDragSession (nsIDOMNode *aDOMNode, nsISupportsArray * aTransferables, nsIScriptableRegion * aRegion, PRUint32 aActionType); - // platform methods, called from nsWindow - void InitDragOver( PDRAGINFO aDragInfo); - MRESULT TermDragOver(); + // nsIDragSession + NS_IMETHOD GetNumDropItems(PRUint32 *aNumDropItems); + NS_IMETHOD GetData(nsITransferable *aTransferable, PRUint32 aItemIndex); + NS_IMETHOD IsDataFlavorSupported(const char *aDataFlavor, PRBool *_retval); - void InitDragExit( PDRAGINFO aDragInfo); - void TermDragExit(); + HWND mDragWnd; - void InitDrop( PDRAGINFO aDragInfo); - void TermDrop(); + // our source data items + nsCOMPtr mSourceDataItems; - protected: - // Natives - void CreateDragItems( PULONG pCount, PDRAGITEM *ppItems, - nsITransferable *aTransferable); - void FillDragItem( PDRAGITEM aItem, nsITransferable *aTransferable); - void FillDragItem( PDRAGITEM aItem, nsFileSpec *aFilespec); - nsresult InvokeDrag( PDRAGITEM aItems, ULONG aCItems, PRUint32 aActionType); - MRESULT HandleMessage( ULONG msg, MPARAM mp1, MPARAM mp2); - void DoPushedOS2FILE( PDRAGITEM pItem, const char *szRf, - void **pData, PRUint32 *cData); - void DoMozillaXfer( PDRAGITEM pItem, char *szFlavour, - void **ppData, PRUint32 *cData); - HWND mDragWnd; - HPOINTER mIcon; - - // State; allocated draginfo & outstanding items - PDRAGINFO mDragInfo; - PFNWP mWndProc; - ULONG mDragItems; - - friend MRESULT EXPENTRY fnwpDragSource(HWND,ULONG,MPARAM,MPARAM); + friend MRESULT EXPENTRY nsDragWindowProc( HWND, ULONG, MPARAM, MPARAM); }; -nsresult NS_GetDragService( nsISupports **aDragService); - -#endif +#endif // nsDragService_h__ diff --git a/widget/src/os2/nsWidgetFactory.cpp b/widget/src/os2/nsWidgetFactory.cpp index 6582c7a495cb..92ceb4661e2d 100644 --- a/widget/src/os2/nsWidgetFactory.cpp +++ b/widget/src/os2/nsWidgetFactory.cpp @@ -63,7 +63,6 @@ #include "nsClipboardHelper.h" #include "nsTransferable.h" #include "nsHTMLFormatConverter.h" -// OS2TODO #include "nsDragService.h" #include "nsFrameWindow.h" // OS/2 only @@ -79,7 +78,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsSound) NS_GENERIC_FACTORY_CONSTRUCTOR(nsToolkit) NS_GENERIC_FACTORY_CONSTRUCTOR(nsTransferable) NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter) -// OS2TODO NS_GENERIC_FACTORY_CONSTRUCTOR(nsDragService) +NS_GENERIC_FACTORY_CONSTRUCTOR(nsDragService) // custom "contructor" methods @@ -240,15 +239,10 @@ static const nsModuleComponentInfo components[] = NS_CLIPBOARDHELPER_CID, "@mozilla.org/widget/clipboardhelper;1", nsClipboardHelperConstructor }, - -// OS2TODO -#if 0 { "OS/2 Drag Service", NS_DRAGSERVICE_CID, "@mozilla.org/widget/dragservice;1", nsDragServiceConstructor }, -#endif - { "OS/2 File Picker", NS_FILEPICKER_CID, "@mozilla.org/filepicker;1", diff --git a/widget/src/os2/nsWindow.cpp b/widget/src/os2/nsWindow.cpp index f406b53ac6b0..20dde9023b8b 100644 --- a/widget/src/os2/nsWindow.cpp +++ b/widget/src/os2/nsWindow.cpp @@ -51,6 +51,7 @@ #include "nsplugindefs.h" #include "nsITimer.h" +#include "nsIServiceManager.h" #include #include @@ -1942,6 +1943,7 @@ PRBool nsWindow::OnKey( MPARAM mp1, MPARAM mp2) gWidgetModuleData->ConvertToUcs( (char *)inbuf, (PRUnichar *)outbuf, 4); event.charCode = outbuf[0]; + if (event.isControl && !(fsFlags & (KC_VIRTUALKEY | KC_DEADKEY))) { if (!event.isShift && (event.charCode >= 'A' && event.charCode <= 'Z')) { @@ -2240,13 +2242,11 @@ PRBool nsWindow::ProcessMessage( ULONG msg, MPARAM mp1, MPARAM mp2, MRESULT &rc) break; case DM_DRAGOVER: - rc = MRFROM2SHORT(DOR_DROP, DO_COPY); - result = PR_TRUE; -// result = OnDragOver( mp1, mp2, rc); + result = OnDragOver(mp1, mp2, rc); break; case DM_DRAGLEAVE: - result = OnDragLeave( mp1, mp2); + result = OnDragLeave(mp1, mp2); break; case DM_DROP: @@ -3000,30 +3000,44 @@ void nsWindow::RemoveFromStyle( ULONG style) #define DispatchDragDropEvent(msg) DispatchStandardEvent(msg,NS_DRAGDROP_EVENT) -// XXXX KNOCKED OUT UNTIL nsDragService.cpp is fixed - -PRBool nsWindow::OnDragOver( MPARAM mp1, MPARAM mp2, MRESULT &mr) +PRBool nsWindow::OnDragOver(MPARAM mp1, MPARAM mp2, MRESULT &mr) { - // Drawing drop feedback should be fun, have to get DrgGetPS() involved - // somehow. + nsresult rv; + USHORT usDrop = DOR_DROP; + USHORT usDefaultOp = DO_MOVE; + PDRAGINFO pdraginfo = (PDRAGINFO)mp1; + + nsCOMPtr dragService = do_GetService("@mozilla.org/widget/dragservice;1", &rv); + nsCOMPtr dragSession; + dragService->GetCurrentSession(getter_AddRefs(dragSession)); + if (dragSession) { + PRBool canDrop; + dragSession->GetCanDrop(&canDrop); + if (!canDrop) + usDrop = DOR_NODROP; + + switch (pdraginfo->usOperation) { + case DO_COPY: + usDefaultOp = DO_COPY; + dragSession->SetDragAction(nsIDragService::DRAGDROP_ACTION_COPY); + break; + case DO_LINK: + usDefaultOp = DO_LINK; + dragSession->SetDragAction(nsIDragService::DRAGDROP_ACTION_LINK); + break; + default: + dragSession->SetDragAction(nsIDragService::DRAGDROP_ACTION_MOVE); + break; + } + } else { + usDrop = DOR_NEVERDROP; + } - // Tell drag service about the drag - // gWidgetModuleData->dragService->InitDragOver( (PDRAGINFO) mp1); + mr = MRFROM2SHORT(usDrop, usDefaultOp); - // Invoke gecko for enter if appropriate - // if( !mDragInside) - // { - // DispatchDragDropEvent( NS_DRAGDROP_ENTER); - // mDragInside = TRUE; - // } + DispatchDragDropEvent(NS_DRAGDROP_OVER); - // Invoke for 'over' to set candrop flag - // DispatchDragDropEvent( NS_DRAGDROP_OVER); - - // Get action back from drag service - // mr = gWidgetModuleData->dragService->TermDragOver(); - - return PR_TRUE; + return PR_TRUE; } PRBool nsWindow::OnDragLeave( MPARAM mp1, MPARAM mp2) @@ -3037,15 +3051,30 @@ PRBool nsWindow::OnDragLeave( MPARAM mp1, MPARAM mp2) return PR_TRUE; } -PRBool nsWindow::OnDrop( MPARAM mp1, MPARAM mp2) +PRBool nsWindow::OnDrop(MPARAM mp1, MPARAM mp2) { - // gWidgetModuleData->dragService->InitDrop( (PDRAGINFO) mp1); - DispatchDragDropEvent( NS_DRAGDROP_DROP); - // gWidgetModuleData->dragService->TermDrop(); + nsresult rv; + PDRAGINFO pdraginfo = (PDRAGINFO)mp1; + + nsCOMPtr dragService = do_GetService("@mozilla.org/widget/dragservice;1", &rv); + nsCOMPtr dragSession; + dragService->GetCurrentSession(getter_AddRefs(dragSession)); - mDragInside = FALSE; + switch (pdraginfo->usOperation) { + case DO_COPY: + dragSession->SetDragAction(nsIDragService::DRAGDROP_ACTION_COPY); + break; + case DO_LINK: + dragSession->SetDragAction(nsIDragService::DRAGDROP_ACTION_LINK); + break; + default: + dragSession->SetDragAction(nsIDragService::DRAGDROP_ACTION_MOVE); + break; + } - return PR_TRUE; + DispatchDragDropEvent( NS_DRAGDROP_DROP); + + return PR_TRUE; } // --------------------------------------------------------------------------