I was wondering how to drag and drop in GTK3. The code here is for GTK2, and does not work in GTK3. The compiler complains about there being no data
element in seldata
in onDragDataReceived
. And also, this would not work if you have multiple files in one drag and drop.
How to do drag and drop in GTK3
The drag and drop implemented here is only for copying files into an application. So, the first thing to do is to make your target entries, that is what sort of thing can be dragged in. For text editors, you would allow text to be dragged in. But in this example, we only want to drag in files.
static GtkTargetEntry targetentries[] =
{
{ "text/uri-list", 0, 0}
};
Now that we have the target entries, we can make the specific widget into a drag and drop destination.
gtk_drag_dest_set ( your_widget_here, GTK_DEST_DEFAULT_ALL, targetentries, 1, GDK_ACTION_COPY);
And now for the signal handler:
g_signal_connect (your_widget_here, "drag-data-received", G_CALLBACK (on_drag_data_received), some_data_to_pass_along);
So, when you drop a file on your widget, it will emit the signal, because you prep’d it by making it a dnd destination.
Here is the callback function:
void on_drag_data_received (GtkWidget *wgt, GdkDragContext *context, gint x, gint y, GtkSelectionData *seldata, guint info, guint time, gpointer data)
{
gchar **filenames = NULL;
filenames = g_uri_list_extract_uris((const gchar *) gtk_selection_data_get_data (seldata));
if (filenames == NULL) // If unable to retrieve filenames:
{
g_printerr(“FAILURE!”);
gtk_drag_finish(context, FALSE, FALSE, time); // Drag and drop was a failure.
return;
}
int iter = 0;
while(filenames[iter] != NULL) // The last URI list element is NULL.
{
char *filename = g_filename_from_uri (filenames[iter], NULL, NULL);
// Do something useful with the file, like opening it, right here.
iter++;
}
gtk_drag_finish(context, TRUE, FALSE, time); // Drag and drop was successful!
}
And you are done!