Bug 483776 - Update original data transfer mozCursor state during drags. r=bz.
authorJim Mathies <jmathies@mozilla.com>
Tue, 06 Oct 2009 21:51:02 -0500
changeset 33528 5bbfae9a5c7e2447de7e3e326cc57cee99b5b268
parent 33527 1db61f2dfded462394b61ac40ca660154a650c4e
child 33529 7c9e123dbb32b3a03ea5d607198ae1c428f26646
push idunknown
push userunknown
push dateunknown
reviewersbz
bugs483776
milestone1.9.3a1pre
Bug 483776 - Update original data transfer mozCursor state during drags. r=bz.
content/events/src/nsEventStateManager.cpp
content/events/src/nsEventStateManager.h
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -3046,29 +3046,34 @@ nsEventStateManager::PostHandleEvent(nsP
       // was set on the dragSession when the drag began.
       nsCOMPtr<nsIDOMNSDataTransfer> dataTransfer;
       nsCOMPtr<nsIDOMDataTransfer> initialDataTransfer;
       dragSession->GetDataTransfer(getter_AddRefs(initialDataTransfer));
 
       nsCOMPtr<nsIDOMNSDataTransfer> initialDataTransferNS = 
         do_QueryInterface(initialDataTransfer);
 
+      nsDragEvent *dragEvent = (nsDragEvent*)aEvent;
+
+      // collect any changes to moz cursor settings stored in the event's
+      // data transfer.
+      UpdateDragDataTransfer(dragEvent);
+
       // cancelling a dragenter or dragover event means that a drop should be
       // allowed, so update the dropEffect and the canDrop state to indicate
       // that a drag is allowed. If the event isn't cancelled, a drop won't be
       // allowed. Essentially, to allow a drop somewhere, specify the effects
       // using the effectAllowed and dropEffect properties in a dragenter or
       // dragover event and cancel the event. To not allow a drop somewhere,
       // don't cancel the event or set the effectAllowed or dropEffect to
       // "none". This way, if the event is just ignored, no drop will be
       // allowed.
       PRUint32 dropEffect = nsIDragService::DRAGDROP_ACTION_NONE;
       if (nsEventStatus_eConsumeNoDefault == *aStatus) {
         // if the event has a dataTransfer set, use it.
-        nsDragEvent *dragEvent = (nsDragEvent*)aEvent;
         if (dragEvent->dataTransfer) {
           // get the dataTransfer and the dropEffect that was set on it
           dataTransfer = do_QueryInterface(dragEvent->dataTransfer);
           dataTransfer->GetDropEffectInt(&dropEffect);
         }
         else {
           // if dragEvent->dataTransfer is null, it means that no attempt was
           // made to access the dataTransfer during the event, yet the event
@@ -3847,23 +3852,59 @@ nsEventStateManager::FireDragEnterOrExit
     if (aTargetContent)
       nsEventDispatcher::Dispatch(aTargetContent, aPresContext, &event,
                                   nsnull, &status);
 
     // adjust the drag hover if the dragenter event was cancelled or this is a drag exit
     if (status == nsEventStatus_eConsumeNoDefault || aMsg == NS_DRAGDROP_EXIT)
       SetContentState((aMsg == NS_DRAGDROP_ENTER) ? aTargetContent : nsnull,
                       NS_EVENT_STATE_DRAGOVER);
+
+    // collect any changes to moz cursor settings stored in the event's
+    // data transfer.
+    if (aMsg == NS_DRAGDROP_LEAVE_SYNTH || aMsg == NS_DRAGDROP_EXIT_SYNTH ||
+        aMsg == NS_DRAGDROP_ENTER)
+      UpdateDragDataTransfer(&event);
   }
 
   // Finally dispatch the event to the frame
   if (aTargetFrame)
     aTargetFrame->HandleEvent(aPresContext, &event, &status);
 }
 
+void
+nsEventStateManager::UpdateDragDataTransfer(nsDragEvent* dragEvent)
+{
+  NS_ASSERTION(dragEvent, "drag event is null in UpdateDragDataTransfer!");
+  if (!dragEvent->dataTransfer)
+    return;
+
+  nsCOMPtr<nsIDragSession> dragSession = nsContentUtils::GetDragSession();
+
+  if (dragSession) {
+    // the initial dataTransfer is the one from the dragstart event that
+    // was set on the dragSession when the drag began.
+    nsCOMPtr<nsIDOMDataTransfer> initialDataTransfer;
+    dragSession->GetDataTransfer(getter_AddRefs(initialDataTransfer));
+
+    // grab the interface that has GetMozCursor.
+    nsCOMPtr<nsIDOMNSDataTransfer> initialDataTransferNS = 
+      do_QueryInterface(initialDataTransfer);
+    nsCOMPtr<nsIDOMNSDataTransfer> eventTransferNS = 
+      do_QueryInterface(dragEvent->dataTransfer);
+
+    if (initialDataTransferNS && eventTransferNS) {
+      // retrieve the current moz cursor setting and save it.
+      nsAutoString mozCursor;
+      eventTransferNS->GetMozCursor(mozCursor);
+      initialDataTransferNS->SetMozCursor(mozCursor);
+    }
+  }
+}
+
 nsresult
 nsEventStateManager::SetClickCount(nsPresContext* aPresContext,
                                    nsMouseEvent *aEvent,
                                    nsEventStatus* aStatus)
 {
   nsCOMPtr<nsIContent> mouseContent;
   mCurrentTarget->GetContentForEvent(aPresContext, aEvent, getter_AddRefs(mouseContent));
 
--- a/content/events/src/nsEventStateManager.h
+++ b/content/events/src/nsEventStateManager.h
@@ -194,16 +194,22 @@ protected:
    * @param aTargetFrame target frame for the event
    */
   void FireDragEnterOrExit(nsPresContext* aPresContext,
                            nsGUIEvent* aEvent,
                            PRUint32 aMsg,
                            nsIContent* aRelatedTarget,
                            nsIContent* aTargetContent,
                            nsWeakFrame& aTargetFrame);
+  /**
+   * Update the initial drag session data transfer with any changes that occur
+   * on cloned data transfer objects used for events.
+   */
+  void UpdateDragDataTransfer(nsDragEvent* dragEvent);
+
   nsresult SetClickCount(nsPresContext* aPresContext, nsMouseEvent *aEvent, nsEventStatus* aStatus);
   nsresult CheckForAndDispatchClick(nsPresContext* aPresContext, nsMouseEvent *aEvent, nsEventStatus* aStatus);
   void EnsureDocument(nsPresContext* aPresContext);
   void FlushPendingEvents(nsPresContext* aPresContext);
 
   /**
    * The phases of HandleAccessKey processing. See below.
    */