]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/dnd.cpp
For MSW, scan line boundary aligned, and >2MB case enabled
[wxWidgets.git] / src / gtk / dnd.cpp
CommitLineData
c801d85f
KB
1///////////////////////////////////////////////////////////////////////////////
2// Name: dnd.cpp
3// Purpose: wxDropTarget class
4// Author: Robert Roebling
a81258be 5// Id: $Id$
01111366
RR
6// Copyright: (c) 1998 Robert Roebling
7// Licence: wxWindows licence
c801d85f
KB
8///////////////////////////////////////////////////////////////////////////////
9
10#ifdef __GNUG__
11#pragma implementation "dnd.h"
12#endif
13
14#include "wx/dnd.h"
ac57418f 15
06cfab17 16#if wxUSE_DRAG_AND_DROP
ac57418f 17
c801d85f
KB
18#include "wx/window.h"
19#include "wx/app.h"
20#include "wx/gdicmn.h"
b527aac5
RR
21#include "wx/intl.h"
22#include "wx/utils.h"
c801d85f 23
83624f79
RR
24#include "gdk/gdk.h"
25#include "gtk/gtk.h"
c801d85f
KB
26#include "gdk/gdkprivate.h"
27
28#include <X11/Xlib.h>
29
30// ----------------------------------------------------------------------------
31// global
32// ----------------------------------------------------------------------------
33
34extern bool g_blockEventsOnDrag;
35
f5368809
RR
36#ifdef NEW_GTK_DND_CODE
37
33a5bc52
RR
38#include "gtk/gtkdnd.h"
39#include "gtk/gtkselection.h"
40
41// ----------------------------------------------------------------------------
42// "drag_leave"
43// ----------------------------------------------------------------------------
44
45static 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
56static 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
71static 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
93static 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
f5368809
RR
118wxDropTarget::wxDropTarget()
119{
120}
121
122wxDropTarget::~wxDropTarget()
123{
124}
125
126void wxDropTarget::UnregisterWidget( GtkWidget *widget )
127{
33a5bc52 128 wxCHECK_RET( widget != NULL, "unregister widget is NULL" );
f5368809 129
33a5bc52
RR
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 );
f5368809
RR
147}
148
149void wxDropTarget::RegisterWidget( GtkWidget *widget )
150{
33a5bc52 151 wxCHECK_RET( widget != NULL, "register widget is NULL" );
f5368809 152
33a5bc52
RR
153 GtkTargetEntry format;
154 format.info = 0;
155 format.flags = 0;
f5368809 156
33a5bc52 157 int valid = 0;
f5368809
RR
158 for ( size_t i = 0; i < GetFormatCount(); i++ )
159 {
160 wxDataFormat df = GetFormat( i );
161 switch (df)
162 {
163 case wxDF_TEXT:
33a5bc52 164 format.target = "text/plain";
f5368809
RR
165 valid++;
166 break;
167 case wxDF_FILENAME:
33a5bc52 168 format.target = "file:ALL";
f5368809
RR
169 valid++;
170 break;
171 default:
172 break;
173 }
174 }
175
33a5bc52 176 wxASSERT_MSG( valid != 0, "No valid DnD format supported." );
f5368809 177
33a5bc52
RR
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 );
f5368809
RR
195}
196
197// ----------------------------------------------------------------------------
198// wxTextDropTarget
199// ----------------------------------------------------------------------------
200
201bool 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
207bool 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
214size_t wxTextDropTarget::GetFormatCount() const
215{
216 return 1;
217}
218
219wxDataFormat wxTextDropTarget::GetFormat(size_t WXUNUSED(n)) const
220{
221 return wxDF_TEXT;
222}
223
224// ----------------------------------------------------------------------------
225// wxFileDropTarget
226// ----------------------------------------------------------------------------
227
228bool 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
240bool 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
266size_t wxFileDropTarget::GetFormatCount() const
267{
268 return 1;
269}
270
271wxDataFormat wxFileDropTarget::GetFormat(size_t WXUNUSED(n)) const
272{
273 return wxDF_FILENAME;
274}
275
276//-------------------------------------------------------------------------
277// wxDropSource
278//-------------------------------------------------------------------------
279
280wxDropSource::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
295wxDropSource::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
310void wxDropSource::SetData( wxDataObject &data )
311{
312 m_data = &data;
313}
314
315wxDropSource::~wxDropSource(void)
316{
317// if (m_data) delete m_data;
318
319 g_blockEventsOnDrag = FALSE;
320}
321
322wxDragResult 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
340void 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
365void wxDropSource::UnregisterWindow(void)
366{
367 if (!m_widget) return;
368
369 // TODO
370}
371
33a5bc52
RR
372
373#else // NEW_CODE
374
a802c3a1
RR
375GtkWidget *shape_create_icon (char **data,
376 gint x,
377 gint y,
378 gint px,
379 gint py,
380 gint window_type);
381
382/* XPM */
383static 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 */
424static 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
33a5bc52
RR
468//-----------------------------------------------------------------------------
469// "drop_data_available_event"
470//-----------------------------------------------------------------------------
471
472static 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
a802c3a1 482// printf( "Drop data is of type %s.\n", event->data_type );
33a5bc52
RR
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}
f5368809 492
c801d85f
KB
493// ----------------------------------------------------------------------------
494// wxDropTarget
495// ----------------------------------------------------------------------------
496
497wxDropTarget::wxDropTarget()
498{
ff7b1510 499}
c801d85f
KB
500
501wxDropTarget::~wxDropTarget()
502{
ff7b1510 503}
c801d85f 504
c801d85f
KB
505void wxDropTarget::UnregisterWidget( GtkWidget *widget )
506{
33a5bc52 507 if (!widget) return;
e3e65dac 508
33a5bc52
RR
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 );
ff7b1510 513}
c801d85f 514
e3e65dac
RR
515void wxDropTarget::RegisterWidget( GtkWidget *widget )
516{
33a5bc52
RR
517 wxString formats;
518 int valid = 0;
e3e65dac 519
33a5bc52 520 for ( size_t i = 0; i < GetFormatCount(); i++ )
e3e65dac 521 {
33a5bc52
RR
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 }
ff7b1510 538 }
e3e65dac 539
33a5bc52 540 char *str = WXSTRINGCAST formats;
e3e65dac 541
33a5bc52
RR
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 );
ff7b1510 546}
e3e65dac 547
c801d85f
KB
548// ----------------------------------------------------------------------------
549// wxTextDropTarget
550// ----------------------------------------------------------------------------
551
dc86cb34 552bool wxTextDropTarget::OnDrop( long x, long y, const void *data, size_t WXUNUSED(size) )
c801d85f 553{
33a5bc52
RR
554 OnDropText( x, y, (const char*)data );
555 return TRUE;
ff7b1510 556}
c801d85f
KB
557
558bool wxTextDropTarget::OnDropText( long x, long y, const char *psz )
559{
33a5bc52
RR
560 printf( "Got dropped text: %s.\n", psz );
561 printf( "At x: %d, y: %d.\n", (int)x, (int)y );
562 return TRUE;
ff7b1510 563}
c801d85f 564
e3e65dac 565size_t wxTextDropTarget::GetFormatCount() const
c801d85f 566{
33a5bc52 567 return 1;
e3e65dac
RR
568}
569
570wxDataFormat wxTextDropTarget::GetFormat(size_t WXUNUSED(n)) const
571{
33a5bc52 572 return wxDF_TEXT;
e3e65dac
RR
573}
574
575// ----------------------------------------------------------------------------
576// wxFileDropTarget
577// ----------------------------------------------------------------------------
578
e5403d7c 579bool wxFileDropTarget::OnDropFiles( long x, long y, size_t nFiles, const char * const aszFiles[] )
e3e65dac 580{
33a5bc52
RR
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;
e3e65dac
RR
589}
590
dc86cb34 591bool wxFileDropTarget::OnDrop(long x, long y, const void *data, size_t size )
e3e65dac 592{
33a5bc52
RR
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++;
e5403d7c 597
33a5bc52 598 if (number == 0) return TRUE;
e5403d7c 599
33a5bc52 600 char **files = new char*[number];
e5403d7c 601
33a5bc52
RR
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 }
e3e65dac 609
33a5bc52 610 bool ret = OnDropFiles( x, y, 1, files );
e5403d7c 611
33a5bc52 612 free( files );
e5403d7c 613
33a5bc52 614 return ret;
e3e65dac
RR
615}
616
617size_t wxFileDropTarget::GetFormatCount() const
618{
33a5bc52 619 return 1;
e3e65dac
RR
620}
621
622wxDataFormat wxFileDropTarget::GetFormat(size_t WXUNUSED(n)) const
623{
33a5bc52 624 return wxDF_FILENAME;
e3e65dac 625}
c801d85f
KB
626
627//-------------------------------------------------------------------------
e3e65dac 628// wxDropSource
c801d85f
KB
629//-------------------------------------------------------------------------
630
b527aac5
RR
631static void
632shape_motion (GtkWidget *widget,
633 GdkEventMotion */*event*/);
634
c801d85f
KB
635//-----------------------------------------------------------------------------
636// drag request
637
b6af8d80 638void gtk_drag_callback( GtkWidget *widget, GdkEvent *event, wxDropSource *source )
c801d85f 639{
8b53e5a2
RR
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
2830bf19
RR
650 char *s = WXSTRINGCAST text;
651
8b53e5a2
RR
652 gtk_widget_dnd_data_set( widget,
653 event,
2830bf19
RR
654 (unsigned char*) s,
655 (int) text.Length()+1 );
8b53e5a2
RR
656
657 break;
658 }
659
660 case wxDF_FILENAME:
661 {
662 wxFileDataObject *file_object = (wxFileDataObject*) data;
663
664 wxString text = file_object->GetFiles();
665
2830bf19
RR
666 char *s = WXSTRINGCAST text;
667
8b53e5a2
RR
668 gtk_widget_dnd_data_set( widget,
669 event,
2830bf19
RR
670 (unsigned char*) s,
671 (int) text.Length()+1 );
8b53e5a2
RR
672
673 break;
674 }
675
676 default:
677 {
678 return;
679 }
680 }
b6af8d80 681
46ccb510 682 source->m_retValue = wxDragCopy;
ff7b1510 683}
c801d85f 684
e3e65dac 685wxDropSource::wxDropSource( wxWindow *win )
c801d85f
KB
686{
687 g_blockEventsOnDrag = TRUE;
e3e65dac 688
c801d85f
KB
689 m_window = win;
690 m_widget = win->m_widget;
691 if (win->m_wxwindow) m_widget = win->m_wxwindow;
c801d85f 692
c67daf87 693 m_data = (wxDataObject *) NULL;
46ccb510 694 m_retValue = wxDragCancel;
e3e65dac 695
c801d85f
KB
696 m_defaultCursor = wxCursor( wxCURSOR_NO_ENTRY );
697 m_goaheadCursor = wxCursor( wxCURSOR_HAND );
ff7b1510 698}
c801d85f 699
e3e65dac 700wxDropSource::wxDropSource( wxDataObject &data, wxWindow *win )
c801d85f 701{
e3e65dac
RR
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;
46ccb510 707 m_retValue = wxDragCancel;
e3e65dac
RR
708
709 m_data = &data;
710
711 m_defaultCursor = wxCursor( wxCURSOR_NO_ENTRY );
712 m_goaheadCursor = wxCursor( wxCURSOR_HAND );
ff7b1510 713}
e3e65dac
RR
714
715void wxDropSource::SetData( wxDataObject &data )
c801d85f 716{
e3e65dac 717 m_data = &data;
ff7b1510 718}
c801d85f 719
e3e65dac 720wxDropSource::~wxDropSource(void)
c801d85f 721{
e3e65dac
RR
722// if (m_data) delete m_data;
723
724 g_blockEventsOnDrag = FALSE;
ff7b1510 725}
e3e65dac 726
46ccb510 727wxDragResult wxDropSource::DoDragDrop( bool WXUNUSED(bAllowMove) )
e3e65dac 728{
46ccb510
JS
729 if (gdk_dnd.dnd_grabbed) return (wxDragResult) wxDragNone;
730 if (gdk_dnd.drag_really) return (wxDragResult) wxDragNone;
e3e65dac 731
f6d53978 732 wxASSERT_MSG( m_data, "wxDragSource: no data" );
b6af8d80 733
46ccb510 734 if (!m_data) return (wxDragResult) wxDragNone;
c801d85f 735
bbe0af5b
RR
736 static GtkWidget *drag_icon = (GtkWidget*) NULL;
737 static GtkWidget *drop_icon = (GtkWidget*) NULL;
a802c3a1
RR
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 }
b527aac5 766
a802c3a1 767
b527aac5 768 gdk_dnd_set_drag_shape( drag_icon->window,
a802c3a1
RR
769 &hotspot_1,
770 drop_icon->window,
771 &hotspot_2);
772
773
c801d85f
KB
774 GdkWindowPrivate *wp = (GdkWindowPrivate*) m_widget->window;
775
776 RegisterWindow();
c801d85f
KB
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 );
c67daf87 787 gdk_dnd.drag_startwindows = (GdkWindow **) NULL;
ff7b1510 788 }
c801d85f
KB
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;
e3e65dac
RR
813
814 int x = 0;
815 int y = 0;
b527aac5 816 wxGetMousePosition( &x, &y );
e3e65dac 817
c801d85f
KB
818 gdk_dnd_display_drag_cursor( x, y, FALSE, TRUE );
819
b527aac5
RR
820/*
821 shape_motion( drag_icon, (GdkEventMotion *)NULL );
822 shape_motion( drop_icon, (GdkEventMotion *)NULL );
823*/
92976ab6 824
c801d85f
KB
825 while (gdk_dnd.drag_really || gdk_dnd.drag_perhaps) wxYield();
826
c801d85f 827 UnregisterWindow();
e3e65dac 828
30dea054
RR
829 g_blockEventsOnDrag = FALSE;
830
b6af8d80 831 return m_retValue;
ff7b1510 832}
c801d85f 833
e3e65dac 834void wxDropSource::RegisterWindow(void)
c801d85f 835{
e3e65dac 836 if (!m_data) return;
c801d85f 837
e3e65dac
RR
838 wxString formats;
839
8b53e5a2 840 wxDataFormat df = m_data->GetFormat();
c801d85f 841
e3e65dac
RR
842 switch (df)
843 {
844 case wxDF_TEXT:
845 formats += "text/plain";
846 break;
847 case wxDF_FILENAME:
61607c36 848 formats += "file:ALL";
e3e65dac
RR
849 break;
850 default:
851 break;
852 }
c801d85f 853
e3e65dac 854 char *str = WXSTRINGCAST formats;
c801d85f 855
e3e65dac 856 gtk_widget_dnd_drag_set( m_widget, TRUE, &str, 1 );
c801d85f 857
e3e65dac 858 gtk_signal_connect( GTK_OBJECT(m_widget), "drag_request_event",
b6af8d80 859 GTK_SIGNAL_FUNC(gtk_drag_callback), (gpointer)this );
ff7b1510 860}
c801d85f 861
e3e65dac 862void wxDropSource::UnregisterWindow(void)
c801d85f
KB
863{
864 if (!m_widget) return;
865
c67daf87 866 gtk_widget_dnd_drag_set( m_widget, FALSE, (gchar **) NULL, 0 );
e3e65dac 867
b6af8d80 868 gtk_signal_disconnect_by_data( GTK_OBJECT(m_widget), (gpointer)this );
ff7b1510 869}
f5368809 870
a802c3a1
RR
871
872/*
873 * Shaped Windows
874 */
bbe0af5b 875static GdkWindow *root_win = (GdkWindow*) NULL;
a802c3a1
RR
876
877typedef struct _cursoroffset {gint x,y;} CursorOffset;
878
879static void
880shape_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
b527aac5 888 p = (CursorOffset *)gtk_object_get_user_data (GTK_OBJECT(widget));
a802c3a1
RR
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,
b527aac5
RR
894 (GdkEventMask)
895 (GDK_BUTTON_RELEASE_MASK |
896 GDK_BUTTON_MOTION_MASK |
897 GDK_POINTER_MOTION_HINT_MASK),
bbe0af5b
RR
898 (GdkWindow*)NULL,
899 (GdkCursor*) NULL, 0);
a802c3a1
RR
900}
901
902
903static void
904shape_released (GtkWidget *widget)
905{
906 gtk_grab_remove (widget);
907 gdk_pointer_ungrab (0);
908}
909
910static void
911shape_motion (GtkWidget *widget,
b527aac5 912 GdkEventMotion */*event*/)
a802c3a1
RR
913{
914 gint xp, yp;
915 CursorOffset * p;
916 GdkModifierType mask;
917
b527aac5 918 p = (CursorOffset *)gtk_object_get_user_data (GTK_OBJECT (widget));
a802c3a1
RR
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
928GtkWidget *
929shape_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 */
b527aac5 951 window = gtk_window_new ((GtkWindowType)window_type);
a802c3a1
RR
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
f5368809
RR
993#endif
994 // NEW_GTK_DND_CODE
995
ac57418f
RR
996#endif
997
998 // wxUSE_DRAG_AND_DROP