]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/dnd.cpp
Corrected memory.cpp compilation error; Cygwin makefile uses generic wxDirDlg
[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"
15#include "wx/window.h"
16#include "wx/app.h"
17#include "wx/gdicmn.h"
b527aac5
RR
18#include "wx/intl.h"
19#include "wx/utils.h"
c801d85f 20
83624f79
RR
21#include "gdk/gdk.h"
22#include "gtk/gtk.h"
c801d85f
KB
23#include "gdk/gdkprivate.h"
24
25#include <X11/Xlib.h>
26
27// ----------------------------------------------------------------------------
28// global
29// ----------------------------------------------------------------------------
30
31extern bool g_blockEventsOnDrag;
32
f5368809
RR
33#ifdef NEW_GTK_DND_CODE
34
33a5bc52
RR
35#include "gtk/gtkdnd.h"
36#include "gtk/gtkselection.h"
37
38// ----------------------------------------------------------------------------
39// "drag_leave"
40// ----------------------------------------------------------------------------
41
42static 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
53static 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
68static 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
90static 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
f5368809
RR
115wxDropTarget::wxDropTarget()
116{
117}
118
119wxDropTarget::~wxDropTarget()
120{
121}
122
123void wxDropTarget::UnregisterWidget( GtkWidget *widget )
124{
33a5bc52 125 wxCHECK_RET( widget != NULL, "unregister widget is NULL" );
f5368809 126
33a5bc52
RR
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 );
f5368809
RR
144}
145
146void wxDropTarget::RegisterWidget( GtkWidget *widget )
147{
33a5bc52 148 wxCHECK_RET( widget != NULL, "register widget is NULL" );
f5368809 149
33a5bc52
RR
150 GtkTargetEntry format;
151 format.info = 0;
152 format.flags = 0;
f5368809 153
33a5bc52 154 int valid = 0;
f5368809
RR
155 for ( size_t i = 0; i < GetFormatCount(); i++ )
156 {
157 wxDataFormat df = GetFormat( i );
158 switch (df)
159 {
160 case wxDF_TEXT:
33a5bc52 161 format.target = "text/plain";
f5368809
RR
162 valid++;
163 break;
164 case wxDF_FILENAME:
33a5bc52 165 format.target = "file:ALL";
f5368809
RR
166 valid++;
167 break;
168 default:
169 break;
170 }
171 }
172
33a5bc52 173 wxASSERT_MSG( valid != 0, "No valid DnD format supported." );
f5368809 174
33a5bc52
RR
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 );
f5368809
RR
192}
193
194// ----------------------------------------------------------------------------
195// wxTextDropTarget
196// ----------------------------------------------------------------------------
197
198bool 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
204bool 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
211size_t wxTextDropTarget::GetFormatCount() const
212{
213 return 1;
214}
215
216wxDataFormat wxTextDropTarget::GetFormat(size_t WXUNUSED(n)) const
217{
218 return wxDF_TEXT;
219}
220
221// ----------------------------------------------------------------------------
222// wxFileDropTarget
223// ----------------------------------------------------------------------------
224
225bool 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
237bool 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
263size_t wxFileDropTarget::GetFormatCount() const
264{
265 return 1;
266}
267
268wxDataFormat wxFileDropTarget::GetFormat(size_t WXUNUSED(n)) const
269{
270 return wxDF_FILENAME;
271}
272
273//-------------------------------------------------------------------------
274// wxDropSource
275//-------------------------------------------------------------------------
276
277wxDropSource::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
292wxDropSource::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
307void wxDropSource::SetData( wxDataObject &data )
308{
309 m_data = &data;
310}
311
312wxDropSource::~wxDropSource(void)
313{
314// if (m_data) delete m_data;
315
316 g_blockEventsOnDrag = FALSE;
317}
318
319wxDragResult 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
337void 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
362void wxDropSource::UnregisterWindow(void)
363{
364 if (!m_widget) return;
365
366 // TODO
367}
368
33a5bc52
RR
369
370#else // NEW_CODE
371
a802c3a1
RR
372GtkWidget *shape_create_icon (char **data,
373 gint x,
374 gint y,
375 gint px,
376 gint py,
377 gint window_type);
378
379/* XPM */
380static 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 */
421static 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
33a5bc52
RR
465//-----------------------------------------------------------------------------
466// "drop_data_available_event"
467//-----------------------------------------------------------------------------
468
469static 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
a802c3a1 479// printf( "Drop data is of type %s.\n", event->data_type );
33a5bc52
RR
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}
f5368809 489
c801d85f
KB
490// ----------------------------------------------------------------------------
491// wxDropTarget
492// ----------------------------------------------------------------------------
493
494wxDropTarget::wxDropTarget()
495{
ff7b1510 496}
c801d85f
KB
497
498wxDropTarget::~wxDropTarget()
499{
ff7b1510 500}
c801d85f 501
c801d85f
KB
502void wxDropTarget::UnregisterWidget( GtkWidget *widget )
503{
33a5bc52 504 if (!widget) return;
e3e65dac 505
33a5bc52
RR
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 );
ff7b1510 510}
c801d85f 511
e3e65dac
RR
512void wxDropTarget::RegisterWidget( GtkWidget *widget )
513{
33a5bc52
RR
514 wxString formats;
515 int valid = 0;
e3e65dac 516
33a5bc52 517 for ( size_t i = 0; i < GetFormatCount(); i++ )
e3e65dac 518 {
33a5bc52
RR
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 }
ff7b1510 535 }
e3e65dac 536
33a5bc52 537 char *str = WXSTRINGCAST formats;
e3e65dac 538
33a5bc52
RR
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 );
ff7b1510 543}
e3e65dac 544
c801d85f
KB
545// ----------------------------------------------------------------------------
546// wxTextDropTarget
547// ----------------------------------------------------------------------------
548
dc86cb34 549bool wxTextDropTarget::OnDrop( long x, long y, const void *data, size_t WXUNUSED(size) )
c801d85f 550{
33a5bc52
RR
551 OnDropText( x, y, (const char*)data );
552 return TRUE;
ff7b1510 553}
c801d85f
KB
554
555bool wxTextDropTarget::OnDropText( long x, long y, const char *psz )
556{
33a5bc52
RR
557 printf( "Got dropped text: %s.\n", psz );
558 printf( "At x: %d, y: %d.\n", (int)x, (int)y );
559 return TRUE;
ff7b1510 560}
c801d85f 561
e3e65dac 562size_t wxTextDropTarget::GetFormatCount() const
c801d85f 563{
33a5bc52 564 return 1;
e3e65dac
RR
565}
566
567wxDataFormat wxTextDropTarget::GetFormat(size_t WXUNUSED(n)) const
568{
33a5bc52 569 return wxDF_TEXT;
e3e65dac
RR
570}
571
572// ----------------------------------------------------------------------------
573// wxFileDropTarget
574// ----------------------------------------------------------------------------
575
e5403d7c 576bool wxFileDropTarget::OnDropFiles( long x, long y, size_t nFiles, const char * const aszFiles[] )
e3e65dac 577{
33a5bc52
RR
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;
e3e65dac
RR
586}
587
dc86cb34 588bool wxFileDropTarget::OnDrop(long x, long y, const void *data, size_t size )
e3e65dac 589{
33a5bc52
RR
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++;
e5403d7c 594
33a5bc52 595 if (number == 0) return TRUE;
e5403d7c 596
33a5bc52 597 char **files = new char*[number];
e5403d7c 598
33a5bc52
RR
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 }
e3e65dac 606
33a5bc52 607 bool ret = OnDropFiles( x, y, 1, files );
e5403d7c 608
33a5bc52 609 free( files );
e5403d7c 610
33a5bc52 611 return ret;
e3e65dac
RR
612}
613
614size_t wxFileDropTarget::GetFormatCount() const
615{
33a5bc52 616 return 1;
e3e65dac
RR
617}
618
619wxDataFormat wxFileDropTarget::GetFormat(size_t WXUNUSED(n)) const
620{
33a5bc52 621 return wxDF_FILENAME;
e3e65dac 622}
c801d85f
KB
623
624//-------------------------------------------------------------------------
e3e65dac 625// wxDropSource
c801d85f
KB
626//-------------------------------------------------------------------------
627
b527aac5
RR
628static void
629shape_motion (GtkWidget *widget,
630 GdkEventMotion */*event*/);
631
c801d85f
KB
632//-----------------------------------------------------------------------------
633// drag request
634
b6af8d80 635void gtk_drag_callback( GtkWidget *widget, GdkEvent *event, wxDropSource *source )
c801d85f 636{
8b53e5a2
RR
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
2830bf19
RR
647 char *s = WXSTRINGCAST text;
648
8b53e5a2
RR
649 gtk_widget_dnd_data_set( widget,
650 event,
2830bf19
RR
651 (unsigned char*) s,
652 (int) text.Length()+1 );
8b53e5a2
RR
653
654 break;
655 }
656
657 case wxDF_FILENAME:
658 {
659 wxFileDataObject *file_object = (wxFileDataObject*) data;
660
661 wxString text = file_object->GetFiles();
662
2830bf19
RR
663 char *s = WXSTRINGCAST text;
664
8b53e5a2
RR
665 gtk_widget_dnd_data_set( widget,
666 event,
2830bf19
RR
667 (unsigned char*) s,
668 (int) text.Length()+1 );
8b53e5a2
RR
669
670 break;
671 }
672
673 default:
674 {
675 return;
676 }
677 }
b6af8d80 678
46ccb510 679 source->m_retValue = wxDragCopy;
ff7b1510 680}
c801d85f 681
e3e65dac 682wxDropSource::wxDropSource( wxWindow *win )
c801d85f
KB
683{
684 g_blockEventsOnDrag = TRUE;
e3e65dac 685
c801d85f
KB
686 m_window = win;
687 m_widget = win->m_widget;
688 if (win->m_wxwindow) m_widget = win->m_wxwindow;
c801d85f 689
c67daf87 690 m_data = (wxDataObject *) NULL;
46ccb510 691 m_retValue = wxDragCancel;
e3e65dac 692
c801d85f
KB
693 m_defaultCursor = wxCursor( wxCURSOR_NO_ENTRY );
694 m_goaheadCursor = wxCursor( wxCURSOR_HAND );
ff7b1510 695}
c801d85f 696
e3e65dac 697wxDropSource::wxDropSource( wxDataObject &data, wxWindow *win )
c801d85f 698{
e3e65dac
RR
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;
46ccb510 704 m_retValue = wxDragCancel;
e3e65dac
RR
705
706 m_data = &data;
707
708 m_defaultCursor = wxCursor( wxCURSOR_NO_ENTRY );
709 m_goaheadCursor = wxCursor( wxCURSOR_HAND );
ff7b1510 710}
e3e65dac
RR
711
712void wxDropSource::SetData( wxDataObject &data )
c801d85f 713{
e3e65dac 714 m_data = &data;
ff7b1510 715}
c801d85f 716
e3e65dac 717wxDropSource::~wxDropSource(void)
c801d85f 718{
e3e65dac
RR
719// if (m_data) delete m_data;
720
721 g_blockEventsOnDrag = FALSE;
ff7b1510 722}
e3e65dac 723
46ccb510 724wxDragResult wxDropSource::DoDragDrop( bool WXUNUSED(bAllowMove) )
e3e65dac 725{
46ccb510
JS
726 if (gdk_dnd.dnd_grabbed) return (wxDragResult) wxDragNone;
727 if (gdk_dnd.drag_really) return (wxDragResult) wxDragNone;
e3e65dac 728
f6d53978 729 wxASSERT_MSG( m_data, "wxDragSource: no data" );
b6af8d80 730
46ccb510 731 if (!m_data) return (wxDragResult) wxDragNone;
c801d85f 732
a802c3a1
RR
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 }
b527aac5 763
a802c3a1 764
b527aac5 765 gdk_dnd_set_drag_shape( drag_icon->window,
a802c3a1
RR
766 &hotspot_1,
767 drop_icon->window,
768 &hotspot_2);
769
770
c801d85f
KB
771 GdkWindowPrivate *wp = (GdkWindowPrivate*) m_widget->window;
772
773 RegisterWindow();
c801d85f
KB
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 );
c67daf87 784 gdk_dnd.drag_startwindows = (GdkWindow **) NULL;
ff7b1510 785 }
c801d85f
KB
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;
e3e65dac
RR
810
811 int x = 0;
812 int y = 0;
b527aac5 813 wxGetMousePosition( &x, &y );
e3e65dac 814
c801d85f
KB
815 gdk_dnd_display_drag_cursor( x, y, FALSE, TRUE );
816
b527aac5
RR
817/*
818 shape_motion( drag_icon, (GdkEventMotion *)NULL );
819 shape_motion( drop_icon, (GdkEventMotion *)NULL );
820*/
92976ab6 821
c801d85f
KB
822 while (gdk_dnd.drag_really || gdk_dnd.drag_perhaps) wxYield();
823
c801d85f 824 UnregisterWindow();
e3e65dac 825
30dea054
RR
826 g_blockEventsOnDrag = FALSE;
827
b6af8d80 828 return m_retValue;
ff7b1510 829}
c801d85f 830
e3e65dac 831void wxDropSource::RegisterWindow(void)
c801d85f 832{
e3e65dac 833 if (!m_data) return;
c801d85f 834
e3e65dac
RR
835 wxString formats;
836
8b53e5a2 837 wxDataFormat df = m_data->GetFormat();
c801d85f 838
e3e65dac
RR
839 switch (df)
840 {
841 case wxDF_TEXT:
842 formats += "text/plain";
843 break;
844 case wxDF_FILENAME:
61607c36 845 formats += "file:ALL";
e3e65dac
RR
846 break;
847 default:
848 break;
849 }
c801d85f 850
e3e65dac 851 char *str = WXSTRINGCAST formats;
c801d85f 852
e3e65dac 853 gtk_widget_dnd_drag_set( m_widget, TRUE, &str, 1 );
c801d85f 854
e3e65dac 855 gtk_signal_connect( GTK_OBJECT(m_widget), "drag_request_event",
b6af8d80 856 GTK_SIGNAL_FUNC(gtk_drag_callback), (gpointer)this );
ff7b1510 857}
c801d85f 858
e3e65dac 859void wxDropSource::UnregisterWindow(void)
c801d85f
KB
860{
861 if (!m_widget) return;
862
c67daf87 863 gtk_widget_dnd_drag_set( m_widget, FALSE, (gchar **) NULL, 0 );
e3e65dac 864
b6af8d80 865 gtk_signal_disconnect_by_data( GTK_OBJECT(m_widget), (gpointer)this );
ff7b1510 866}
f5368809 867
a802c3a1
RR
868
869/*
870 * Shaped Windows
871 */
872static GdkWindow *root_win = NULL;
873
874typedef struct _cursoroffset {gint x,y;} CursorOffset;
875
876static void
877shape_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
b527aac5 885 p = (CursorOffset *)gtk_object_get_user_data (GTK_OBJECT(widget));
a802c3a1
RR
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,
b527aac5
RR
891 (GdkEventMask)
892 (GDK_BUTTON_RELEASE_MASK |
893 GDK_BUTTON_MOTION_MASK |
894 GDK_POINTER_MOTION_HINT_MASK),
a802c3a1
RR
895 NULL, NULL, 0);
896}
897
898
899static void
900shape_released (GtkWidget *widget)
901{
902 gtk_grab_remove (widget);
903 gdk_pointer_ungrab (0);
904}
905
906static void
907shape_motion (GtkWidget *widget,
b527aac5 908 GdkEventMotion */*event*/)
a802c3a1
RR
909{
910 gint xp, yp;
911 CursorOffset * p;
912 GdkModifierType mask;
913
b527aac5 914 p = (CursorOffset *)gtk_object_get_user_data (GTK_OBJECT (widget));
a802c3a1
RR
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
924GtkWidget *
925shape_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 */
b527aac5 947 window = gtk_window_new ((GtkWindowType)window_type);
a802c3a1
RR
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
f5368809
RR
992#endif
993 // NEW_GTK_DND_CODE
994