Re: Drag And Drop - "drag-motion" cursor lockup? [FIXED]



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 <gtk/gtk.h>
%}
%{

// 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 = NULL;
selfp->drop_data_ready = FALSE;
}
 // Un-draw the highlight.
if (TRUE == selfp->drop_highlight) {
gtk_drag_unhighlight(widget);
selfp->drop_highlight = FALSE;
}
}
}

On Thu, Apr 1, 2010 at 8:06 PM, Dan Saul <daniel saul gmail com> wrote:

Hi,

I am trying to implement drag and drop. Currently just trying to get the
destination working. I have the basics working, but if I attempt to do
custom "drag-motion" validation and I call gtk_drag_get_data() the Xserver
locks with a drag cursor. The only way to get out is to Alt-F1 then kill the
xserver (just the program doesn't unlock).
Has anyone encountered this before?

I am probably missing something simple.

Here is my code, thanks.

Tar'd with build script: http://www.slello.com/tmp/testdnd.tar.gz

Dan

/*http://www.jirka.org/gob2.1.html*/
%h{
#include <gtk/gtk.h>
%}
%{

enum {
        INFO_DEFAULT = 0,
        INFO_INT32,
        INFO_STRING,
        INFO_ROOTWIN
};

static GtkTargetEntry target_list[] = {
        //{ "INTEGER",    0, TARGET_INT32 },
        //{ "STRING",     0, TARGET_STRING },
        { "text/plain", 0, INFO_STRING },
        { "text/uri-list", 0, INFO_STRING },
        //{ "application/x-rootwindow-drop", 0, TARGET_ROOTWIN }
};

static guint n_targets = G_N_ELEMENTS (target_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),
GTK_DEST_DEFAULT_HIGHLIGHT|GTK_DEST_DEFAULT_DROP, target_list, n_targets,
GDK_ACTION_COPY);
 g_signal_connect (GTK_OBJECT(selfp->button), "drag-data-received",
G_CALLBACK(test_app_do_drag_data_recieved), self);
 g_signal_connect (GTK_OBJECT(selfp->button), "drag-motion",
G_CALLBACK(test_app_do_drag_motion), self);
 gtk_widget_show_all(GTK_WIDGET(selfp->window));
}
  private gboolean drag_highlight = FALSE;
private gboolean drag_pending = FALSE;
 private void do_drag_motion(GtkWidget *widget,
GdkDragContext *context,
 gint x,
gint y,
guint time,
 gpointer user_data)
{
g_print("do_drag_motion\n");
 GdkAtom target;
 Self* self = SELF(user_data);
 if (FALSE == selfp->drag_highlight) {
 selfp->drag_highlight = TRUE;
gtk_drag_highlight(widget);
}
 target = gtk_drag_dest_find_target (widget, context, NULL);
if (target == GDK_NONE)
 {
g_print("1\n");
gdk_drag_status (context, 0, time);
 }
else
 {
g_print("2\n");
  selfp->drag_pending = TRUE;
gtk_drag_get_data(widget, context, target, time);
  //gdk_drag_status(context,GDK_ACTION_COPY,time);
 }
 return TRUE;
 }

 private void do_drag_data_recieved(GtkWidget* widget,
       GdkDragContext* context,
       gint x,
       gint y,
       GtkSelectionData* data,
       guint info,
       guint time,
       gpointer user_data)
{
g_print("do_drag_data_recieved\n");
  Self* self = SELF(user_data);
 if (selfp->drag_pending)
{
 g_print("asdhfajklshdfljkash\n");
  gdk_drag_status(context,GDK_ACTION_COPY,time);
  selfp->drag_pending = FALSE;
}
 else
{
if (selfp->drag_highlight) {
 selfp->drag_highlight = FALSE;
gtk_drag_unhighlight(widget);
}
 if (NULL != data && data->length >= 0)
{
  //switch(info)
 //{
 //}
 g_print("do_drag_data_recieved %u %s\n",info,data->data);
 }
}
 }
}




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]