NSDragPboard still contains dragged file information when dragging has ended

Originator:tj
Number:rdar://25892115 Date Originated:23-Apr-2016 11:38 AM
Status:Open Resolved:
Product:OS X SDK Product Version:10.11.x
Classification:Other bug Reproducible:Always
 
Summary:
This was originally a request to DTS (see additional notes for original DTS request).

There seems to be an issue with [NSPasteboard pasteboardWithName:NSDragPboard]. Whereas it correctly contains the information about a dragged file when the file is being dragged, it keeps the information when dragging has long ended. Therefore it is impossible to tell from the NSDragPboard if currently a file is being dragged, or not.

Steps to Reproduce:
Please see sample code attached.

Install Xcode, create new Mac App, copy the following code to AppDelegate.m/applicationDidFinishLaunching:

[NSEvent addGlobalMonitorForEventsMatchingMask:NSLeftMouseDraggedMask handler:^(NSEvent* event) {
        NSPasteboard* pb = [NSPasteboard pasteboardWithName:NSDragPboard];
        NSLog(@"%@", [pb propertyListForType:NSFilenamesPboardType]);
    }];

Run the application. Open Finder.app, and start dragging around a random file from your Mac. You will see that information about the file being dragged is being written to the Xcode console. Let off that file, and start dragging around the Finder window. You will notice that still the information about the file you have already let off is being printed to the Xcode console. Hence, NSDragPboard seems to contain this information still when the dragging operation has long ended.

Expected Results:
NSLog(@"%@", [pb propertyListForType:NSFilenamesPboardType]);

should return nil when no file is being dragged currently.

Actual Results:
NSLog(@"%@", [pb propertyListForType:NSFilenamesPboardType]);

will print the information about the file that has been dragged before when currently no file is being dragged, but something else, e.g. the Finder window (in the context of NSEvent addGlobalMonitorForEventsMatchingMask:)

Version:
Xcode Version 7.3 (7D175), OS X 10.11 (and all patches)

Notes:
Original DTS request:

Hi Apple Engineer, thanks for taking time for my question.

I'm trying to be notified when a user is dragging any file in OS X, not only in my app.

My current approach was using addGlobalMonitorForEventsMatchingMask:handler: on NSEvent, as follows:

(see code above)

This works partially - the handler is being called when I start dragging a file from my desktop or Finder, however propertyListForType: also returns a valid file path when I perform every other operation that contains a left-mouse-drag, e.g. moving a window. The issue is that the NSDragPboard still seems to contain the latest dragged file path e.g. when I let off the file I was dragging and start moving a window, which makes it hard to distinguish between these operations.

TL;DR - I am interested in file drag operations system-wide. I do not need any information about the dragged file itself, just the information that a file drag operation has been started or stopped. I would appreciate any hint.

Configuration:
All hardware I have tested with: rMBP 15", MB 12"

Comments

This has always been the behavior and I don't expect it to change any time soon. Perhaps you could use the pasteboard's changeCount to find out when it is being changed?

I neither expect a change, but Apple DTS advised me to file a bug since they think it is one.

I am now using the Accessibility API to validate if the item under the mouse is a file when the dragging starts.


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!