Bug 471848, flag for whether a drag was cancelled by the user, r+sr=roc

This commit is contained in:
Neil Deakin 2009-02-17 10:51:12 -05:00
parent 90c37e3e72
commit 7ae9acbaf5
13 changed files with 64 additions and 15 deletions

View File

@ -74,6 +74,7 @@ nsDOMDataTransfer::nsDOMDataTransfer()
mEffectAllowed(nsIDragService::DRAGDROP_ACTION_UNINITIALIZED),
mReadOnly(PR_FALSE),
mIsExternal(PR_FALSE),
mUserCancelled(PR_FALSE),
mDragImageX(0),
mDragImageY(0)
{
@ -84,6 +85,7 @@ nsDOMDataTransfer::nsDOMDataTransfer(PRUint32 aEventType, PRUint32 aAction)
mDropEffect(nsIDragService::DRAGDROP_ACTION_NONE),
mReadOnly(PR_TRUE),
mIsExternal(PR_TRUE),
mUserCancelled(PR_FALSE),
mDragImageX(0),
mDragImageY(0)
{
@ -98,6 +100,7 @@ nsDOMDataTransfer::nsDOMDataTransfer(PRUint32 aEventType, PRUint32 aAction)
nsDOMDataTransfer::nsDOMDataTransfer(PRUint32 aEventType,
const PRUint32 aEffectAllowed,
PRBool aIsExternal,
PRBool aUserCancelled,
nsTArray<nsTArray<TransferItem> >& aItems,
nsIDOMElement* aDragImage,
PRUint32 aDragImageX,
@ -107,6 +110,7 @@ nsDOMDataTransfer::nsDOMDataTransfer(PRUint32 aEventType,
mEffectAllowed(aEffectAllowed),
mReadOnly(PR_TRUE),
mIsExternal(aIsExternal),
mUserCancelled(aUserCancelled),
mItems(aItems),
mDragImage(aDragImage),
mDragImageX(aDragImageX),
@ -207,6 +211,13 @@ nsDOMDataTransfer::SetEffectAllowedInt(PRUint32 aEffectAllowed)
return NS_OK;
}
NS_IMETHODIMP
nsDOMDataTransfer::GetMozUserCancelled(PRBool* aUserCancelled)
{
*aUserCancelled = mUserCancelled;
return NS_OK;
}
NS_IMETHODIMP
nsDOMDataTransfer::GetTypes(nsIDOMDOMStringList** aTypes)
{
@ -453,11 +464,11 @@ nsDOMDataTransfer::AddElement(nsIDOMElement* aElement)
}
nsresult
nsDOMDataTransfer::Clone(PRUint32 aEventType,
nsDOMDataTransfer::Clone(PRUint32 aEventType, PRBool aUserCancelled,
nsIDOMDataTransfer** aNewDataTransfer)
{
nsDOMDataTransfer* newDataTransfer =
new nsDOMDataTransfer(aEventType, mEffectAllowed, mIsExternal,
new nsDOMDataTransfer(aEventType, mEffectAllowed, mIsExternal, aUserCancelled,
mItems, mDragImage, mDragImageX, mDragImageY);
NS_ENSURE_TRUE(newDataTransfer, NS_ERROR_OUT_OF_MEMORY);

View File

@ -94,6 +94,7 @@ protected:
nsDOMDataTransfer(PRUint32 aEventType,
const PRUint32 aEffectAllowed,
PRBool aIsExternal,
PRBool aUserCancelled,
nsTArray<nsTArray<TransferItem> >& aItems,
nsIDOMElement* aDragImage,
PRUint32 aDragImageX,
@ -174,6 +175,9 @@ protected:
// another application.
PRPackedBool mIsExternal;
// true if the user cancelled the drag. Used only for the dragend event.
PRPackedBool mUserCancelled;
// array of items, each containing an array of format->data pairs
nsTArray<nsTArray<TransferItem> > mItems;

View File

@ -173,7 +173,7 @@ nsDOMDragEvent::GetDataTransfer(nsIDOMDataTransfer** aDataTransfer)
nsCOMPtr<nsIDOMNSDataTransfer> initialDataTransferNS =
do_QueryInterface(initialDataTransfer);
NS_ENSURE_TRUE(initialDataTransferNS, NS_ERROR_FAILURE);
initialDataTransferNS->Clone(mEvent->message,
initialDataTransferNS->Clone(mEvent->message, dragEvent->userCancelled,
getter_AddRefs(dragEvent->dataTransfer));
NS_ENSURE_TRUE(dragEvent->dataTransfer, NS_ERROR_OUT_OF_MEMORY);

View File

@ -155,6 +155,8 @@ function test_DataTransfer(dt)
expectError(function() dt.mozSetDataAt("text/plain", "Some Text", 1),
"NS_ERROR_DOM_INDEX_SIZE_ERR", "setDataAt index too high");
is(dt.mozUserCancelled, false, "userCancelled");
// because an exception occured, the data should not have been added
is(dt.mozItemCount, 0, "empty setDataAt index too high itemCount");
dt.getData("text/plain", "", "empty setDataAt index too high getData");

View File

@ -154,7 +154,7 @@ interface nsIDOMDataTransfer : nsISupports
void addElement(in nsIDOMElement element);
};
[scriptable, uuid(A884E56C-1678-4978-AD20-142EE94108F5)]
[scriptable, uuid(53C854FC-33F9-4647-B045-46D7AB06A6F1)]
interface nsIDOMNSDataTransfer : nsISupports
{
/*
@ -169,9 +169,11 @@ interface nsIDOMNSDataTransfer : nsISupports
[noscript] attribute unsigned long effectAllowedInt;
/**
* Creates a copy of the data transfer object
* Creates a copy of the data transfer object, for the given event type and
* user cancelled flag.
*/
[noscript] nsIDOMDataTransfer clone(in PRUint32 aEventType);
[noscript] nsIDOMDataTransfer clone(in PRUint32 aEventType,
in PRBool aUserCancelled);
/**
* The number of items being dragged.
@ -234,4 +236,11 @@ interface nsIDOMNSDataTransfer : nsISupports
* @throws NS_ERROR_DOM_INDEX_SIZE_ERR if index is greater or equal than itemCount
*/
nsIVariant mozGetDataAt(in DOMString format, in unsigned long index);
/**
* Will be true if the user cancelled the drag (typically by pressing Escape).
* This will be false otherwise, including if a drag failed for any other reason.
* This property is only relevant for the dragend event.
*/
readonly attribute boolean mozUserCancelled;
};

View File

@ -775,7 +775,8 @@ class nsDragEvent : public nsMouseEvent
{
public:
nsDragEvent(PRBool isTrusted, PRUint32 msg, nsIWidget *w)
: nsMouseEvent(isTrusted, msg, w, NS_DRAG_EVENT, eReal)
: nsMouseEvent(isTrusted, msg, w, NS_DRAG_EVENT, eReal),
userCancelled(PR_FALSE)
{
if (msg == NS_DRAGDROP_EXIT_SYNTH ||
msg == NS_DRAGDROP_LEAVE_SYNTH ||
@ -785,6 +786,7 @@ public:
}
nsCOMPtr<nsIDOMDataTransfer> dataTransfer;
PRPackedBool userCancelled;
};
/**

View File

@ -146,6 +146,7 @@ nsIWidget * gRollupWidget = nsnull;
PRUint32 gLastModifierState = 0;
PRBool gUserCancelledDrag = PR_FALSE;
@interface ChildView(Private)
@ -6361,6 +6362,10 @@ static BOOL keyUpAlreadySentKeyDown = NO;
gDraggedTransferables = nsnull;
NSEvent *currentEvent = [NSApp currentEvent];
gUserCancelledDrag = ([currentEvent type] == NSKeyDown &&
[currentEvent keyCode] == kEscapeKeyCode);
if (!mDragService) {
CallGetService(kDragServiceContractID, &mDragService);
NS_ASSERTION(mDragService, "Couldn't get a drag service - big problem!");

View File

@ -78,6 +78,7 @@ extern PRLogModuleInfo* sCocoaLog;
extern NSPasteboard* globalDragPboard;
extern NSView* gLastDragView;
extern NSEvent* gLastDragEvent;
extern PRBool gUserCancelledDrag;
// This global makes the transferable array available to Cocoa's promised
// file destination callback.
@ -308,6 +309,7 @@ nsDragService::InvokeDragSession(nsIDOMNode* aDOMNode, nsISupportsArray* aTransf
mNativeDragView = [gLastDragView retain];
mNativeDragEvent = [gLastDragEvent retain];
gUserCancelledDrag = PR_FALSE;
[mNativeDragView dragImage:image
at:localPoint
offset:NSMakeSize(0,0)
@ -315,6 +317,7 @@ nsDragService::InvokeDragSession(nsIDOMNode* aDOMNode, nsISupportsArray* aTransf
pasteboard:[NSPasteboard pasteboardWithName:NSDragPboard]
source:mNativeDragView
slideBack:YES];
gUserCancelledDrag = PR_FALSE;
if (mDoingDrag)
nsBaseDragService::EndDragSession(PR_FALSE);
@ -587,6 +590,8 @@ nsDragService::EndDragSession(PRBool aDoneDrag)
mNativeDragEvent = nil;
}
mUserCancelled = gUserCancelledDrag;
nsresult rv = nsBaseDragService::EndDragSession(aDoneDrag);
mDataItems = nsnull;
return rv;

View File

@ -270,11 +270,12 @@ nsDragService::StartInvokingDragSession(IDataObject * aDataObj,
{
// To do the drag we need to create an object that
// implements the IDataObject interface (for OLE)
NS_IF_RELEASE(mNativeDragSrc);
mNativeDragSrc = (IDropSource *)new nsNativeDragSource();
if (!mNativeDragSrc)
nsNativeDragSource* nativeDragSource = new nsNativeDragSource();
if (!nativeDragSource)
return NS_ERROR_OUT_OF_MEMORY;
NS_IF_RELEASE(mNativeDragSrc);
mNativeDragSrc = (IDropSource *)nativeDragSource;
mNativeDragSrc->AddRef();
// Now figure out what the native drag effect should be
@ -351,7 +352,9 @@ nsDragService::StartInvokingDragSession(IDataObject * aDataObj,
dataTransfer->SetDropEffectInt(DRAGDROP_ACTION_NONE);
}
}
mUserCancelled = nativeDragSource->UserCancelled();
// We're done dragging
EndDragSession(PR_TRUE);

View File

@ -44,7 +44,7 @@
* class nsNativeDragSource
*/
nsNativeDragSource::nsNativeDragSource()
: m_cRef(0)
: m_cRef(0), mUserCancelled(PR_FALSE)
{
}
@ -99,6 +99,7 @@ nsNativeDragSource::QueryContinueDrag(BOOL fEsc, DWORD grfKeyState)
#ifdef DEBUG
//printf("fEsc\n");
#endif
mUserCancelled = PR_TRUE;
return ResultFromScode(DRAGDROP_S_CANCEL);
}

View File

@ -37,6 +37,7 @@
#ifndef _nsNativeDragSource_h_
#define _nsNativeDragSource_h_
#include "nscore.h"
#include <ole2.h>
#include <oleidl.h>
@ -74,11 +75,13 @@ public:
// to execute the drop, otherwise NOERROR.
STDMETHODIMP QueryContinueDrag(BOOL fESC, DWORD grfKeyState);
PRPackedBool UserCancelled() { return mUserCancelled; }
protected:
ULONG m_cRef; // reference count
//nsIDragSource * mDragSource; // adapter
//CfDragDrop * mDragSource; // adapter
// true if the user cancelled the drag by pressing escape
PRPackedBool mUserCancelled;
};
#endif // _nsNativeDragSource_h_

View File

@ -78,7 +78,7 @@
#define DRAGIMAGES_PREF "nglayout.enable_drag_images"
nsBaseDragService::nsBaseDragService()
: mCanDrop(PR_FALSE), mDoingDrag(PR_FALSE), mHasImage(PR_FALSE),
: mCanDrop(PR_FALSE), mDoingDrag(PR_FALSE), mHasImage(PR_FALSE), mUserCancelled(PR_FALSE),
mDragAction(DRAGDROP_ACTION_NONE), mTargetSize(0,0),
mImageX(0), mImageY(0), mScreenX(-1), mScreenY(-1), mSuppressLevel(0)
{
@ -354,6 +354,7 @@ nsBaseDragService::EndDragSession(PRBool aDoneDrag)
mSelection = nsnull;
mDataTransfer = nsnull;
mHasImage = PR_FALSE;
mUserCancelled = PR_FALSE;
mImage = nsnull;
mImageX = 0;
mImageY = 0;
@ -373,6 +374,7 @@ nsBaseDragService::FireDragEventAtSource(PRUint32 aMsg)
if (presShell) {
nsEventStatus status = nsEventStatus_eIgnore;
nsDragEvent event(PR_TRUE, aMsg, nsnull);
event.userCancelled = (aMsg == NS_DRAGDROP_END && mUserCancelled);
nsCOMPtr<nsIContent> content = do_QueryInterface(mSourceNode);
return presShell->HandleDOMEventWithTarget(content, &event, &status);

View File

@ -129,6 +129,8 @@ protected:
PRPackedBool mDoingDrag;
// true if mImage should be used to set a drag image
PRPackedBool mHasImage;
// true if the user cancelled the drag operation
PRPackedBool mUserCancelled;
PRUint32 mDragAction;
nsSize mTargetSize;