diff --git a/shell/browser/ui/drag_util_mac.mm b/shell/browser/ui/drag_util_mac.mm index 811a0c8d103b1..4c4649c6cb434 100644 --- a/shell/browser/ui/drag_util_mac.mm +++ b/shell/browser/ui/drag_util_mac.mm @@ -10,52 +10,78 @@ #include "base/strings/sys_string_conversions.h" #include "shell/browser/ui/drag_util.h" -namespace electron { +// Contents largely copied from +// chrome/browser/download/drag_download_item_mac.mm. + +@interface DragDownloadItemSource : NSObject +@end + +@implementation DragDownloadItemSource + +- (NSDragOperation)draggingSession:(NSDraggingSession*)session + sourceOperationMaskForDraggingContext:(NSDraggingContext)context { + return NSDragOperationEvery; +} + +@end namespace { -// Write information about the file being dragged to the pasteboard. -void AddFilesToPasteboard(NSPasteboard* pasteboard, - const std::vector& files) { - NSMutableArray* fileList = [NSMutableArray array]; - for (const base::FilePath& file : files) - [fileList addObject:base::SysUTF8ToNSString(file.value())]; - [pasteboard declareTypes:[NSArray arrayWithObject:NSFilenamesPboardType] - owner:nil]; - [pasteboard setPropertyList:fileList forType:NSFilenamesPboardType]; +id GetDraggingSource() { + static id source = [[DragDownloadItemSource alloc] init]; + return source; } } // namespace +namespace electron { + void DragFileItems(const std::vector& files, const gfx::Image& icon, gfx::NativeView view) { - NSPasteboard* pasteboard = [NSPasteboard pasteboardWithName:NSDragPboard]; - AddFilesToPasteboard(pasteboard, files); + auto* native_view = view.GetNativeNSView(); + NSPoint current_position = + [[native_view window] mouseLocationOutsideOfEventStream]; + current_position = + [native_view backingAlignedRect:NSMakeRect(current_position.x, + current_position.y, 0, 0) + options:NSAlignAllEdgesOutward] + .origin; + + NSMutableArray* file_items = [NSMutableArray array]; + for (auto const& file : files) { + NSURL* file_url = + [NSURL fileURLWithPath:base::SysUTF8ToNSString(file.value())]; + NSDraggingItem* file_item = [[[NSDraggingItem alloc] + initWithPasteboardWriter:file_url] autorelease]; + NSImage* file_image = icon.ToNSImage(); + NSSize image_size = file_image.size; + NSRect image_rect = NSMakeRect(current_position.x - image_size.width / 2, + current_position.y - image_size.height / 2, + image_size.width, image_size.height); + [file_item setDraggingFrame:image_rect contents:file_image]; + [file_items addObject:file_item]; + } // Synthesize a drag event, since we don't have access to the actual event // that initiated a drag (possibly consumed by the Web UI, for example). - NSWindow* window = [view.GetNativeNSView() window]; - NSPoint position = [window mouseLocationOutsideOfEventStream]; + NSPoint position = [[native_view window] mouseLocationOutsideOfEventStream]; NSTimeInterval eventTime = [[NSApp currentEvent] timestamp]; - NSEvent* dragEvent = [NSEvent mouseEventWithType:NSLeftMouseDragged - location:position - modifierFlags:NSLeftMouseDraggedMask - timestamp:eventTime - windowNumber:[window windowNumber] - context:nil - eventNumber:0 - clickCount:1 - pressure:1.0]; + NSEvent* dragEvent = + [NSEvent mouseEventWithType:NSEventTypeLeftMouseDragged + location:position + modifierFlags:NSEventMaskLeftMouseDragged + timestamp:eventTime + windowNumber:[[native_view window] windowNumber] + context:nil + eventNumber:0 + clickCount:1 + pressure:1.0]; // Run the drag operation. - [window dragImage:icon.ToNSImage() - at:position - offset:NSZeroSize - event:dragEvent - pasteboard:pasteboard - source:view.GetNativeNSView() - slideBack:YES]; + [native_view beginDraggingSessionWithItems:file_items + event:dragEvent + source:GetDraggingSource()]; } } // namespace electron