diff --git a/widget/cocoa/nsChildView.mm b/widget/cocoa/nsChildView.mm index 75d4009ffa3d..3e7eef9d9847 100644 --- a/widget/cocoa/nsChildView.mm +++ b/widget/cocoa/nsChildView.mm @@ -3078,9 +3078,10 @@ NSPasteboard* globalDragPboard = nil; // gLastDragView and gLastDragMouseDownEvent are used to communicate information // to the drag service during drag invocation (starting a drag in from the view). -// gLastDragView is only non-null while mouseDragged is on the call stack. -NSView* gLastDragView = nil; -NSEvent* gLastDragMouseDownEvent = nil; +// gLastDragView is only non-null while a mouse button is pressed, so between +// mouseDown and mouseUp. +NSView* gLastDragView = nil; // [weak] +NSEvent* gLastDragMouseDownEvent = nil; // [strong] + (void)initialize { static BOOL initialized = NO; @@ -3321,6 +3322,10 @@ NSEvent* gLastDragMouseDownEvent = nil; [mPixelHostingView removeFromSuperview]; [mPixelHostingView release]; + if (gLastDragView == self) { + gLastDragView = nil; + } + [super dealloc]; NS_OBJC_END_TRY_ABORT_BLOCK; @@ -4235,6 +4240,7 @@ NSEvent* gLastDragMouseDownEvent = nil; [gLastDragMouseDownEvent release]; gLastDragMouseDownEvent = [theEvent retain]; + gLastDragView = self; // We need isClickThrough because at this point the window we're in might // already have become main, so the check for isMainWindow in @@ -4287,6 +4293,8 @@ NSEvent* gLastDragMouseDownEvent = nil; - (void)mouseUp:(NSEvent*)theEvent { NS_OBJC_BEGIN_TRY_ABORT_BLOCK; + gLastDragView = nil; + if (!mGeckoChild || mBlockedLastMouseDown) return; if (mTextInputHandler->OnHandleEvent(theEvent)) { return; @@ -4369,8 +4377,6 @@ NSEvent* gLastDragMouseDownEvent = nil; return; } - gLastDragView = self; - WidgetMouseEvent geckoEvent(true, eMouseMove, mGeckoChild, WidgetMouseEvent::eReal); [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; @@ -4378,7 +4384,6 @@ NSEvent* gLastDragMouseDownEvent = nil; // Note, sending the above event might have destroyed our widget since we didn't retain. // Fine so long as we don't access any local variables from here on. - gLastDragView = nil; // XXX maybe call markedTextSelectionChanged:client: here? diff --git a/widget/cocoa/nsDragService.mm b/widget/cocoa/nsDragService.mm index 73a2a95495f2..f42789291de6 100644 --- a/widget/cocoa/nsDragService.mm +++ b/widget/cocoa/nsDragService.mm @@ -252,13 +252,10 @@ nsresult nsDragService::InvokeDragSessionImpl(nsIArray* aTransferableArray, NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; if (!gLastDragView) { - // gLastDragView is only set during -[ChildView mouseDragged:]. - // InvokeDragSessionImpl is only called while Gecko processes a mouse move - // event. So if we get here with gLastDragView being null, that means that - // the mouse button has already been released, and mouseMoved is on the - // stack instead of mouseDragged. In that case we need to abort the drag - // because the OS won't know where to drop whatever's being dragged, and we - // might end up with a stuck drag & drop session. + // gLastDragView is non-null between -[ChildView mouseDown:] and -[ChildView mouseUp:]. + // If we get here with gLastDragView being null, that means that the mouse button has already + // been released. In that case we need to abort the drag because the OS won't know where to drop + // whatever's being dragged, and we might end up with a stuck drag & drop session. return NS_ERROR_FAILURE; }