/* testdnd.c * Copyright (C) 1998 Red Hat, Inc. * Author: Owen Taylor * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #include "config.h" #include "gtk/gtk.h" /* Target side drag signals */ /* XPM */ static const char * drag_icon_xpm[] = { "36 48 9 1", " c None", ". c #020204", "+ c #8F8F90", "@ c #D3D3D2", "# c #AEAEAC", "$ c #ECECEC", "% c #A2A2A4", "& c #FEFEFC", "* c #BEBEBC", " .....................", " ..&&&&&&&&&&&&&&&&&&&.", " ...&&&&&&&&&&&&&&&&&&&.", " ..&.&&&&&&&&&&&&&&&&&&&.", " ..&&.&&&&&&&&&&&&&&&&&&&.", " ..&&&.&&&&&&&&&&&&&&&&&&&.", " ..&&&&.&&&&&&&&&&&&&&&&&&&.", " ..&&&&&.&&&@&&&&&&&&&&&&&&&.", " ..&&&&&&.*$%$+$&&&&&&&&&&&&&.", " ..&&&&&&&.%$%$+&&&&&&&&&&&&&&.", " ..&&&&&&&&.#&#@$&&&&&&&&&&&&&&.", " ..&&&&&&&&&.#$**#$&&&&&&&&&&&&&.", " ..&&&&&&&&&&.&@%&%$&&&&&&&&&&&&&.", " ..&&&&&&&&&&&.&&&&&&&&&&&&&&&&&&&.", " ..&&&&&&&&&&&&.&&&&&&&&&&&&&&&&&&&.", "................&$@&&&@&&&&&&&&&&&&.", ".&&&&&&&+&&#@%#+@#@*$%$+$&&&&&&&&&&.", ".&&&&&&&+&&#@#@&&@*%$%$+&&&&&&&&&&&.", ".&&&&&&&+&$%&#@&#@@#&#@$&&&&&&&&&&&.", ".&&&&&&@#@@$&*@&@#@#$**#$&&&&&&&&&&.", ".&&&&&&&&&&&&&&&&&&&@%&%$&&&&&&&&&&.", ".&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.", ".&&&&&&&&$#@@$&&&&&&&&&&&&&&&&&&&&&.", ".&&&&&&&&&+&$+&$&@&$@&&$@&&&&&&&&&&.", ".&&&&&&&&&+&&#@%#+@#@*$%&+$&&&&&&&&.", ".&&&&&&&&&+&&#@#@&&@*%$%$+&&&&&&&&&.", ".&&&&&&&&&+&$%&#@&#@@#&#@$&&&&&&&&&.", ".&&&&&&&&@#@@$&*@&@#@#$#*#$&&&&&&&&.", ".&&&&&&&&&&&&&&&&&&&&&$%&%$&&&&&&&&.", ".&&&&&&&&&&$#@@$&&&&&&&&&&&&&&&&&&&.", ".&&&&&&&&&&&+&$%&$$@&$@&&$@&&&&&&&&.", ".&&&&&&&&&&&+&&#@%#+@#@*$%$+$&&&&&&.", ".&&&&&&&&&&&+&&#@#@&&@*#$%$+&&&&&&&.", ".&&&&&&&&&&&+&$+&*@&#@@#&#@$&&&&&&&.", ".&&&&&&&&&&$%@@&&*@&@#@#$#*#&&&&&&&.", ".&&&&&&&&&&&&&&&&&&&&&&&$%&%$&&&&&&.", ".&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.", ".&&&&&&&&&&&&&&$#@@$&&&&&&&&&&&&&&&.", ".&&&&&&&&&&&&&&&+&$%&$$@&$@&&$@&&&&.", ".&&&&&&&&&&&&&&&+&&#@%#+@#@*$%$+$&&.", ".&&&&&&&&&&&&&&&+&&#@#@&&@*#$%$+&&&.", ".&&&&&&&&&&&&&&&+&$+&*@&#@@#&#@$&&&.", ".&&&&&&&&&&&&&&$%@@&&*@&@#@#$#*#&&&.", ".&&&&&&&&&&&&&&&&&&&&&&&&&&&$%&%$&&.", ".&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.", ".&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.", ".&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.", "...................................."}; /* XPM */ static const char * trashcan_closed_xpm[] = { "64 80 17 1", " c None", ". c #030304", "+ c #5A5A5C", "@ c #323231", "# c #888888", "$ c #1E1E1F", "% c #767677", "& c #494949", "* c #9E9E9C", "= c #111111", "- c #3C3C3D", "; c #6B6B6B", "> c #949494", ", c #282828", "' c #808080", ") c #545454", "! c #AEAEAC", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ==......=$$...=== ", " ..$------)+++++++++++++@$$... ", " ..=@@-------&+++++++++++++++++++-.... ", " =.$$@@@-&&)++++)-,$$$$=@@&+++++++++++++,..$ ", " .$$$$@@&+++++++&$$$@@@@-&,$,-++++++++++;;;&.. ", " $$$$,@--&++++++&$$)++++++++-,$&++++++;%%'%%;;$@ ", " .-@@-@-&++++++++-@++++++++++++,-++++++;''%;;;%*-$ ", " +------++++++++++++++++++++++++++++++;;%%%;;##*!. ", " =+----+++++++++++++++++++++++;;;;;;;;;;;;%'>>). ", " .=)&+++++++++++++++++;;;;;;;;;;;;;;%''>>#>#@. ", " =..=&++++++++++++;;;;;;;;;;;;;%###>>###+%== ", " .&....=-+++++%;;####''''''''''##'%%%)..#. ", " .+-++@....=,+%#####'%%%%%%%%%;@$-@-@*++!. ", " .+-++-+++-&-@$$=$=......$,,,@;&)+!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " =+-++-+++-+++++++++!++++!++++!+++!++!+++= ", " $.++-+++-+++++++++!++++!++++!+++!++!+.$ ", " =.++++++++++++++!++++!++++!+++!++.= ", " $..+++++++++++++++!++++++...$ ", " $$=.............=$$ ", " ", " ", " ", " ", " ", " ", " ", " ", " "}; /* XPM */ static const char * trashcan_open_xpm[] = { "64 80 17 1", " c None", ". c #030304", "+ c #5A5A5C", "@ c #323231", "# c #888888", "$ c #1E1E1F", "% c #767677", "& c #494949", "* c #9E9E9C", "= c #111111", "- c #3C3C3D", "; c #6B6B6B", "> c #949494", ", c #282828", "' c #808080", ") c #545454", "! c #AEAEAC", " ", " ", " ", " ", " ", " ", " .=.==.,@ ", " ==.,@-&&&)-= ", " .$@,&++;;;%>*- ", " $,-+)+++%%;;'#+. ", " =---+++++;%%%;%##@. ", " @)++++++++;%%%%'#%$ ", " $&++++++++++;%%;%##@= ", " ,-++++)+++++++;;;'#%) ", " @+++&&--&)++++;;%'#'-. ", " ,&++-@@,,,,-)++;;;'>'+, ", " =-++&@$@&&&&-&+;;;%##%+@ ", " =,)+)-,@@&+++++;;;;%##%&@ ", " @--&&,,@&)++++++;;;;'#)@ ", " ---&)-,@)+++++++;;;%''+, ", " $--&)+&$-+++++++;;;%%'';- ", " .,-&+++-$&++++++;;;%''%&= ", " $,-&)++)-@++++++;;%''%), ", " =,@&)++++&&+++++;%'''+$@&++++++ ", " .$@-++++++++++++;'#';,........=$@&++++ ", " =$@@&)+++++++++++'##-.................=&++ ", " .$$@-&)+++++++++;%#+$.....................=)+ ", " $$,@-)+++++++++;%;@=........................,+ ", " .$$@@-++++++++)-)@=............................ ", " $,@---)++++&)@===............................,. ", " $-@---&)))-$$=..............................=)!. ", " --&-&&,,$=,==...........................=&+++!. ", " =,=$..=$+)+++++&@$=.............=$@&+++++!++!. ", " .)-++-+++++++++++++++++++++++++++!++!++!. ", " .+-++-+++++++++++++++++++++++!+++!++!++!. ", " .+-++-+++-+++++++++!+++!!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", " =+-++-+++-+++++++++!++++!++++!+++!++!+++= ", " $.++-+++-+++++++++!++++!++++!+++!++!+.$ ", " =.++++++++++++++!++++!++++!+++!++.= ", " $..+++++++++++++++!++++++...$ ", " $$==...........==$$ ", " ", " ", " ", " ", " ", " ", " ", " ", " "}; GdkPixbuf *trashcan_open; GdkPixbuf *trashcan_closed; gboolean have_drag; enum { TARGET_STRING, TARGET_ROOTWIN }; static GtkTargetEntry target_table[] = { { "STRING", 0, TARGET_STRING }, { "text/plain", 0, TARGET_STRING }, { "application/x-rootwindow-drop", 0, TARGET_ROOTWIN } }; static guint n_targets = sizeof(target_table) / sizeof(target_table[0]); void target_drag_leave (GtkWidget *widget, GdkDragContext *context, guint time) { g_print("leave\n"); have_drag = FALSE; gtk_image_set_from_pixbuf (GTK_IMAGE (widget), trashcan_closed); } gboolean target_drag_motion (GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint time) { GtkWidget *source_widget; GList *tmp_list; if (!have_drag) { have_drag = TRUE; gtk_image_set_from_pixbuf (GTK_IMAGE (widget), trashcan_open); } source_widget = gtk_drag_get_source_widget (context); g_print ("motion, source %s\n", source_widget ? G_OBJECT_TYPE_NAME (source_widget) : "NULL"); tmp_list = context->targets; while (tmp_list) { char *name = gdk_atom_name (GDK_POINTER_TO_ATOM (tmp_list->data)); g_print ("%s\n", name); g_free (name); tmp_list = tmp_list->next; } gdk_drag_status (context, context->suggested_action, time); return TRUE; } gboolean target_drag_drop (GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint time) { g_print("drop\n"); have_drag = FALSE; gtk_image_set_from_pixbuf (GTK_IMAGE (widget), trashcan_closed); if (context->targets) { gtk_drag_get_data (widget, context, GDK_POINTER_TO_ATOM (context->targets->data), time); return TRUE; } return FALSE; } void target_drag_data_received (GtkWidget *widget, GdkDragContext *context, gint x, gint y, GtkSelectionData *data, guint info, guint time) { if ((data->length >= 0) && (data->format == 8)) { g_print ("Received \"%s\" in trashcan\n", (gchar *)data->data); gtk_drag_finish (context, TRUE, FALSE, time); return; } gtk_drag_finish (context, FALSE, FALSE, time); } void label_drag_data_received (GtkWidget *widget, GdkDragContext *context, gint x, gint y, GtkSelectionData *data, guint info, guint time) { if ((data->length >= 0) && (data->format == 8)) { g_print ("Received \"%s\" in label\n", (gchar *)data->data); gtk_drag_finish (context, TRUE, FALSE, time); return; } gtk_drag_finish (context, FALSE, FALSE, time); } void source_drag_data_get (GtkWidget *widget, GdkDragContext *context, GtkSelectionData *selection_data, guint info, guint time, gpointer data) { if (info == TARGET_ROOTWIN) g_print ("I was dropped on the rootwin\n"); else gtk_selection_data_set (selection_data, selection_data->target, 8, (guchar *) "I'm Data!", 9); } /* The following is a rather elaborate example demonstrating/testing * changing of the window hierarchy during a drag - in this case, * via a "spring-loaded" popup window. */ static GtkWidget *popup_window = NULL; static gboolean popped_up = FALSE; static gboolean in_popup = FALSE; static guint popdown_timer = 0; static guint popup_timer = 0; gint popdown_cb (gpointer data) { popdown_timer = 0; gtk_widget_hide (popup_window); popped_up = FALSE; return FALSE; } gboolean popup_motion (GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint time) { if (!in_popup) { in_popup = TRUE; if (popdown_timer) { g_print ("removed popdown\n"); g_source_remove (popdown_timer); popdown_timer = 0; } } return TRUE; } void popup_leave (GtkWidget *widget, GdkDragContext *context, guint time) { if (in_popup) { in_popup = FALSE; if (!popdown_timer) { g_print ("added popdown\n"); popdown_timer = gdk_threads_add_timeout (500, popdown_cb, NULL); } } } gboolean popup_cb (gpointer data) { if (!popped_up) { if (!popup_window) { GtkWidget *button; GtkWidget *table; int i, j; popup_window = gtk_window_new (GTK_WINDOW_POPUP); gtk_window_set_position (GTK_WINDOW (popup_window), GTK_WIN_POS_MOUSE); table = gtk_table_new (3,3, FALSE); for (i=0; i<3; i++) for (j=0; j<3; j++) { char buffer[128]; g_snprintf(buffer, sizeof(buffer), "%d,%d", i, j); button = gtk_button_new_with_label (buffer); gtk_table_attach (GTK_TABLE (table), button, i, i+1, j, j+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_drag_dest_set (button, GTK_DEST_DEFAULT_ALL, target_table, n_targets - 1, /* no rootwin */ GDK_ACTION_COPY | GDK_ACTION_MOVE); g_signal_connect (button, "drag_motion", G_CALLBACK (popup_motion), NULL); g_signal_connect (button, "drag_leave", G_CALLBACK (popup_leave), NULL); } gtk_widget_show_all (table); gtk_container_add (GTK_CONTAINER (popup_window), table); } gtk_widget_show (popup_window); popped_up = TRUE; } popdown_timer = gdk_threads_add_timeout (500, popdown_cb, NULL); g_print ("added popdown\n"); popup_timer = FALSE; return FALSE; } gboolean popsite_motion (GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint time) { if (!popup_timer) popup_timer = gdk_threads_add_timeout (500, popup_cb, NULL); return TRUE; } void popsite_leave (GtkWidget *widget, GdkDragContext *context, guint time) { if (popup_timer) { g_source_remove (popup_timer); popup_timer = 0; } } void source_drag_data_delete (GtkWidget *widget, GdkDragContext *context, gpointer data) { g_print ("Delete the data!\n"); } void test_init (void) { if (g_file_test ("../gdk-pixbuf/libpixbufloader-pnm.la", G_FILE_TEST_EXISTS)) { g_setenv ("GDK_PIXBUF_MODULE_FILE", "../gdk-pixbuf/gdk-pixbuf.loaders", TRUE); g_setenv ("GTK_IM_MODULE_FILE", "../modules/input/gtk.immodules", TRUE); } } int main (int argc, char **argv) { GtkWidget *window; GtkWidget *table; GtkWidget *label; GtkWidget *pixmap; GtkWidget *button; GdkPixbuf *drag_icon; test_init (); gtk_init (&argc, &argv); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL); table = gtk_table_new (2, 2, FALSE); gtk_container_add (GTK_CONTAINER (window), table); drag_icon = gdk_pixbuf_new_from_xpm_data (drag_icon_xpm); trashcan_open = gdk_pixbuf_new_from_xpm_data (trashcan_open_xpm); trashcan_closed = gdk_pixbuf_new_from_xpm_data (trashcan_closed_xpm); label = gtk_label_new ("Drop Here\n"); gtk_drag_dest_set (label, GTK_DEST_DEFAULT_ALL, target_table, n_targets - 1, /* no rootwin */ GDK_ACTION_COPY | GDK_ACTION_MOVE); g_signal_connect (label, "drag_data_received", G_CALLBACK( label_drag_data_received), NULL); gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); label = gtk_label_new ("Popup\n"); gtk_drag_dest_set (label, GTK_DEST_DEFAULT_ALL, target_table, n_targets - 1, /* no rootwin */ GDK_ACTION_COPY | GDK_ACTION_MOVE); gtk_table_attach (GTK_TABLE (table), label, 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); g_signal_connect (label, "drag_motion", G_CALLBACK (popsite_motion), NULL); g_signal_connect (label, "drag_leave", G_CALLBACK (popsite_leave), NULL); pixmap = gtk_image_new_from_pixbuf (trashcan_closed); gtk_drag_dest_set (pixmap, 0, NULL, 0, 0); gtk_table_attach (GTK_TABLE (table), pixmap, 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); g_signal_connect (pixmap, "drag_leave", G_CALLBACK (target_drag_leave), NULL); g_signal_connect (pixmap, "drag_motion", G_CALLBACK (target_drag_motion), NULL); g_signal_connect (pixmap, "drag_drop", G_CALLBACK (target_drag_drop), NULL); g_signal_connect (pixmap, "drag_data_received", G_CALLBACK (target_drag_data_received), NULL); /* Drag site */ button = gtk_button_new_with_label ("Drag Here\n"); gtk_drag_source_set (button, GDK_BUTTON1_MASK | GDK_BUTTON3_MASK, target_table, n_targets, GDK_ACTION_COPY | GDK_ACTION_MOVE); gtk_drag_source_set_icon_pixbuf (button, drag_icon); g_object_unref (drag_icon); gtk_table_attach (GTK_TABLE (table), button, 0, 1, 1, 2, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); g_signal_connect (button, "drag_data_get", G_CALLBACK (source_drag_data_get), NULL); g_signal_connect (button, "drag_data_delete", G_CALLBACK (source_drag_data_delete), NULL); gtk_widget_show_all (window); gtk_main (); return 0; }