0

In my cocoa code, I’ve implemented a drag & drop for a file path. It is triggered not by a mouseDown, but as a result of a callback I receive from javascript code (after click-dragging an HTML object).

The problem is that it works only 80% of the time: I do the same click-drag operation over and over again and get two behaviors. In both, an icon representing the dragged file path begins following the cursor around (as expected).

Now, in most of the times the dragged file path is “accepted” by the receiver, an appropriate visual feedback is given during the drag, and eventually when the mouse is released – the file path is accepted and dropped. However there are times where the file path is not “accepted” when hovering over the target. When this happens and the mouse is released, the icon slides back to its origin and the file path is not dropped onto the target.

Here’s my code (simplified), based on Apple’s docs:

void myInitiateDrag(const char * in_filepath, NSView * view)
{
    NSString *nsfilepath = [NSString stringWithUTF8String:in_filepath];
    NSEvent *theEvent = [[view window] currentEvent];
    NSPoint dragPosition = [view convertPoint:[theEvent locationInWindow] fromView:nil];    
    NSRect aRect = NSMakeRect(dragPosition.x, dragPosition.y, 10, 10);
     
    [view dragFile:nsfilepath fromRect:aRect slideBack:YES event:theEvent];
}

Using this exact code within mouseDown works perfectly fine, 100% of the times. However as I said, I don’t receive a mouseDown in my case.

Another observation: when the mouse button is released after a drag operation, mouseUp is not being called. This is regardless of where I initiate the drag operation, and is also mentioned in another SO question. So, I don’t know if this has to do with my problem.

Among the things I’ve done, I tried to find differences between the currentEvent when successful and when not successful, with no luck.

In the developer docs it explicitly says “A dragging session is initiated by the user clicking the mouse inside a window or view and moving the mouse [...] You invoke this method in the mouseDown: or mouseDragged: method of your subclass of NSView or NSWindow.”.

Is this mandatory? What is wrong with what I’m doing and what other options do I have?

2
  • See NSView, the "Dragging Operations" section. dragFile:fromRect:slideBack:event: is deprecated and "must be invoked only within an implementation of the mouseDown: method.". Have you tried beginDraggingSessionWithItems:event:source:? Is theEvent always a mouseDown event?
    – Willeke
    Commented Nov 3, 2020 at 1:34
  • @Willeke, tried with beginDraggingSessionWithItems:event:source - it works only from within mouseDown or mouseDragged, not from the js callback.
    – gil_mo
    Commented Nov 4, 2020 at 10:18

1 Answer 1

0

Have the same issue, finally was able to make it work with event copy:

[ NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskLeftMouseDragged handler:^NSEvent * _Nullable(NSEvent * _Nonnull event) {
    [self.controller mouseEventGlobal:event];
    return event;
}];

After that in the controller, I'm able to use beginDraggingSessionWithItems:event:source after I have callback from JS.

Not the answer you're looking for? Browse other questions tagged or ask your own question.