diff --git a/content/base/src/nsContentAreaDragDrop.cpp b/content/base/src/nsContentAreaDragDrop.cpp index 474ec7bfadf..1100f29ade9 100644 --- a/content/base/src/nsContentAreaDragDrop.cpp +++ b/content/base/src/nsContentAreaDragDrop.cpp @@ -395,6 +395,22 @@ nsContentAreaDragDrop::DragExit(nsIDOMEvent* aMouseEvent) } +NS_IMETHODIMP +nsContentAreaDragDrop::Drag(nsIDOMEvent* aMouseEvent) +{ + // nothing really to do here. + return NS_OK; +} + + +NS_IMETHODIMP +nsContentAreaDragDrop::DragEnd(nsIDOMEvent* aMouseEvent) +{ + // nothing really to do here. + return NS_OK; +} + + // // ExtractURLFromData // diff --git a/content/base/src/nsContentAreaDragDrop.h b/content/base/src/nsContentAreaDragDrop.h index de2af39d8f1..9522fed1219 100644 --- a/content/base/src/nsContentAreaDragDrop.h +++ b/content/base/src/nsContentAreaDragDrop.h @@ -93,6 +93,8 @@ public: NS_IMETHOD DragExit(nsIDOMEvent* aMouseEvent); NS_IMETHOD DragDrop(nsIDOMEvent* aMouseEvent); NS_IMETHOD DragGesture(nsIDOMEvent* aMouseEvent); + NS_IMETHOD Drag(nsIDOMEvent* aMouseEvent); + NS_IMETHOD DragEnd(nsIDOMEvent* aMouseEvent); NS_IMETHOD HandleEvent(nsIDOMEvent *event); private: diff --git a/content/base/src/nsGkAtomList.h b/content/base/src/nsGkAtomList.h index cf00d7bb5aa..82648b88771 100755 --- a/content/base/src/nsGkAtomList.h +++ b/content/base/src/nsGkAtomList.h @@ -278,14 +278,19 @@ GK_ATOM(DOMNodeInsertedIntoDocument, "DOMNodeInsertedInfoDocument") GK_ATOM(DOMNodeRemoved, "DOMNodeRemoved") GK_ATOM(DOMNodeRemovedFromDocument, "DOMNodeRemovedFromDocument") GK_ATOM(DOMSubtreeModified, "DOMSubtreeModified") +GK_ATOM(drag, "drag") GK_ATOM(dragdrop, "dragdrop") +GK_ATOM(dragend, "dragend") GK_ATOM(dragenter, "dragenter") GK_ATOM(dragevent, "dragevent") GK_ATOM(dragexit, "dragexit") GK_ATOM(draggesture, "draggesture") GK_ATOM(dragging, "dragging") +GK_ATOM(dragleave, "dragleave") GK_ATOM(dragover, "dragover") GK_ATOM(dragSession, "dragSession") +GK_ATOM(dragstart, "dragstart") +GK_ATOM(drop, "drop") GK_ATOM(dropAfter, "dropAfter") GK_ATOM(dropBefore, "dropBefore") GK_ATOM(dropOn, "dropOn") @@ -559,11 +564,16 @@ GK_ATOM(onDOMNodeInsertedIntoDocument, "onDOMNodeInsertedIntoDocument") GK_ATOM(onDOMNodeRemoved, "onDOMNodeRemoved") GK_ATOM(onDOMNodeRemovedFromDocument, "onDOMNodeRemovedFromDocument") GK_ATOM(onDOMSubtreeModified, "onDOMSubtreeModified") +GK_ATOM(ondrag, "ondrag") GK_ATOM(ondragdrop, "ondragdrop") +GK_ATOM(ondragend, "ondragend") GK_ATOM(ondragenter, "ondragenter") GK_ATOM(ondragexit, "ondragexit") GK_ATOM(ondraggesture, "ondraggesture") +GK_ATOM(ondragleave, "ondragleave") GK_ATOM(ondragover, "ondragover") +GK_ATOM(ondragstart, "ondragstart") +GK_ATOM(ondrop, "ondrop") GK_ATOM(onerror, "onerror") GK_ATOM(onfocus, "onfocus") GK_ATOM(onget, "onget") diff --git a/content/base/src/nsHTMLContentSerializer.cpp b/content/base/src/nsHTMLContentSerializer.cpp index 4325581e658..17990eeda95 100644 --- a/content/base/src/nsHTMLContentSerializer.cpp +++ b/content/base/src/nsHTMLContentSerializer.cpp @@ -472,7 +472,10 @@ nsHTMLContentSerializer::IsJavaScript(nsIAtom* aAttrNameAtom, const nsAString& a || (aAttrNameAtom == nsGkAtoms::oncommand) || (aAttrNameAtom == nsGkAtoms::oncommandupdate) || (aAttrNameAtom == nsGkAtoms::ondragdrop) || (aAttrNameAtom == nsGkAtoms::ondragenter) || (aAttrNameAtom == nsGkAtoms::ondragexit) || (aAttrNameAtom == nsGkAtoms::ondraggesture) - || (aAttrNameAtom == nsGkAtoms::ondragover) || (aAttrNameAtom == nsGkAtoms::oninput); + || (aAttrNameAtom == nsGkAtoms::ondragover) || (aAttrNameAtom == nsGkAtoms::ondragstart) + || (aAttrNameAtom == nsGkAtoms::ondragleave) || (aAttrNameAtom == nsGkAtoms::ondrop) + || (aAttrNameAtom == nsGkAtoms::ondragend) || (aAttrNameAtom == nsGkAtoms::ondrag) + || (aAttrNameAtom == nsGkAtoms::oninput); return result; } diff --git a/content/events/src/nsDOMEvent.cpp b/content/events/src/nsDOMEvent.cpp index 6cbf85b8b13..138c0b57d61 100644 --- a/content/events/src/nsDOMEvent.cpp +++ b/content/events/src/nsDOMEvent.cpp @@ -63,8 +63,9 @@ static const char* const sEventNames[] = { "submit", "reset", "change", "select", "input", "paint" ,"text", "compositionstart", "compositionend", "popupshowing", "popupshown", "popuphiding", "popuphidden", "close", "command", "broadcast", "commandupdate", - "dragenter", "dragover", "dragexit", "dragdrop", "draggesture", "resize", - "scroll","overflow", "underflow", "overflowchanged", + "dragenter", "dragover", "dragexit", "dragdrop", "draggesture", + "drag", "dragend", "dragstart", "dragleave", "drop", "resize", + "scroll", "overflow", "underflow", "overflowchanged", "DOMSubtreeModified", "DOMNodeInserted", "DOMNodeRemoved", "DOMNodeRemovedFromDocument", "DOMNodeInsertedIntoDocument", "DOMAttrModified", "DOMCharacterDataModified", @@ -1177,10 +1178,20 @@ const char* nsDOMEvent::GetEventName(PRUint32 aEventType) return sEventNames[eDOMEvents_dragover]; case NS_DRAGDROP_EXIT_SYNTH: return sEventNames[eDOMEvents_dragexit]; - case NS_DRAGDROP_DROP: + case NS_DRAGDROP_DRAGDROP: return sEventNames[eDOMEvents_dragdrop]; case NS_DRAGDROP_GESTURE: return sEventNames[eDOMEvents_draggesture]; + case NS_DRAGDROP_DRAG: + return sEventNames[eDOMEvents_drag]; + case NS_DRAGDROP_END: + return sEventNames[eDOMEvents_dragend]; + case NS_DRAGDROP_START: + return sEventNames[eDOMEvents_dragstart]; + case NS_DRAGDROP_LEAVE_SYNTH: + return sEventNames[eDOMEvents_dragleave]; + case NS_DRAGDROP_DROP: + return sEventNames[eDOMEvents_drop]; case NS_SCROLLPORT_OVERFLOW: return sEventNames[eDOMEvents_overflow]; case NS_SCROLLPORT_UNDERFLOW: diff --git a/content/events/src/nsDOMEvent.h b/content/events/src/nsDOMEvent.h index d7ec5ccdc5a..1c8a3d62683 100644 --- a/content/events/src/nsDOMEvent.h +++ b/content/events/src/nsDOMEvent.h @@ -107,6 +107,11 @@ public: eDOMEvents_dragexit, eDOMEvents_dragdrop, eDOMEvents_draggesture, + eDOMEvents_drag, + eDOMEvents_dragend, + eDOMEvents_dragstart, + eDOMEvents_dragleave, + eDOMEvents_drop, eDOMEvents_resize, eDOMEvents_scroll, eDOMEvents_overflow, diff --git a/content/events/src/nsEventListenerManager.cpp b/content/events/src/nsEventListenerManager.cpp index 7061acd3905..1087d2315aa 100644 --- a/content/events/src/nsEventListenerManager.cpp +++ b/content/events/src/nsEventListenerManager.cpp @@ -261,11 +261,16 @@ static const EventDispatchData sLoadEvents[] = { }; static const EventDispatchData sDragEvents[] = { - { NS_DRAGDROP_ENTER, HANDLER(&nsIDOMDragListener::DragEnter) }, - { NS_DRAGDROP_OVER_SYNTH, HANDLER(&nsIDOMDragListener::DragOver) }, - { NS_DRAGDROP_EXIT_SYNTH, HANDLER(&nsIDOMDragListener::DragExit) }, - { NS_DRAGDROP_DROP, HANDLER(&nsIDOMDragListener::DragDrop) }, - { NS_DRAGDROP_GESTURE, HANDLER(&nsIDOMDragListener::DragGesture) } + { NS_DRAGDROP_ENTER, HANDLER(&nsIDOMDragListener::DragEnter) }, + { NS_DRAGDROP_OVER_SYNTH, HANDLER(&nsIDOMDragListener::DragOver) }, + { NS_DRAGDROP_EXIT_SYNTH, HANDLER(&nsIDOMDragListener::DragExit) }, + { NS_DRAGDROP_DRAGDROP, HANDLER(&nsIDOMDragListener::DragDrop) }, + { NS_DRAGDROP_GESTURE, HANDLER(&nsIDOMDragListener::DragGesture) }, + { NS_DRAGDROP_DRAG, HANDLER(&nsIDOMDragListener::Drag) }, + { NS_DRAGDROP_END, HANDLER(&nsIDOMDragListener::DragEnd) }, + { NS_DRAGDROP_START, HANDLER(&nsIDOMDragListener::DragStart) }, + { NS_DRAGDROP_LEAVE_SYNTH, HANDLER(&nsIDOMDragListener::DragLeave) }, + { NS_DRAGDROP_DROP, HANDLER(&nsIDOMDragListener::Drop) }, }; static const EventDispatchData sXULEvents[] = { diff --git a/content/events/src/nsEventStateManager.cpp b/content/events/src/nsEventStateManager.cpp index 9733a3b002b..e237404d139 100644 --- a/content/events/src/nsEventStateManager.cpp +++ b/content/events/src/nsEventStateManager.cpp @@ -1716,11 +1716,16 @@ nsEventStateManager::GenerateDragGesture(nsPresContext* aPresContext, // reentering GenerateDragGesture inside DOM event processing. StopTrackingDragGesture(); + nsCOMPtr widget = mCurrentTarget->GetWindow(); + // get the widget from the target frame - nsEventStatus status = nsEventStatus_eIgnore; - nsMouseEvent event(NS_IS_TRUSTED_EVENT(aEvent), NS_DRAGDROP_GESTURE, - mCurrentTarget->GetWindow(), nsMouseEvent::eReal); - FillInEventFromGestureDown(&event); + nsMouseEvent startEvent(NS_IS_TRUSTED_EVENT(aEvent), NS_DRAGDROP_START, + widget, nsMouseEvent::eReal); + FillInEventFromGestureDown(&startEvent); + + nsMouseEvent gestureEvent(NS_IS_TRUSTED_EVENT(aEvent), NS_DRAGDROP_GESTURE, + widget, nsMouseEvent::eReal); + FillInEventFromGestureDown(&gestureEvent); // Dispatch to the DOM. By setting mCurrentTarget we are faking // out the ESM and telling it that the current target frame is @@ -1737,10 +1742,17 @@ nsEventStateManager::GenerateDragGesture(nsPresContext* aPresContext, // Set the current target to the content for the mouse down mCurrentTargetContent = targetContent; - // Dispatch to DOM - nsEventDispatcher::Dispatch(targetContent, aPresContext, &event, nsnull, + // Dispatch both the dragstart and draggesture events to the DOM + nsEventStatus status = nsEventStatus_eIgnore; + nsEventDispatcher::Dispatch(targetContent, aPresContext, &startEvent, nsnull, &status); + if (status != nsEventStatus_eConsumeNoDefault) { + status = nsEventStatus_eIgnore; + nsEventDispatcher::Dispatch(targetContent, aPresContext, &gestureEvent, nsnull, + &status); + } + // Note that frame event handling doesn't care about NS_DRAGDROP_GESTURE, // which is just as well since we don't really know which frame to // send it to @@ -2223,6 +2235,34 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext, break; case NS_DRAGDROP_DROP: + { + // now fire the dragdrop event, for compatibility with XUL + if (mCurrentTarget) { + nsCOMPtr targetContent; + mCurrentTarget->GetContentForEvent(presContext, aEvent, + getter_AddRefs(targetContent)); + + nsCOMPtr widget = mCurrentTarget->GetWindow(); + nsMouseEvent event(NS_IS_TRUSTED_EVENT(aEvent), NS_DRAGDROP_DRAGDROP, + widget, nsMouseEvent::eReal); + + nsMouseEvent* mouseEvent = NS_STATIC_CAST(nsMouseEvent*, aEvent); + event.refPoint = mouseEvent->refPoint; + event.isShift = mouseEvent->isShift; + event.isControl = mouseEvent->isControl; + event.isAlt = mouseEvent->isAlt; + event.isMeta = mouseEvent->isMeta; + + nsEventStatus status = nsEventStatus_eIgnore; + nsCOMPtr presShell = mPresContext->GetPresShell(); + if (presShell) { + presShell->HandleEventWithTarget(&event, mCurrentTarget, + targetContent, &status); + } + } + // fall through and call GenerateDragDropEnterExit + } + case NS_DRAGDROP_EXIT: // clean up after ourselves. make sure we do this _after_ the event, else we'll // clean up too early! @@ -2844,71 +2884,17 @@ nsEventStateManager::GenerateDragDropEnterExit(nsPresContext* aPresContext, mCurrentTarget->GetContentForEvent(aPresContext, aEvent, getter_AddRefs(targetContent)); if ( mLastDragOverFrame ) { - //fire drag exit - nsEventStatus status = nsEventStatus_eIgnore; - nsMouseEvent event(NS_IS_TRUSTED_EVENT(aEvent), - NS_DRAGDROP_EXIT_SYNTH, aEvent->widget, - nsMouseEvent::eReal); - event.refPoint = aEvent->refPoint; - event.isShift = ((nsMouseEvent*)aEvent)->isShift; - event.isControl = ((nsMouseEvent*)aEvent)->isControl; - event.isAlt = ((nsMouseEvent*)aEvent)->isAlt; - event.isMeta = ((nsMouseEvent*)aEvent)->isMeta; - event.relatedTarget = targetContent; - - //The frame has change but the content may not have. Check before dispatching to content + //The frame has changed but the content may not have. Check before dispatching to content mLastDragOverFrame->GetContentForEvent(aPresContext, aEvent, getter_AddRefs(lastContent)); - mCurrentTargetContent = lastContent; - - if ( lastContent != targetContent ) { - //XXX This event should still go somewhere!! - if (lastContent) - nsEventDispatcher::Dispatch(lastContent, aPresContext, &event, - nsnull, &status); - - // clear the drag hover - if (status != nsEventStatus_eConsumeNoDefault ) - SetContentState(nsnull, NS_EVENT_STATE_DRAGOVER); - } - - // Finally dispatch exit to the frame - if ( mLastDragOverFrame ) { - mLastDragOverFrame->HandleEvent(aPresContext, &event, &status); - - } + FireDragEnterOrExit(aPresContext, aEvent, NS_DRAGDROP_LEAVE_SYNTH, + targetContent, lastContent, mLastDragOverFrame); + FireDragEnterOrExit(aPresContext, aEvent, NS_DRAGDROP_EXIT_SYNTH, + targetContent, lastContent, mLastDragOverFrame); } - //fire drag enter - nsEventStatus status = nsEventStatus_eIgnore; - nsMouseEvent event(NS_IS_TRUSTED_EVENT(aEvent), NS_DRAGDROP_ENTER, - aEvent->widget, nsMouseEvent::eReal); - event.refPoint = aEvent->refPoint; - event.isShift = ((nsMouseEvent*)aEvent)->isShift; - event.isControl = ((nsMouseEvent*)aEvent)->isControl; - event.isAlt = ((nsMouseEvent*)aEvent)->isAlt; - event.isMeta = ((nsMouseEvent*)aEvent)->isMeta; - event.relatedTarget = lastContent; - - mCurrentTargetContent = targetContent; - - //The frame has change but the content may not have. Check before dispatching to content - if (lastContent != targetContent) { - //XXX This event should still go somewhere!! - if (targetContent) - nsEventDispatcher::Dispatch(targetContent, aPresContext, &event, - nsnull, &status); - - // set drag hover on this frame - if (status != nsEventStatus_eConsumeNoDefault) - SetContentState(targetContent, NS_EVENT_STATE_DRAGOVER); - } - - // Finally dispatch to the frame - if (mCurrentTarget) { - //XXX Get the new frame - mCurrentTarget->HandleEvent(aPresContext, &event, &status); - } + FireDragEnterOrExit(aPresContext, aEvent, NS_DRAGDROP_ENTER, + lastContent, targetContent, mCurrentTarget); mLastDragOverFrame = mCurrentTarget; } @@ -2920,37 +2906,16 @@ nsEventStateManager::GenerateDragDropEnterExit(nsPresContext* aPresContext, { //This is actually the window mouse exit event. if ( mLastDragOverFrame ) { - - // fire mouseout - nsEventStatus status = nsEventStatus_eIgnore; - nsMouseEvent event(NS_IS_TRUSTED_EVENT(aEvent), NS_DRAGDROP_EXIT_SYNTH, - aEvent->widget, nsMouseEvent::eReal); - event.refPoint = aEvent->refPoint; - event.isShift = ((nsMouseEvent*)aEvent)->isShift; - event.isControl = ((nsMouseEvent*)aEvent)->isControl; - event.isAlt = ((nsMouseEvent*)aEvent)->isAlt; - event.isMeta = ((nsMouseEvent*)aEvent)->isMeta; - - // dispatch to content via DOM nsCOMPtr lastContent; mLastDragOverFrame->GetContentForEvent(aPresContext, aEvent, getter_AddRefs(lastContent)); - mCurrentTargetContent = lastContent; + FireDragEnterOrExit(aPresContext, aEvent, NS_DRAGDROP_LEAVE_SYNTH, + nsnull, lastContent, mLastDragOverFrame); + FireDragEnterOrExit(aPresContext, aEvent, NS_DRAGDROP_EXIT_SYNTH, + nsnull, lastContent, mLastDragOverFrame); - if (lastContent) { - nsEventDispatcher::Dispatch(lastContent, aPresContext, &event, nsnull, - &status); - if (status != nsEventStatus_eConsumeNoDefault) - SetContentState(nsnull, NS_EVENT_STATE_DRAGOVER); - } - - // Finally dispatch to the frame - if ( mLastDragOverFrame ) { - //XXX Get the new frame - mLastDragOverFrame->HandleEvent(aPresContext, &event, &status); - mLastDragOverFrame = nsnull; - } - } + mLastDragOverFrame = nsnull; + } } break; } @@ -2962,6 +2927,43 @@ nsEventStateManager::GenerateDragDropEnterExit(nsPresContext* aPresContext, FlushPendingEvents(aPresContext); } +void +nsEventStateManager::FireDragEnterOrExit(nsPresContext* aPresContext, + nsGUIEvent* aEvent, + PRUint32 aMsg, + nsIContent* aRelatedTarget, + nsIContent* aTargetContent, + nsWeakFrame& aTargetFrame) +{ + nsEventStatus status = nsEventStatus_eIgnore; + nsMouseEvent event(NS_IS_TRUSTED_EVENT(aEvent), aMsg, + aEvent->widget, nsMouseEvent::eReal); + event.refPoint = aEvent->refPoint; + event.isShift = ((nsMouseEvent*)aEvent)->isShift; + event.isControl = ((nsMouseEvent*)aEvent)->isControl; + event.isAlt = ((nsMouseEvent*)aEvent)->isAlt; + event.isMeta = ((nsMouseEvent*)aEvent)->isMeta; + event.relatedTarget = aRelatedTarget; + + mCurrentTargetContent = aTargetContent; + + if (aTargetContent != aRelatedTarget) { + //XXX This event should still go somewhere!! + if (aTargetContent) + nsEventDispatcher::Dispatch(aTargetContent, aPresContext, &event, + nsnull, &status); + + // adjust the drag hover + if (status != nsEventStatus_eConsumeNoDefault) + SetContentState((aMsg == NS_DRAGDROP_ENTER) ? aTargetContent : nsnull, + NS_EVENT_STATE_DRAGOVER); + } + + // Finally dispatch the event to the frame + if (aTargetFrame) + aTargetFrame->HandleEvent(aPresContext, &event, &status); +} + nsresult nsEventStateManager::SetClickCount(nsPresContext* aPresContext, nsMouseEvent *aEvent, diff --git a/content/events/src/nsEventStateManager.h b/content/events/src/nsEventStateManager.h index 0322b449325..838e14e0465 100644 --- a/content/events/src/nsEventStateManager.h +++ b/content/events/src/nsEventStateManager.h @@ -194,6 +194,20 @@ protected: */ void NotifyMouseOut(nsGUIEvent* aEvent, nsIContent* aMovingInto); void GenerateDragDropEnterExit(nsPresContext* aPresContext, nsGUIEvent* aEvent); + /** + * Fire the dragenter and dragexit/dragleave events when the mouse moves to a + * new target. + * + * @param aRelatedTarget relatedTarget to set for the event + * @param aTargetContent target to set for the event + * @param aTargetFrame target frame for the event + */ + void FireDragEnterOrExit(nsPresContext* aPresContext, + nsGUIEvent* aEvent, + PRUint32 aMsg, + nsIContent* aRelatedTarget, + nsIContent* aTargetContent, + nsWeakFrame& aTargetFrame); nsresult SetClickCount(nsPresContext* aPresContext, nsMouseEvent *aEvent, nsEventStatus* aStatus); nsresult CheckForAndDispatchClick(nsPresContext* aPresContext, nsMouseEvent *aEvent, nsEventStatus* aStatus); nsresult GetNextTabbableContent(nsIContent* aRootContent, diff --git a/dom/public/coreEvents/nsIDOMDragListener.h b/dom/public/coreEvents/nsIDOMDragListener.h index cc2479f4b49..66a383c684f 100644 --- a/dom/public/coreEvents/nsIDOMDragListener.h +++ b/dom/public/coreEvents/nsIDOMDragListener.h @@ -43,13 +43,17 @@ #include "nsIDOMEventListener.h" /* - * Mouse up/down/move event listener + * The listener for drag events. * + * The reason for two events for the same operation are for compatibility + * between the WHAT-WG drag and drop spec and existing XUL code. */ #define NS_IDOMDRAGLISTENER_IID \ -{ /* 6b8b25d0-ded5-11d1-bd85-00805f8ae3f4 */ \ -0x6b8b25d0, 0xded5, 0x11d1, \ -{0xbd, 0x85, 0x00, 0x80, 0x5f, 0x8a, 0xe3, 0xf4} } +{ /* 1A107271-1E26-419A-BCF1-0A4CF7A66B45 */ \ +0x1a107271, 0x1e26, 0x419a, \ +{0xbc, 0xf1, 0x0a, 0x4c, 0xf7, 0xa6, 0x6b, 0x45} } + + class nsIDOMDragListener : public nsIDOMEventListener { @@ -58,40 +62,81 @@ public: NS_DECLARE_STATIC_IID_ACCESSOR(NS_IDOMDRAGLISTENER_IID) /** - * Processes a drag enter event + * The dragenter event is fired when the mouse is moved from one node onto + * another. The target is the node that the mouse is moved onto and the + * related target is the node that the mouse left. + * * @param aMouseEvent @see nsIDOMEvent.h * @returns whether the event was consumed or ignored. @see nsresult */ NS_IMETHOD DragEnter(nsIDOMEvent* aMouseEvent) = 0; /** - * Processes a drag over event + * The dragover event is fired at regular intervals (several times per second) + * while a drag is occuring. The target of this event is the node that the + * mouse is over. + * * @param aMouseEvent @see nsIDOMEvent.h * @returns whether the event was consumed or ignored. @see nsresult */ NS_IMETHOD DragOver(nsIDOMEvent* aMouseEvent) = 0; /** - * Processes a drag Exit event + * The dragleave event is fired when the mouse leaves a node for another + * node. The dragexit event is fired immediately afterwards which will + * call this method. The target is the node that the mouse left and the + * related target is the node that the mouse is entering. A dragenter + * event will be fired on the node that the mouse is entering after both + * the dragleave and dragexit event are fired. + * * @param aMouseEvent @see nsIDOMEvent.h * @returns whether the event was consumed or ignored. @see nsresult */ NS_IMETHOD DragExit(nsIDOMEvent* aMouseEvent) = 0; /** - * Processes a drag drop event + * The drop event will be fired on the node that the mouse is over once + * the drag is complete. The dragdrop event will be fired immediately + * afterwards which will call this method. + * * @param aMouseEvent @see nsIDOMEvent.h * @returns whether the event was consumed or ignored. @see nsresult */ NS_IMETHOD DragDrop(nsIDOMEvent* aMouseEvent) = 0; /** - * Processes a drag gesture event + * When the user begins a drag by pressing the mouse button and moving the + * mouse slightly, a dragstart event will be fired. Afterwards a draggesture + * event will be fired which will call this method. + * * @param aMouseEvent @see nsIDOMEvent.h * @returns whether the event was consumed or ignored. @see nsresult */ NS_IMETHOD DragGesture(nsIDOMEvent* aMouseEvent) = 0; + /** + * The dragend event is fired when a drag is finished, whether the data was + * dropped successfully or whether the drag was cancelled. The target of + * this event is the source node of the drag. + * + * @param aMouseEvent @see nsIDOMEvent.h + * @returns whether the event was consumed or ignored. @see nsresult + */ + NS_IMETHOD DragEnd(nsIDOMEvent* aMouseEvent) = 0; + + /** + * The drag event is fired just before a dragover event is fired. The target + * of this event is the source node of the drag. + * + * @param aMouseEvent @see nsIDOMEvent.h + * @returns whether the event was consumed or ignored. @see nsresult + */ + NS_IMETHOD Drag(nsIDOMEvent* aMouseEvent) = 0; + + // these methods are for compatibility + NS_IMETHOD DragStart(nsIDOMEvent* aMouseEvent) { return NS_OK; } + NS_IMETHOD DragLeave(nsIDOMEvent* aMouseEvent) { return NS_OK; } + NS_IMETHOD Drop(nsIDOMEvent* aMouseEvent) { return NS_OK; } }; NS_DEFINE_STATIC_IID_ACCESSOR(nsIDOMDragListener, NS_IDOMDRAGLISTENER_IID) diff --git a/editor/libeditor/text/nsEditorEventListeners.cpp b/editor/libeditor/text/nsEditorEventListeners.cpp index c200c3e4490..d76f5802b53 100644 --- a/editor/libeditor/text/nsEditorEventListeners.cpp +++ b/editor/libeditor/text/nsEditorEventListeners.cpp @@ -672,6 +672,18 @@ nsTextEditorDragListener::DragDrop(nsIDOMEvent* aMouseEvent) return mEditor->InsertFromDrop(aMouseEvent); } +nsresult +nsTextEditorDragListener::Drag(nsIDOMEvent* aDragEvent) +{ + return NS_OK; +} + +nsresult +nsTextEditorDragListener::DragEnd(nsIDOMEvent* aDragEvent) +{ + return NS_OK; +} + PRBool nsTextEditorDragListener::CanDrop(nsIDOMEvent* aEvent) { diff --git a/editor/libeditor/text/nsEditorEventListeners.h b/editor/libeditor/text/nsEditorEventListeners.h index 225f618fe9c..9ef7eb9f0ba 100644 --- a/editor/libeditor/text/nsEditorEventListeners.h +++ b/editor/libeditor/text/nsEditorEventListeners.h @@ -223,6 +223,8 @@ public: NS_IMETHOD DragExit(nsIDOMEvent* aDragEvent); NS_IMETHOD DragDrop(nsIDOMEvent* aDragEvent); NS_IMETHOD DragGesture(nsIDOMEvent* aDragEvent); + NS_IMETHOD Drag(nsIDOMEvent* aDragEvent); + NS_IMETHOD DragEnd(nsIDOMEvent* aDragEvent); /*END implementations of dragevent handler interface*/ protected: diff --git a/layout/generic/nsObjectFrame.cpp b/layout/generic/nsObjectFrame.cpp index 535c0d57361..af1bc887080 100644 --- a/layout/generic/nsObjectFrame.cpp +++ b/layout/generic/nsObjectFrame.cpp @@ -326,6 +326,8 @@ public: NS_IMETHOD DragExit(nsIDOMEvent* aMouseEvent); NS_IMETHOD DragDrop(nsIDOMEvent* aMouseEvent); NS_IMETHOD DragGesture(nsIDOMEvent* aMouseEvent); + NS_IMETHOD Drag(nsIDOMEvent* aMouseEvent); + NS_IMETHOD DragEnd(nsIDOMEvent* aMouseEvent); nsresult Destroy(); @@ -2766,6 +2768,28 @@ nsresult nsPluginInstanceOwner::DragGesture(nsIDOMEvent* aMouseEvent) return NS_OK; } +nsresult nsPluginInstanceOwner::Drag(nsIDOMEvent* aMouseEvent) +{ + if (mInstance) { + // Let the plugin handle drag events. + aMouseEvent->PreventDefault(); + aMouseEvent->StopPropagation(); + } + + return NS_OK; +} + +nsresult nsPluginInstanceOwner::DragEnd(nsIDOMEvent* aMouseEvent) +{ + if (mInstance) { + // Let the plugin handle drag events. + aMouseEvent->PreventDefault(); + aMouseEvent->StopPropagation(); + } + + return NS_OK; +} + /*=============== nsIKeyListener ======================*/ diff --git a/widget/public/nsGUIEvent.h b/widget/public/nsGUIEvent.h index 2f74fa9e035..b7a3dd8f3fb 100644 --- a/widget/public/nsGUIEvent.h +++ b/widget/public/nsGUIEvent.h @@ -245,10 +245,15 @@ class nsHashKey; #define NS_DRAGDROP_ENTER (NS_DRAGDROP_EVENT_START) #define NS_DRAGDROP_OVER (NS_DRAGDROP_EVENT_START + 1) #define NS_DRAGDROP_EXIT (NS_DRAGDROP_EVENT_START + 2) -#define NS_DRAGDROP_DROP (NS_DRAGDROP_EVENT_START + 3) +#define NS_DRAGDROP_DRAGDROP (NS_DRAGDROP_EVENT_START + 3) #define NS_DRAGDROP_GESTURE (NS_DRAGDROP_EVENT_START + 4) +#define NS_DRAGDROP_DRAG (NS_DRAGDROP_EVENT_START + 5) +#define NS_DRAGDROP_END (NS_DRAGDROP_EVENT_START + 6) +#define NS_DRAGDROP_START (NS_DRAGDROP_EVENT_START + 7) +#define NS_DRAGDROP_DROP (NS_DRAGDROP_EVENT_START + 8) #define NS_DRAGDROP_OVER_SYNTH (NS_DRAGDROP_EVENT_START + 1) #define NS_DRAGDROP_EXIT_SYNTH (NS_DRAGDROP_EVENT_START + 2) +#define NS_DRAGDROP_LEAVE_SYNTH (NS_DRAGDROP_EVENT_START + 9) // Events for popups #define NS_XUL_EVENT_START 1500 diff --git a/widget/public/nsIDragService.idl b/widget/public/nsIDragService.idl index 99fb57e9472..52aaa940359 100644 --- a/widget/public/nsIDragService.idl +++ b/widget/public/nsIDragService.idl @@ -47,7 +47,7 @@ interface nsIDOMNode; interface nsIDOMMouseEvent; interface nsISelection; -[scriptable, uuid(D2875740-95D3-4F12-8E97-9FAB76C87093)] +[scriptable, uuid(E8CD74A6-8BB6-4D27-9C65-4ED1B4398F8C)] interface nsIDragService : nsISupports { const long DRAGDROP_ACTION_NONE = 0; @@ -124,9 +124,16 @@ interface nsIDragService : nsISupports /** * Tells the Drag Service to end a drag session. This is called when * an external drag occurs + * + * If aDoneDrag is true, the drag has finished, otherwise the drag has + * just left the window. */ - void endDragSession ( ) ; - + void endDragSession ( in PRBool aDoneDrag ) ; + + /** + * Fire a drag event at the source of the drag + */ + void fireDragEventAtSource ( in unsigned long aMsg ); }; diff --git a/widget/src/beos/nsDragService.cpp b/widget/src/beos/nsDragService.cpp index 52f2b70417c..bbb343bf4c1 100644 --- a/widget/src/beos/nsDragService.cpp +++ b/widget/src/beos/nsDragService.cpp @@ -338,7 +338,7 @@ nsDragService::StartDragSession() // //------------------------------------------------------------------------- NS_IMETHODIMP -nsDragService::EndDragSession() +nsDragService::EndDragSession(PRBool aDoneDrag) { PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::EndDragSession()")); //Don't reset drag info, keep it until there is a new drag, in case a negotiated drag'n'drop wants the info. @@ -347,7 +347,7 @@ nsDragService::EndDragSession() //That way the dragsession is always ended when we go outside mozilla windows, but we do throw away the // mSourceDocument and mSourceNode. We do hold on to the nsTransferable if it was a internal drag. //ResetDragInfo(); - return nsBaseDragService::EndDragSession(); + return nsBaseDragService::EndDragSession(aDoneDrag); } //------------------------------------------------------------------------- diff --git a/widget/src/beos/nsDragService.h b/widget/src/beos/nsDragService.h index 946d943b66e..3b0c2b497ff 100644 --- a/widget/src/beos/nsDragService.h +++ b/widget/src/beos/nsDragService.h @@ -64,7 +64,7 @@ public: nsIScriptableRegion * aRegion, PRUint32 aActionType); NS_IMETHOD StartDragSession(); - NS_IMETHOD EndDragSession(); + NS_IMETHOD EndDragSession(PRBool aDoneDrag); // nsIDragSession NS_IMETHOD GetNumDropItems (PRUint32 * aNumItems); diff --git a/widget/src/beos/nsWindow.cpp b/widget/src/beos/nsWindow.cpp index 9dff21b9d34..4fdc30e8de5 100644 --- a/widget/src/beos/nsWindow.cpp +++ b/widget/src/beos/nsWindow.cpp @@ -2006,7 +2006,7 @@ bool nsWindow::CallMethod(MethodInfo *info) NS_RELEASE(event.widget); if (dragService) - dragService->EndDragSession(); + dragService->EndDragSession(PR_TRUE); } break; @@ -3106,11 +3106,16 @@ void nsViewBeOS::MouseMoved(BPoint point, uint32 transit, const BMessage *msg) if (msg == NULL) break; nsCOMPtr dragService = do_GetService(kCDragServiceCID); - dragService->EndDragSession(); + dragService->EndDragSession(PR_FALSE); } break; default: args[0]= msg == NULL ? NS_MOUSE_MOVE : NS_DRAGDROP_OVER; + // fire the drag event at the source + if (msg != NULL) { + nsCOMPtr dragService = do_GetService(kCDragServiceCID); + dragService->FireDragEventAtSource(NS_DRAGDROP_DRAG); + } } MethodInfo *moveInfo = nsnull; diff --git a/widget/src/cocoa/nsChildView.mm b/widget/src/cocoa/nsChildView.mm index 4cd2bf7b2ea..3ff483482f4 100644 --- a/widget/src/cocoa/nsChildView.mm +++ b/widget/src/cocoa/nsChildView.mm @@ -3689,8 +3689,12 @@ static PRBool IsSpecialGeckoKey(UInt32 macKeyCode) nsCOMPtr dragSession; mDragService->GetCurrentSession(getter_AddRefs(dragSession)); if (dragSession) { - if (aMessage == NS_DRAGDROP_OVER) + if (aMessage == NS_DRAGDROP_OVER) { + // fire the drag event at the source. Just ignore whether it was + // cancelled or not as there isn't actually a means to stop the drag + mDragService->FireDragEventAtSource(NS_DRAGDROP_DRAG); dragSession->SetCanDrop(PR_FALSE); + } else if (aMessage == NS_DRAGDROP_DROP) { // We make the assuption that the dragOver handlers have correctly set // the |canDrop| property of the Drag Session. @@ -3728,7 +3732,7 @@ static PRBool IsSpecialGeckoKey(UInt32 macKeyCode) // initiated in a different app. End the drag session, // since we're done with it for now (until the user // drags back into mozilla). - mDragService->EndDragSession(); + mDragService->EndDragSession(PR_FALSE); } } diff --git a/widget/src/cocoa/nsDragService.mm b/widget/src/cocoa/nsDragService.mm index bffed205731..d7e3c7e0303 100644 --- a/widget/src/cocoa/nsDragService.mm +++ b/widget/src/cocoa/nsDragService.mm @@ -364,7 +364,7 @@ nsDragService::InvokeDragSession(nsIDOMNode* aDOMNode, nsISupportsArray* aTransf pasteboard:[NSPasteboard pasteboardWithName:NSDragPboard] source:globalDragView slideBack:YES]; - nsBaseDragService::EndDragSession(); + nsBaseDragService::EndDragSession(PR_TRUE); return NS_OK; } diff --git a/widget/src/gtk/nsDragService.cpp b/widget/src/gtk/nsDragService.cpp index 78f10eecca4..e0f7bf6be9b 100644 --- a/widget/src/gtk/nsDragService.cpp +++ b/widget/src/gtk/nsDragService.cpp @@ -230,12 +230,12 @@ nsDragService::StartDragSession() } NS_IMETHODIMP -nsDragService::EndDragSession() +nsDragService::EndDragSession(PRBool aDoneDrag) { PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::EndDragSession")); // unset our drag action SetDragAction(DRAGDROP_ACTION_NONE); - return nsBaseDragService::EndDragSession(); + return nsBaseDragService::EndDragSession(aDoneDrag); } // nsIDragSession @@ -974,7 +974,7 @@ nsDragService::SourceEndDrag(void) mSourceDataItems = 0; // Inform the drag session that we're ending the drag. - EndDragSession(); + EndDragSession(PR_TRUE); } static void diff --git a/widget/src/gtk/nsDragService.h b/widget/src/gtk/nsDragService.h index fc4e2eed0f0..82fa11abc34 100644 --- a/widget/src/gtk/nsDragService.h +++ b/widget/src/gtk/nsDragService.h @@ -69,7 +69,7 @@ public: nsIScriptableRegion * aRegion, PRUint32 aActionType); NS_IMETHOD StartDragSession(); - NS_IMETHOD EndDragSession(); + NS_IMETHOD EndDragSession(PRBool aDragDone); // nsIDragSession NS_IMETHOD SetCanDrop (PRBool aCanDrop); diff --git a/widget/src/gtk/nsWindow.cpp b/widget/src/gtk/nsWindow.cpp index 6b664051585..5cd8ca2a968 100644 --- a/widget/src/gtk/nsWindow.cpp +++ b/widget/src/gtk/nsWindow.cpp @@ -3430,7 +3430,7 @@ nsWindow::OnDragDropSignal (GtkWidget *aWidget, // Make sure to end the drag session. If this drag started in a // different app, we won't get a drag_end signal to end it from. - dragService->EndDragSession(); + dragService->EndDragSession(PR_TRUE); return TRUE; } @@ -3501,7 +3501,7 @@ nsWindow::OnDragLeave(void) // initiated in a different app. End the drag session, since // we're done with it for now (until the user drags back into // mozilla). - dragService->EndDragSession(); + dragService->EndDragSession(PR_FALSE); } } } diff --git a/widget/src/gtk2/nsDragService.cpp b/widget/src/gtk2/nsDragService.cpp index 47c5dabe6f5..abb38397172 100644 --- a/widget/src/gtk2/nsDragService.cpp +++ b/widget/src/gtk2/nsDragService.cpp @@ -240,12 +240,12 @@ nsDragService::StartDragSession() } NS_IMETHODIMP -nsDragService::EndDragSession() +nsDragService::EndDragSession(PRBool aDoneDrag) { PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::EndDragSession")); // unset our drag action SetDragAction(DRAGDROP_ACTION_NONE); - return nsBaseDragService::EndDragSession(); + return nsBaseDragService::EndDragSession(aDoneDrag); } // nsIDragSession @@ -1038,7 +1038,7 @@ nsDragService::SourceEndDrag(void) mSourceDataItems = 0; // Inform the drag session that we're ending the drag. - EndDragSession(); + EndDragSession(PR_TRUE); } static void diff --git a/widget/src/gtk2/nsDragService.h b/widget/src/gtk2/nsDragService.h index c1d7bf3b320..efbcde7fded 100644 --- a/widget/src/gtk2/nsDragService.h +++ b/widget/src/gtk2/nsDragService.h @@ -69,7 +69,7 @@ public: nsIScriptableRegion * aRegion, PRUint32 aActionType); NS_IMETHOD StartDragSession(); - NS_IMETHOD EndDragSession(); + NS_IMETHOD EndDragSession(PRBool aDoneDrag); // nsIDragSession NS_IMETHOD SetCanDrop (PRBool aCanDrop); diff --git a/widget/src/gtk2/nsWindow.cpp b/widget/src/gtk2/nsWindow.cpp index b39085a0638..1d035011ba1 100644 --- a/widget/src/gtk2/nsWindow.cpp +++ b/widget/src/gtk2/nsWindow.cpp @@ -2474,6 +2474,8 @@ nsWindow::OnDragMotionEvent(GtkWidget *aWidget, // notify the drag service that we are starting a drag motion. dragSessionGTK->TargetStartDragMotion(); + dragService->FireDragEventAtSource(NS_DRAGDROP_DRAG); + nsMouseEvent event(PR_TRUE, NS_DRAGDROP_OVER, innerMostWidget, nsMouseEvent::eReal); @@ -2632,7 +2634,7 @@ nsWindow::OnDragDropEvent(GtkWidget *aWidget, // Make sure to end the drag session. If this drag started in a // different app, we won't get a drag_end signal to end it from. - dragService->EndDragSession(); + dragService->EndDragSession(PR_TRUE); return TRUE; } @@ -2684,7 +2686,7 @@ nsWindow::OnDragLeave(void) // initiated in a different app. End the drag session, // since we're done with it for now (until the user // drags back into mozilla). - dragService->EndDragSession(); + dragService->EndDragSession(PR_FALSE); } } } diff --git a/widget/src/mac/nsDragHelperService.cpp b/widget/src/mac/nsDragHelperService.cpp index 25d4a208e48..d94be9f175d 100644 --- a/widget/src/mac/nsDragHelperService.cpp +++ b/widget/src/mac/nsDragHelperService.cpp @@ -190,7 +190,7 @@ nsDragHelperService::Leave(DragReference inDragRef, nsIEventSink *inSink) // initiated in a differnt app. End the drag session, // since we're done with it for now (until the user // drags back into mozilla). - mDragService->EndDragSession(); + mDragService->EndDragSession(PR_FALSE); } } diff --git a/widget/src/mac/nsDragService.cpp b/widget/src/mac/nsDragService.cpp index a67ef14ec3a..6699e6c606d 100644 --- a/widget/src/mac/nsDragService.cpp +++ b/widget/src/mac/nsDragService.cpp @@ -318,7 +318,7 @@ nsDragService::InvokeDragSession (nsIDOMNode *aDOMNode, nsISupportsArray * aTran // reset by the dragTrackingHandler). StartDragSession(); ::TrackDrag ( theDragRef, &theEvent, theDragRgn ); - EndDragSession(); + EndDragSession(PR_TRUE); // clean up after ourselves ::DisposeRgn ( theDragRgn ); diff --git a/widget/src/os2/nsDragService.cpp b/widget/src/os2/nsDragService.cpp index cbba566bb8e..17f7b877aee 100644 --- a/widget/src/os2/nsDragService.cpp +++ b/widget/src/os2/nsDragService.cpp @@ -237,6 +237,7 @@ NS_IMETHODIMP nsDragService::InvokeDragSession(nsIDOMNode *aDOMNode, mDoingDrag = PR_TRUE; HWND hwndDest = DrgDrag(mDragWnd, pDragInfo, &dragimage, 1, VK_BUTTON2, (void*)0x80000000L); // Don't lock the desktop PS + FireDragEventAtSource(NS_DRAGDROP_END); mDoingDrag = PR_FALSE; // do clean up; if the drop completed, @@ -352,7 +353,7 @@ NS_IMETHODIMP nsDragService::StartDragSession() return NS_OK; } -NS_IMETHODIMP nsDragService::EndDragSession() +NS_IMETHODIMP nsDragService::EndDragSession(PRBool aDragDone) { NS_ASSERTION(0, "OS/2 version of EndDragSession() should never be called!"); return NS_OK; diff --git a/widget/src/os2/nsDragService.h b/widget/src/os2/nsDragService.h index a9033523e11..d2159bea1eb 100644 --- a/widget/src/os2/nsDragService.h +++ b/widget/src/os2/nsDragService.h @@ -63,7 +63,7 @@ public: nsIScriptableRegion* aRegion, PRUint32 aActionType); NS_IMETHOD StartDragSession(); - NS_IMETHOD EndDragSession(); + NS_IMETHOD EndDragSession(PRBool aDoneDrag); // nsIDragSession NS_IMETHOD GetNumDropItems(PRUint32* aNumDropItems); diff --git a/widget/src/os2/nsWindow.cpp b/widget/src/os2/nsWindow.cpp index e229c4ed506..7ed96baf86d 100644 --- a/widget/src/os2/nsWindow.cpp +++ b/widget/src/os2/nsWindow.cpp @@ -3922,6 +3922,8 @@ PRBool nsWindow::OnDragDropMsg(ULONG msg, MPARAM mp1, MPARAM mp2, MRESULT &mr) switch (msg) { case DM_DRAGOVER: + dragService->FireDragEventAtSource(NS_DRAGDROP_DRAG); + rv = dragSession->DragOverMsg((PDRAGINFO)mp1, mr, &dragFlags); eventType = NS_DRAGDROP_OVER; break; diff --git a/widget/src/photon/nsWidget.cpp b/widget/src/photon/nsWidget.cpp index 000582f91a5..267c5abd073 100644 --- a/widget/src/photon/nsWidget.cpp +++ b/widget/src/photon/nsWidget.cpp @@ -1313,6 +1313,7 @@ int nsWidget::DndCallback( PtWidget_t *widget, void *data, PtCallbackInfo_t *cbi break; case Ph_EV_DND_MOTION: { + sDragService->FireDragEventAtSource(NS_DRAGDROP_DRAG); pWidget->ProcessDrag( cbinfo->event, NS_DRAGDROP_OVER, &ptrev->pos ); } break; @@ -1321,18 +1322,18 @@ int nsWidget::DndCallback( PtWidget_t *widget, void *data, PtCallbackInfo_t *cbi d = ( nsDragService * )sDragService; if( d->SetDropData( (char*)cbdnd->data ) != NS_OK ) break; pWidget->ProcessDrag( cbinfo->event, NS_DRAGDROP_DROP, &ptrev->pos ); - sDragService->EndDragSession(); + sDragService->EndDragSession(PR_TRUE); ((nsDragService*) sDragService)->SourceEndDrag(); break; case Ph_EV_DND_LEAVE: pWidget->ProcessDrag( cbinfo->event, NS_DRAGDROP_EXIT, &ptrev->pos ); - sDragService->EndDragSession(); + sDragService->EndDragSession(PR_FALSE); break; case Ph_EV_DND_CANCEL: pWidget->ProcessDrag( cbinfo->event, NS_DRAGDROP_EXIT, &ptrev->pos ); - sDragService->EndDragSession(); + sDragService->EndDragSession(PR_TRUE); ((nsDragService*) sDragService)->SourceEndDrag(); break; } diff --git a/widget/src/qt/nsDragService.cpp b/widget/src/qt/nsDragService.cpp index e6b9ee4cbe6..c65fefbf1b6 100644 --- a/widget/src/qt/nsDragService.cpp +++ b/widget/src/qt/nsDragService.cpp @@ -190,13 +190,13 @@ NS_IMETHODIMP nsDragService::StartDragSession() return nsBaseDragService::StartDragSession(); } -NS_IMETHODIMP nsDragService::EndDragSession() +NS_IMETHODIMP nsDragService::EndDragSession(PRBool aDragDone) { #ifdef NS_DEBUG printf(" DnD: EndDragSession\n"); #endif mDragObject = 0; - return nsBaseDragService::EndDragSession(); + return nsBaseDragService::EndDragSession(aDragDone); } // nsIDragSession diff --git a/widget/src/qt/nsDragService.h b/widget/src/qt/nsDragService.h index 632af76a71a..b2f4ca3c56d 100644 --- a/widget/src/qt/nsDragService.h +++ b/widget/src/qt/nsDragService.h @@ -62,7 +62,7 @@ public: nsIScriptableRegion *aRegion, PRUint32 aActionType); NS_IMETHOD StartDragSession(); - NS_IMETHOD EndDragSession(); + NS_IMETHOD EndDragSession(PRBool aDragDone); // nsIDragSession NS_IMETHOD SetCanDrop(PRBool aCanDrop); diff --git a/widget/src/windows/nsDragService.cpp b/widget/src/windows/nsDragService.cpp index 427d409b72c..f5efacdc07b 100644 --- a/widget/src/windows/nsDragService.cpp +++ b/widget/src/windows/nsDragService.cpp @@ -226,7 +226,7 @@ nsDragService::StartInvokingDragSession(IDataObject * aDataObj, } // We're done dragging - EndDragSession(); + EndDragSession(PR_TRUE); // For some drag/drop interactions, IDataObject::SetData doesn't get // called with a CFSTR_PERFORMEDDROPEFFECT format and the @@ -482,9 +482,9 @@ nsDragService::IsCollectionObject(IDataObject* inDataObj) // w/out crashing when we're still holding onto their data // NS_IMETHODIMP -nsDragService::EndDragSession() +nsDragService::EndDragSession(PRBool aDoneDrag) { - nsBaseDragService::EndDragSession(); + nsBaseDragService::EndDragSession(aDoneDrag); NS_IF_RELEASE(mDataObject); return NS_OK; diff --git a/widget/src/windows/nsDragService.h b/widget/src/windows/nsDragService.h index 3458d758bac..535b5e679f5 100644 --- a/widget/src/windows/nsDragService.h +++ b/widget/src/windows/nsDragService.h @@ -68,7 +68,7 @@ public: NS_IMETHOD GetData(nsITransferable * aTransferable, PRUint32 anItem); NS_IMETHOD GetNumDropItems(PRUint32 * aNumItems); NS_IMETHOD IsDataFlavorSupported(const char *aDataFlavor, PRBool *_retval); - NS_IMETHOD EndDragSession(); + NS_IMETHOD EndDragSession(PRBool aDoneDrag); // native impl. NS_IMETHOD SetIDataObject(IDataObject * aDataObj); diff --git a/widget/src/windows/nsNativeDragTarget.cpp b/widget/src/windows/nsNativeDragTarget.cpp index 3a6f15d282f..4cf85245028 100644 --- a/widget/src/windows/nsNativeDragTarget.cpp +++ b/widget/src/windows/nsNativeDragTarget.cpp @@ -294,6 +294,8 @@ nsNativeDragTarget::DragOver(DWORD grfKeyState, return ResultFromScode(E_FAIL); } + mDragService->FireDragEventAtSource(NS_DRAGDROP_DRAG); + // Now process the native drag state and then dispatch the event ProcessDrag(nsnull, NS_DRAGDROP_OVER, grfKeyState, pt, pdwEffect); return S_OK; @@ -325,7 +327,7 @@ nsNativeDragTarget::DragLeave() // initiated in a different app. End the drag session, since // we're done with it for now (until the user drags back into // mozilla). - mDragService->EndDragSession(); + mDragService->EndDragSession(PR_FALSE); } } @@ -360,6 +362,6 @@ nsNativeDragTarget::Drop(LPDATAOBJECT pData, ProcessDrag(pData, NS_DRAGDROP_DROP, grfKeyState, aPT, pdwEffect); // tell the drag service we're done with the session - serv->EndDragSession(); + serv->EndDragSession(PR_TRUE); return S_OK; } diff --git a/widget/src/xlib/nsAppShell.cpp b/widget/src/xlib/nsAppShell.cpp index d974274a9e1..44136027d91 100644 --- a/widget/src/xlib/nsAppShell.cpp +++ b/widget/src/xlib/nsAppShell.cpp @@ -1148,6 +1148,8 @@ void nsAppShell::HandleDragMotionEvent(XEvent *event, nsWidget *aWidget) { if (currentlyDragging) { dragServiceXlib->UpdatePosition(event->xmotion.x, event->xmotion.y); + dragService->FireDragEventAtSource(NS_DRAGDROP_DRAG); + nsMouseEvent mevent(PR_TRUE, NS_DRAGDROP_OVER, aWidget, nsMouseEvent::eReal); mevent.refPoint.x = event->xmotion.x; diff --git a/widget/src/xlib/nsDragService.cpp b/widget/src/xlib/nsDragService.cpp index 05787679510..13dbea09876 100644 --- a/widget/src/xlib/nsDragService.cpp +++ b/widget/src/xlib/nsDragService.cpp @@ -139,7 +139,7 @@ NS_IMETHODIMP nsDragService::StartDragSession() return nsBaseDragService::StartDragSession(); } -NS_IMETHODIMP nsDragService::EndDragSession() +NS_IMETHODIMP nsDragService::EndDragSession(PRBool aDoneDrag) { if (sWindow) { XDestroyWindow(sDisplay, sWindow); @@ -147,7 +147,7 @@ NS_IMETHODIMP nsDragService::EndDragSession() } mDragging = PR_FALSE; - return nsBaseDragService::EndDragSession(); + return nsBaseDragService::EndDragSession(aDoneDrag); } // nsIDragSession @@ -231,7 +231,7 @@ NS_IMETHODIMP nsDragService::GetData(nsITransferable *aTransferable, PRUint32 an } } - EndDragSession(); + EndDragSession(PR_TRUE); return NS_OK; } diff --git a/widget/src/xlib/nsDragService.h b/widget/src/xlib/nsDragService.h index 2f9d17cec6e..f809255f2d7 100644 --- a/widget/src/xlib/nsDragService.h +++ b/widget/src/xlib/nsDragService.h @@ -68,7 +68,7 @@ public: nsIScriptableRegion * aRegion, PRUint32 aActionType); NS_IMETHOD StartDragSession(); - NS_IMETHOD EndDragSession(); + NS_IMETHOD EndDragSession(PRBool aDoneDrag); // nsIDragSession NS_IMETHOD GetCurrentSession (nsIDragSession **aSession); diff --git a/widget/src/xpwidgets/nsBaseDragService.cpp b/widget/src/xpwidgets/nsBaseDragService.cpp index 1b93f109c2f..e8f1cc658a0 100644 --- a/widget/src/xpwidgets/nsBaseDragService.cpp +++ b/widget/src/xpwidgets/nsBaseDragService.cpp @@ -68,6 +68,7 @@ #include "imgIRequest.h" #include "nsIViewObserver.h" #include "nsRegion.h" +#include "nsGUIEvent.h" #ifdef MOZ_CAIRO_GFX #include "gfxContext.h" @@ -324,12 +325,15 @@ nsBaseDragService::StartDragSession() //------------------------------------------------------------------------- NS_IMETHODIMP -nsBaseDragService::EndDragSession() +nsBaseDragService::EndDragSession(PRBool aDoneDrag) { if (!mDoingDrag) { return NS_ERROR_FAILURE; } + if (aDoneDrag) + FireDragEventAtSource(NS_DRAGDROP_END); + mDoingDrag = PR_FALSE; // release the source we've been holding on to. @@ -346,6 +350,26 @@ nsBaseDragService::EndDragSession() return NS_OK; } +NS_IMETHODIMP +nsBaseDragService::FireDragEventAtSource(PRUint32 aMsg) +{ + if (mSourceNode) { + nsCOMPtr doc = do_QueryInterface(mSourceDocument); + if (doc) { + nsCOMPtr presShell = doc->GetShellAt(0); + if (presShell) { + nsEventStatus status = nsEventStatus_eIgnore; + nsMouseEvent event(PR_TRUE, aMsg, nsnull, nsMouseEvent::eReal); + + nsCOMPtr content = do_QueryInterface(mSourceNode); + return presShell->HandleDOMEventWithTarget(content, &event, &status); + } + } + } + + return NS_OK; +} + #ifdef MOZ_CAIRO_GFX static nsIPresShell*