]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/dnd.cpp
Changed m_children to GetChildren() -- not all ports are the same!
[wxWidgets.git] / src / gtk / 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 char *s = WXSTRINGCAST text;
646
647 gtk_widget_dnd_data_set( widget,
648 event,
649 (unsigned char*) s,
650 (int) text.Length()+1 );
651
652 break;
653 }
654
655 case wxDF_FILENAME:
656 {
657 wxFileDataObject *file_object = (wxFileDataObject*) data;
658
659 wxString text = file_object->GetFiles();
660
661 char *s = WXSTRINGCAST text;
662
663 gtk_widget_dnd_data_set( widget,
664 event,
665 (unsigned char*) s,
666 (int) text.Length()+1 );
667
668 break;
669 }
670
671 default:
672 {
673 return;
674 }
675 }
676
677 source->m_retValue = wxDragCopy;
678 }
679
680 wxDropSource::wxDropSource( wxWindow *win )
681 {
682 g_blockEventsOnDrag = TRUE;
683
684 m_window = win;
685 m_widget = win->m_widget;
686 if (win->m_wxwindow) m_widget = win->m_wxwindow;
687
688 m_data = (wxDataObject *) NULL;
689 m_retValue = wxDragCancel;
690
691 m_defaultCursor = wxCursor( wxCURSOR_NO_ENTRY );
692 m_goaheadCursor = wxCursor( wxCURSOR_HAND );
693 }
694
695 wxDropSource::wxDropSource( wxDataObject &data, wxWindow *win )
696 {
697 g_blockEventsOnDrag = TRUE;
698
699 m_window = win;
700 m_widget = win->m_widget;
701 if (win->m_wxwindow) m_widget = win->m_wxwindow;
702 m_retValue = wxDragCancel;
703
704 m_data = &data;
705
706 m_defaultCursor = wxCursor( wxCURSOR_NO_ENTRY );
707 m_goaheadCursor = wxCursor( wxCURSOR_HAND );
708 }
709
710 void wxDropSource::SetData( wxDataObject &data )
711 {
712 m_data = &data;
713 }
714
715 wxDropSource::~wxDropSource(void)
716 {
717 // if (m_data) delete m_data;
718
719 g_blockEventsOnDrag = FALSE;
720 }
721
722 wxDragResult wxDropSource::DoDragDrop( bool WXUNUSED(bAllowMove) )
723 {
724 if (gdk_dnd.dnd_grabbed) return (wxDragResult) wxDragNone;
725 if (gdk_dnd.drag_really) return (wxDragResult) wxDragNone;
726
727 wxASSERT_MSG( m_data, "wxDragSource: no data" );
728
729 if (!m_data) return (wxDragResult) wxDragNone;
730
731 static GtkWidget *drag_icon = NULL;
732 static GtkWidget *drop_icon = NULL;
733
734 GdkPoint hotspot_1 = {0,-5 };
735
736 if (!drag_icon)
737 {
738 drag_icon = shape_create_icon ( gv_xpm,
739 440, 140, 0,0, GTK_WINDOW_POPUP);
740
741 gtk_signal_connect (GTK_OBJECT (drag_icon), "destroy",
742 GTK_SIGNAL_FUNC(gtk_widget_destroyed),
743 &drag_icon);
744
745 gtk_widget_hide (drag_icon);
746 }
747
748 GdkPoint hotspot_2 = {-5,-5};
749
750 if (!drop_icon)
751 {
752 drop_icon = shape_create_icon ( page_xpm,
753 440, 140, 0,0, GTK_WINDOW_POPUP);
754
755 gtk_signal_connect (GTK_OBJECT (drop_icon), "destroy",
756 GTK_SIGNAL_FUNC(gtk_widget_destroyed),
757 &drop_icon);
758
759 gtk_widget_hide (drop_icon);
760 }
761
762
763 gdk_dnd_set_drag_shape( drag_icon->window,
764 &hotspot_1,
765 drop_icon->window,
766 &hotspot_2);
767
768
769 GdkWindowPrivate *wp = (GdkWindowPrivate*) m_widget->window;
770
771 RegisterWindow();
772
773 gdk_dnd.drag_perhaps = TRUE;
774
775 gdk_dnd.dnd_drag_start.x = 5;
776 gdk_dnd.dnd_drag_start.y = 5;
777 gdk_dnd.real_sw = wp;
778
779 if (gdk_dnd.drag_startwindows)
780 {
781 g_free( gdk_dnd.drag_startwindows );
782 gdk_dnd.drag_startwindows = (GdkWindow **) NULL;
783 }
784 gdk_dnd.drag_numwindows = gdk_dnd.drag_really = 0;
785
786 XWindowAttributes dnd_winattr;
787 XGetWindowAttributes( gdk_display, wp->xwindow, &dnd_winattr );
788 wp->dnd_drag_savedeventmask = dnd_winattr.your_event_mask;
789
790 gdk_dnd_drag_addwindow( m_widget->window );
791
792 GdkEventDragBegin ev;
793 ev.type = GDK_DRAG_BEGIN;
794 ev.window = m_widget->window;
795 ev.u.allflags = 0;
796 ev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
797
798 gdk_event_put( (GdkEvent*)&ev );
799
800 XGrabPointer( gdk_display, wp->xwindow, False,
801 ButtonMotionMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
802 GrabModeAsync, GrabModeAsync, gdk_root_window, None, CurrentTime );
803
804 gdk_dnd_set_drag_cursors( m_defaultCursor.GetCursor(), m_goaheadCursor.GetCursor() );
805
806 gdk_dnd.dnd_grabbed = TRUE;
807 gdk_dnd.drag_really = 1;
808
809 int x = 0;
810 int y = 0;
811 wxGetMousePosition( &x, &y );
812
813 gdk_dnd_display_drag_cursor( x, y, FALSE, TRUE );
814
815 /*
816 shape_motion( drag_icon, (GdkEventMotion *)NULL );
817 shape_motion( drop_icon, (GdkEventMotion *)NULL );
818 */
819
820 while (gdk_dnd.drag_really || gdk_dnd.drag_perhaps) wxYield();
821
822 UnregisterWindow();
823
824 g_blockEventsOnDrag = FALSE;
825
826 return m_retValue;
827 }
828
829 void wxDropSource::RegisterWindow(void)
830 {
831 if (!m_data) return;
832
833 wxString formats;
834
835 wxDataFormat df = m_data->GetFormat();
836
837 switch (df)
838 {
839 case wxDF_TEXT:
840 formats += "text/plain";
841 break;
842 case wxDF_FILENAME:
843 formats += "file:ALL";
844 break;
845 default:
846 break;
847 }
848
849 char *str = WXSTRINGCAST formats;
850
851 gtk_widget_dnd_drag_set( m_widget, TRUE, &str, 1 );
852
853 gtk_signal_connect( GTK_OBJECT(m_widget), "drag_request_event",
854 GTK_SIGNAL_FUNC(gtk_drag_callback), (gpointer)this );
855 }
856
857 void wxDropSource::UnregisterWindow(void)
858 {
859 if (!m_widget) return;
860
861 gtk_widget_dnd_drag_set( m_widget, FALSE, (gchar **) NULL, 0 );
862
863 gtk_signal_disconnect_by_data( GTK_OBJECT(m_widget), (gpointer)this );
864 }
865
866
867 /*
868 * Shaped Windows
869 */
870 static GdkWindow *root_win = NULL;
871
872 typedef struct _cursoroffset {gint x,y;} CursorOffset;
873
874 static void
875 shape_pressed (GtkWidget *widget, GdkEventButton *event)
876 {
877 CursorOffset *p;
878
879 /* ignore double and triple click */
880 if (event->type != GDK_BUTTON_PRESS)
881 return;
882
883 p = (CursorOffset *)gtk_object_get_user_data (GTK_OBJECT(widget));
884 p->x = (int) event->x;
885 p->y = (int) event->y;
886
887 gtk_grab_add (widget);
888 gdk_pointer_grab (widget->window, TRUE,
889 (GdkEventMask)
890 (GDK_BUTTON_RELEASE_MASK |
891 GDK_BUTTON_MOTION_MASK |
892 GDK_POINTER_MOTION_HINT_MASK),
893 NULL, NULL, 0);
894 }
895
896
897 static void
898 shape_released (GtkWidget *widget)
899 {
900 gtk_grab_remove (widget);
901 gdk_pointer_ungrab (0);
902 }
903
904 static void
905 shape_motion (GtkWidget *widget,
906 GdkEventMotion */*event*/)
907 {
908 gint xp, yp;
909 CursorOffset * p;
910 GdkModifierType mask;
911
912 p = (CursorOffset *)gtk_object_get_user_data (GTK_OBJECT (widget));
913
914 /*
915 * Can't use event->x / event->y here
916 * because I need absolute coordinates.
917 */
918 gdk_window_get_pointer (root_win, &xp, &yp, &mask);
919 gtk_widget_set_uposition (widget, xp - p->x, yp - p->y);
920 }
921
922 GtkWidget *
923 shape_create_icon (char **data,
924 gint x,
925 gint y,
926 gint px,
927 gint py,
928 gint window_type)
929 {
930 GtkWidget *window;
931 GtkWidget *pixmap;
932 GtkWidget *fixed;
933 CursorOffset* icon_pos;
934 GdkGC* gc;
935 GdkBitmap *gdk_pixmap_mask;
936 GdkPixmap *gdk_pixmap;
937 GtkStyle *style;
938
939 style = gtk_widget_get_default_style ();
940 gc = style->black_gc;
941
942 /*
943 * GDK_WINDOW_TOPLEVEL works also, giving you a title border
944 */
945 window = gtk_window_new ((GtkWindowType)window_type);
946
947 fixed = gtk_fixed_new ();
948 gtk_widget_set_usize (fixed, 100,100);
949 gtk_container_add (GTK_CONTAINER (window), fixed);
950 gtk_widget_show (fixed);
951
952 gtk_widget_set_events (window,
953 gtk_widget_get_events (window) |
954 GDK_BUTTON_MOTION_MASK |
955 GDK_POINTER_MOTION_HINT_MASK |
956 GDK_BUTTON_PRESS_MASK);
957
958 gtk_widget_realize (window);
959
960 gdk_pixmap = gdk_pixmap_create_from_xpm_d (window->window, &gdk_pixmap_mask,
961 &style->bg[GTK_STATE_NORMAL],
962 (gchar**) data );
963
964 pixmap = gtk_pixmap_new (gdk_pixmap, gdk_pixmap_mask);
965 gtk_fixed_put (GTK_FIXED (fixed), pixmap, px,py);
966 gtk_widget_show (pixmap);
967
968 gtk_widget_shape_combine_mask (window, gdk_pixmap_mask, px,py);
969
970
971 gtk_signal_connect (GTK_OBJECT (window), "button_press_event",
972 GTK_SIGNAL_FUNC (shape_pressed),NULL);
973 gtk_signal_connect (GTK_OBJECT (window), "button_release_event",
974 GTK_SIGNAL_FUNC (shape_released),NULL);
975 gtk_signal_connect (GTK_OBJECT (window), "motion_notify_event",
976 GTK_SIGNAL_FUNC (shape_motion),NULL);
977
978 icon_pos = g_new (CursorOffset, 1);
979 gtk_object_set_user_data(GTK_OBJECT(window), icon_pos);
980
981 gtk_widget_set_uposition (window, x, y);
982 gtk_widget_show (window);
983
984 return window;
985 }
986
987
988
989
990 #endif
991 // NEW_GTK_DND_CODE
992