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();