diff --git a/mozilla/content/base/src/nsContentAreaDragDrop.cpp b/mozilla/content/base/src/nsContentAreaDragDrop.cpp index 2e31bd62a8c..e19fbf0016b 100644 --- a/mozilla/content/base/src/nsContentAreaDragDrop.cpp +++ b/mozilla/content/base/src/nsContentAreaDragDrop.cpp @@ -52,6 +52,7 @@ #include "nsIDOMNodeList.h" #include "nsIDOMEventReceiver.h" #include "nsIDOMEvent.h" +#include "nsIDOMNSEvent.h" #include "nsIDOMMouseEvent.h" #include "nsIDOMAbstractView.h" #include "nsIDOMWindow.h" @@ -724,7 +725,7 @@ nsContentAreaDragDrop::BuildDragData(nsIDOMEvent* inMouseEvent, nsAString & outU nsCOMPtr uiEvent(do_QueryInterface(inMouseEvent)); if ( !uiEvent ) - return NS_ERROR_FAILURE; + return PR_FALSE; nsCOMPtr target; inMouseEvent->GetTarget(getter_AddRefs(target)); @@ -759,7 +760,16 @@ nsContentAreaDragDrop::BuildDragData(nsIDOMEvent* inMouseEvent, nsAString & outU PRBool containsTarget = PR_FALSE; if ( selection ) { selection->GetIsCollapsed(&isCollapsed); - selection->ContainsNode(draggedNode, PR_FALSE, &containsTarget); + // Get the real target and see if it is in the selection + nsCOMPtr internalEvent = do_QueryInterface(inMouseEvent); + if (internalEvent) { + nsCOMPtr realTarget; + internalEvent->GetExplicitOriginalTarget(getter_AddRefs(realTarget)); + nsCOMPtr realTargetNode = do_QueryInterface(realTarget); + if (realTargetNode) { + selection->ContainsNode(realTargetNode, PR_FALSE, &containsTarget); + } + } } PRBool getFormattedStrings = PR_FALSE; diff --git a/mozilla/content/events/src/nsDOMEvent.cpp b/mozilla/content/events/src/nsDOMEvent.cpp index 8841ebb5c52..a7200ea81a7 100644 --- a/mozilla/content/events/src/nsDOMEvent.cpp +++ b/mozilla/content/events/src/nsDOMEvent.cpp @@ -196,6 +196,21 @@ nsDOMEvent::nsDOMEvent(nsIPresContext* aPresContext, nsEvent* aEvent, mTarget = nsnull; mCurrentTarget = nsnull; mOriginalTarget = nsnull; + // Get the explicit original target (if it's anonymous make it null) + { + GetTargetFromFrame(&mExplicitOriginalTarget); + nsCOMPtr content = do_QueryInterface(mExplicitOriginalTarget); + if (content) { + if (content->IsNativeAnonymous()) { + mExplicitOriginalTarget = nsnull; + } + nsCOMPtr bindingParent; + content->GetBindingParent(getter_AddRefs(bindingParent)); + if (bindingParent) { + mExplicitOriginalTarget = nsnull; + } + } + } mText = nsnull; mTextRange = nsnull; mButton = -1; @@ -260,6 +275,7 @@ nsDOMEvent::~nsDOMEvent() nsCOMPtr shell; if (mPresContext) { // we were arena-allocated, prepare to recycle myself + // XXX this does not appear to be needed anymore mPresContext->GetShell(getter_AddRefs(shell)); } NS_IF_RELEASE(mPresContext); @@ -364,6 +380,45 @@ nsDOMEvent::GetCurrentTarget(nsIDOMEventTarget** aCurrentTarget) return NS_OK; } +// +// Get the actual event target node (may have been retargeted for mouse events) +// +void +nsDOMEvent::GetTargetFromFrame(nsIDOMEventTarget** aTarget) +{ + *aTarget = nsnull; + + if (!mPresContext) { return; } + + // Get the target frame (have to get the ESM first) + nsCOMPtr esm; + mPresContext->GetEventStateManager(getter_AddRefs(esm)); + + nsIFrame* targetFrame = nsnull; + esm->GetEventTarget(&targetFrame); + if (!targetFrame) { return; } + + // get the real content + nsCOMPtr realEventContent; + targetFrame->GetContentForEvent(mPresContext, mEvent, getter_AddRefs(realEventContent)); + if (!realEventContent) { return; } + + // Finally, we have the real content. QI it and return. + CallQueryInterface(realEventContent, aTarget); +} + +NS_IMETHODIMP +nsDOMEvent::GetExplicitOriginalTarget(nsIDOMEventTarget** aRealEventTarget) +{ + if (mExplicitOriginalTarget) { + *aRealEventTarget = mExplicitOriginalTarget; + NS_ADDREF(*aRealEventTarget); + return NS_OK; + } + + return GetTarget(aRealEventTarget); +} + NS_IMETHODIMP nsDOMEvent::GetOriginalTarget(nsIDOMEventTarget** aOriginalTarget) { diff --git a/mozilla/content/events/src/nsDOMEvent.h b/mozilla/content/events/src/nsDOMEvent.h index dc1f45b0d13..7a7b0a3920c 100644 --- a/mozilla/content/events/src/nsDOMEvent.h +++ b/mozilla/content/events/src/nsDOMEvent.h @@ -226,12 +226,14 @@ protected: float* aT2P); nsresult SetEventType(const nsAString& aEventTypeArg); const char* GetEventName(PRUint32 aEventType); + void GetTargetFromFrame(nsIDOMEventTarget** aTarget); nsEvent* mEvent; nsIPresContext* mPresContext; nsIDOMEventTarget* mTarget; nsIDOMEventTarget* mCurrentTarget; nsIDOMEventTarget* mOriginalTarget; + nsIDOMEventTarget* mExplicitOriginalTarget; nsString* mText; nsIPrivateTextRangeList* mTextRange; PRPackedBool mEventIsInternal; diff --git a/mozilla/dom/public/idl/events/nsIDOMNSEvent.idl b/mozilla/dom/public/idl/events/nsIDOMNSEvent.idl index 1fd6cf800bc..ad71dc2d852 100644 --- a/mozilla/dom/public/idl/events/nsIDOMNSEvent.idl +++ b/mozilla/dom/public/idl/events/nsIDOMNSEvent.idl @@ -79,7 +79,19 @@ interface nsIDOMNSEvent : nsISupports const long SHIFT_MASK = 0x00000004; const long META_MASK = 0x00000008; + /** The original target of the event, before any retargetings. */ readonly attribute nsIDOMEventTarget originalTarget; + /** + * The explicit original target of the event. If the event was retargeted + * for some reason other than an anonymous boundary crossing, this will be set + * to the target before the retargeting occurs. For example, mouse events + * are retargeted to their parent node when they happen over text nodes (bug + * 185889), and in that case .target will show the parent and + * .explicitOriginalTarget will show the text node. + * .explicitOriginalTarget differs from .originalTarget in that it will never + * contain anonymous content. + */ + readonly attribute nsIDOMEventTarget explicitOriginalTarget; void preventBubble(); void preventCapture(); diff --git a/mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp b/mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp index ca2a48b2cc5..5384079e468 100644 --- a/mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp +++ b/mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp @@ -1284,7 +1284,7 @@ NS_IMETHODIMP nsHTMLEditor::CanDrag(nsIDOMEvent *aDragEvent, PRBool *aCanDrag) if (nsevent) { - res = nsevent->GetOriginalTarget(getter_AddRefs(eventTarget)); + res = nsevent->GetExplicitOriginalTarget(getter_AddRefs(eventTarget)); if (NS_FAILED(res)) { return res;