DragAndDropContainer::performExternalDragDropOfFiles() Asynchronous and DragImageComponent issue


#1

The comments say that DragAndDropContainer::performExternalDragDropOfFiles() is synchronous… but it isn’t.

My real issue…

(On MacOS)

I have a screen repaint issue if you start a drag from a TableListBox and drop it (drag, stop dragging and lift your mouse finger) on the plug-in UI… Say on the TableListBox itself… it won’t delete the DragImageComponent until you move the mouse… and DragAndDropContainer::dragOperationEnded() is triggered only after a mouse move… so I can’t try:

void CGrooveComponent::dragOperationEnded (const DragAndDropTarget::SourceDetails&)
{
    auto mainMouse = Desktop::getInstance().getMainMouseSource();
    
    mainMouse.triggerFakeMove();
}

It’s odd 'cause DragImageComponent::mouseUp() only gets triggered after the mouse is moved… not on the actual mouseUp event.

Any ideas?

Rail


performExternalDragDropOfFiles is not synchronous on MAC
#2

It happens if you call DragAndDropContainer::performExternalDragDropOfFiles() in the TableListBox’s getDragSourceDescription() method… and is only a MacOS issue.

To isolate the cause, by temporarily bypassing the code below fixes the issue…

bool DragAndDropContainer::performExternalDragDropOfFiles (const StringArray& files, bool /*canMoveFiles*/,
                                                           Component* sourceComponent)
{
    if (files.isEmpty())
        return false;

    if (auto* view = getNSViewForDragEvent (sourceComponent))
    {
        JUCE_AUTORELEASEPOOL
        {
            if (auto* event = [[view window] currentEvent])
            {
                auto* dragItems = [[[NSMutableArray alloc] init] autorelease];

                for (auto& filename : files)
                {
                    auto* nsFilename = juceStringToNS (filename);
                    auto* fileURL = [NSURL fileURLWithPath: nsFilename];
                    auto* dragItem = [[NSDraggingItem alloc] initWithPasteboardWriter: fileURL];

                    auto eventPos = [event locationInWindow];
                    auto dragRect = [view convertRect: NSMakeRect (eventPos.x - 16.0f, eventPos.y - 16.0f, 32.0f, 32.0f)
                                             fromView: nil];
                    auto* dragImage = [[NSWorkspace sharedWorkspace] iconForFile: nsFilename];
                    [dragItem setDraggingFrame: dragRect
                                      contents: dragImage];

                    [dragItems addObject: dragItem];
                    [dragItem release];
                }
            
            /*
                // Bypass this temporarily...

                auto* helper = [draggingSourceHelper.createInstance() autorelease];

                return [view beginDraggingSessionWithItems: dragItems
                                                     event: event
                                                    source: helper];
             
            */
            
            return true;
            }
        }
    }

    return false;
}

Rail


#3

I’m confused… surely removing that code simply stops external drag + drop from doing anything at all?


#4

Yes it does… I removed it to indicate it’s the cause of the issue I’m reporting.

Hence my comment:

// Bypass this temporarily...

The NSDraggingSourceHelper may need to watch for:

https://developer.apple.com/documentation/appkit/nsdraggingsource/1416017-draggingsession?language=objc

and use that to trigger a callback??

Rail


#5

I created a thread for this same issue, simply asking if the documentation is wrong or if the implementation on MAC indeed is wrong and if this would be fixed but i was pointed to join this thread instead.

It would help immensely if the implementation on MAC is the same as on WIN(where it works as the documentation states)
Currently we do a lot of ugly/unstable hacks that could be removed if this would be fixed.


#6

Hi, any updates on this? Also getting diff behaviour on Mac and Windows as detailed above


#7

Thanks @Rail_Jon_Rogut. This commit has updated the docs to reflect that the operation is asynchronous and has unified the behaviour across all platforms (see this post) and this commit should fix the missing mouse up causing your screen repaint issue.


#8

I’m getting a small compilation error when building for i386 instead of x86_64 with your latest commit (something like can’t convert NSPoint to CGPoint ) : https://github.com/WeAreROLI/JUCE/commit/2fd19af539cfd3748249ba40b3a83076713a7e51
Replacing the p argument in the CGEventCreateMouseEvent() call by CGPointMake(p.x, p.y) fixes it


#9

Thanks, I’ll sort that out.