Since gtk-app-devel-list was useless, I am going to post a working full DnD
example here that others can use in case they search for the same problem
and locate this thread.
This example is going to be in GOB format. But since that generates C you
can use that if you care. This example will accept file-system drops but
only if a URI contains .jpg
/*http://www.jirka.org/gob2.1.html*/
%h{
#include
%}
%{
// Identifiers for DnD target types.
enum
{
TARGET_TEXT_URI_LIST,
};
// Target types for dropping into the tree view.
static const GtkTargetEntry drop_targets[] = {
{ "text/uri-list", 0, TARGET_TEXT_URI_LIST },
};
%}
class Test:App from G:Object
{
private GtkBuilder* builder = {gtk_builder_new()} unrefwith g_object_unref;
private GtkWindow* window = NULL;
private GtkButton* button = NULL;
init(self)
{
gtk_builder_add_from_file(selfp->builder,"MainWindow.glade", NULL);
selfp->window =
GTK_WINDOW(gtk_builder_get_object(selfp->builder,"window1"));
selfp->button =
GTK_BUTTON(gtk_builder_get_object(selfp->builder,"button1"));
gtk_builder_connect_signals (selfp->builder, NULL);
g_signal_connect (selfp->window, "destroy", G_CALLBACK (gtk_main_quit),
NULL);
gtk_drag_dest_set (GTK_WIDGET (selfp->button), 0, drop_targets,
G_N_ELEMENTS (drop_targets),
GDK_ACTION_COPY | GDK_ACTION_LINK | GDK_ACTION_MOVE);
// Connect to drag and drop signals.
g_signal_connect (GTK_OBJECT(selfp->button), "drag-data-received",
G_CALLBACK(self_do_drag_data_received), self);
g_signal_connect (GTK_OBJECT(selfp->button), "drag-drop",
G_CALLBACK(self_do_drag_drop), self);
g_signal_connect (GTK_OBJECT(selfp->button), "drag-motion",
G_CALLBACK(self_do_drag_motion), self);
g_signal_connect (GTK_OBJECT(selfp->button), "drag-leave",
G_CALLBACK(self_do_drag_leave), self);
// Show the window.
gtk_widget_show_all(GTK_WIDGET(selfp->window));
}
//
http://library.gnome.org/devel/gtk/unstable/GtkWidget.html#GtkWidget-drag-drop
private gboolean drop_data_ready = FALSE;
private gboolean drop_occurred = FALSE;
private gboolean drop_highlight = FALSE;
private gchar* drop_data = NULL destroywith g_free;
private void do_drag_data_received(GtkWidget* widget,
GdkDragContext* context,
gint x,
gint y,
GtkSelectionData* data,
guint info,
guint time,
gpointer user_data)
{
Self* self = SELF(user_data);
// Check to see if we have the drop data yet.
if (FALSE == selfp->drop_data_ready)
{
// If this is data we expected or can handle, then process it.
if (TARGET_TEXT_URI_LIST == info &&
gtk_selection_data_get_format(data) == 8 &&
gtk_selection_data_get_length(data) > 0)
{
selfp->drop_data = g_strdup((gchar*)gtk_selection_data_get_data(data));
selfp->drop_data_ready = TRUE;
}
}
// Actual drop handling code.
if (TRUE == selfp->drop_occurred)
{
// Reset state.
selfp->drop_occurred = FALSE;
g_print("RECEIVED DROP `%s`\n",selfp->drop_data);
// Notify whether we handled the drop or not.
gtk_drag_finish(context,TRUE /* success or not */,FALSE,time);
// Clean up.
self_do_drag_leave(widget, context, time, user_data);
}
}
private gboolean do_drag_drop(GtkWidget* widget, GdkDragContext* context,
gint x, gint y, guint time, gpointer user_data)
{
Self* self = SELF(user_data);
// Get drop target datatype.
GdkAtom target = gtk_drag_dest_find_target (widget, context, NULL);
// Is it something we can handle?
if (target == gdk_atom_intern("text/uri-list", FALSE))
{
// Tell data recieved handler (do_drag_data_received) we can actually handle
the drop.
selfp->drop_occurred = TRUE;
gtk_drag_get_data(widget,context,target,time);
// We can handle this data type.
return TRUE;
}
else
{
// We cannot handle the drop.
return FALSE;
}
}
private gboolean do_drag_motion(GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
guint time,
gpointer user_data)
{
Self* self = SELF(user_data);
// Get drop target datatype.
GdkAtom target = gtk_drag_dest_find_target (widget, context, NULL);
if (target != gdk_atom_intern ("text/uri-list", FALSE))
{
// not something we can handle
return FALSE;
}
// If we don't have the drop data yet, request it (so we can validate it).
if (FALSE == selfp->drop_data_ready)
{
// Request drag data from the source.
gtk_drag_get_data (widget, context, target, time);
// Tell Gdk we are unsure whether we can handle this drop.
gdk_drag_status (context, 0, time);
return TRUE;
}
else
{
// Make sure the drop data has `.jpg` inside of it.
if (NULL == g_strstr_len(selfp->drop_data,-1,".jpg")) {
return FALSE;
}
else
{
// Tell Gdk we can handle this.
gdk_drag_status(context, GDK_ACTION_COPY, time);
// Draw drop highlight (but only once).
if (FALSE == selfp->drop_highlight) {
gtk_drag_highlight(widget);
selfp->drop_highlight = TRUE;
}
return TRUE;
}
}
}
private void do_drag_leave(GtkWidget* widget, GdkDragContext* context,
guint time, gpointer user_data)
{
Self* self = SELF(user_data);
// Cleanup drag data.
if (TRUE == selfp->drop_data_ready)
{
g_free(selfp->drop_data);
selfp->drop_data =