diff --git a/widget/public/nsIDragService.idl b/widget/public/nsIDragService.idl index 309b1b925b3..1b714e31b85 100644 --- a/widget/public/nsIDragService.idl +++ b/widget/public/nsIDragService.idl @@ -26,6 +26,9 @@ #include "nsIScriptableRegion.idl" +interface nsIDOMNode; + + [scriptable, uuid(8B5314BB-DB01-11d2-96CE-0060B0FB9956)] interface nsIDragService : nsISupports { @@ -42,7 +45,7 @@ interface nsIDragService : nsISupports * in window coordinates. * @param aActionType - specified which of copy/move/link are allowed */ - void invokeDragSession ( in nsISupportsArray aTransferables, + void invokeDragSession ( in nsIDOMNode aDOMNode, in nsISupportsArray aTransferables, in nsIScriptableRegion aRegion, in unsigned long aActionType ); /** diff --git a/widget/src/mac/nsDragService.cpp b/widget/src/mac/nsDragService.cpp index 31da4f3fa9e..4ef6de48b67 100644 --- a/widget/src/mac/nsDragService.cpp +++ b/widget/src/mac/nsDragService.cpp @@ -43,6 +43,19 @@ #include "nsPrimitiveHelpers.h" #include "nsILocalFileMac.h" +// rjc +#include +#include "nsIContent.h" +#include "nsIDOMNode.h" +#include "nsIDocument.h" +#include "nsIPresShell.h" +#include "nsIPresContext.h" +#include "nsIFrame.h" +#include "nsIView.h" +#include "nsRect.h" +#include "nsPoint.h" +#include "nsIWidget.h" + #if !TARGET_CARBON DragSendDataUPP nsDragService::sDragSendDataUPP = NewDragSendDataProc(DragSendDataProc); @@ -58,8 +71,15 @@ NS_IMPL_QUERY_INTERFACE3(nsDragService, nsIDragService, nsIDragSession, nsIDragS // DragService constructor // nsDragService::nsDragService() - : mDragRef(0), mDataItems(nsnull) + : mDragRef(0), mDataItems(nsnull), mImageDraggingSupported(PR_FALSE) { + // rjc - check if the Drag Manager supports image dragging + long response; + OSErr err = Gestalt(gestaltDragMgrAttr, &response); + if (err == noErr && (response & (1L << gestaltDragMgrHasImageSupport))) + { + mImageDraggingSupported = PR_TRUE; + } } @@ -77,8 +97,86 @@ nsDragService::~nsDragService() // Do all the work to kick it off. // NS_IMETHODIMP -nsDragService :: InvokeDragSession (nsISupportsArray * aTransferableArray, nsIScriptableRegion * aDragRgn, PRUint32 aActionType) +nsDragService :: InvokeDragSession (nsIDOMNode *aDOMNode, nsISupportsArray * aTransferableArray, nsIScriptableRegion * aDragRgn, PRUint32 aActionType) { + // rjc - compute rect of drag area in global coordinants + PRBool haveRectFlag = PR_FALSE; + Rect aMacRect; + aMacRect.left = aMacRect.right = aMacRect.top = aMacRect.bottom = 0; + + nsCOMPtr contentNode; + if (aDOMNode) contentNode = do_QueryInterface(aDOMNode); + + nsCOMPtr doc; + if (contentNode) contentNode->GetDocument(*getter_AddRefs(doc)); + nsCOMPtr presShell; + if (doc) presShell = getter_AddRefs(doc->GetShellAt(0)); + nsCOMPtrpresContext; + // note: nsIFrames are not refcounted + nsIFrame *aFrame = nsnull; + if (presShell) + { + presShell->GetPresContext(getter_AddRefs(presContext)); + presShell->GetPrimaryFrameFor(contentNode, &aFrame); + } + + nsRect aRect(0,0,0,0); + nsPoint offset(0,0); + + // note: are nsIViews recounted ??? + nsIView *parentView = nsnull; + if (aFrame && presContext) + { + aFrame->GetRect(aRect); + + nsIView *containingView = nsnull; + aFrame->GetOffsetFromView(presContext, offset, &containingView); + + aFrame->GetView(presContext, &parentView); + if (!parentView) + { + // note: nsIFrames are not refcounted + nsIFrame *aParentFrame = nsnull; + aFrame->GetParentWithView(presContext, &aParentFrame); + if (aParentFrame) + { + aParentFrame->GetView(presContext, &parentView); + } + } + } + + nsCOMPtr aWidget = nsnull; + if (parentView) + { + // note: are nsIViews recounted ??? + nsIView *view = parentView; + while (!aWidget && view) + { + view->GetWidget(*getter_AddRefs(aWidget)); + if (!aWidget) + { + view->GetParent(view); + } + } + } + if (aWidget) + { + nsRect screenRect(0,0,0,0); + aWidget->WidgetToScreen ( aRect, screenRect ); + aRect.MoveBy(screenRect.x, screenRect.y); + + float twips2Pixels = 1.0; + presContext->GetTwipsToPixels(&twips2Pixels); + + aMacRect.left = aRect.x + offset.x * twips2Pixels; + aMacRect.top = aRect.y + offset.y * twips2Pixels; + aMacRect.right = aMacRect.left + aRect.width * twips2Pixels; + aMacRect.bottom = aMacRect.top + aRect.height * twips2Pixels; + + haveRectFlag = PR_TRUE; + } + + DragReference theDragRef; OSErr result = ::NewDrag(&theDragRef); if ( result != noErr ) @@ -113,7 +211,22 @@ printf("**** created drag ref %ld\n", theDragRef); theEvent.modifiers = 0; RgnHandle theDragRgn = ::NewRgn(); - BuildDragRegion ( aDragRgn, globalMouseLoc, theDragRgn ); + ::RectRgn(theDragRgn, &aMacRect); // rjc: set rect + + if ((haveRectFlag == PR_TRUE) && (mImageDraggingSupported == PR_TRUE)) + { + Point imgOffsetPt; + imgOffsetPt.v = imgOffsetPt.h = 0; + + // rjc - note: passing in null for image's PixMapHandle + // to SetDragImage() means use bits on screen + ::SetDragImage (theDragRef, nsnull, theDragRgn, + imgOffsetPt, kDragDarkerTranslucency); + } + else + { + BuildDragRegion ( aDragRgn, globalMouseLoc, theDragRgn ); + } // register drag send proc which will call us back when asked for the actual // flavor data (instead of placing it all into the drag manager) diff --git a/widget/src/mac/nsDragService.h b/widget/src/mac/nsDragService.h index 7af6a32e0c8..87c76ee916e 100644 --- a/widget/src/mac/nsDragService.h +++ b/widget/src/mac/nsDragService.h @@ -52,7 +52,7 @@ public: NS_DECL_ISUPPORTS_INHERITED //nsIDragService - NS_IMETHOD InvokeDragSession (nsISupportsArray * anArrayTransferables, nsIScriptableRegion * aRegion, PRUint32 aActionType); + NS_IMETHOD InvokeDragSession (nsIDOMNode *aDOMNode, nsISupportsArray * anArrayTransferables, nsIScriptableRegion * aRegion, PRUint32 aActionType); //nsIDragSession NS_IMETHOD GetData (nsITransferable * aTransferable, PRUint32 aItemIndex); @@ -77,6 +77,7 @@ private: static pascal OSErr DragSendDataProc ( FlavorType inFlavor, void* inRefCon, ItemReference theItemRef, DragReference inDragRef ) ; + PRBool mImageDraggingSupported; static DragSendDataUPP sDragSendDataUPP; DragReference mDragRef; // reference to _the_ drag. There can be only one. nsISupportsArray* mDataItems; // cached here for when we start the drag so the diff --git a/widget/src/xpwidgets/nsBaseDragService.cpp b/widget/src/xpwidgets/nsBaseDragService.cpp index 4af8f3bf5c2..9d8b58359bf 100644 --- a/widget/src/xpwidgets/nsBaseDragService.cpp +++ b/widget/src/xpwidgets/nsBaseDragService.cpp @@ -134,7 +134,7 @@ NS_IMETHODIMP nsBaseDragService::IsDataFlavorSupported(const char *aDataFlavor, } //------------------------------------------------------------------------- -NS_IMETHODIMP nsBaseDragService::InvokeDragSession (nsISupportsArray * anArrayTransferables, nsIScriptableRegion * aRegion, PRUint32 aActionType) +NS_IMETHODIMP nsBaseDragService::InvokeDragSession (nsIDOMNode *aDOMNode, nsISupportsArray * anArrayTransferables, nsIScriptableRegion * aRegion, PRUint32 aActionType) { return NS_ERROR_FAILURE; } diff --git a/xpfe/browser/resources/content/navigatorDD.js b/xpfe/browser/resources/content/navigatorDD.js index 6f8eddffce3..7253102709d 100644 --- a/xpfe/browser/resources/content/navigatorDD.js +++ b/xpfe/browser/resources/content/navigatorDD.js @@ -138,7 +138,7 @@ this doesn't work anymore (target is null), not sure why. var genTrans = trans.QueryInterface(Components.interfaces.nsISupports); transArray.AppendElement(genTrans); var nsIDragService = Components.interfaces.nsIDragService; - dragService.invokeDragSession ( transArray, null, nsIDragService.DRAGDROP_ACTION_COPY + + dragService.invokeDragSession ( event.target, transArray, null, nsIDragService.DRAGDROP_ACTION_COPY + nsIDragService.DRAGDROP_ACTION_MOVE ); dragStarted = true; } @@ -351,7 +351,7 @@ function BeginDragContentArea ( event ) var genTrans = trans.QueryInterface(Components.interfaces.nsISupports); transArray.AppendElement(genTrans); var nsIDragService = Components.interfaces.nsIDragService; - dragService.invokeDragSession ( transArray, null, nsIDragService.DRAGDROP_ACTION_COPY + + dragService.invokeDragSession ( event.target, transArray, null, nsIDragService.DRAGDROP_ACTION_COPY + nsIDragService.DRAGDROP_ACTION_MOVE ); dragStarted = true; } @@ -525,7 +525,7 @@ function DragProxyIcon ( event ) var genTrans = trans.QueryInterface(Components.interfaces.nsISupports); transArray.AppendElement(genTrans); var nsIDragService = Components.interfaces.nsIDragService; - dragService.invokeDragSession ( transArray, null, nsIDragService.DRAGDROP_ACTION_COPY + + dragService.invokeDragSession ( event.target, transArray, null, nsIDragService.DRAGDROP_ACTION_COPY + nsIDragService.DRAGDROP_ACTION_MOVE ); dragStarted = true; } @@ -586,7 +586,7 @@ function DragContentLink ( event ) var genTrans = trans.QueryInterface(Components.interfaces.nsISupports); transArray.AppendElement(genTrans); var nsIDragService = Components.interfaces.nsIDragService; - dragService.invokeDragSession ( transArray, null, nsIDragService.DRAGDROP_ACTION_COPY + + dragService.invokeDragSession ( event.target, transArray, null, nsIDragService.DRAGDROP_ACTION_COPY + nsIDragService.DRAGDROP_ACTION_MOVE ); dragStarted = true; } diff --git a/xpfe/components/bookmarks/resources/bookmarksDD.js b/xpfe/components/bookmarks/resources/bookmarksDD.js index 4db85a7cc55..cda6c937ef0 100644 --- a/xpfe/components/bookmarks/resources/bookmarksDD.js +++ b/xpfe/components/bookmarks/resources/bookmarksDD.js @@ -121,7 +121,7 @@ dump("genData is " + genData.data + " len is " + genData.data.length + "\n"); if ( !dragService ) return(false); var nsIDragService = Components.interfaces.nsIDragService; - dragService.invokeDragSession ( transArray, null, nsIDragService.DRAGDROP_ACTION_COPY + + dragService.invokeDragSession ( event.target, transArray, null, nsIDragService.DRAGDROP_ACTION_COPY + nsIDragService.DRAGDROP_ACTION_MOVE ); dragStarted = true;