]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/dnd.cpp
Added OLE automation sample, changed BC++ makefiles
[wxWidgets.git] / src / gtk1 / 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
KB
20
21#include "gdk/gdkprivate.h"
22
23#include <X11/Xlib.h>
24
25// ----------------------------------------------------------------------------
26// global
27// ----------------------------------------------------------------------------
28
29extern bool g_blockEventsOnDrag;
30
f5368809
RR
31#ifdef NEW_GTK_DND_CODE
32
33a5bc52
RR
33#include "gtk/gtkdnd.h"
34#include "gtk/gtkselection.h"
35
36// ----------------------------------------------------------------------------
37// "drag_leave"
38// ----------------------------------------------------------------------------
39
40static 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
51static 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
66static 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
88static 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
f5368809
RR
113wxDropTarget::wxDropTarget()
114{
115}
116
117wxDropTarget::~wxDropTarget()
118{
119}
120
121void wxDropTarget::UnregisterWidget( GtkWidget *widget )
122{
33a5bc52 123 wxCHECK_RET( widget != NULL, "unregister widget is NULL" );
f5368809 124
33a5bc52
RR
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 );
f5368809
RR
142}
143
144void wxDropTarget::RegisterWidget( GtkWidget *widget )
145{
33a5bc52 146 wxCHECK_RET( widget != NULL, "register widget is NULL" );
f5368809 147
33a5bc52
RR
148 GtkTargetEntry format;
149 format.info = 0;
150 format.flags = 0;
f5368809 151
33a5bc52 152 int valid = 0;
f5368809
RR
153 for ( size_t i = 0; i < GetFormatCount(); i++ )
154 {
155 wxDataFormat df = GetFormat( i );
156 switch (df)
157 {
158 case wxDF_TEXT:
33a5bc52 159 format.target = "text/plain";
f5368809
RR
160 valid++;
161 break;
162 case wxDF_FILENAME:
33a5bc52 163 format.target = "file:ALL";
f5368809
RR
164 valid++;
165 break;
166 default:
167 break;
168 }
169 }
170
33a5bc52 171 wxASSERT_MSG( valid != 0, "No valid DnD format supported." );
f5368809 172
33a5bc52
RR
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 );
f5368809
RR
190}
191
192// ----------------------------------------------------------------------------
193// wxTextDropTarget
194// ----------------------------------------------------------------------------
195
196bool 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
202bool 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
209size_t wxTextDropTarget::GetFormatCount() const
210{
211 return 1;
212}
213
214wxDataFormat wxTextDropTarget::GetFormat(size_t WXUNUSED(n)) const
215{
216 return wxDF_TEXT;
217}
218
219// ----------------------------------------------------------------------------
220// wxFileDropTarget
221// ----------------------------------------------------------------------------
222
223bool 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
235bool 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
261size_t wxFileDropTarget::GetFormatCount() const
262{
263 return 1;
264}
265
266wxDataFormat wxFileDropTarget::GetFormat(size_t WXUNUSED(n)) const
267{
268 return wxDF_FILENAME;
269}
270
271//-------------------------------------------------------------------------
272// wxDropSource
273//-------------------------------------------------------------------------
274
275wxDropSource::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
290wxDropSource::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
305void wxDropSource::SetData( wxDataObject &data )
306{
307 m_data = &data;
308}
309
310wxDropSource::~wxDropSource(void)
311{
312// if (m_data) delete m_data;
313
314 g_blockEventsOnDrag = FALSE;
315}
316
317wxDragResult 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
335void 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
360void wxDropSource::UnregisterWindow(void)
361{
362 if (!m_widget) return;
363
364 // TODO
365}
366
33a5bc52
RR
367
368#else // NEW_CODE
369
a802c3a1
RR
370GtkWidget *shape_create_icon (char **data,
371 gint x,
372 gint y,
373 gint px,
374 gint py,
375 gint window_type);
376
377/* XPM */
378static 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 */
419static 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
33a5bc52
RR
463//-----------------------------------------------------------------------------
464// "drop_data_available_event"
465//-----------------------------------------------------------------------------
466
467static 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
a802c3a1 477// printf( "Drop data is of type %s.\n", event->data_type );
33a5bc52
RR
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}
f5368809 487
c801d85f
KB
488// ----------------------------------------------------------------------------
489// wxDropTarget
490// ----------------------------------------------------------------------------
491
492wxDropTarget::wxDropTarget()
493{
ff7b1510 494}
c801d85f
KB
495
496wxDropTarget::~wxDropTarget()
497{
ff7b1510 498}
c801d85f 499
c801d85f
KB
500void wxDropTarget::UnregisterWidget( GtkWidget *widget )
501{
33a5bc52 502 if (!widget) return;
e3e65dac 503
33a5bc52
RR
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 );
ff7b1510 508}
c801d85f 509
e3e65dac
RR
510void wxDropTarget::RegisterWidget( GtkWidget *widget )
511{
33a5bc52
RR
512 wxString formats;
513 int valid = 0;
e3e65dac 514
33a5bc52 515 for ( size_t i = 0; i < GetFormatCount(); i++ )
e3e65dac 516 {
33a5bc52
RR
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 }
ff7b1510 533 }
e3e65dac 534
33a5bc52 535 char *str = WXSTRINGCAST formats;
e3e65dac 536
33a5bc52
RR
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 );
ff7b1510 541}
e3e65dac 542
c801d85f
KB
543// ----------------------------------------------------------------------------
544// wxTextDropTarget
545// ----------------------------------------------------------------------------
546
dc86cb34 547bool wxTextDropTarget::OnDrop( long x, long y, const void *data, size_t WXUNUSED(size) )
c801d85f 548{
33a5bc52
RR
549 OnDropText( x, y, (const char*)data );
550 return TRUE;
ff7b1510 551}
c801d85f
KB
552
553bool wxTextDropTarget::OnDropText( long x, long y, const char *psz )
554{
33a5bc52
RR
555 printf( "Got dropped text: %s.\n", psz );
556 printf( "At x: %d, y: %d.\n", (int)x, (int)y );
557 return TRUE;
ff7b1510 558}
c801d85f 559
e3e65dac 560size_t wxTextDropTarget::GetFormatCount() const
c801d85f 561{
33a5bc52 562 return 1;
e3e65dac
RR
563}
564
565wxDataFormat wxTextDropTarget::GetFormat(size_t WXUNUSED(n)) const
566{
33a5bc52 567 return wxDF_TEXT;
e3e65dac
RR
568}
569
570// ----------------------------------------------------------------------------
571// wxFileDropTarget
572// ----------------------------------------------------------------------------
573
e5403d7c 574bool wxFileDropTarget::OnDropFiles( long x, long y, size_t nFiles, const char * const aszFiles[] )
e3e65dac 575{
33a5bc52
RR
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;
e3e65dac
RR
584}
585
dc86cb34 586bool wxFileDropTarget::OnDrop(long x, long y, const void *data, size_t size )
e3e65dac 587{
33a5bc52
RR
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++;
e5403d7c 592
33a5bc52 593 if (number == 0) return TRUE;
e5403d7c 594
33a5bc52 595 char **files = new char*[number];
e5403d7c 596
33a5bc52
RR
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 }
e3e65dac 604
33a5bc52 605 bool ret = OnDropFiles( x, y, 1, files );
e5403d7c 606
33a5bc52 607 free( files );
e5403d7c 608
33a5bc52 609 return ret;
e3e65dac
RR
610}
611
612size_t wxFileDropTarget::GetFormatCount() const
613{
33a5bc52 614 return 1;
e3e65dac
RR
615}
616
617wxDataFormat wxFileDropTarget::GetFormat(size_t WXUNUSED(n)) const
618{
33a5bc52 619 return wxDF_FILENAME;
e3e65dac 620}
c801d85f
KB
621
622//-------------------------------------------------------------------------
e3e65dac 623// wxDropSource
c801d85f
KB
624//-------------------------------------------------------------------------
625
b527aac5
RR
626static void
627shape_motion (GtkWidget *widget,
628 GdkEventMotion */*event*/);
629
c801d85f
KB
630//-----------------------------------------------------------------------------
631// drag request
632
b6af8d80 633void gtk_drag_callback( GtkWidget *widget, GdkEvent *event, wxDropSource *source )
c801d85f 634{
b6af8d80
RR
635 wxDataObject *data = source->m_data;
636
c86f1403 637 size_t size = data->GetDataSize();
e3e65dac
RR
638 char *ptr = new char[size];
639 data->GetDataHere( ptr );
640
641 gtk_widget_dnd_data_set( widget, event, ptr, size );
c801d85f 642
e3e65dac 643 delete ptr;
b6af8d80 644
46ccb510 645 source->m_retValue = wxDragCopy;
ff7b1510 646}
c801d85f 647
e3e65dac 648wxDropSource::wxDropSource( wxWindow *win )
c801d85f
KB
649{
650 g_blockEventsOnDrag = TRUE;
e3e65dac 651
c801d85f
KB
652 m_window = win;
653 m_widget = win->m_widget;
654 if (win->m_wxwindow) m_widget = win->m_wxwindow;
c801d85f 655
c67daf87 656 m_data = (wxDataObject *) NULL;
46ccb510 657 m_retValue = wxDragCancel;
e3e65dac 658
c801d85f
KB
659 m_defaultCursor = wxCursor( wxCURSOR_NO_ENTRY );
660 m_goaheadCursor = wxCursor( wxCURSOR_HAND );
ff7b1510 661}
c801d85f 662
e3e65dac 663wxDropSource::wxDropSource( wxDataObject &data, wxWindow *win )
c801d85f 664{
e3e65dac
RR
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;
46ccb510 670 m_retValue = wxDragCancel;
e3e65dac
RR
671
672 m_data = &data;
673
674 m_defaultCursor = wxCursor( wxCURSOR_NO_ENTRY );
675 m_goaheadCursor = wxCursor( wxCURSOR_HAND );
ff7b1510 676}
e3e65dac
RR
677
678void wxDropSource::SetData( wxDataObject &data )
c801d85f 679{
e3e65dac 680 m_data = &data;
ff7b1510 681}
c801d85f 682
e3e65dac 683wxDropSource::~wxDropSource(void)
c801d85f 684{
e3e65dac
RR
685// if (m_data) delete m_data;
686
687 g_blockEventsOnDrag = FALSE;
ff7b1510 688}
e3e65dac 689
46ccb510 690wxDragResult wxDropSource::DoDragDrop( bool WXUNUSED(bAllowMove) )
e3e65dac 691{
46ccb510
JS
692 if (gdk_dnd.dnd_grabbed) return (wxDragResult) wxDragNone;
693 if (gdk_dnd.drag_really) return (wxDragResult) wxDragNone;
e3e65dac 694
f6d53978 695 wxASSERT_MSG( m_data, "wxDragSource: no data" );
b6af8d80 696
46ccb510
JS
697 if (!m_data) return (wxDragResult) wxDragNone;
698 if (m_data->GetDataSize() == 0) return (wxDragResult) wxDragNone;
c801d85f 699
a802c3a1
RR
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 }
b527aac5 730
a802c3a1 731
b527aac5 732 gdk_dnd_set_drag_shape( drag_icon->window,
a802c3a1
RR
733 &hotspot_1,
734 drop_icon->window,
735 &hotspot_2);
736
737
c801d85f
KB
738 GdkWindowPrivate *wp = (GdkWindowPrivate*) m_widget->window;
739
740 RegisterWindow();
c801d85f
KB
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 );
c67daf87 751 gdk_dnd.drag_startwindows = (GdkWindow **) NULL;
ff7b1510 752 }
c801d85f
KB
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;
e3e65dac
RR
777
778 int x = 0;
779 int y = 0;
b527aac5 780 wxGetMousePosition( &x, &y );
e3e65dac 781
c801d85f
KB
782 gdk_dnd_display_drag_cursor( x, y, FALSE, TRUE );
783
b527aac5
RR
784/*
785 shape_motion( drag_icon, (GdkEventMotion *)NULL );
786 shape_motion( drop_icon, (GdkEventMotion *)NULL );
787*/
788
c801d85f
KB
789 while (gdk_dnd.drag_really || gdk_dnd.drag_perhaps) wxYield();
790
c801d85f 791 UnregisterWindow();
e3e65dac 792
30dea054
RR
793 g_blockEventsOnDrag = FALSE;
794
b6af8d80 795 return m_retValue;
ff7b1510 796}
c801d85f 797
e3e65dac 798void wxDropSource::RegisterWindow(void)
c801d85f 799{
e3e65dac 800 if (!m_data) return;
c801d85f 801
e3e65dac
RR
802 wxString formats;
803
804 wxDataFormat df = m_data->GetPreferredFormat();
c801d85f 805
e3e65dac
RR
806 switch (df)
807 {
808 case wxDF_TEXT:
809 formats += "text/plain";
810 break;
811 case wxDF_FILENAME:
61607c36 812 formats += "file:ALL";
e3e65dac
RR
813 break;
814 default:
815 break;
816 }
c801d85f 817
e3e65dac 818 char *str = WXSTRINGCAST formats;
c801d85f 819
e3e65dac 820 gtk_widget_dnd_drag_set( m_widget, TRUE, &str, 1 );
c801d85f 821
e3e65dac 822 gtk_signal_connect( GTK_OBJECT(m_widget), "drag_request_event",
b6af8d80 823 GTK_SIGNAL_FUNC(gtk_drag_callback), (gpointer)this );
ff7b1510 824}
c801d85f 825
e3e65dac 826void wxDropSource::UnregisterWindow(void)
c801d85f
KB
827{
828 if (!m_widget) return;
829
c67daf87 830 gtk_widget_dnd_drag_set( m_widget, FALSE, (gchar **) NULL, 0 );
e3e65dac 831
b6af8d80 832 gtk_signal_disconnect_by_data( GTK_OBJECT(m_widget), (gpointer)this );
ff7b1510 833}
f5368809 834
a802c3a1
RR
835
836/*
837 * Shaped Windows
838 */
839static GdkWindow *root_win = NULL;
840
841typedef struct _cursoroffset {gint x,y;} CursorOffset;
842
843static void
844shape_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
b527aac5 852 p = (CursorOffset *)gtk_object_get_user_data (GTK_OBJECT(widget));
a802c3a1
RR
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,
b527aac5
RR
858 (GdkEventMask)
859 (GDK_BUTTON_RELEASE_MASK |
860 GDK_BUTTON_MOTION_MASK |
861 GDK_POINTER_MOTION_HINT_MASK),
a802c3a1
RR
862 NULL, NULL, 0);
863}
864
865
866static void
867shape_released (GtkWidget *widget)
868{
869 gtk_grab_remove (widget);
870 gdk_pointer_ungrab (0);
871}
872
873static void
874shape_motion (GtkWidget *widget,
b527aac5 875 GdkEventMotion */*event*/)
a802c3a1
RR
876{
877 gint xp, yp;
878 CursorOffset * p;
879 GdkModifierType mask;
880
b527aac5 881 p = (CursorOffset *)gtk_object_get_user_data (GTK_OBJECT (widget));
a802c3a1
RR
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
891GtkWidget *
892shape_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 */
b527aac5 914 window = gtk_window_new ((GtkWindowType)window_type);
a802c3a1
RR
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
f5368809
RR
959#endif
960 // NEW_GTK_DND_CODE
961