From 325f6d6a00c0c39f81872c9d6ed61981efd00a93 Mon Sep 17 00:00:00 2001 From: "mkaply%us.ibm.com" Date: Wed, 26 Mar 2003 01:01:27 +0000 Subject: [PATCH] #183622 r=pedemont, sr=blizzard (platform specific) OS/2 only - allowing dropping of objects onto the browser, make holding down Ctrl download stuff git-svn-id: svn://10.0.0.236/trunk@140308 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/widget/src/os2/Makefile.in | 1 + mozilla/widget/src/os2/nsDragService.cpp | 87 +++++++++++++-- mozilla/widget/src/os2/nsDragService.h | 2 + mozilla/widget/src/os2/nsWindow.cpp | 134 +++++++++++++++++++++-- mozilla/widget/src/os2/nsWindow.h | 3 +- 5 files changed, 207 insertions(+), 20 deletions(-) diff --git a/mozilla/widget/src/os2/Makefile.in b/mozilla/widget/src/os2/Makefile.in index e094b063d55..2ff4019c5d8 100644 --- a/mozilla/widget/src/os2/Makefile.in +++ b/mozilla/widget/src/os2/Makefile.in @@ -41,6 +41,7 @@ REQUIRES = gfx \ pref \ plugin \ webshell \ + webbrowserpersist \ $(NULL) ifdef ENABLE_TESTS diff --git a/mozilla/widget/src/os2/nsDragService.cpp b/mozilla/widget/src/os2/nsDragService.cpp index 84ea54a3977..2bb20f14bc7 100644 --- a/mozilla/widget/src/os2/nsDragService.cpp +++ b/mozilla/widget/src/os2/nsDragService.cpp @@ -40,6 +40,11 @@ #include "nsString.h" #include "nsXPIDLString.h" #include "nsReadableUtils.h" +#include "nsIWebBrowserPersist.h" +#include "nsILocalFile.h" +#include "nsIURI.h" +#include "nsIURL.h" +#include "nsNetUtil.h" void WriteTypeEA(const char* filename, const char* type); @@ -62,20 +67,49 @@ MRESULT EXPENTRY nsDragWindowProc(HWND hWnd, ULONG msg, MPARAM mp1, ULONG ulLength; PSZ pszURL; CHAR chPath[CCHMAXPATH]; + CHAR chOrigPath[CCHMAXPATH]; + nsDragService* dragservice; switch (msg) { + case DM_RENDERPREPARE: + pdragtransfer = (PDRAGTRANSFER)mp1; + if (pdragtransfer->usOperation == DO_COPY) { + ulLength = DrgQueryStrNameLen(pdragtransfer->pditem->hstrSourceName); + pszURL = (PSZ)nsMemory::Alloc(ulLength+1); + DrgQueryStrName(pdragtransfer->pditem->hstrSourceName, ulLength+1, pszURL); + nsCOMPtr linkURI; + NS_NewURI(getter_AddRefs(linkURI), pszURL); + nsCOMPtr linkURL(do_QueryInterface(linkURI)); + /* use URI for filename */ + nsCAutoString filename; + linkURL->GetFileName(filename); + if (filename.IsEmpty()) { + filename = pszURL; + } + DrgDeleteStrHandle(pdragtransfer->pditem->hstrTargetName); + pdragtransfer->pditem->hstrTargetName = DrgAddStrHandle(ToNewCString(filename)); + return (MRESULT)TRUE; + } + break; case DM_RENDER: pdragtransfer = (PDRAGTRANSFER)mp1; + dragservice = (nsDragService*)pdragtransfer->pditem->ulItemID; DrgQueryStrName(pdragtransfer->hstrRenderToName, CCHMAXPATH, chPath); + strcpy(chOrigPath, 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, fp); - fclose(fp); - WriteTypeEA(chPath, "UniformResourceLocator"); + if (pdragtransfer->usOperation == DO_COPY) { + dragservice->WriteData(chPath, pszURL); + } else { + fp = fopen(chPath, "wb+"); + fwrite(pszURL, ulLength, 1, fp); + fclose(fp); + WriteTypeEA(chPath, "UniformResourceLocator"); + } nsMemory::Free(pszURL); DrgPostTransferMsg(pdragtransfer->hwndClient, DM_RENDERCOMPLETE, pdragtransfer, DMFL_RENDEROK,0,TRUE); DrgFreeDragtransfer(pdragtransfer); + DosMove(chOrigPath, chPath); return (MRESULT)TRUE; break; default: @@ -92,6 +126,11 @@ nsDragService::~nsDragService() NS_IMETHODIMP nsDragService::InvokeDragSession(nsIDOMNode *aDOMNode, nsISupportsArray *aTransferables, nsIScriptableRegion *aRegion, PRUint32 aActionType) { + if (!aDOMNode && !aRegion && !aActionType) { + /* Utter hack for drag drop - provide a way for nsWindow to set mSourceDataItems */ + mSourceDataItems = aTransferables; + return NS_OK; + } nsBaseDragService::InvokeDragSession ( aDOMNode, aTransferables, aRegion, aActionType ); // set our reference to the transferables. this will also addref @@ -109,7 +148,7 @@ NS_IMETHODIMP nsDragService::InvokeDragSession(nsIDOMNode *aDOMNode, nsISupports pDragInfo->usOperation = DO_DEFAULT; DRAGITEM dragitem; dragitem.hwndItem = mDragWnd; - dragitem.ulItemID = (ULONG)0; + dragitem.ulItemID = (ULONG)this; dragitem.hstrType = DrgAddStrHandle("UniformResourceLocator"); dragitem.hstrRMF = DrgAddStrHandle(""); dragitem.hstrContainerName = DrgAddStrHandle(""); @@ -147,7 +186,12 @@ NS_IMETHODIMP nsDragService::InvokeDragSession(nsIDOMNode *aDOMNode, nsISupports } else { dragitem.hstrRMF = DrgAddStrHandle(""); /* Moz only drag */ } - dragitem.fsControl = DC_OPEN; + +#ifndef DC_PREPAREITEM +#define DC_PREPAREITEM 0x0040; +#endif + + dragitem.fsControl = DC_OPEN | DC_PREPAREITEM; dragitem.cxOffset = 2; dragitem.cyOffset = 2; dragitem.fsSupportedOps = DO_COPYABLE|DO_MOVEABLE|DO_LINKABLE; @@ -165,7 +209,7 @@ NS_IMETHODIMP nsDragService::InvokeDragSession(nsIDOMNode *aDOMNode, nsISupports #ifdef DEBUG if (!hwndDest) { ERRORID eid = WinGetLastError((HAB)0); - printf("Drag did not finish - error = %x error=%x\n", eid); + printf("Drag did not finish - error=%x\n", eid); } #endif @@ -174,6 +218,8 @@ NS_IMETHODIMP nsDragService::InvokeDragSession(nsIDOMNode *aDOMNode, nsISupports DrgFreeDraginfo(pDragInfo); } + mSourceDataItems = 0; + return NS_OK; } @@ -272,6 +318,33 @@ NS_IMETHODIMP nsDragService::IsDataFlavorSupported(const char *aDataFlavor, PRBo return NS_OK; } +BOOL nsDragService::WriteData(PSZ szDest, PSZ szURL) +{ + FILE *fp; + nsresult rv; + nsCOMPtr webPersist(do_CreateInstance("@mozilla.org/embedding/browser/nsWebBrowserPersist;1", &rv)); + nsCOMPtr linkURI; + rv = NS_NewURI(getter_AddRefs(linkURI), szURL); + nsCOMPtr file; + NS_NewNativeLocalFile(nsDependentCString(szDest), TRUE, getter_AddRefs(file)); + + nsCAutoString temp; + file->GetNativePath(temp); + fp = fopen(temp.get(), "wb+"); + fwrite(szURL, strlen(szURL), 1, fp); + fclose(fp); + nsCAutoString filename; + nsCOMPtr linkURL(do_QueryInterface(linkURI)); + linkURL->GetFileName(filename); + if (filename.IsEmpty()) { + /* If we don't have a filename, just mark it text/html */ + /* This can only be fixed if we write mime type on putting */ + /* any file to disk */ + WriteTypeEA(temp.get(), "text/html"); + } + webPersist->SaveURI(linkURI, nsnull, nsnull, nsnull, nsnull, file); +} + /* Helper functions */ void WriteTypeEA(const char* filename, const char* type) { diff --git a/mozilla/widget/src/os2/nsDragService.h b/mozilla/widget/src/os2/nsDragService.h index c780d426315..dc1af344d97 100644 --- a/mozilla/widget/src/os2/nsDragService.h +++ b/mozilla/widget/src/os2/nsDragService.h @@ -57,6 +57,8 @@ public: NS_IMETHOD GetData(nsITransferable *aTransferable, PRUint32 aItemIndex); NS_IMETHOD IsDataFlavorSupported(const char *aDataFlavor, PRBool *_retval); + BOOL WriteData(PSZ szDest, PSZ szURL); + HWND mDragWnd; // our source data items diff --git a/mozilla/widget/src/os2/nsWindow.cpp b/mozilla/widget/src/os2/nsWindow.cpp index 42faad34fff..6126a15dbdd 100644 --- a/mozilla/widget/src/os2/nsWindow.cpp +++ b/mozilla/widget/src/os2/nsWindow.cpp @@ -44,6 +44,7 @@ //#include "nsMenu.h" #include "nsDragService.h" #include "nsILocalFile.h" +#include "nsNetUtil.h" #include "nsIRollupListener.h" #include "nsIMenuRollup.h" @@ -61,6 +62,8 @@ #include "nsXPIDLString.h" #include "nsIFile.h" +#include "nsISupportsPrimitives.h" + #include "nsOS2Uni.h" #include "nsPaletteOS2.h" @@ -159,7 +162,7 @@ nsWindow::nsWindow() : nsBaseWidget() mFrameIcon = 0; mPS = 0; mPSRefs = 0; - mDragInside = FALSE; + mNativeDrag = FALSE; mDeadKey = 0; mHaveDeadKey = FALSE; // This is so that frame windows can be destroyed from their destructors. @@ -372,13 +375,16 @@ void nsWindow::InitEvent(nsGUIEvent& event, PRUint32 aEventType, nsPoint* aPoint { event.widget = this; NS_ADDREF(event.widget); - event.nativeMsg = nsnull; + event.nativeMsg = 0; if (nsnull == aPoint) { // use the point from the event // get the message position in client coordinates and in twips POINTL ptl; WinQueryMsgPos( 0/*hab*/, &ptl); WinMapWindowPoints( HWND_DESKTOP, mWnd, &ptl, 1); + if ((aEventType == NS_DRAGDROP_DROP) && (mNativeDrag)) { + ptl.x = ptl.y = 1; + } #if 0 printf("++++++++++nsWindow::InitEvent (!pt) mapped point = %ld, %ld\n", ptl.x, ptl.y); @@ -946,6 +952,11 @@ void nsWindow::RealDoCreate( HWND hwndP, if( mParent) mParent->AddChild( this); + mContentType = aInitData? aInitData->mContentType : eContentTypeInherit; + if (mContentType == eContentTypeInherit && aParent) { + mContentType = aParent->mContentType; + } + // call the event callback to notify about creation DispatchStandardEvent( NS_CREATE ); @@ -1887,7 +1898,7 @@ void* nsWindow::GetNativeData(PRUint32 aDataType) case NS_NATIVE_GRAPHIC: if( !mPS) { - if( mDragInside) { + if( mNativeDrag) { mPS = DrgGetPS(mWnd); } else { mPS = WinGetPS(mWnd); @@ -1924,7 +1935,7 @@ void nsWindow::FreeNativeData(void * data, PRUint32 aDataType) if( !mPSRefs) { BOOL rc; - if( mDragInside) rc = DrgReleasePS( mPS); + if( mNativeDrag) rc = DrgReleasePS( mPS); else rc = WinReleasePS( mPS); #ifdef DEBUG if( !rc) @@ -2595,7 +2606,7 @@ PRBool nsWindow::ProcessMessage( ULONG msg, MPARAM mp1, MPARAM mp2, MRESULT &rc) // is a drag inside the window; we need to do *this* so that we can // generate DRAGENTER messages [which os/2 doesn't provide]. case DM_DROPHELP: - mDragInside = FALSE; + mNativeDrag = FALSE; break; } @@ -3389,11 +3400,25 @@ PRBool nsWindow::OnDragOver(MPARAM mp1, MPARAM mp2, MRESULT &mr) USHORT usDrop = DOR_DROP; USHORT usDefaultOp = DO_MOVE; PDRAGINFO pdraginfo = (PDRAGINFO)mp1; + DRAGITEM dragitem; nsCOMPtr dragService = do_GetService("@mozilla.org/widget/dragservice;1", &rv); nsCOMPtr dragSession; dragService->GetCurrentSession(getter_AddRefs(dragSession)); - if (dragSession) { + DrgAccessDraginfo(pdraginfo); + if (!dragSession) { + /* Check to see if we can handle it. If we can, create a drag session */ + DrgQueryDragitem(pdraginfo, sizeof(DRAGITEM), &dragitem, 0); + if (DrgVerifyRMF(&dragitem, "DRM_OS2FILE","DRF_TEXT") || + DrgVerifyRMF(&dragitem, "DRM_OS2FILE","DRF_UNKNOWN")) { + dragService->StartDragSession(); + dragService->GetCurrentSession(getter_AddRefs(dragSession)); + mNativeDrag = TRUE; + } else { + usDrop = DOR_NEVERDROP; + } + } + if ((dragSession) && (!mNativeDrag)) { PRBool canDrop; dragSession->GetCanDrop(&canDrop); if (!canDrop) @@ -3412,9 +3437,12 @@ PRBool nsWindow::OnDragOver(MPARAM mp1, MPARAM mp2, MRESULT &mr) dragSession->SetDragAction(nsIDragService::DRAGDROP_ACTION_MOVE); break; } + } else if (mNativeDrag && (mContentType == eContentTypeContent)) { + usDefaultOp = DO_MOVE; } else { usDrop = DOR_NEVERDROP; } + DrgFreeDraginfo(pdraginfo); mr = MRFROM2SHORT(usDrop, usDefaultOp); @@ -3425,24 +3453,35 @@ PRBool nsWindow::OnDragOver(MPARAM mp1, MPARAM mp2, MRESULT &mr) PRBool nsWindow::OnDragLeave( MPARAM mp1, MPARAM mp2) { - // gWidgetModuleData->dragService->InitDragExit( (PDRAGINFO) mp1); - // DispatchDragDropEvent( NS_DRAGDROP_EXIT); - // gWidgetModuleData->dragService->TermDragExit(); + if (mNativeDrag) { + nsresult rv; + nsCOMPtr dragService = do_GetService("@mozilla.org/widget/dragservice;1", &rv); + nsCOMPtr dragSession; + dragService->GetCurrentSession(getter_AddRefs(dragSession)); + if (dragSession) { + dragService->EndDragSession(); + mNativeDrag = FALSE; + } + } - // mDragInside = FALSE; + DispatchDragDropEvent(NS_DRAGDROP_EXIT); - return PR_TRUE; + return PR_TRUE; } +extern BOOL GetURLObjectContents(PDRAGITEM pDragItem); + PRBool nsWindow::OnDrop(MPARAM mp1, MPARAM mp2) { nsresult rv; PDRAGINFO pdraginfo = (PDRAGINFO)mp1; + DRAGITEM dragitem; nsCOMPtr dragService = do_GetService("@mozilla.org/widget/dragservice;1", &rv); nsCOMPtr dragSession; dragService->GetCurrentSession(getter_AddRefs(dragSession)); + DrgAccessDraginfo(pdraginfo); switch (pdraginfo->usOperation) { case DO_COPY: dragSession->SetDragAction(nsIDragService::DRAGDROP_ACTION_COPY); @@ -3455,7 +3494,78 @@ PRBool nsWindow::OnDrop(MPARAM mp1, MPARAM mp2) break; } - DispatchDragDropEvent( NS_DRAGDROP_DROP); + if (mNativeDrag) { + dragSession->SetDragAction(nsIDragService::DRAGDROP_ACTION_MOVE); + // now create the transferable and stuff data into it. + nsCOMPtr trans(do_CreateInstance("@mozilla.org/widget/transferable;1")); + + DrgQueryDragitem(pdraginfo, sizeof(DRAGITEM), &dragitem, 0); + if (DrgVerifyType(&dragitem, "UniformResourceLocator")) + { + GetURLObjectContents(&dragitem); + } + + PSZ pszURL; + PSZ pszProtocol; + PSZ pszTargetName; + ULONG ulLength; + ulLength = DrgQueryStrNameLen(dragitem.hstrSourceName); + pszURL = (PSZ)nsMemory::Alloc(ulLength+1); + DrgQueryStrName(dragitem.hstrSourceName, ulLength+1, pszURL); + ulLength = DrgQueryStrNameLen(dragitem.hstrContainerName); + pszProtocol = (PSZ)nsMemory::Alloc(ulLength+1); + DrgQueryStrName(dragitem.hstrContainerName, ulLength+1, pszProtocol); + ulLength = DrgQueryStrNameLen(dragitem.hstrTargetName); + pszTargetName = (PSZ)nsMemory::Alloc(ulLength+1); + DrgQueryStrName(dragitem.hstrTargetName, ulLength+1, pszTargetName); + + + // add a special flavor if we're an anchor to indicate that we have a URL + // in the drag data + nsCAutoString dragData; + if (DrgVerifyType(&dragitem, "UniformResourceLocator")) + { + dragData += pszProtocol; + dragData += pszURL; + } else { + nsCOMPtr file; + char filepath[CCHMAXPATH]; + strcpy(filepath, pszProtocol); + strcat(filepath, pszURL); + if ( NS_SUCCEEDED(NS_NewNativeLocalFile(nsDependentCString(filepath), PR_TRUE, getter_AddRefs(file))) ) { + nsCAutoString urlSpec; + NS_GetURLSpecFromFile(file, urlSpec); + dragData += urlSpec; + + } + } + dragData += NS_LITERAL_CSTRING("\n"); + dragData += pszTargetName; + nsMemory::Free(pszURL); + nsMemory::Free(pszProtocol); + nsMemory::Free(pszTargetName); + DrgFreeDraginfo(pdraginfo); + + nsCOMPtr urlPrimitive(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID)); + if ( !urlPrimitive ) + return NS_ERROR_FAILURE; + urlPrimitive->SetData(NS_ConvertASCIItoUCS2(dragData)); + trans->SetTransferData(kURLMime, urlPrimitive, dragData.Length() * 2); + + nsCOMPtr transArray(do_CreateInstance("@mozilla.org/supports-array;1")); + if ( !transArray ) + return NS_ERROR_FAILURE; + transArray->InsertElementAt(trans, 0); + + dragService->InvokeDragSession(0, transArray, 0, 0); + } + + DispatchDragDropEvent(NS_DRAGDROP_DROP); + + if (mNativeDrag && dragSession) { + dragService->EndDragSession(); + mNativeDrag = PR_FALSE; + } return PR_TRUE; } diff --git a/mozilla/widget/src/os2/nsWindow.h b/mozilla/widget/src/os2/nsWindow.h index 4d2c1791337..eacec4df9ae 100644 --- a/mozilla/widget/src/os2/nsWindow.h +++ b/mozilla/widget/src/os2/nsWindow.h @@ -242,7 +242,7 @@ protected: HPOINTER mFrameIcon; // current frame icon HPS mPS; // cache PS for window ULONG mPSRefs; // number of refs to cache ps - BOOL mDragInside; // track draginside state + BOOL mNativeDrag; // is the drag from outside Mozilla VDKEY mDeadKey; // dead key from previous keyevent BOOL mHaveDeadKey; // is mDeadKey valid [0 may be a valid dead key, for all I know] HWND mHackDestroyWnd; // access GetMainWindow() window from destructor @@ -250,6 +250,7 @@ protected: PRBool mIsTopWidgetWindow; BOOL mIsScrollBar; BOOL mInSetFocus; + nsContentType mContentType; HWND GetParentHWND() const; HWND GetHWND() const { return mWnd; }