The way my Cocoa app works is to have one subclassed NSView per window and many internal views rendered inside that. I recently moved to using NSView's beginDraggingSessionWithItems:event:source function to support dragging file promises to external applications (like Finder). But the internal drag types (base type String and Binary blob) needed to be ported over from NSWindow's dragImage. The main difference I've noted is that beginDraggingSessionWithItems doesn't by default allow me to drag from my application TO my application... as in internal to itself. For instance if I have a tree control and use DnD to move elements around it doesn't work. Dragging files into the app works. Dragging promises out of the app works. Just nothing internally.
Some code. Here is where I create a binary item:
auto drag_items = [[NSMutableArray alloc] init];
auto item = [[NSPasteboardItem alloc] init];
NSData *data = [NSData dataWithBytes:myBinary.Data length:myBinary.Length];
[item setData:data forType:dd.Format.NsStr()];
auto drag_item = [[NSDraggingItem alloc] initWithPasteboardWriter:item];
drag_item.draggingFrame = NSMakeRect(floor(position.x), floor(position.y), 32, 32);
[drag_items addObject:drag_item];
And then start the drag:
NSDraggingSession *session = [myNsWindow.contentView beginDraggingSessionWithItems:drag_items
event:myEvent
source:DragSrc];
The drag source implements draggingSession like this:
- (NSDragOperation)draggingSession:(nonnull NSDraggingSession *)session
sourceOperationMaskForDraggingContext:(NSDraggingContext)context
{
switch (context)
{
case NSDraggingContextOutsideApplication:
return NSDragOperationCopy;
case NSDraggingContextWithinApplication:
return NSDragOperationCopy | NSDragOperationGeneric | NSDragOperationMove;
default:
return NSDragOperationNone;
}
}
The full drag source code is available in GDragAndDrop.mm, and the full drag target code is available in LCocoaView.mm.
What I see is that none of the drag target methods get called, and when I release the mouse, the image snaps back to the source of the drag.
I remember there being a flag or something to set that allows the same view to be both the source and target. But for the life of me can't find it.
Edit: These are the types I pass to NSView's registerForDraggedTypes:
"public.item"
"com.apple.NSFilePromiseItemMetaData"
"dyn.ah62d4rv4gu8yc6durvwwa3xmrvw1gkdusm1044pxqyuha2pxsvw0e55bsmwca7d3sbwu"
"com.apple.pasteboard.promised-file-content-type"
I think what's happening is the registered types don't match up with what I'm trying to drag. What I want is a wildcard so that the receiver gets all types and I do the filtering at a lower layer. That's why there is 'public.item' in the list, but it's not working how I intended.
registerForDraggedTypes:
? – Willeke