]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/dnd.cpp
Listctrl updates
[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"
1a5a8367 18#include <wx/intl.h>
c801d85f
KB
19
20#include "gdk/gdkprivate.h"
21
22#include <X11/Xlib.h>
23
24// ----------------------------------------------------------------------------
25// global
26// ----------------------------------------------------------------------------
27
28extern bool g_blockEventsOnDrag;
29
f5368809
RR
30#ifdef NEW_GTK_DND_CODE
31
33a5bc52
RR
32#include "gtk/gtkdnd.h"
33#include "gtk/gtkselection.h"
34
35// ----------------------------------------------------------------------------
36// "drag_leave"
37// ----------------------------------------------------------------------------
38
39static 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
50static 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
65static 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
87static 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
f5368809
RR
112wxDropTarget::wxDropTarget()
113{
114}
115
116wxDropTarget::~wxDropTarget()
117{
118}
119
120void wxDropTarget::UnregisterWidget( GtkWidget *widget )
121{
33a5bc52 122 wxCHECK_RET( widget != NULL, "unregister widget is NULL" );
f5368809 123
33a5bc52
RR
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 );
f5368809
RR
141}
142
143void wxDropTarget::RegisterWidget( GtkWidget *widget )
144{
33a5bc52 145 wxCHECK_RET( widget != NULL, "register widget is NULL" );
f5368809 146
33a5bc52
RR
147 GtkTargetEntry format;
148 format.info = 0;
149 format.flags = 0;
f5368809 150
33a5bc52 151 int valid = 0;
f5368809
RR
152 for ( size_t i = 0; i < GetFormatCount(); i++ )
153 {
154 wxDataFormat df = GetFormat( i );
155 switch (df)
156 {
157 case wxDF_TEXT:
33a5bc52 158 format.target = "text/plain";
f5368809
RR
159 valid++;
160 break;
161 case wxDF_FILENAME:
33a5bc52 162 format.target = "file:ALL";
f5368809
RR
163 valid++;
164 break;
165 default:
166 break;
167 }
168 }
169
33a5bc52 170 wxASSERT_MSG( valid != 0, "No valid DnD format supported." );
f5368809 171
33a5bc52
RR
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 );
f5368809
RR
189}
190
191// ----------------------------------------------------------------------------
192// wxTextDropTarget
193// ----------------------------------------------------------------------------
194
195bool 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
201bool 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
208size_t wxTextDropTarget::GetFormatCount() const
209{
210 return 1;
211}
212
213wxDataFormat wxTextDropTarget::GetFormat(size_t WXUNUSED(n)) const
214{
215 return wxDF_TEXT;
216}
217
218// ----------------------------------------------------------------------------
219// wxFileDropTarget
220// ----------------------------------------------------------------------------
221
222bool 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
234bool 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
260size_t wxFileDropTarget::GetFormatCount() const
261{
262 return 1;
263}
264
265wxDataFormat wxFileDropTarget::GetFormat(size_t WXUNUSED(n)) const
266{
267 return wxDF_FILENAME;
268}
269
270//-------------------------------------------------------------------------
271// wxDropSource
272//-------------------------------------------------------------------------
273
274wxDropSource::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
289wxDropSource::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
304void wxDropSource::SetData( wxDataObject &data )
305{
306 m_data = &data;
307}
308
309wxDropSource::~wxDropSource(void)
310{
311// if (m_data) delete m_data;
312
313 g_blockEventsOnDrag = FALSE;
314}
315
316wxDragResult 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
334void 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
359void wxDropSource::UnregisterWindow(void)
360{
361 if (!m_widget) return;
362
363 // TODO
364}
365
33a5bc52
RR
366
367#else // NEW_CODE
368
a802c3a1
RR
369GtkWidget *shape_create_icon (char **data,
370 gint x,
371 gint y,
372 gint px,
373 gint py,
374 gint window_type);
375
376/* XPM */
377static 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 */
418static 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
33a5bc52
RR
462//-----------------------------------------------------------------------------
463// "drop_data_available_event"
464//-----------------------------------------------------------------------------
465
466static 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
a802c3a1 476// printf( "Drop data is of type %s.\n", event->data_type );
33a5bc52
RR
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}
f5368809 486
c801d85f
KB
487// ----------------------------------------------------------------------------
488// wxDropTarget
489// ----------------------------------------------------------------------------
490
491wxDropTarget::wxDropTarget()
492{
ff7b1510 493}
c801d85f
KB
494
495wxDropTarget::~wxDropTarget()
496{
ff7b1510 497}
c801d85f 498
c801d85f
KB
499void wxDropTarget::UnregisterWidget( GtkWidget *widget )
500{
33a5bc52 501 if (!widget) return;
e3e65dac 502
33a5bc52
RR
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 );
ff7b1510 507}
c801d85f 508
e3e65dac
RR
509void wxDropTarget::RegisterWidget( GtkWidget *widget )
510{
33a5bc52
RR
511 wxString formats;
512 int valid = 0;
e3e65dac 513
33a5bc52 514 for ( size_t i = 0; i < GetFormatCount(); i++ )
e3e65dac 515 {
33a5bc52
RR
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 }
ff7b1510 532 }
e3e65dac 533
33a5bc52 534 char *str = WXSTRINGCAST formats;
e3e65dac 535
33a5bc52
RR
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 );
ff7b1510 540}
e3e65dac 541
c801d85f
KB
542// ----------------------------------------------------------------------------
543// wxTextDropTarget
544// ----------------------------------------------------------------------------
545
dc86cb34 546bool wxTextDropTarget::OnDrop( long x, long y, const void *data, size_t WXUNUSED(size) )
c801d85f 547{
33a5bc52
RR
548 OnDropText( x, y, (const char*)data );
549 return TRUE;
ff7b1510 550}
c801d85f
KB
551
552bool wxTextDropTarget::OnDropText( long x, long y, const char *psz )
553{
33a5bc52
RR
554 printf( "Got dropped text: %s.\n", psz );
555 printf( "At x: %d, y: %d.\n", (int)x, (int)y );
556 return TRUE;
ff7b1510 557}
c801d85f 558
e3e65dac 559size_t wxTextDropTarget::GetFormatCount() const
c801d85f 560{
33a5bc52 561 return 1;
e3e65dac
RR
562}
563
564wxDataFormat wxTextDropTarget::GetFormat(size_t WXUNUSED(n)) const
565{
33a5bc52 566 return wxDF_TEXT;
e3e65dac
RR
567}
568
569// ----------------------------------------------------------------------------
570// wxFileDropTarget
571// ----------------------------------------------------------------------------
572
e5403d7c 573bool wxFileDropTarget::OnDropFiles( long x, long y, size_t nFiles, const char * const aszFiles[] )
e3e65dac 574{
33a5bc52
RR
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;
e3e65dac
RR
583}
584
dc86cb34 585bool wxFileDropTarget::OnDrop(long x, long y, const void *data, size_t size )
e3e65dac 586{
33a5bc52
RR
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++;
e5403d7c 591
33a5bc52 592 if (number == 0) return TRUE;
e5403d7c 593
33a5bc52 594 char **files = new char*[number];
e5403d7c 595
33a5bc52
RR
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 }
e3e65dac 603
33a5bc52 604 bool ret = OnDropFiles( x, y, 1, files );
e5403d7c 605
33a5bc52 606 free( files );
e5403d7c 607
33a5bc52 608 return ret;
e3e65dac
RR
609}
610
611size_t wxFileDropTarget::GetFormatCount() const
612{
33a5bc52 613 return 1;
e3e65dac
RR
614}
615
616wxDataFormat wxFileDropTarget::GetFormat(size_t WXUNUSED(n)) const
617{
33a5bc52 618 return wxDF_FILENAME;
e3e65dac 619}
c801d85f
KB
620
621//-------------------------------------------------------------------------
e3e65dac 622// wxDropSource
c801d85f
KB
623//-------------------------------------------------------------------------
624
625//-----------------------------------------------------------------------------
626// drag request
627
b6af8d80 628void gtk_drag_callback( GtkWidget *widget, GdkEvent *event, wxDropSource *source )
c801d85f 629{
b6af8d80
RR
630 wxDataObject *data = source->m_data;
631
c86f1403 632 size_t size = data->GetDataSize();
e3e65dac
RR
633 char *ptr = new char[size];
634 data->GetDataHere( ptr );
635
636 gtk_widget_dnd_data_set( widget, event, ptr, size );
c801d85f 637
e3e65dac 638 delete ptr;
b6af8d80 639
46ccb510 640 source->m_retValue = wxDragCopy;
ff7b1510 641}
c801d85f 642
e3e65dac 643wxDropSource::wxDropSource( wxWindow *win )
c801d85f
KB
644{
645 g_blockEventsOnDrag = TRUE;
e3e65dac 646
c801d85f
KB
647 m_window = win;
648 m_widget = win->m_widget;
649 if (win->m_wxwindow) m_widget = win->m_wxwindow;
c801d85f 650
c67daf87 651 m_data = (wxDataObject *) NULL;
46ccb510 652 m_retValue = wxDragCancel;
e3e65dac 653
c801d85f
KB
654 m_defaultCursor = wxCursor( wxCURSOR_NO_ENTRY );
655 m_goaheadCursor = wxCursor( wxCURSOR_HAND );
ff7b1510 656}
c801d85f 657
e3e65dac 658wxDropSource::wxDropSource( wxDataObject &data, wxWindow *win )
c801d85f 659{
e3e65dac
RR
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;
46ccb510 665 m_retValue = wxDragCancel;
e3e65dac
RR
666
667 m_data = &data;
668
669 m_defaultCursor = wxCursor( wxCURSOR_NO_ENTRY );
670 m_goaheadCursor = wxCursor( wxCURSOR_HAND );
ff7b1510 671}
e3e65dac
RR
672
673void wxDropSource::SetData( wxDataObject &data )
c801d85f 674{
e3e65dac 675 m_data = &data;
ff7b1510 676}
c801d85f 677
e3e65dac 678wxDropSource::~wxDropSource(void)
c801d85f 679{
e3e65dac
RR
680// if (m_data) delete m_data;
681
682 g_blockEventsOnDrag = FALSE;
ff7b1510 683}
e3e65dac 684
46ccb510 685wxDragResult wxDropSource::DoDragDrop( bool WXUNUSED(bAllowMove) )
e3e65dac 686{
46ccb510
JS
687 if (gdk_dnd.dnd_grabbed) return (wxDragResult) wxDragNone;
688 if (gdk_dnd.drag_really) return (wxDragResult) wxDragNone;
e3e65dac 689
f6d53978 690 wxASSERT_MSG( m_data, "wxDragSource: no data" );
b6af8d80 691
46ccb510
JS
692 if (!m_data) return (wxDragResult) wxDragNone;
693 if (m_data->GetDataSize() == 0) return (wxDragResult) wxDragNone;
c801d85f 694
a802c3a1
RR
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
c801d85f
KB
732 GdkWindowPrivate *wp = (GdkWindowPrivate*) m_widget->window;
733
734 RegisterWindow();
c801d85f
KB
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 );
c67daf87 745 gdk_dnd.drag_startwindows = (GdkWindow **) NULL;
ff7b1510 746 }
c801d85f
KB
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;
e3e65dac
RR
771
772 int x = 0;
773 int y = 0;
c67daf87 774 gdk_window_get_pointer( m_widget->window, &x, &y, (GdkModifierType *) NULL );
e3e65dac 775
c801d85f
KB
776 gdk_dnd_display_drag_cursor( x, y, FALSE, TRUE );
777
778 while (gdk_dnd.drag_really || gdk_dnd.drag_perhaps) wxYield();
779
c801d85f 780 UnregisterWindow();
e3e65dac 781
30dea054
RR
782 g_blockEventsOnDrag = FALSE;
783
b6af8d80 784 return m_retValue;
ff7b1510 785}
c801d85f 786
e3e65dac 787void wxDropSource::RegisterWindow(void)
c801d85f 788{
e3e65dac 789 if (!m_data) return;
c801d85f 790
e3e65dac
RR
791 wxString formats;
792
793 wxDataFormat df = m_data->GetPreferredFormat();
c801d85f 794
e3e65dac
RR
795 switch (df)
796 {
797 case wxDF_TEXT:
798 formats += "text/plain";
799 break;
800 case wxDF_FILENAME:
61607c36 801 formats += "file:ALL";
e3e65dac
RR
802 break;
803 default:
804 break;
805 }
c801d85f 806
e3e65dac 807 char *str = WXSTRINGCAST formats;
c801d85f 808
e3e65dac 809 gtk_widget_dnd_drag_set( m_widget, TRUE, &str, 1 );
c801d85f 810
e3e65dac 811 gtk_signal_connect( GTK_OBJECT(m_widget), "drag_request_event",
b6af8d80 812 GTK_SIGNAL_FUNC(gtk_drag_callback), (gpointer)this );
ff7b1510 813}
c801d85f 814
e3e65dac 815void wxDropSource::UnregisterWindow(void)
c801d85f
KB
816{
817 if (!m_widget) return;
818
c67daf87 819 gtk_widget_dnd_drag_set( m_widget, FALSE, (gchar **) NULL, 0 );
e3e65dac 820
b6af8d80 821 gtk_signal_disconnect_by_data( GTK_OBJECT(m_widget), (gpointer)this );
ff7b1510 822}
f5368809 823
a802c3a1
RR
824
825/*
826 * Shaped Windows
827 */
828static GdkWindow *root_win = NULL;
829
830typedef struct _cursoroffset {gint x,y;} CursorOffset;
831
832static void
833shape_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
854static void
855shape_released (GtkWidget *widget)
856{
857 gtk_grab_remove (widget);
858 gdk_pointer_ungrab (0);
859}
860
861static void
862shape_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
879GtkWidget *
880shape_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
f5368809
RR
947#endif
948 // NEW_GTK_DND_CODE
949