New wxDataObject, DnD and Clipboard code
[wxWidgets.git] / src / gtk1 / dnd.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: dnd.cpp
3 // Purpose: wxDropTarget class
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 ///////////////////////////////////////////////////////////////////////////////
9
10 #ifdef __GNUG__
11 #pragma implementation "dnd.h"
12 #endif
13
14 #include "wx/dnd.h"
15 #include "wx/window.h"
16 #include "wx/app.h"
17 #include "wx/gdicmn.h"
18 #include "wx/intl.h"
19 #include "wx/utils.h"
20
21 #include "gdk/gdkprivate.h"
22
23 #include <X11/Xlib.h>
24
25 // ----------------------------------------------------------------------------
26 // global
27 // ----------------------------------------------------------------------------
28
29 extern bool g_blockEventsOnDrag;
30
31 #ifdef NEW_GTK_DND_CODE
32
33 #include "gtk/gtkdnd.h"
34 #include "gtk/gtkselection.h"
35
36 // ----------------------------------------------------------------------------
37 // "drag_leave"
38 // ----------------------------------------------------------------------------
39
40 static void target_drag_leave( GtkWidget *WXUNUSED(widget),
41 GdkDragContext *WXUNUSED(context),
42 guint WXUNUSED(time) )
43 {
44 printf( "leave.\n" );
45 }
46
47 // ----------------------------------------------------------------------------
48 // "drag_motion"
49 // ----------------------------------------------------------------------------
50
51 static gboolean target_drag_motion( GtkWidget *WXUNUSED(widget),
52 GdkDragContext *context,
53 gint WXUNUSED(x),
54 gint WXUNUSED(y),
55 guint time )
56 {
57 printf( "motion.\n" );
58 gdk_drag_status( context, context->suggested_action, time );
59 return TRUE;
60 }
61
62 // ----------------------------------------------------------------------------
63 // "drag_drop"
64 // ----------------------------------------------------------------------------
65
66 static gboolean target_drag_drop( GtkWidget *widget,
67 GdkDragContext *context,
68 gint x,
69 gint y,
70 guint time )
71 {
72 printf( "drop at: %d,%d.\n", x, y );
73
74 if (context->targets)
75 {
76 gtk_drag_get_data( widget,
77 context,
78 GPOINTER_TO_INT (context->targets->data),
79 time );
80 }
81 return FALSE;
82 }
83
84 // ----------------------------------------------------------------------------
85 // "drag_data_received"
86 // ----------------------------------------------------------------------------
87
88 static void target_drag_data_received( GtkWidget *WXUNUSED(widget),
89 GdkDragContext *context,
90 gint x,
91 gint y,
92 GtkSelectionData *data,
93 guint WXUNUSED(info),
94 guint time )
95 {
96 printf( "data receive at: %d,%d.\n", x, y );
97
98 if ((data->length >= 0) && (data->format == 8))
99 {
100 wxString str = (const char*)data->data;
101 printf( "Received %s\n.", WXSTRINGCAST str );
102 gtk_drag_finish( context, TRUE, FALSE, time );
103 return;
104 }
105
106 gtk_drag_finish (context, FALSE, FALSE, time);
107 }
108
109 // ----------------------------------------------------------------------------
110 // wxDropTarget
111 // ----------------------------------------------------------------------------
112
113 wxDropTarget::wxDropTarget()
114 {
115 }
116
117 wxDropTarget::~wxDropTarget()
118 {
119 }
120
121 void wxDropTarget::UnregisterWidget( GtkWidget *widget )
122 {
123 wxCHECK_RET( widget != NULL, "unregister widget is NULL" );
124
125 gtk_drag_dest_set( widget,
126 (GtkDestDefaults) 0,
127 (GtkTargetEntry*) NULL,
128 0,
129 (GdkDragAction) 0 );
130
131 gtk_signal_disconnect_by_func( GTK_OBJECT(widget),
132 GTK_SIGNAL_FUNC(target_drag_leave), (gpointer) this );
133
134 gtk_signal_disconnect_by_func( GTK_OBJECT(widget),
135 GTK_SIGNAL_FUNC(target_drag_motion), (gpointer) this );
136
137 gtk_signal_disconnect_by_func( GTK_OBJECT(widget),
138 GTK_SIGNAL_FUNC(target_drag_drop), (gpointer) this );
139
140 gtk_signal_disconnect_by_func( GTK_OBJECT(widget),
141 GTK_SIGNAL_FUNC(target_drag_data_received), (gpointer) this );
142 }
143
144 void wxDropTarget::RegisterWidget( GtkWidget *widget )
145 {
146 wxCHECK_RET( widget != NULL, "register widget is NULL" );
147
148 GtkTargetEntry format;
149 format.info = 0;
150 format.flags = 0;
151
152 int valid = 0;
153 for ( size_t i = 0; i < GetFormatCount(); i++ )
154 {
155 wxDataFormat df = GetFormat( i );
156 switch (df)
157 {
158 case wxDF_TEXT:
159 format.target = "text/plain";
160 valid++;
161 break;
162 case wxDF_FILENAME:
163 format.target = "file:ALL";
164 valid++;
165 break;
166 default:
167 break;
168 }
169 }
170
171 wxASSERT_MSG( valid != 0, "No valid DnD format supported." );
172
173 gtk_drag_dest_set( widget,
174 GTK_DEST_DEFAULT_ALL,
175 &format,
176 1,
177 (GdkDragAction)(GDK_ACTION_COPY | GDK_ACTION_MOVE) );
178
179 gtk_signal_connect( GTK_OBJECT(widget), "drag_leave",
180 GTK_SIGNAL_FUNC(target_drag_leave), (gpointer) this );
181
182 gtk_signal_connect( GTK_OBJECT(widget), "drag_motion",
183 GTK_SIGNAL_FUNC(target_drag_motion), (gpointer) this );
184
185 gtk_signal_connect( GTK_OBJECT(widget), "drag_drop",
186 GTK_SIGNAL_FUNC(target_drag_drop), (gpointer) this );
187
188 gtk_signal_connect( GTK_OBJECT(widget), "drag_data_received",
189 GTK_SIGNAL_FUNC(target_drag_data_received), (gpointer) this );
190 }
191
192 // ----------------------------------------------------------------------------
193 // wxTextDropTarget
194 // ----------------------------------------------------------------------------
195
196 bool wxTextDropTarget::OnDrop( long x, long y, const void *data, size_t WXUNUSED(size) )
197 {
198 OnDropText( x, y, (const char*)data );
199 return TRUE;
200 }
201
202 bool wxTextDropTarget::OnDropText( long x, long y, const char *psz )
203 {
204 printf( "Got dropped text: %s.\n", psz );
205 printf( "At x: %d, y: %d.\n", (int)x, (int)y );
206 return TRUE;
207 }
208
209 size_t wxTextDropTarget::GetFormatCount() const
210 {
211 return 1;
212 }
213
214 wxDataFormat wxTextDropTarget::GetFormat(size_t WXUNUSED(n)) const
215 {
216 return wxDF_TEXT;
217 }
218
219 // ----------------------------------------------------------------------------
220 // wxFileDropTarget
221 // ----------------------------------------------------------------------------
222
223 bool wxFileDropTarget::OnDropFiles( long x, long y, size_t nFiles, const char * const aszFiles[] )
224 {
225 printf( "Got %d dropped files.\n", (int)nFiles );
226 printf( "At x: %d, y: %d.\n", (int)x, (int)y );
227 for (size_t i = 0; i < nFiles; i++)
228 {
229 printf( aszFiles[i] );
230 printf( "\n" );
231 }
232 return TRUE;
233 }
234
235 bool wxFileDropTarget::OnDrop(long x, long y, const void *data, size_t size )
236 {
237 size_t number = 0;
238 char *text = (char*) data;
239 for (size_t i = 0; i < size; i++)
240 if (text[i] == 0) number++;
241
242 if (number == 0) return TRUE;
243
244 char **files = new char*[number];
245
246 text = (char*) data;
247 for (size_t i = 0; i < number; i++)
248 {
249 files[i] = text;
250 int len = strlen( text );
251 text += len+1;
252 }
253
254 bool ret = OnDropFiles( x, y, 1, files );
255
256 free( files );
257
258 return ret;
259 }
260
261 size_t wxFileDropTarget::GetFormatCount() const
262 {
263 return 1;
264 }
265
266 wxDataFormat wxFileDropTarget::GetFormat(size_t WXUNUSED(n)) const
267 {
268 return wxDF_FILENAME;
269 }
270
271 //-------------------------------------------------------------------------
272 // wxDropSource
273 //-------------------------------------------------------------------------
274
275 wxDropSource::wxDropSource( wxWindow *win )
276 {
277 g_blockEventsOnDrag = TRUE;
278
279 m_window = win;
280 m_widget = win->m_widget;
281 if (win->m_wxwindow) m_widget = win->m_wxwindow;
282
283 m_data = (wxDataObject *) NULL;
284 m_retValue = wxDragCancel;
285
286 m_defaultCursor = wxCursor( wxCURSOR_NO_ENTRY );
287 m_goaheadCursor = wxCursor( wxCURSOR_HAND );
288 }
289
290 wxDropSource::wxDropSource( wxDataObject &data, wxWindow *win )
291 {
292 g_blockEventsOnDrag = TRUE;
293
294 m_window = win;
295 m_widget = win->m_widget;
296 if (win->m_wxwindow) m_widget = win->m_wxwindow;
297 m_retValue = wxDragCancel;
298
299 m_data = &data;
300
301 m_defaultCursor = wxCursor( wxCURSOR_NO_ENTRY );
302 m_goaheadCursor = wxCursor( wxCURSOR_HAND );
303 }
304
305 void wxDropSource::SetData( wxDataObject &data )
306 {
307 m_data = &data;
308 }
309
310 wxDropSource::~wxDropSource(void)
311 {
312 // if (m_data) delete m_data;
313
314 g_blockEventsOnDrag = FALSE;
315 }
316
317 wxDragResult wxDropSource::DoDragDrop( bool WXUNUSED(bAllowMove) )
318 {
319 wxASSERT_MSG( m_data, "wxDragSource: no data" );
320
321 if (!m_data) return (wxDragResult) wxDragNone;
322 if (m_data->GetDataSize() == 0) return (wxDragResult) wxDragNone;
323
324 RegisterWindow();
325
326 // TODO
327
328 UnregisterWindow();
329
330 g_blockEventsOnDrag = FALSE;
331
332 return m_retValue;
333 }
334
335 void wxDropSource::RegisterWindow(void)
336 {
337 if (!m_data) return;
338
339 wxString formats;
340
341 wxDataFormat df = m_data->GetPreferredFormat();
342
343 switch (df)
344 {
345 case wxDF_TEXT:
346 formats += "text/plain";
347 break;
348 case wxDF_FILENAME:
349 formats += "file:ALL";
350 break;
351 default:
352 break;
353 }
354
355 char *str = WXSTRINGCAST formats;
356
357 // TODO
358 }
359
360 void wxDropSource::UnregisterWindow(void)
361 {
362 if (!m_widget) return;
363
364 // TODO
365 }
366
367
368 #else // NEW_CODE
369
370 GtkWidget *shape_create_icon (char **data,
371 gint x,
372 gint y,
373 gint px,
374 gint py,
375 gint window_type);
376
377 /* XPM */
378 static char * gv_xpm[] = {
379 "40 34 3 1",
380 " s None c None",
381 ". c black",
382 "X c white",
383 " ",
384 " ",
385 " ...... ",
386 " ..XXXXXX.. ",
387 " .XXXXXXXXXX. ",
388 " .XXXXXXXXXXXX. ",
389 " .XXXXXXXXXXXX. ",
390 " .XXXXXXXXXXXXXX. ",
391 " .XXX..XXXX..XXX. ",
392 " ....XX....XX....XX. ",
393 " .XXX.XXX..XXXX..XXX.... ",
394 " .XXXXXXXXXXXXXXXXXXX.XXX. ",
395 " .XXXXXXXXXXXXXXXXXXXXXXXX. ",
396 " .XXXXXXXXXXXXXXXXXXXXXXXX. ",
397 " ..XXXXXXXXXXXXXXXXXXXXXX. ",
398 " .XXXXXXXXXXXXXXXXXX... ",
399 " ..XXXXXXXXXXXXXXXX. ",
400 " .XXXXXXXXXXXXXXXX. ",
401 " .XXXXXXXXXXXXXXXX. ",
402 " .XXXXXXXXXXXXXXXXX. ",
403 " .XXXXXXXXXXXXXXXXX. ",
404 " .XXXXXXXXXXXXXXXXXX. ",
405 " .XXXXXXXXXXXXXXXXXXX. ",
406 " .XXXXXXXXXXXXXXXXXXXXX. ",
407 " .XXXXXXXXXXXXXX.XXXXXXX. ",
408 " .XXXXXXX.XXXXXXX.XXXXXXX. ",
409 " .XXXXXXXX.XXXXXXX.XXXXXXX. ",
410 " .XXXXXXX...XXXXX...XXXXX. ",
411 " .XXXXXXX. ..... ..... ",
412 " ..XXXX.. ",
413 " .... ",
414 " ",
415 " ",
416 " "};
417
418 /* XPM */
419 static char * page_xpm[] = {
420 /* width height ncolors chars_per_pixel */
421 "32 32 5 1",
422 /* colors */
423 " s None c None",
424 ". c black",
425 "X c wheat",
426 "o c tan",
427 "O c #6699FF",
428 /* pixels */
429 " ................... ",
430 " .XXXXXXXXXXXXXXXXX.. ",
431 " .XXXXXXXXXXXXXXXXX.o. ",
432 " .XXXXXXXXXXXXXXXXX.oo. ",
433 " .XXXXXXXXXXXXXXXXX.ooo. ",
434 " .XXXXXXXXXXXXXXXXX.oooo. ",
435 " .XXXXXXXXXXXXXXXXX....... ",
436 " .XXXXXOOOOOOOOOOXXXooooo. ",
437 " .XXXXXXXXXXXXXXXXXXooooo. ",
438 " .XXXXXOOOOOOOOOOXXXXXXXX. ",
439 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
440 " .XXXXXXXOOOOOOOOOXXXXXXX. ",
441 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
442 " .XXXXXXOOOOOOOOOOXXXXXXX. ",
443 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
444 " .XXXXXOOOOOOOOOOXXXXXXXX. ",
445 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
446 " .XXXXXXXOOOOOOOOOXXXXXXX. ",
447 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
448 " .XXXXXXOOOOOOOOOOXXXXXXX. ",
449 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
450 " .XXXXXOOOOOOOOOOXXXXXXXX. ",
451 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
452 " .XXXXXXOOOOOOOOOOXXXXXXX. ",
453 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
454 " .XXXXXOOOOOOOXXXXXXXXXXX. ",
455 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
456 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
457 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
458 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
459 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
460 " ......................... "};
461
462
463 //-----------------------------------------------------------------------------
464 // "drop_data_available_event"
465 //-----------------------------------------------------------------------------
466
467 static void gtk_target_callback( GtkWidget *widget,
468 GdkEventDropDataAvailable *event,
469 wxDropTarget *target )
470 {
471 if (target)
472 {
473 int x = 0;
474 int y = 0;
475 gdk_window_get_pointer( widget->window, &x, &y, (GdkModifierType *) NULL );
476
477 // printf( "Drop data is of type %s.\n", event->data_type );
478
479 target->OnDrop( x, y, (const void*)event->data, (size_t)event->data_numbytes );
480 }
481
482 /*
483 g_free (event->data);
484 g_free (event->data_type);
485 */
486 }
487
488 // ----------------------------------------------------------------------------
489 // wxDropTarget
490 // ----------------------------------------------------------------------------
491
492 wxDropTarget::wxDropTarget()
493 {
494 }
495
496 wxDropTarget::~wxDropTarget()
497 {
498 }
499
500 void wxDropTarget::UnregisterWidget( GtkWidget *widget )
501 {
502 if (!widget) return;
503
504 gtk_signal_disconnect_by_func( GTK_OBJECT(widget),
505 GTK_SIGNAL_FUNC(gtk_target_callback), (gpointer) this );
506
507 gtk_widget_dnd_drop_set( widget, FALSE, (gchar **) NULL, 0, FALSE );
508 }
509
510 void wxDropTarget::RegisterWidget( GtkWidget *widget )
511 {
512 wxString formats;
513 int valid = 0;
514
515 for ( size_t i = 0; i < GetFormatCount(); i++ )
516 {
517 wxDataFormat df = GetFormat( i );
518 switch (df)
519 {
520 case wxDF_TEXT:
521 if (i > 0) formats += ";";
522 formats += "text/plain";
523 valid++;
524 break;
525 case wxDF_FILENAME:
526 if (i > 0) formats += ";";
527 formats += "file:ALL";
528 valid++;
529 break;
530 default:
531 break;
532 }
533 }
534
535 char *str = WXSTRINGCAST formats;
536
537 gtk_widget_dnd_drop_set( widget, TRUE, &str, valid, FALSE );
538
539 gtk_signal_connect( GTK_OBJECT(widget), "drop_data_available_event",
540 GTK_SIGNAL_FUNC(gtk_target_callback), (gpointer) this );
541 }
542
543 // ----------------------------------------------------------------------------
544 // wxTextDropTarget
545 // ----------------------------------------------------------------------------
546
547 bool wxTextDropTarget::OnDrop( long x, long y, const void *data, size_t WXUNUSED(size) )
548 {
549 OnDropText( x, y, (const char*)data );
550 return TRUE;
551 }
552
553 bool wxTextDropTarget::OnDropText( long x, long y, const char *psz )
554 {
555 printf( "Got dropped text: %s.\n", psz );
556 printf( "At x: %d, y: %d.\n", (int)x, (int)y );
557 return TRUE;
558 }
559
560 size_t wxTextDropTarget::GetFormatCount() const
561 {
562 return 1;
563 }
564
565 wxDataFormat wxTextDropTarget::GetFormat(size_t WXUNUSED(n)) const
566 {
567 return wxDF_TEXT;
568 }
569
570 // ----------------------------------------------------------------------------
571 // wxFileDropTarget
572 // ----------------------------------------------------------------------------
573
574 bool wxFileDropTarget::OnDropFiles( long x, long y, size_t nFiles, const char * const aszFiles[] )
575 {
576 printf( "Got %d dropped files.\n", (int)nFiles );
577 printf( "At x: %d, y: %d.\n", (int)x, (int)y );
578 for (size_t i = 0; i < nFiles; i++)
579 {
580 printf( aszFiles[i] );
581 printf( "\n" );
582 }
583 return TRUE;
584 }
585
586 bool wxFileDropTarget::OnDrop(long x, long y, const void *data, size_t size )
587 {
588 size_t number = 0;
589 char *text = (char*) data;
590 for (size_t i = 0; i < size; i++)
591 if (text[i] == 0) number++;
592
593 if (number == 0) return TRUE;
594
595 char **files = new char*[number];
596
597 text = (char*) data;
598 for (size_t i = 0; i < number; i++)
599 {
600 files[i] = text;
601 int len = strlen( text );
602 text += len+1;
603 }
604
605 bool ret = OnDropFiles( x, y, 1, files );
606
607 free( files );
608
609 return ret;
610 }
611
612 size_t wxFileDropTarget::GetFormatCount() const
613 {
614 return 1;
615 }
616
617 wxDataFormat wxFileDropTarget::GetFormat(size_t WXUNUSED(n)) const
618 {
619 return wxDF_FILENAME;
620 }
621
622 //-------------------------------------------------------------------------
623 // wxDropSource
624 //-------------------------------------------------------------------------
625
626 static void
627 shape_motion (GtkWidget *widget,
628 GdkEventMotion */*event*/);
629
630 //-----------------------------------------------------------------------------
631 // drag request
632
633 void gtk_drag_callback( GtkWidget *widget, GdkEvent *event, wxDropSource *source )
634 {
635 wxDataObject *data = source->m_data;
636
637 switch (data->GetFormat())
638 {
639 case wxDF_TEXT:
640 {
641 wxTextDataObject *text_object = (wxTextDataObject*) data;
642
643 wxString text = text_object->GetText();
644
645 gtk_widget_dnd_data_set( widget,
646 event,
647 (unsigned char*) text.c_str,
648 (int) text.Length() );
649
650 break;
651 }
652
653 case wxDF_FILENAME:
654 {
655 wxFileDataObject *file_object = (wxFileDataObject*) data;
656
657 wxString text = file_object->GetFiles();
658
659 gtk_widget_dnd_data_set( widget,
660 event,
661 (unsigned char*) text.c_str,
662 (int) text.Length() );
663
664 break;
665 }
666
667 default:
668 {
669 return;
670 }
671 }
672
673 source->m_retValue = wxDragCopy;
674 }
675
676 wxDropSource::wxDropSource( wxWindow *win )
677 {
678 g_blockEventsOnDrag = TRUE;
679
680 m_window = win;
681 m_widget = win->m_widget;
682 if (win->m_wxwindow) m_widget = win->m_wxwindow;
683
684 m_data = (wxDataObject *) NULL;
685 m_retValue = wxDragCancel;
686
687 m_defaultCursor = wxCursor( wxCURSOR_NO_ENTRY );
688 m_goaheadCursor = wxCursor( wxCURSOR_HAND );
689 }
690
691 wxDropSource::wxDropSource( wxDataObject &data, wxWindow *win )
692 {
693 g_blockEventsOnDrag = TRUE;
694
695 m_window = win;
696 m_widget = win->m_widget;
697 if (win->m_wxwindow) m_widget = win->m_wxwindow;
698 m_retValue = wxDragCancel;
699
700 m_data = &data;
701
702 m_defaultCursor = wxCursor( wxCURSOR_NO_ENTRY );
703 m_goaheadCursor = wxCursor( wxCURSOR_HAND );
704 }
705
706 void wxDropSource::SetData( wxDataObject &data )
707 {
708 m_data = &data;
709 }
710
711 wxDropSource::~wxDropSource(void)
712 {
713 // if (m_data) delete m_data;
714
715 g_blockEventsOnDrag = FALSE;
716 }
717
718 wxDragResult wxDropSource::DoDragDrop( bool WXUNUSED(bAllowMove) )
719 {
720 if (gdk_dnd.dnd_grabbed) return (wxDragResult) wxDragNone;
721 if (gdk_dnd.drag_really) return (wxDragResult) wxDragNone;
722
723 wxASSERT_MSG( m_data, "wxDragSource: no data" );
724
725 if (!m_data) return (wxDragResult) wxDragNone;
726
727 static GtkWidget *drag_icon = NULL;
728 static GtkWidget *drop_icon = NULL;
729
730 GdkPoint hotspot_1 = {0,-5 };
731
732 if (!drag_icon)
733 {
734 drag_icon = shape_create_icon ( gv_xpm,
735 440, 140, 0,0, GTK_WINDOW_POPUP);
736
737 gtk_signal_connect (GTK_OBJECT (drag_icon), "destroy",
738 GTK_SIGNAL_FUNC(gtk_widget_destroyed),
739 &drag_icon);
740
741 gtk_widget_hide (drag_icon);
742 }
743
744 GdkPoint hotspot_2 = {-5,-5};
745
746 if (!drop_icon)
747 {
748 drop_icon = shape_create_icon ( page_xpm,
749 440, 140, 0,0, GTK_WINDOW_POPUP);
750
751 gtk_signal_connect (GTK_OBJECT (drop_icon), "destroy",
752 GTK_SIGNAL_FUNC(gtk_widget_destroyed),
753 &drop_icon);
754
755 gtk_widget_hide (drop_icon);
756 }
757
758
759 gdk_dnd_set_drag_shape( drag_icon->window,
760 &hotspot_1,
761 drop_icon->window,
762 &hotspot_2);
763
764
765 GdkWindowPrivate *wp = (GdkWindowPrivate*) m_widget->window;
766
767 RegisterWindow();
768
769 gdk_dnd.drag_perhaps = TRUE;
770
771 gdk_dnd.dnd_drag_start.x = 5;
772 gdk_dnd.dnd_drag_start.y = 5;
773 gdk_dnd.real_sw = wp;
774
775 if (gdk_dnd.drag_startwindows)
776 {
777 g_free( gdk_dnd.drag_startwindows );
778 gdk_dnd.drag_startwindows = (GdkWindow **) NULL;
779 }
780 gdk_dnd.drag_numwindows = gdk_dnd.drag_really = 0;
781
782 XWindowAttributes dnd_winattr;
783 XGetWindowAttributes( gdk_display, wp->xwindow, &dnd_winattr );
784 wp->dnd_drag_savedeventmask = dnd_winattr.your_event_mask;
785
786 gdk_dnd_drag_addwindow( m_widget->window );
787
788 GdkEventDragBegin ev;
789 ev.type = GDK_DRAG_BEGIN;
790 ev.window = m_widget->window;
791 ev.u.allflags = 0;
792 ev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
793
794 gdk_event_put( (GdkEvent*)&ev );
795
796 XGrabPointer( gdk_display, wp->xwindow, False,
797 ButtonMotionMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
798 GrabModeAsync, GrabModeAsync, gdk_root_window, None, CurrentTime );
799
800 gdk_dnd_set_drag_cursors( m_defaultCursor.GetCursor(), m_goaheadCursor.GetCursor() );
801
802 gdk_dnd.dnd_grabbed = TRUE;
803 gdk_dnd.drag_really = 1;
804
805 int x = 0;
806 int y = 0;
807 wxGetMousePosition( &x, &y );
808
809 gdk_dnd_display_drag_cursor( x, y, FALSE, TRUE );
810
811 /*
812 shape_motion( drag_icon, (GdkEventMotion *)NULL );
813 shape_motion( drop_icon, (GdkEventMotion *)NULL );
814 */
815
816 while (gdk_dnd.drag_really || gdk_dnd.drag_perhaps) wxYield();
817
818 UnregisterWindow();
819
820 g_blockEventsOnDrag = FALSE;
821
822 return m_retValue;
823 }
824
825 void wxDropSource::RegisterWindow(void)
826 {
827 if (!m_data) return;
828
829 wxString formats;
830
831 wxDataFormat df = m_data->GetFormat();
832
833 switch (df)
834 {
835 case wxDF_TEXT:
836 formats += "text/plain";
837 break;
838 case wxDF_FILENAME:
839 formats += "file:ALL";
840 break;
841 default:
842 break;
843 }
844
845 char *str = WXSTRINGCAST formats;
846
847 gtk_widget_dnd_drag_set( m_widget, TRUE, &str, 1 );
848
849 gtk_signal_connect( GTK_OBJECT(m_widget), "drag_request_event",
850 GTK_SIGNAL_FUNC(gtk_drag_callback), (gpointer)this );
851 }
852
853 void wxDropSource::UnregisterWindow(void)
854 {
855 if (!m_widget) return;
856
857 gtk_widget_dnd_drag_set( m_widget, FALSE, (gchar **) NULL, 0 );
858
859 gtk_signal_disconnect_by_data( GTK_OBJECT(m_widget), (gpointer)this );
860 }
861
862
863 /*
864 * Shaped Windows
865 */
866 static GdkWindow *root_win = NULL;
867
868 typedef struct _cursoroffset {gint x,y;} CursorOffset;
869
870 static void
871 shape_pressed (GtkWidget *widget, GdkEventButton *event)
872 {
873 CursorOffset *p;
874
875 /* ignore double and triple click */
876 if (event->type != GDK_BUTTON_PRESS)
877 return;
878
879 p = (CursorOffset *)gtk_object_get_user_data (GTK_OBJECT(widget));
880 p->x = (int) event->x;
881 p->y = (int) event->y;
882
883 gtk_grab_add (widget);
884 gdk_pointer_grab (widget->window, TRUE,
885 (GdkEventMask)
886 (GDK_BUTTON_RELEASE_MASK |
887 GDK_BUTTON_MOTION_MASK |
888 GDK_POINTER_MOTION_HINT_MASK),
889 NULL, NULL, 0);
890 }
891
892
893 static void
894 shape_released (GtkWidget *widget)
895 {
896 gtk_grab_remove (widget);
897 gdk_pointer_ungrab (0);
898 }
899
900 static void
901 shape_motion (GtkWidget *widget,
902 GdkEventMotion */*event*/)
903 {
904 gint xp, yp;
905 CursorOffset * p;
906 GdkModifierType mask;
907
908 p = (CursorOffset *)gtk_object_get_user_data (GTK_OBJECT (widget));
909
910 /*
911 * Can't use event->x / event->y here
912 * because I need absolute coordinates.
913 */
914 gdk_window_get_pointer (root_win, &xp, &yp, &mask);
915 gtk_widget_set_uposition (widget, xp - p->x, yp - p->y);
916 }
917
918 GtkWidget *
919 shape_create_icon (char **data,
920 gint x,
921 gint y,
922 gint px,
923 gint py,
924 gint window_type)
925 {
926 GtkWidget *window;
927 GtkWidget *pixmap;
928 GtkWidget *fixed;
929 CursorOffset* icon_pos;
930 GdkGC* gc;
931 GdkBitmap *gdk_pixmap_mask;
932 GdkPixmap *gdk_pixmap;
933 GtkStyle *style;
934
935 style = gtk_widget_get_default_style ();
936 gc = style->black_gc;
937
938 /*
939 * GDK_WINDOW_TOPLEVEL works also, giving you a title border
940 */
941 window = gtk_window_new ((GtkWindowType)window_type);
942
943 fixed = gtk_fixed_new ();
944 gtk_widget_set_usize (fixed, 100,100);
945 gtk_container_add (GTK_CONTAINER (window), fixed);
946 gtk_widget_show (fixed);
947
948 gtk_widget_set_events (window,
949 gtk_widget_get_events (window) |
950 GDK_BUTTON_MOTION_MASK |
951 GDK_POINTER_MOTION_HINT_MASK |
952 GDK_BUTTON_PRESS_MASK);
953
954 gtk_widget_realize (window);
955
956 gdk_pixmap = gdk_pixmap_create_from_xpm_d (window->window, &gdk_pixmap_mask,
957 &style->bg[GTK_STATE_NORMAL],
958 (gchar**) data );
959
960 pixmap = gtk_pixmap_new (gdk_pixmap, gdk_pixmap_mask);
961 gtk_fixed_put (GTK_FIXED (fixed), pixmap, px,py);
962 gtk_widget_show (pixmap);
963
964 gtk_widget_shape_combine_mask (window, gdk_pixmap_mask, px,py);
965
966
967 gtk_signal_connect (GTK_OBJECT (window), "button_press_event",
968 GTK_SIGNAL_FUNC (shape_pressed),NULL);
969 gtk_signal_connect (GTK_OBJECT (window), "button_release_event",
970 GTK_SIGNAL_FUNC (shape_released),NULL);
971 gtk_signal_connect (GTK_OBJECT (window), "motion_notify_event",
972 GTK_SIGNAL_FUNC (shape_motion),NULL);
973
974 icon_pos = g_new (CursorOffset, 1);
975 gtk_object_set_user_data(GTK_OBJECT(window), icon_pos);
976
977 gtk_widget_set_uposition (window, x, y);
978 gtk_widget_show (window);
979
980 return window;
981 }
982
983
984
985
986 #endif
987 // NEW_GTK_DND_CODE
988