drop zone only work from Finder #25
Replies: 5 comments 4 replies
|
It should work from anywhere where you drag a "real" file, e.g. Finder or your desktop. Unfortunately, it does not work when dragging & dropping from within another application due to an API limitation of Apple. |
|
I wonder how other developers get around this limitation? Ironic Software's Fresh, for instance, doesn't have this limitation. For people who use file managers instead of the Finder, it's a big limitation. |
|
The issue is not drag & drop, the issue is knowing when drag & drop is happening. Dropshare Zone needs to have access to the file that is part of the drag & drop operation, and know when an operation has started, without being the frontmost or active app. Dropshare Zone is just a UI overlay on your screen, so that it does not interfere with your active application or steal it's focus every time you drag & drop a file. The accessibility API that I use to detect this does not allow me to be informed about drag & drop operations and their attached files when such operations are started from outside of Apple applications. To be fair, all of that was true when I implemented Zone a few years back. The situation might have changed meanwhile. Anyway as of now, these are the limitations that exist in the current implementation. |
|
Noticed this as well, and I encountered the same problem about a year ago in another app I was building, but it seems to have been fixed in the latest macOS version. Clop for example can use the drag pasteboard to peek into the types of dragged files. One catch is that you need to avoid looking into the contents of file promises, otherwise you consume that promise and make it unavailable for when the drop event actually happens. clop-drop-zone-demo.mp4Something like this should help with the implementation: const NSPasteboardType NSPasteboardTypePromise = @"com.apple.pasteboard.promised-file-content-type";
const NSPasteboardType NSPasteboardTypePromisedFileName = @"com.apple.pasteboard.promised-file-name";
const NSPasteboardType NSPasteboardTypePromisedFileURL = @"com.apple.pasteboard.promised-file-url";
@interface ViewController : NSViewController
@property (readwrite, nonatomic) BOOL showDropZone;
@property (readonly) NSInteger dragChangeCount;
@end
@implementation ViewController
@synthesize showDropZone;
@synthesize dragChangeCount;
static bool pasteboardHasExistingFilePath(NSPasteboardItem *item) {
NSSet<NSPasteboardType>* fileTypes = [NSSet setWithObjects:NSPasteboardTypeFileURL, NSPasteboardTypeString, nil];
NSSet * _Nonnull itemTypes = [NSSet setWithArray:item.types];
if (![fileTypes intersectsSet:itemTypes]) {
return false;
}
NSString* fileURL = [item stringForType:NSPasteboardTypeFileURL];
NSFileManager* fm = [NSFileManager defaultManager];
if (fileURL) {
NSURL* url = [NSURL URLWithString:fileURL];
if ([fm fileExistsAtPath:url.path]) {
NSLog(@"Dragging file %@", url.path);
return true;
}
} else {
NSString* filePath = [item stringForType:NSPasteboardTypeString];
if ([fm fileExistsAtPath:filePath]) {
NSLog(@"Dragging file %@", filePath);
return true;
}
}
return false;
}
- (void)viewDidLoad {
[super viewDidLoad];
[NSEvent addGlobalMonitorForEventsMatchingMask:NSEventMaskLeftMouseDragged
handler:^(NSEvent* event) {
// Ignore ghost drag events
if ([NSEvent pressedMouseButtons] == 0) {
return;
}
NSPasteboard* drag = [NSPasteboard pasteboardWithName:NSPasteboardNameDrag];
// Only proceed if we have new contents in the drag pasteboard
if (self->dragChangeCount == [drag changeCount]) {
return;
}
self->dragChangeCount = [drag changeCount];
NSArray<NSPasteboardItem*>* items = [drag pasteboardItems];
NSSet<NSPasteboardType>* promisedTypes = [NSSet setWithObjects:NSPasteboardTypePromise, NSPasteboardTypePromisedFileURL, NSPasteboardTypePromisedFileName, nil];
BOOL containsPromisedTypes = NO;
BOOL containsFilePath = NO;
for (NSPasteboardItem* item in items) {
NSSet * _Nonnull itemTypes = [NSSet setWithArray:item.types];
NSLog(@"%@", itemTypes);
if ([promisedTypes intersectsSet:itemTypes]) {
// Never check the contents of the file promise
// from outside of a drag destination
containsPromisedTypes = YES;
break;
}
containsFilePath = pasteboardHasExistingFilePath(item);
if (containsFilePath) {
break;
}
}
if (containsPromisedTypes || containsFilePath) {
NSLog(@"Showing drop zone");
} else {
NSLog(@"Not showing drop zone");
}
}];
}
@endI also, would love to see Dropshare's drop zone appear when dragging files from Yoink or Alfred, I noticed I do that a lot when trying to share something and I'm in a hurry. |
|
I have released version 5.40 today which should improve support for Dropshare Zone for files dragged with mostly all applications. |
Uh oh!
There was an error while loading. Please reload this page.
The drop zone only appear and work if dragging a file from the Finder.
This limitation only applies to the drop zone—with the menu bar icon, I can drag files from any program.
All reactions