Preloading a GObject on a GtkDropTarget

,

Hello,

I’m trying to preload a custom GObject on a GtkDropTarget so that I can accept or reject the drop based on its data. Following the documentation, I have set the preload property of the target to true and connected to the notify::value signal.

However, it is never preloaded. The notify::value handler is only called when the cursor leaves the drop target and the value is set to null. When dropping the value, in the drop signal handler, I get the object as expected. But when dragging a GFile, it is correctly preloaded.

Do I need to implement something in my GObject? Or do I have to do something in particular in my GdkContentProvider/GdkContentFormats?

Here’s a minimal example:

import Gdk from 'gi://Gdk?version=4.0';
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk?version=4.0';

Gtk.init();


// Register a custom GObject
const MyObject = GObject.registerClass(class extends GObject.Object {});


const loop = GLib.MainLoop.new(null, false);


const window = new Gtk.Window();
window.connect('close-request', () => {
	loop.quit();
});

const box = new Gtk.Box({ spacing: 12 });
window.set_child(box);

// Create a draggable button holding a MyObject instance
const button1 = new Gtk.Button({ label: 'Drag me' });
button1.myObject = new MyObject();
box.append(button1);

const dragValue = new GObject.Value();
dragValue.init_from_instance(button1.myObject);

const dragSource = new Gtk.DragSource({
	actions: Gdk.DragAction.MOVE,
	content: Gdk.ContentProvider.new_for_value(dragValue),
});

button1.add_controller(dragSource);

// Create a second button acting as a drop target, accepting MyObjects and GFiles
const button2 = new Gtk.Button({ label: 'Drop here' });
box.append(button2);

const dropTarget = new Gtk.DropTarget({
	actions: Gdk.DragAction.MOVE,
	formats: Gdk.ContentFormats.new_for_gtype(MyObject).union(Gdk.ContentFormats.new_for_gtype(Gio.File)),
	preload: true,
});

dropTarget.connect('notify::value', (target) => {
	console.log(target.value);
});

dropTarget.connect('drop', (_target, value, _x, _y) => {
	console.log(value);
});

button2.add_controller(dropTarget);


window.present();


loop.run();