1/* testdnd.c
2 * Copyright (C) 1998 Red Hat, Inc.
3 * Author: Owen Taylor
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include "config.h"
20#include "gtk/gtk.h"
21
22/* Target side drag signals */
23
24/* XPM */
25static const char * drag_icon_xpm[] = {
26"36 48 9 1",
27" c None",
28". c #020204",
29"+ c #8F8F90",
30"@ c #D3D3D2",
31"# c #AEAEAC",
32"$ c #ECECEC",
33"% c #A2A2A4",
34"& c #FEFEFC",
35"* c #BEBEBC",
36" .....................",
37" ..&&&&&&&&&&&&&&&&&&&.",
38" ...&&&&&&&&&&&&&&&&&&&.",
39" ..&.&&&&&&&&&&&&&&&&&&&.",
40" ..&&.&&&&&&&&&&&&&&&&&&&.",
41" ..&&&.&&&&&&&&&&&&&&&&&&&.",
42" ..&&&&.&&&&&&&&&&&&&&&&&&&.",
43" ..&&&&&.&&&@&&&&&&&&&&&&&&&.",
44" ..&&&&&&.*$%$+$&&&&&&&&&&&&&.",
45" ..&&&&&&&.%$%$+&&&&&&&&&&&&&&.",
46" ..&&&&&&&&.#&#@$&&&&&&&&&&&&&&.",
47" ..&&&&&&&&&.#$**#$&&&&&&&&&&&&&.",
48" ..&&&&&&&&&&.&@%&%$&&&&&&&&&&&&&.",
49" ..&&&&&&&&&&&.&&&&&&&&&&&&&&&&&&&.",
50" ..&&&&&&&&&&&&.&&&&&&&&&&&&&&&&&&&.",
51"................&$@&&&@&&&&&&&&&&&&.",
52".&&&&&&&+&&#@%#+@#@*$%$+$&&&&&&&&&&.",
53".&&&&&&&+&&#@#@&&@*%$%$+&&&&&&&&&&&.",
54".&&&&&&&+&$%&#@&#@@#&#@$&&&&&&&&&&&.",
55".&&&&&&@#@@$&*@&@#@#$**#$&&&&&&&&&&.",
56".&&&&&&&&&&&&&&&&&&&@%&%$&&&&&&&&&&.",
57".&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.",
58".&&&&&&&&$#@@$&&&&&&&&&&&&&&&&&&&&&.",
59".&&&&&&&&&+&$+&$&@&$@&&$@&&&&&&&&&&.",
60".&&&&&&&&&+&&#@%#+@#@*$%&+$&&&&&&&&.",
61".&&&&&&&&&+&&#@#@&&@*%$%$+&&&&&&&&&.",
62".&&&&&&&&&+&$%&#@&#@@#&#@$&&&&&&&&&.",
63".&&&&&&&&@#@@$&*@&@#@#$#*#$&&&&&&&&.",
64".&&&&&&&&&&&&&&&&&&&&&$%&%$&&&&&&&&.",
65".&&&&&&&&&&$#@@$&&&&&&&&&&&&&&&&&&&.",
66".&&&&&&&&&&&+&$%&$$@&$@&&$@&&&&&&&&.",
67".&&&&&&&&&&&+&&#@%#+@#@*$%$+$&&&&&&.",
68".&&&&&&&&&&&+&&#@#@&&@*#$%$+&&&&&&&.",
69".&&&&&&&&&&&+&$+&*@&#@@#&#@$&&&&&&&.",
70".&&&&&&&&&&$%@@&&*@&@#@#$#*#&&&&&&&.",
71".&&&&&&&&&&&&&&&&&&&&&&&$%&%$&&&&&&.",
72".&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.",
73".&&&&&&&&&&&&&&$#@@$&&&&&&&&&&&&&&&.",
74".&&&&&&&&&&&&&&&+&$%&$$@&$@&&$@&&&&.",
75".&&&&&&&&&&&&&&&+&&#@%#+@#@*$%$+$&&.",
76".&&&&&&&&&&&&&&&+&&#@#@&&@*#$%$+&&&.",
77".&&&&&&&&&&&&&&&+&$+&*@&#@@#&#@$&&&.",
78".&&&&&&&&&&&&&&$%@@&&*@&@#@#$#*#&&&.",
79".&&&&&&&&&&&&&&&&&&&&&&&&&&&$%&%$&&.",
80".&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.",
81".&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.",
82".&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.",
83"...................................."};
84
85/* XPM */
86static const char * trashcan_closed_xpm[] = {
87"64 80 17 1",
88" c None",
89". c #030304",
90"+ c #5A5A5C",
91"@ c #323231",
92"# c #888888",
93"$ c #1E1E1F",
94"% c #767677",
95"& c #494949",
96"* c #9E9E9C",
97"= c #111111",
98"- c #3C3C3D",
99"; c #6B6B6B",
100"> c #949494",
101", c #282828",
102"' c #808080",
103") c #545454",
104"! c #AEAEAC",
105" ",
106" ",
107" ",
108" ",
109" ",
110" ",
111" ",
112" ",
113" ",
114" ",
115" ",
116" ",
117" ",
118" ",
119" ",
120" ",
121" ",
122" ",
123" ",
124" ",
125" ",
126" ",
127" ==......=$$...=== ",
128" ..$------)+++++++++++++@$$... ",
129" ..=@@-------&+++++++++++++++++++-.... ",
130" =.$$@@@-&&)++++)-,$$$$=@@&+++++++++++++,..$ ",
131" .$$$$@@&+++++++&$$$@@@@-&,$,-++++++++++;;;&.. ",
132" $$$$,@--&++++++&$$)++++++++-,$&++++++;%%'%%;;$@ ",
133" .-@@-@-&++++++++-@++++++++++++,-++++++;''%;;;%*-$ ",
134" +------++++++++++++++++++++++++++++++;;%%%;;##*!. ",
135" =+----+++++++++++++++++++++++;;;;;;;;;;;;%'>>). ",
136" .=)&+++++++++++++++++;;;;;;;;;;;;;;%''>>#>#@. ",
137" =..=&++++++++++++;;;;;;;;;;;;;%###>>###+%== ",
138" .&....=-+++++%;;####''''''''''##'%%%)..#. ",
139" .+-++@....=,+%#####'%%%%%%%%%;@$-@-@*++!. ",
140" .+-++-+++-&-@$$=$=......$,,,@;&)+!++!++!. ",
141" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
142" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
143" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
144" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
145" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
146" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
147" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
148" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
149" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
150" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
151" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
152" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
153" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
154" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
155" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
156" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
157" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
158" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
159" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
160" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
161" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
162" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
163" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
164" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
165" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
166" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
167" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
168" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
169" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
170" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
171" =+-++-+++-+++++++++!++++!++++!+++!++!+++= ",
172" $.++-+++-+++++++++!++++!++++!+++!++!+.$ ",
173" =.++++++++++++++!++++!++++!+++!++.= ",
174" $..+++++++++++++++!++++++...$ ",
175" $$=.............=$$ ",
176" ",
177" ",
178" ",
179" ",
180" ",
181" ",
182" ",
183" ",
184" "};
185
186/* XPM */
187static const char * trashcan_open_xpm[] = {
188"64 80 17 1",
189" c None",
190". c #030304",
191"+ c #5A5A5C",
192"@ c #323231",
193"# c #888888",
194"$ c #1E1E1F",
195"% c #767677",
196"& c #494949",
197"* c #9E9E9C",
198"= c #111111",
199"- c #3C3C3D",
200"; c #6B6B6B",
201"> c #949494",
202", c #282828",
203"' c #808080",
204") c #545454",
205"! c #AEAEAC",
206" ",
207" ",
208" ",
209" ",
210" ",
211" ",
212" .=.==.,@ ",
213" ==.,@-&&&)-= ",
214" .$@,&++;;;%>*- ",
215" $,-+)+++%%;;'#+. ",
216" =---+++++;%%%;%##@. ",
217" @)++++++++;%%%%'#%$ ",
218" $&++++++++++;%%;%##@= ",
219" ,-++++)+++++++;;;'#%) ",
220" @+++&&--&)++++;;%'#'-. ",
221" ,&++-@@,,,,-)++;;;'>'+, ",
222" =-++&@$@&&&&-&+;;;%##%+@ ",
223" =,)+)-,@@&+++++;;;;%##%&@ ",
224" @--&&,,@&)++++++;;;;'#)@ ",
225" ---&)-,@)+++++++;;;%''+, ",
226" $--&)+&$-+++++++;;;%%'';- ",
227" .,-&+++-$&++++++;;;%''%&= ",
228" $,-&)++)-@++++++;;%''%), ",
229" =,@&)++++&&+++++;%'''+$@&++++++ ",
230" .$@-++++++++++++;'#';,........=$@&++++ ",
231" =$@@&)+++++++++++'##-.................=&++ ",
232" .$$@-&)+++++++++;%#+$.....................=)+ ",
233" $$,@-)+++++++++;%;@=........................,+ ",
234" .$$@@-++++++++)-)@=............................ ",
235" $,@---)++++&)@===............................,. ",
236" $-@---&)))-$$=..............................=)!. ",
237" --&-&&,,$=,==...........................=&+++!. ",
238" =,=$..=$+)+++++&@$=.............=$@&+++++!++!. ",
239" .)-++-+++++++++++++++++++++++++++!++!++!. ",
240" .+-++-+++++++++++++++++++++++!+++!++!++!. ",
241" .+-++-+++-+++++++++!+++!!++++!+++!++!++!. ",
242" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
243" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
244" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
245" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
246" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
247" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
248" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
249" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
250" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
251" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
252" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
253" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
254" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
255" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
256" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
257" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
258" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
259" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
260" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
261" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
262" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
263" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
264" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
265" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
266" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
267" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
268" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
269" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
270" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
271" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ",
272" =+-++-+++-+++++++++!++++!++++!+++!++!+++= ",
273" $.++-+++-+++++++++!++++!++++!+++!++!+.$ ",
274" =.++++++++++++++!++++!++++!+++!++.= ",
275" $..+++++++++++++++!++++++...$ ",
276" $$==...........==$$ ",
277" ",
278" ",
279" ",
280" ",
281" ",
282" ",
283" ",
284" ",
285" "};
286
287GdkPixbuf *trashcan_open;
288GdkPixbuf *trashcan_closed;
289
290
291static GdkDragAction
292action_make_unique (GdkDragAction action)
293{
294 if (gdk_drag_action_is_unique (action))
295 return action;
296
297 if (action & GDK_ACTION_COPY)
298 return GDK_ACTION_COPY;
299
300 if (action & GDK_ACTION_MOVE)
301 return GDK_ACTION_MOVE;
302
303 if (action & GDK_ACTION_LINK)
304 return GDK_ACTION_LINK;
305
306 g_assert_not_reached ();
307 return 0;
308}
309
310static GdkDragAction
311trash_drag_enter (GtkDropTarget *dest,
312 GdkDrop *drop,
313 double x,
314 double y,
315 GtkWidget *widget)
316{
317 char *s;
318
319 gtk_image_set_from_pixbuf (GTK_IMAGE (widget), pixbuf: trashcan_open);
320
321 s = gdk_content_formats_to_string (formats: gdk_drop_get_formats (self: drop));
322 g_print (format: "trash enter: %s\n", s);
323 g_free (mem: s);
324
325 return action_make_unique (action: gdk_drop_get_actions (self: drop));;
326}
327
328static GdkDragAction
329trash_drag_leave (GtkDropTarget *dest,
330 GdkDrop *drop,
331 GtkWidget *widget)
332{
333 char *s;
334
335 gtk_image_set_from_pixbuf (GTK_IMAGE (widget), pixbuf: trashcan_closed);
336
337 s = gdk_content_formats_to_string (formats: gdk_drop_get_formats (self: drop));
338 g_print (format: "trash leave: %s\n", s);
339 g_free (mem: s);
340
341 return action_make_unique (action: gdk_drop_get_actions (self: drop));
342}
343
344static gboolean
345trash_drag_drop (GtkDropTarget *dest,
346 GdkDrop *drop,
347 double x,
348 double y,
349 GtkWidget *widget)
350{
351 char *s;
352
353 s = gdk_content_formats_to_string (formats: gdk_drop_get_formats (self: drop));
354 g_print (format: "trash drop: %s\n", s);
355 g_free (mem: s);
356
357 gdk_drop_finish (self: drop, action: action_make_unique (action: gdk_drop_get_actions (self: drop)));
358
359 return TRUE;
360}
361
362static gboolean
363label_drag_drop (GtkDropTarget *dest,
364 const GValue *value,
365 int x,
366 int y,
367 GtkWidget *widget)
368{
369 g_print (format: "Received \"%s\" in label\n", g_value_get_string (value));
370 return TRUE;
371}
372
373/* The following is a rather elaborate example demonstrating/testing
374 * changing of the window hierarchy during a drag - in this case,
375 * via a "spring-loaded" popup window.
376 */
377static GtkWidget *popup_window = NULL;
378
379static gboolean popped_up = FALSE;
380static gboolean in_popup = FALSE;
381static guint popdown_timer = 0;
382static guint popup_timer = 0;
383
384static int
385popdown_cb (gpointer data)
386{
387 popdown_timer = 0;
388
389 gtk_widget_hide (widget: popup_window);
390 popped_up = FALSE;
391
392 return FALSE;
393}
394
395static void
396popup_enter (GtkDropTarget *dest)
397{
398 g_print (format: "popup enter\n");
399 if (!in_popup)
400 {
401 in_popup = TRUE;
402 if (popdown_timer)
403 {
404 g_print (format: "removed popdown\n");
405 g_source_remove (tag: popdown_timer);
406 popdown_timer = 0;
407 }
408 }
409}
410
411static void
412popup_leave (GtkDropTarget *dest)
413{
414g_print (format: "popup leave\n");
415 if (in_popup)
416 {
417 in_popup = FALSE;
418 if (!popdown_timer)
419 {
420 g_print (format: "added popdown\n");
421 popdown_timer = g_timeout_add (interval: 500, function: popdown_cb, NULL);
422 }
423 }
424}
425
426static gboolean
427popup_drop (GtkDropTarget *dest)
428{
429 popdown_cb (NULL);
430 return TRUE;
431}
432
433static gboolean
434popup_cb (gpointer data)
435{
436 if (!popped_up)
437 {
438 if (!popup_window)
439 {
440 GtkWidget *button;
441 GtkWidget *grid;
442 int i, j;
443
444 popup_window = gtk_window_new ();
445
446 grid = gtk_grid_new ();
447
448 for (i=0; i<3; i++)
449 for (j=0; j<3; j++)
450 {
451 char buffer[128];
452 GtkDropTarget *dest;
453
454 g_snprintf(string: buffer, n: sizeof(buffer), format: "%d,%d", i, j);
455 button = gtk_button_new_with_label (label: buffer);
456 gtk_widget_set_hexpand (widget: button, TRUE);
457 gtk_widget_set_vexpand (widget: button, TRUE);
458 gtk_grid_attach (GTK_GRID (grid), child: button, column: i, row: j, width: 1, height: 1);
459
460 dest = gtk_drop_target_new (G_TYPE_STRING, actions: GDK_ACTION_COPY | GDK_ACTION_MOVE);
461 g_signal_connect (dest, "enter", G_CALLBACK (popup_enter), NULL);
462 g_signal_connect (dest, "leave", G_CALLBACK (popup_leave), NULL);
463 g_signal_connect (dest, "drop", G_CALLBACK (popup_drop), NULL);
464 gtk_widget_add_controller (widget: button, GTK_EVENT_CONTROLLER (dest));
465 }
466 gtk_window_set_child (GTK_WINDOW (popup_window), child: grid);
467 }
468 gtk_widget_show (widget: popup_window);
469 popped_up = TRUE;
470 }
471
472 popup_timer = FALSE;
473
474 return FALSE;
475}
476
477static void
478popsite_enter (GtkDropControllerMotion *motion)
479{
480 g_print (format: "popsite enter\n");
481 if (!popup_timer)
482 popup_timer = g_timeout_add (interval: 500, function: popup_cb, NULL);
483}
484
485static void
486popsite_leave (GtkDropControllerMotion *motion)
487{
488 g_print (format: "popsite leave\n");
489 if (popup_timer)
490 {
491 g_source_remove (tag: popup_timer);
492 popup_timer = 0;
493 }
494}
495
496static void
497quit_cb (GtkWidget *widget,
498 gpointer data)
499{
500 gboolean *done = data;
501
502 *done = TRUE;
503
504 g_main_context_wakeup (NULL);
505}
506
507int
508main (int argc, char **argv)
509{
510 GtkWidget *window;
511 GtkWidget *grid;
512 GtkWidget *label;
513 GtkWidget *pixmap;
514 GtkWidget *button;
515 GdkPixbuf *drag_icon;
516 GdkTexture *texture;
517 GdkContentProvider *content;
518 GtkDragSource *source;
519 GtkDropTarget *dest;
520 GtkDropTargetAsync *async;
521 GtkEventController *controller;
522 gboolean done = FALSE;
523
524 gtk_init ();
525
526 window = gtk_window_new ();
527 g_signal_connect (window, "destroy",
528 G_CALLBACK (quit_cb), &done);
529
530
531 grid = gtk_grid_new ();
532 gtk_window_set_child (GTK_WINDOW (window), child: grid);
533
534 drag_icon = gdk_pixbuf_new_from_xpm_data (data: drag_icon_xpm);
535 texture = gdk_texture_new_for_pixbuf (pixbuf: drag_icon);
536 g_object_unref (object: drag_icon);
537 trashcan_open = gdk_pixbuf_new_from_xpm_data (data: trashcan_open_xpm);
538 trashcan_closed = gdk_pixbuf_new_from_xpm_data (data: trashcan_closed_xpm);
539
540 label = gtk_label_new (str: "Drop Here\n");
541
542 dest = gtk_drop_target_new (G_TYPE_STRING, actions: GDK_ACTION_COPY | GDK_ACTION_MOVE);
543 g_signal_connect (dest, "drop", G_CALLBACK (label_drag_drop), NULL);
544 gtk_widget_add_controller (widget: label, GTK_EVENT_CONTROLLER (dest));
545
546 gtk_widget_set_hexpand (widget: label, TRUE);
547 gtk_widget_set_vexpand (widget: label, TRUE);
548 gtk_grid_attach (GTK_GRID (grid), child: label, column: 0, row: 0, width: 1, height: 1);
549
550 label = gtk_label_new (str: "Popup\n");
551
552 controller = gtk_drop_controller_motion_new ();
553 g_signal_connect (controller, "enter", G_CALLBACK (popsite_enter), NULL);
554 g_signal_connect (controller, "leave", G_CALLBACK (popsite_leave), NULL);
555 gtk_widget_add_controller (widget: label, controller);
556
557 gtk_widget_set_hexpand (widget: label, TRUE);
558 gtk_widget_set_vexpand (widget: label, TRUE);
559 gtk_grid_attach (GTK_GRID (grid), child: label, column: 1, row: 1, width: 1, height: 1);
560
561 pixmap = gtk_image_new_from_pixbuf (pixbuf: trashcan_closed);
562 async = gtk_drop_target_async_new (NULL, GDK_ACTION_ALL);
563 g_signal_connect (async, "drag-enter", G_CALLBACK (trash_drag_enter), pixmap);
564 g_signal_connect (async, "drag-leave", G_CALLBACK (trash_drag_leave), pixmap);
565 g_signal_connect (async, "drop", G_CALLBACK (trash_drag_drop), pixmap);
566 gtk_widget_add_controller (widget: pixmap, GTK_EVENT_CONTROLLER (async));
567
568 gtk_widget_set_hexpand (widget: pixmap, TRUE);
569 gtk_widget_set_vexpand (widget: pixmap, TRUE);
570 gtk_grid_attach (GTK_GRID (grid), child: pixmap, column: 1, row: 0, width: 1, height: 1);
571
572
573 /* Drag site */
574
575 button = gtk_label_new (str: "Drag Here\n");
576
577 source = gtk_drag_source_new ();
578 content = gdk_content_provider_new_typed (G_TYPE_STRING, "I'm data!");
579 gtk_drag_source_set_content (source, content);
580 g_object_unref (object: content);
581 gtk_drag_source_set_actions (source, actions: GDK_ACTION_COPY|GDK_ACTION_MOVE);
582 gtk_widget_add_controller (widget: button, GTK_EVENT_CONTROLLER (source));
583 gtk_drag_source_set_icon (source, paintable: GDK_PAINTABLE (ptr: texture), hot_x: 0, hot_y: 0);
584
585 g_object_unref (object: texture);
586
587 gtk_widget_set_hexpand (widget: button, TRUE);
588 gtk_widget_set_vexpand (widget: button, TRUE);
589 gtk_grid_attach (GTK_GRID (grid), child: button, column: 0, row: 1, width: 1, height: 1);
590
591 gtk_widget_show (widget: window);
592
593 while (!done)
594 g_main_context_iteration (NULL, TRUE);
595
596 return 0;
597}
598

source code of gtk/tests/testdnd.c