Bug 463088 - Tab tear off cursor needs to be constant on Windows. r=enndeakin.
authorJim Mathies <jmathies@mozilla.com>
Fri, 06 Mar 2009 11:54:29 -0600
changeset 25809 37207402f983
parent 25808 f939168ee9f4
child 25810 d3f6a9661766
push id5754
push userjmathies@mozilla.com
push dateFri, 06 Mar 2009 17:55:01 +0000
treeherdermozilla-central@37207402f983 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersenndeakin
bugs463088
milestone1.9.2a1pre
Bug 463088 - Tab tear off cursor needs to be constant on Windows. r=enndeakin.
browser/base/content/tabbrowser.xml
content/events/src/nsDOMDataTransfer.cpp
content/events/src/nsDOMDataTransfer.h
dom/interfaces/events/nsIDOMDataTransfer.idl
widget/src/windows/nsDragService.cpp
widget/src/windows/nsNativeDragSource.cpp
widget/src/windows/nsNativeDragSource.h
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -1919,16 +1919,19 @@
             dt.mozSetDataAt(TAB_DROP_TYPE, target, 0);
             var uri = this.getBrowserForTab(aEvent.target).currentURI;
             var spec = uri ? uri.spec : "about:blank";
 
             // We must not set text/x-moz-url data, otherwise trying to deatch
             // the tab by dropping it on the desktop would result in an
             // "internet shortcut"
             dt.mozSetDataAt("text/plain", spec, 0);
+            
+            // Set the cursor to an arrow during tab drags.
+            dt.mozCursor = "default";
 
             var canvas = tabPreviews.capture(target, false);
             dt.setDragImage(canvas, 0, 0);
             aEvent.stopPropagation();
           }
 
           this._dragLeftWindow = false;
         ]]>
--- a/content/events/src/nsDOMDataTransfer.cpp
+++ b/content/events/src/nsDOMDataTransfer.cpp
@@ -71,17 +71,18 @@ const char nsDOMDataTransfer::sEffects[8
 nsDOMDataTransfer::nsDOMDataTransfer()
   : mEventType(NS_DRAGDROP_START),
     mDropEffect(nsIDragService::DRAGDROP_ACTION_NONE),
     mEffectAllowed(nsIDragService::DRAGDROP_ACTION_UNINITIALIZED),
     mReadOnly(PR_FALSE),
     mIsExternal(PR_FALSE),
     mUserCancelled(PR_FALSE),
     mDragImageX(0),
-    mDragImageY(0)
+    mDragImageY(0),
+    mCursorState(PR_FALSE)
 {
 }
 
 nsDOMDataTransfer::nsDOMDataTransfer(PRUint32 aEventType, PRUint32 aAction)
   : mEventType(aEventType),
     mDropEffect(nsIDragService::DRAGDROP_ACTION_NONE),
     mReadOnly(PR_TRUE),
     mIsExternal(PR_TRUE),
@@ -293,16 +294,35 @@ nsDOMDataTransfer::ClearData(const nsASt
 NS_IMETHODIMP
 nsDOMDataTransfer::GetMozItemCount(PRUint32* aCount)
 {
   *aCount = mItems.Length();
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsDOMDataTransfer::GetMozCursor(nsAString& aCursorState)
+{
+  if (mCursorState)
+    aCursorState.AssignASCII("default");
+  else
+    aCursorState.AssignASCII("auto");
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::SetMozCursor(const nsAString& aCursorState)
+{
+  // Lock the cursor to an arrow during the drag.
+  mCursorState = aCursorState.EqualsASCII("default");
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsDOMDataTransfer::MozTypesAt(PRUint32 aIndex, nsIDOMDOMStringList** aTypes)
 {
   *aTypes = nsnull;
 
   nsRefPtr<nsDOMStringList> types = new nsDOMStringList();
   NS_ENSURE_TRUE(types, NS_ERROR_OUT_OF_MEMORY);
 
   if (aIndex < mItems.Length()) {
--- a/content/events/src/nsDOMDataTransfer.h
+++ b/content/events/src/nsDOMDataTransfer.h
@@ -162,16 +162,19 @@ protected:
   // the event type this data transfer is for. This will correspond to an
   // event->message value.
   PRUint32 mEventType;
 
   // the drop effect and effect allowed
   PRUint32 mDropEffect;
   PRUint32 mEffectAllowed;
 
+  // Indicates the behavior of the cursor during drag operations
+  PRPackedBool mCursorState;
+
   // readonly data transfers may not be modified except the drop effect and
   // effect allowed.
   PRPackedBool mReadOnly;
 
   // true for drags started without a data transfer, for example, those from
   // another application.
   PRPackedBool mIsExternal;
 
--- a/dom/interfaces/events/nsIDOMDataTransfer.idl
+++ b/dom/interfaces/events/nsIDOMDataTransfer.idl
@@ -34,17 +34,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "domstubs.idl"
 
 interface nsIVariant;
 
-[scriptable, uuid(B5947DD0-8E86-4B9C-AA65-C86303EFCF94)]
+[scriptable, uuid(E4970BA1-9567-455C-8B4E-4607D7E741BB)]
 interface nsIDOMDataTransfer : nsISupports
 {
   /**
    * The actual effect that will be used, and should always be one of the
    * possible values of effectAllowed.
    *
    * For dragstart, drag and dragleave events, the dropEffect is initialized
    * to none. Any value assigned to the dropEffect will be set, but the value
@@ -176,16 +176,26 @@ interface nsIDOMNSDataTransfer : nsISupp
                                       in PRBool aUserCancelled);
 
   /**
    * The number of items being dragged.
    */
   readonly attribute unsigned long mozItemCount;
 
   /**
+   * Sets the drag cursor state. Primarily used to control the cursor during
+   * tab drags, but could be expanded to other uses.
+   *
+   * Possible values:
+   *  auto - use default system behavior.
+   *  default - set the cursor to an arrow during the drag operation.
+   */
+  attribute DOMString mozCursor;
+
+  /**
    * Holds a list of the format types of the data that is stored for an item
    * at the specified index. If the index is not in the range from 0 to
    * itemCount - 1, an empty string list is returned.
    */
   nsIDOMDOMStringList mozTypesAt(in unsigned long index);
 
   /**
    * Remove the data associated with the given format for an item at the
--- a/widget/src/windows/nsDragService.cpp
+++ b/widget/src/windows/nsDragService.cpp
@@ -265,17 +265,17 @@ nsDragService::InvokeDragSession(nsIDOMN
 
 //-------------------------------------------------------------------------
 NS_IMETHODIMP
 nsDragService::StartInvokingDragSession(IDataObject * aDataObj,
                                         PRUint32 aActionType)
 {
   // To do the drag we need to create an object that
   // implements the IDataObject interface (for OLE)
-  nsNativeDragSource* nativeDragSource = new nsNativeDragSource();
+  nsNativeDragSource* nativeDragSource = new nsNativeDragSource(mDataTransfer);
   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
--- a/widget/src/windows/nsNativeDragSource.cpp
+++ b/widget/src/windows/nsNativeDragSource.cpp
@@ -33,24 +33,27 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsNativeDragSource.h"
 #include <stdio.h>
 #include "nsISupportsImpl.h"
-
+#include "nsString.h"
 
 /*
  * class nsNativeDragSource
  */
-nsNativeDragSource::nsNativeDragSource()
-  : m_cRef(0), mUserCancelled(PR_FALSE)
+nsNativeDragSource::nsNativeDragSource(nsIDOMDataTransfer* aDataTransfer) :
+  m_cRef(0),
+  mUserCancelled(PR_FALSE),
+  m_hCursor(nsnull)
 {
+  mDataTransfer = do_QueryInterface(aDataTransfer);
 }
 
 nsNativeDragSource::~nsNativeDragSource()
 {
 }
 
 STDMETHODIMP
 nsNativeDragSource::QueryInterface(REFIID riid, void** ppv)
@@ -117,10 +120,28 @@ nsNativeDragSource::QueryContinueDrag(BO
 }
 
 STDMETHODIMP
 nsNativeDragSource::GiveFeedback(DWORD dwEffect)
 {
 #ifdef DEBUG
   //printf("GiveFeedback\n");
 #endif
+  
+  // For drags involving tabs, we do some custom work with cursors. 
+  if (mDataTransfer) {
+    nsAutoString cursor;
+    mDataTransfer->GetMozCursor(cursor);
+    if (cursor.EqualsASCII("default")) {
+      m_hCursor = ::LoadCursor(0, IDC_ARROW);
+    } else {
+      m_hCursor =  nsnull;
+    }
+  }
+
+  if (m_hCursor) {
+    ::SetCursor(m_hCursor);
+    return S_OK;
+  }
+  
+  // Let the system choose which cursor to apply.
 	return ResultFromScode(DRAGDROP_S_USEDEFAULTCURSORS);
 }
--- a/widget/src/windows/nsNativeDragSource.h
+++ b/widget/src/windows/nsNativeDragSource.h
@@ -33,32 +33,34 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 #ifndef _nsNativeDragSource_h_
 #define _nsNativeDragSource_h_
 
 #include "nscore.h"
+#include "nsIDOMDataTransfer.h"
+#include "nsCOMPtr.h"
 #include <ole2.h>
 #include <oleidl.h>
 
 //class nsIDragSource;
 
 /*
  * nsNativeDragSource implements the IDropSource interface and gets
  * most of its behavior from the associated adapter (m_dragDrop).
  */
 class nsNativeDragSource : public IDropSource
 {
 public:
 
   // construct an nsNativeDragSource referencing adapter
   // nsNativeDragSource(nsIDragSource * adapter);
-  nsNativeDragSource();
+  nsNativeDragSource(nsIDOMDataTransfer* aDataTransfer);
   ~nsNativeDragSource();
 
   // IUnknown methods - see iunknown.h for documentation
 
   STDMETHODIMP QueryInterface(REFIID, void**);
   STDMETHODIMP_(ULONG) AddRef();
   STDMETHODIMP_(ULONG) Release();
 
@@ -73,16 +75,23 @@ public:
   // This method gets called if there is any change in the mouse or key
   // state.  Return DRAGDROP_S_CANCEL to stop the drag, DRAGDROP_S_DROP
   // to execute the drop, otherwise NOERROR.
   STDMETHODIMP QueryContinueDrag(BOOL fESC, DWORD grfKeyState);
 
   PRPackedBool UserCancelled() { return mUserCancelled; }
 
 protected:
-  ULONG        m_cRef;     // reference count
+  // Reference count
+  ULONG m_cRef;
+
+  // Data object, hold information about cursor state
+  nsCOMPtr<nsIDOMNSDataTransfer> mDataTransfer;
+
+  // Custom drag cursor
+  HCURSOR m_hCursor;
 
   // true if the user cancelled the drag by pressing escape
   PRPackedBool mUserCancelled;
 };
 
 #endif // _nsNativeDragSource_h_