always release cached drag data as soon as the drag is over, call EndDragSession correctly. b=386226 r=cbarrett sr=pinkerton
authorjoshmoz@gmail.com
Fri, 29 Jun 2007 20:19:41 -0700
changeset 2958 1610cea502cb82f83d5d7e703d0b40452150e1e2
parent 2957 7bfc7ae65ba854e0c833e6eeb7ddb2e43960f827
child 2959 9b2739d27fa1f88c62b2cc3199b1ea050dced4e8
push idunknown
push userunknown
push dateunknown
reviewerscbarrett, pinkerton
bugs386226
milestone1.9a6pre
always release cached drag data as soon as the drag is over, call EndDragSession correctly. b=386226 r=cbarrett sr=pinkerton
widget/src/cocoa/nsChildView.mm
widget/src/cocoa/nsDragService.mm
--- a/widget/src/cocoa/nsChildView.mm
+++ b/widget/src/cocoa/nsChildView.mm
@@ -3859,19 +3859,26 @@ static PRBool IsSpecialGeckoKey(UInt32 m
 
 
 // This is a utility function used by NSView drag event methods
 // to send events. It contains all of the logic needed for Gecko
 // dragging to work. Returns YES if the event was handled, NO
 // if it wasn't.
 - (BOOL)doDragAction:(PRUint32)aMessage sender:(id)aSender
 {
-  if (!mGeckoChild || !mDragService)
+  if (!mGeckoChild)
     return NO;
 
+  if (!mDragService) {
+    CallGetService(kDragServiceContractID, &mDragService);
+    NS_ASSERTION(mDragService, "Couldn't get a drag service - big problem!");
+    if (!mDragService)
+      return NO;
+  }
+
   if (aMessage == NS_DRAGDROP_ENTER)
     mDragService->StartDragSession();
 
   nsCOMPtr<nsIDragSession> dragSession;
   mDragService->GetCurrentSession(getter_AddRefs(dragSession));
   if (dragSession) {
     if (aMessage == NS_DRAGDROP_OVER) {
       // fire the drag event at the source. Just ignore whether it was
@@ -3921,21 +3928,16 @@ static PRBool IsSpecialGeckoKey(UInt32 m
   }
 
   return handled ? YES : NO;
 }
 
 
 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
 {
-  CallGetService(kDragServiceContractID, &mDragService);
-  NS_ASSERTION(mDragService, "Couldn't get a drag service - big problem!");
-  if (!mDragService)
-    return NSDragOperationNone;
-
   // there should never be a globalDragPboard when "draggingEntered:" is
   // called, but just in case we'll take care of it here.
   [globalDragPboard release];
 
   // Set the global drag pasteboard that will be used for this drag session.
   // This will be set back to nil when the drag session ends (mouse exits
   // the view or a drop happens within the view).
   globalDragPboard = [[sender draggingPasteboard] retain];
@@ -3943,54 +3945,56 @@ static PRBool IsSpecialGeckoKey(UInt32 m
   BOOL handled = [self doDragAction:NS_DRAGDROP_ENTER sender:sender];
 
   return handled ? NSDragOperationGeneric : NSDragOperationNone;
 }
 
 
 - (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
 {
-  if (!mDragService)
-    return NSDragOperationNone;
-
   BOOL handled = [self doDragAction:NS_DRAGDROP_OVER sender:sender];
-
   return handled ? NSDragOperationGeneric : NSDragOperationNone;
 }
 
 
 - (void)draggingExited:(id <NSDraggingInfo>)sender
 {
-  if (!mDragService)
-    return;
-
   [self doDragAction:NS_DRAGDROP_EXIT sender:sender];
-
-  // Gecko event handling for this drag session is over. Release our
-  // cached drag service and set globalDragPboard back to nil.
-  NS_IF_RELEASE(mDragService);
-  [globalDragPboard release];
-  globalDragPboard = nil;
 }
 
 
 - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
 {
-  if (!mDragService)
-    return NO;
-
-  BOOL rv = [self doDragAction:NS_DRAGDROP_DROP sender:sender];
-
-  // Gecko event handling for this drag session is over. Release our
-  // cached drag service and set globalDragPboard back to nil.
-  NS_IF_RELEASE(mDragService);
+  return [self doDragAction:NS_DRAGDROP_DROP sender:sender];
+}
+
+
+// NSDraggingSource
+- (void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation
+{
+  if (!mDragService) {
+    CallGetService(kDragServiceContractID, &mDragService);
+    NS_ASSERTION(mDragService, "Couldn't get a drag service - big problem!");
+  }
+
+  if (mDragService) {
+    mDragService->EndDragSession(PR_TRUE);
+    NS_RELEASE(mDragService);
+  }
+
   [globalDragPboard release];
   globalDragPboard = nil;
-
-  return rv;
+}
+
+
+// NSDraggingSource
+// this is just implemented so we comply with the NSDraggingSource informal protocol
+- (unsigned int)draggingSourceOperationMaskForLocal:(BOOL)isLocal
+{
+  return UINT_MAX;
 }
 
 
 #pragma mark -
 
 
 #ifdef ACCESSIBILITY
 
--- a/widget/src/cocoa/nsDragService.mm
+++ b/widget/src/cocoa/nsDragService.mm
@@ -266,17 +266,16 @@ nsDragService::InvokeDragSession(nsIDOMN
   nsBaseDragService::StartDragSession();
   [globalDragView dragImage:image
                          at:localPoint
                      offset:NSMakeSize(0,0)
                       event:globalDragEvent
                  pasteboard:[NSPasteboard pasteboardWithName:NSDragPboard]
                      source:globalDragView
                   slideBack:YES];
-  nsBaseDragService::EndDragSession(PR_TRUE);
 
   return NS_OK;
 }
 
 
 NS_IMETHODIMP
 nsDragService::GetData(nsITransferable* aTransferable, PRUint32 aItemIndex)
 {