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