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