After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 763659 - DND Drop on root with Pixbuf leaves image behind
DND Drop on root with Pixbuf leaves image behind
Status: RESOLVED FIXED
Product: gtk+
Classification: Platform
Component: Widget: Other
3.19.x
Other Linux
: Normal minor
: ---
Assigned To: gtk-bugs
gtk-bugs
Depends on:
Blocks:
 
 
Reported: 2016-03-15 02:53 UTC by Gerald Nunn
Modified: 2016-03-21 15:35 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
dnd: Hide the drag window when we're done (2.43 KB, patch)
2016-03-16 20:52 UTC, Matthias Clasen
committed Details | Review

Description Gerald Nunn 2016-03-15 02:53:31 UTC
In my application I support dragging a widget off the application and dropping it on the root window to detach them. It uses similar code as GtkNotebook except I use a Pixbuf as the drag image instead of a window. This all works fine in 3.18 and earlier, however in 3.19 (on Rawhide) I'm finding that it leaves the drag image behind.

A video of the problematic behavior can be viewed here:

https://www.youtube.com/watch?v=gPArxtvCmY4

If I change my code to use identical behavior as GtkNotebook, i.e. drag a window, destroy it in drag end, it all works fine.
Comment 1 Matthias Clasen 2016-03-15 11:20:37 UTC
is this X11 or wayland ?
Comment 2 Gerald Nunn 2016-03-15 13:57:26 UTC
I tested with both, no change on either. Note I was using a VM to test but I think my user who made that video was not virtual.
Comment 3 Matthias Clasen 2016-03-15 20:13:25 UTC
I have not been able to reproduce with testnotebookdnd, which has some cases where it does set a pixbuf icon for a drag that tears a tab off.

Can you produce a testcase, or show your code ?
Comment 4 Gerald Nunn 2016-03-15 20:51:49 UTC
Here's the code I was using for the DragBegin and DragFailed before switching to using a Window instead. It's D code but hopefully it should be relatively easy to follow:

void onTitleDragBegin(DragContext dc, Widget widget) {
        trace("Title Drag begin");
        Pixbuf pb = getWidgetImage(this, 0.20);
        DragAndDrop.dragSetIconPixbuf(dc, pb, 0, 0);
    }

    /**
     * Called when drag failed, used this to detach a terminal into a new window
     */
    bool onTitleDragFailed(DragContext dc, GtkDragResult dr, Widget widget) {
        trace("Drag Failed with ", dr);
        if (dr == GtkDragResult.NO_TARGET) {
            //Only allow detach if whole heirarchy agrees (application, window, session)
            if (!notifyIsActionAllowed(ActionType.DETACH))
                return false;
            trace("Detaching terminal");
            Screen screen;
            int x, y;
            dc.getDevice().getPosition(screen, x, y);
            //Detach here
            Terminal terminal = getDragTerminal(dc);
            if (terminal !is null) {
                trace("Detaching terminal ", dr);
                notifyTerminalRequestDetach(terminal, x, y);
                terminalState = TerminalState.NORMAL;
                updateActions();
            } else {
                error("Failed to get terminal therefore detach request failed");
            }
            return true;
        }
        return false;
    }

Note you only get the leftover image if the DragFailed returns true, on false you get the normal failed animation and no leftover image.

The easiest way I can give you a reproducer is to build an older version of my application with the issue. If you need a small self-container reproducer, I can build one in D but it will take me a few days to get to it.
Comment 5 Matthias Clasen 2016-03-16 00:16:14 UTC
I dunno. Adding a few printfs to the GtkNotebook drag_Failed function, I see it take the same path and return TRUE, yet the icon gets cleared up just fine.
Comment 6 Gerald Nunn 2016-03-16 16:05:11 UTC
I just re-tested an older version of my application before I switched to Window on Rawhide just confirm the issue and still see it. You can try my app if you want, but it's a bit of a pain to setup manually because I don't have an archive of old RPMs.

1. Download terminix here: https://github.com/gnunn1/terminix/releases/download/0.52.1/terminix.zip

2. sudo unzip terminix.zip -d /

3. sudo glib-compile-schemas /usr/share/glib-2.0/schemas/

4. Run the app (terminix) and split the terminal into two using the menubutton over the terminal. Drag one of the terminals to the desktop and let go. It should detach the terminal and the pixbuf image will be left behind

Note I can completely understand not wanting to download some app off the internet and install it in your root file system just to reproduce this issue if you don't have a virtualized environment handy. I can work on a smaller, more self-container reproducer but can't get to it until the weekend at the earliest.
Comment 7 Matthias Clasen 2016-03-16 19:57:30 UTC
briefly looked at terminal.d, but didn't see anything obviously wrong. The only way I see for the icon to stick around is if we (or you) managed to leak a reference to the drag context somehow - we remove the drag icon/window in finalize(). So if the context doesn't get finalized, it might stick around
Comment 8 Gerald Nunn 2016-03-16 20:06:33 UTC
Did you look at the current code or the 52.1 tag, keep in mind that the current code in github works fine because I switched to a Window. I also had the thought it could be due to D's GC missing a reference or not destroying the Pixbuf promptly enough as I've had that problem with other cases. I did try adding a DragEnd handler that destroyed my reference to the Pixbuf that I passed and it didn't make any difference. Also, this same code worked fine in 3.18 so from my perspective the only change was to 3.19.

I set the severity to minor because I was able to workaround it by switching my implementation so I'm not looking for an urgent solution to this, just wanted to capture it in case others have the same problem. 

If you need a small reproducer let me know and I'm happy to spend an hour to build one during the weekend, though it will be in D.
Comment 9 Matthias Clasen 2016-03-16 20:30:52 UTC
(In reply to Gerald Nunn from comment #8)
> Did you look at the current code or the 52.1 tag, keep in mind that the
> current code in github works fine because I switched to a Window. I also had
> the thought it could be due to D's GC missing a reference or not destroying
> the Pixbuf promptly enough as I've had that problem with other cases. I did
> try adding a DragEnd handler that destroyed my reference to the Pixbuf that
> I passed and it didn't make any difference. Also, this same code worked fine
> in 3.18 so from my perspective the only change was to 3.19.

The problem is not the pixbuf, GDK creates a window internally to display it, and that window is destroyed when the drag context is finalized. It could well be that what you are seeing is the drag context being kept alive until gc kicks in. 

Is there a way to trigger gc explicitly in D ? that might be a way to test that theory.
Comment 10 Gerald Nunn 2016-03-16 20:45:34 UTC
There is a way, however it would have to be triggered outside the drag method since while in the method the reference to the D DragContext wrapping class is still valid. I'll pull my old code tonite and add an action to trigger it to see if it makes any difference and post the result.
Comment 11 Matthias Clasen 2016-03-16 20:52:39 UTC
Created attachment 324140 [details] [review]
dnd: Hide the drag window when we're done

We were just relying on the drag context finalize() to destroy
the window. But with garbage-collected bindings, that might
not happen as soon as we like, so explicitly hide the window
when the drag ends successfully.
Comment 12 Carlos Garnacho 2016-03-16 21:20:14 UTC
Review of attachment 324140 [details] [review]:

Looks good, FWIW it seems that you can just hide the window always in wayland, as far as I've seen we just keep the last buffer around in the mutter side.

I'll leave a-c-n or a-c-afterfreeze to your discretion.
Comment 13 Gerald Nunn 2016-03-17 00:50:30 UTC
So I tested out calling GC.collect and it does indeed cause the drag image to disappear, interesting this was only ever in issue in GTK 3.19 and not previous versions.
Comment 14 Matthias Clasen 2016-03-17 01:02:53 UTC
(In reply to Gerald Nunn from comment #13)
> So I tested out calling GC.collect and it does indeed cause the drag image
> to disappear, interesting this was only ever in issue in GTK 3.19 and not
> previous versions.

Thats because DND support was rearchitected this cycle, moving much of the implementation down into GDK.
Comment 15 Matthias Clasen 2016-03-17 01:04:39 UTC
Review of attachment 324140 [details] [review]:

going to hold this until after the release.
Comment 16 Matthias Clasen 2016-03-21 15:35:53 UTC
Attachment 324140 [details] pushed as 068d382 - dnd: Hide the drag window when we're done