Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Register for global file drag events in Cocoa

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

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

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

This works partially - the handler is being called when I start dragging a file from my desktop or Finder, however it also is being called 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 URL e.g. when I let off the file 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 to a possible solution for this question.

like image 312
Timo Josten Avatar asked Apr 18 '16 15:04

Timo Josten


2 Answers

After having talked to Apple DTS, this is most likely a bug. I have filed rdar://25892115 for this issue. There currently seems to be no way to solve my original question with the given API.

To solve my problem, I am now using the Accessibility API to figure out if the item below the cursor is a file (kAXFilenameAttribute is not NULL).

like image 82
Timo Josten Avatar answered Oct 17 '22 02:10

Timo Josten


NSPasteboard* pb = [NSPasteboard pasteboardWithName:NSDragPboard];
NSArray* filenames = [pb propertyListForType:NSFilenamesPboardType];
NSInteger changeCount = pb.changeCount;

//when moving a window. the changeCount is not changed, use it to distinguish
if (filenames.count > 0 && self.lastChangeCount != changeCount){ 
    self.lastChangeCount = changeCount;
//your code here
}
like image 2
kebing1011 Avatar answered Oct 17 '22 02:10

kebing1011