4
votes

My application allows dragging to both the main window and to a Status item.

  • If I drag a file from Stacks to my window, it works perfectly.
  • If I drag a file from Finder to my window, it works perfectly.
  • If I drag a file from Finder to my status item, it works perfectly.
  • If I drag a file from Stack to my status item, it doesn't work.

Both window and status item use the exact same drag and drop handling code.

The funny thing is that when a file is dragged from Stacks onto the status item, the cursor changes as expected because the - (NSDragOperation)draggingEntered:(id )sender { NSPasteboard *pboard; NSDragOperation sourceDragMask; method is called as expected.

When the file is dropped, however, the - (BOOL)performDragOperation:(id )sender { NSPasteboard *pboard; NSDragOperation sourceDragMask; method is NOT called.

Here is the implementation of the first method:

- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender {
    NSPasteboard *pboard;
    NSDragOperation sourceDragMask;

    sourceDragMask = [sender draggingSourceOperationMask];
    pboard = [sender draggingPasteboard];

    if ( [[pboard types] containsObject:NSColorPboardType] ) {
        if (sourceDragMask & NSDragOperationGeneric) {
            return NSDragOperationGeneric;
        }
    }
    if ( [[pboard types] containsObject:NSFilenamesPboardType] ) {
        if (sourceDragMask & NSDragOperationLink) {
            return NSDragOperationLink;
        } else if (sourceDragMask & NSDragOperationCopy) {
            return NSDragOperationCopy;
        }
    }

    return NSDragOperationNone;
}

Thanks!

2

2 Answers

6
votes

This is a legitimate issue. I've submitted a bug report for this to Apple. http://openradar.appspot.com/radar?id=1745403

In the meantime, I've figured out a workaround. Even though performDragOperation: is never called, draggingEnded: still is. You can still tell if the file was dropped on the NSStatusItem by checking if the "draggingLocation" point was inside NSView's rect. Here's an example:

- (void)draggingEnded:(id<NSDraggingInfo>)sender
{
    if(NSPointInRect([sender draggingLocation],self.frame)){
        //The file was actually dropped on the view so call the performDrag manually
        [self performDragOperation:sender];
    }
}

Hope this helps until the bug gets fixed.

3
votes

Not sure why this happens. Didn't like the forced solution which was top voted answer. This should do the trick:

- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
{
    return [sender draggingSourceOperationMask];
}