Redrawing a view during a dragging session [SOLVED]

Graham Cox

As usual, the answer was staring me in the face.

The old code was synchronous, the new is asynchronous.

I was restoring the view after the call to -dragImage… because that used to keep control until the drag finished. But the replacement returns immediately, so restoring the view just undoes the hiding step, and with it not hidden, the stack animation has no “gap” to work with.

A small re-arrangement of where the clean-up of the drag is done restores full working visuals (and my sanity!).

Sory for the noise - but if anyone else has a similar issue, this might be of some help.


On 3 Jul 2020, at 4:11 pm, Graham Cox <graham@...> wrote:

Hi all,

I’m updating some legacy code that currently uses the ‘classic’ way to drag stuff, namely

[NSView dragImage:at:offset:event:pasteboard:source:slideBack:];

This code has been deprecated forever (10.7+ anyway), so it’s about time it was updated to the modern dragging session API. However, the old code still works perfectly and has served faithfully for years.

The dragging session is created OK, and the dragging image drags as a semi-transparent image, so the drag is taking place alright. I can also see that the dragging destination methods are called as they should be.

The problem is that the source view needs to update while the drag is going on. The view is actually a stack of subviews, and the thing being dragged is one of them, to re-arrange the order of the views. So the first thing is that the view being dragged is hidden. This opens up a gap in the stack. As the drag proceeds, the remaining views animate their position to open up a gap where the view can be dropped.

In the old code, works great.

In the new code, nothing I do allows the view’s visual appearance to be updated during the drag. The view being dragged doesn’t hide (its ‘hidden’ state becomes YES, but it still shows), and the animation doesn’t happen, though once again the code that handles that is being called as expected. That calls -setAnimatedFrame: to reposition the other views to make space, but though its being called with sensible values, nothing actually gets drawn or redrawn.

It’s as if the run loop is suspended during the dragging session, so window updates are not processed. I’m not sure what to check to verify that guess.

SUrely normal updates should be allowed during a drag? How can the old code (that freely handles updates) be replaced if the new one doesn’t work the same way?

Anyone run into this problem, or knows what I should do here?