I wrote a program that can send file to and receive from Nautilus or Nemo file managers, and it worked fine in Gnome Shell 3.30 and its Nautilus. But now I can’t send files to Nautilus from my app under Wayland, it always returns a Gtk.DragResult.ERROR, even before call drag-data-get. But under X11 it works like a charm.
I attach a proof-of-concept piece of code that shows an icon that can be dragged over a Nautilus or Nemo window. If you try it, you will see that under X11 it works fine (and, of course, fails, because it is dragging a non-existent file, but that is OK); but under Wayland, when doing the Drop, the “drag-failed” signal is triggered instead of “drag-data-get”, and with a “generic error”.
Is it a bug in Gtk, or it is my fault?
#!/usr/bin/env gjs
imports.gi.versions.Gtk = '3.0';
const Gtk = imports.gi.Gtk;
const Gdk = imports.gi.Gdk;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const ByteArray = imports.byteArray;
Gtk.init(null);
let window = new Gtk.Window();
let eventBox = new Gtk.EventBox({visible: true});
let container = new Gtk.Box({orientation: Gtk.Orientation.VERTICAL});
let label = new Gtk.Label({label: "Drag the icon into a Nautilus or Nemo window"});
eventBox.add(container);
window.add(eventBox);
let pixbuf = Gtk.IconTheme.get_default().load_icon("text-x-generic", 32, Gtk.IconLookupFlags.FORCE_SIZE);
let icon = new Gtk.Image();
icon.set_from_pixbuf(pixbuf);
container.pack_start(icon, true, true, 0);
container.pack_start(label, true, true, 0);
eventBox.drag_source_set(Gdk.ModifierType.BUTTON1_MASK, null, Gdk.DragAction.MOVE || Gdk.DragAction.COPY);
eventBox.drag_source_set_icon_pixbuf(pixbuf);
let targets = new Gtk.TargetList(null);
targets.add(Gdk.atom_intern('x-special/gnome-icon-list', false), 0, 0);
targets.add(Gdk.atom_intern('text/uri-list', false), 0, 1);
eventBox.drag_source_set_target_list(targets);
eventBox.connect('drag-begin', (widget, context) => {
print("Drag begin");
});
eventBox.connect('drag-failed', (widget, context, result) => {
print("Drag failed");
switch(result) {
case Gtk.DragResult.ERROR:
print("Gtk.DragResult.ERROR");
break;
case Gtk.DragResult.GRAB_BROKEN:
print("Gtk.DragResult.GRAB_BROKEN");
break;
case Gtk.DragResult.NO_TARGET:
print("Gtk.DragResult.NO_TARGET");
break;
case Gtk.DragResult.SUCCESS:
print("Gtk.DragResult.SUCCESS");
break;
case Gtk.DragResult.TIMEOUT_EXPIRED:
print("Gtk.DragResult.TIMEOUT_EXPIRED");
break;
case Gtk.DragResult.USER_CANCELLED:
print("Gtk.DragResult.USER_CANCELLED");
break;
default:
print("Unknown DragResult error");
break;
}
});
eventBox.connect('drag-data-get', (widget, context, data, info, time) => {
print("Called drag-data-get");
let atom;
switch(info) {
case 0: // x-special/gnome-icon-list
atom = Gdk.atom_intern('x-special/gnome-icon-list', false);
break;
case 1: // text/uri-list
atom = Gdk.atom_intern('text/uri-list', false);
break;
}
let dragData = "file:///a_drag_test.txt\r\n";
let list = ByteArray.fromString(dragData);
data.set(atom, 8, list);
});
window.show_all();
Gtk.main();