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