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