1 ///////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxDropTarget class
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 ///////////////////////////////////////////////////////////////////////////////
11 #pragma implementation "dnd.h"
16 #if wxUSE_DRAG_AND_DROP
18 #include "wx/window.h"
20 #include "wx/gdicmn.h"
26 #include "gdk/gdkprivate.h"
30 // ----------------------------------------------------------------------------
32 // ----------------------------------------------------------------------------
34 extern bool g_blockEventsOnDrag
;
36 #ifdef NEW_GTK_DND_CODE
38 #include "gtk/gtkdnd.h"
39 #include "gtk/gtkselection.h"
41 // ----------------------------------------------------------------------------
43 // ----------------------------------------------------------------------------
45 static void target_drag_leave( GtkWidget
*WXUNUSED(widget
),
46 GdkDragContext
*WXUNUSED(context
),
47 guint
WXUNUSED(time
) )
52 // ----------------------------------------------------------------------------
54 // ----------------------------------------------------------------------------
56 static gboolean
target_drag_motion( GtkWidget
*WXUNUSED(widget
),
57 GdkDragContext
*context
,
62 printf( "motion.\n" );
63 gdk_drag_status( context
, context
->suggested_action
, time
);
67 // ----------------------------------------------------------------------------
69 // ----------------------------------------------------------------------------
71 static gboolean
target_drag_drop( GtkWidget
*widget
,
72 GdkDragContext
*context
,
77 printf( "drop at: %d,%d.\n", x
, y
);
81 gtk_drag_get_data( widget
,
83 GPOINTER_TO_INT (context
->targets
->data
),
89 // ----------------------------------------------------------------------------
90 // "drag_data_received"
91 // ----------------------------------------------------------------------------
93 static void target_drag_data_received( GtkWidget
*WXUNUSED(widget
),
94 GdkDragContext
*context
,
97 GtkSelectionData
*data
,
101 printf( "data receive at: %d,%d.\n", x
, y
);
103 if ((data
->length
>= 0) && (data
->format
== 8))
105 wxString str
= (const char*)data
->data
;
106 printf( "Received %s\n.", WXSTRINGCAST str
);
107 gtk_drag_finish( context
, TRUE
, FALSE
, time
);
111 gtk_drag_finish (context
, FALSE
, FALSE
, time
);
114 // ----------------------------------------------------------------------------
116 // ----------------------------------------------------------------------------
118 wxDropTarget::wxDropTarget()
122 wxDropTarget::~wxDropTarget()
126 void wxDropTarget::UnregisterWidget( GtkWidget
*widget
)
128 wxCHECK_RET( widget
!= NULL
, "unregister widget is NULL" );
130 gtk_drag_dest_set( widget
,
132 (GtkTargetEntry
*) NULL
,
136 gtk_signal_disconnect_by_func( GTK_OBJECT(widget
),
137 GTK_SIGNAL_FUNC(target_drag_leave
), (gpointer
) this );
139 gtk_signal_disconnect_by_func( GTK_OBJECT(widget
),
140 GTK_SIGNAL_FUNC(target_drag_motion
), (gpointer
) this );
142 gtk_signal_disconnect_by_func( GTK_OBJECT(widget
),
143 GTK_SIGNAL_FUNC(target_drag_drop
), (gpointer
) this );
145 gtk_signal_disconnect_by_func( GTK_OBJECT(widget
),
146 GTK_SIGNAL_FUNC(target_drag_data_received
), (gpointer
) this );
149 void wxDropTarget::RegisterWidget( GtkWidget
*widget
)
151 wxCHECK_RET( widget
!= NULL
, "register widget is NULL" );
153 GtkTargetEntry format
;
159 for ( size_t i
= 0; i
< GetFormatCount(); i
++ )
161 wxDataFormat df
= GetFormat( i
);
165 format
.target
= "text/plain";
169 format
.target
= "file:ALL";
173 wxPrivateDropTarget
*pdt
= (wxPrivateDropTarget
*)this;
174 strcpy( buf
, WXSTRINGCAST pdt
->GetID() );
182 wxASSERT_MSG( valid
!= 0, "No valid DnD format supported." );
184 gtk_drag_dest_set( widget
,
185 GTK_DEST_DEFAULT_ALL
,
188 (GdkDragAction
)(GDK_ACTION_COPY
| GDK_ACTION_MOVE
) );
190 gtk_signal_connect( GTK_OBJECT(widget
), "drag_leave",
191 GTK_SIGNAL_FUNC(target_drag_leave
), (gpointer
) this );
193 gtk_signal_connect( GTK_OBJECT(widget
), "drag_motion",
194 GTK_SIGNAL_FUNC(target_drag_motion
), (gpointer
) this );
196 gtk_signal_connect( GTK_OBJECT(widget
), "drag_drop",
197 GTK_SIGNAL_FUNC(target_drag_drop
), (gpointer
) this );
199 gtk_signal_connect( GTK_OBJECT(widget
), "drag_data_received",
200 GTK_SIGNAL_FUNC(target_drag_data_received
), (gpointer
) this );
203 // ----------------------------------------------------------------------------
205 // ----------------------------------------------------------------------------
207 bool wxTextDropTarget::OnDrop( long x
, long y
, const void *data
, size_t WXUNUSED(size
) )
209 OnDropText( x
, y
, (const char*)data
);
213 bool wxTextDropTarget::OnDropText( long x
, long y
, const char *psz
)
215 printf( "Got dropped text: %s.\n", psz
);
216 printf( "At x: %d, y: %d.\n", (int)x
, (int)y
);
220 size_t wxTextDropTarget::GetFormatCount() const
225 wxDataFormat
wxTextDropTarget::GetFormat(size_t WXUNUSED(n
)) const
230 // ----------------------------------------------------------------------------
232 // ----------------------------------------------------------------------------
234 bool wxFileDropTarget::OnDropFiles( long x
, long y
, size_t nFiles
, const char * const aszFiles
[] )
236 printf( "Got %d dropped files.\n", (int)nFiles
);
237 printf( "At x: %d, y: %d.\n", (int)x
, (int)y
);
238 for (size_t i
= 0; i
< nFiles
; i
++)
240 printf( aszFiles
[i
] );
246 bool wxFileDropTarget::OnDrop(long x
, long y
, const void *data
, size_t size
)
250 char *text
= (char*) data
;
251 for (i
= 0; i
< size
; i
++)
252 if (text
[i
] == 0) number
++;
254 if (number
== 0) return TRUE
;
256 char **files
= new char*[number
];
259 for (i
= 0; i
< number
; i
++)
262 int len
= strlen( text
);
266 bool ret
= OnDropFiles( x
, y
, 1, files
);
273 size_t wxFileDropTarget::GetFormatCount() const
278 wxDataFormat
wxFileDropTarget::GetFormat(size_t WXUNUSED(n
)) const
280 return wxDF_FILENAME
;
283 //-------------------------------------------------------------------------
285 //-------------------------------------------------------------------------
287 wxDropSource::wxDropSource( wxWindow
*win
)
289 g_blockEventsOnDrag
= TRUE
;
292 m_widget
= win
->m_widget
;
293 if (win
->m_wxwindow
) m_widget
= win
->m_wxwindow
;
295 m_data
= (wxDataObject
*) NULL
;
296 m_retValue
= wxDragCancel
;
298 m_defaultCursor
= wxCursor( wxCURSOR_NO_ENTRY
);
299 m_goaheadCursor
= wxCursor( wxCURSOR_HAND
);
302 wxDropSource::wxDropSource( wxDataObject
&data
, wxWindow
*win
)
304 g_blockEventsOnDrag
= TRUE
;
307 m_widget
= win
->m_widget
;
308 if (win
->m_wxwindow
) m_widget
= win
->m_wxwindow
;
309 m_retValue
= wxDragCancel
;
313 m_defaultCursor
= wxCursor( wxCURSOR_NO_ENTRY
);
314 m_goaheadCursor
= wxCursor( wxCURSOR_HAND
);
317 void wxDropSource::SetData( wxDataObject
&data
)
322 wxDropSource::~wxDropSource(void)
324 // if (m_data) delete m_data;
326 g_blockEventsOnDrag
= FALSE
;
329 wxDragResult
wxDropSource::DoDragDrop( bool WXUNUSED(bAllowMove
) )
331 wxASSERT_MSG( m_data
, "wxDragSource: no data" );
333 if (!m_data
) return (wxDragResult
) wxDragNone
;
334 if (m_data
->GetDataSize() == 0) return (wxDragResult
) wxDragNone
;
342 g_blockEventsOnDrag
= FALSE
;
347 void wxDropSource::RegisterWindow(void)
353 wxDataFormat df
= m_data
->GetPreferredFormat();
358 formats
+= "text/plain";
361 formats
+= "file:ALL";
367 char *str
= WXSTRINGCAST formats
;
372 void wxDropSource::UnregisterWindow(void)
374 if (!m_widget
) return;
382 GtkWidget
*shape_create_icon ( const wxIcon
&shape
,
390 static char * gv_xpm
[] = {
402 " .XXXXXXXXXXXXXX. ",
403 " .XXX..XXXX..XXX. ",
404 " ....XX....XX....XX. ",
405 " .XXX.XXX..XXXX..XXX.... ",
406 " .XXXXXXXXXXXXXXXXXXX.XXX. ",
407 " .XXXXXXXXXXXXXXXXXXXXXXXX. ",
408 " .XXXXXXXXXXXXXXXXXXXXXXXX. ",
409 " ..XXXXXXXXXXXXXXXXXXXXXX. ",
410 " .XXXXXXXXXXXXXXXXXX... ",
411 " ..XXXXXXXXXXXXXXXX. ",
412 " .XXXXXXXXXXXXXXXX. ",
413 " .XXXXXXXXXXXXXXXX. ",
414 " .XXXXXXXXXXXXXXXXX. ",
415 " .XXXXXXXXXXXXXXXXX. ",
416 " .XXXXXXXXXXXXXXXXXX. ",
417 " .XXXXXXXXXXXXXXXXXXX. ",
418 " .XXXXXXXXXXXXXXXXXXXXX. ",
419 " .XXXXXXXXXXXXXX.XXXXXXX. ",
420 " .XXXXXXX.XXXXXXX.XXXXXXX. ",
421 " .XXXXXXXX.XXXXXXX.XXXXXXX. ",
422 " .XXXXXXX...XXXXX...XXXXX. ",
423 " .XXXXXXX. ..... ..... ",
431 static char * page_xpm
[] = {
432 /* width height ncolors chars_per_pixel */
441 " ................... ",
442 " .XXXXXXXXXXXXXXXXX.. ",
443 " .XXXXXXXXXXXXXXXXX.o. ",
444 " .XXXXXXXXXXXXXXXXX.oo. ",
445 " .XXXXXXXXXXXXXXXXX.ooo. ",
446 " .XXXXXXXXXXXXXXXXX.oooo. ",
447 " .XXXXXXXXXXXXXXXXX....... ",
448 " .XXXXXOOOOOOOOOOXXXooooo. ",
449 " .XXXXXXXXXXXXXXXXXXooooo. ",
450 " .XXXXXOOOOOOOOOOXXXXXXXX. ",
451 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
452 " .XXXXXXXOOOOOOOOOXXXXXXX. ",
453 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
454 " .XXXXXXOOOOOOOOOOXXXXXXX. ",
455 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
456 " .XXXXXOOOOOOOOOOXXXXXXXX. ",
457 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
458 " .XXXXXXXOOOOOOOOOXXXXXXX. ",
459 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
460 " .XXXXXXOOOOOOOOOOXXXXXXX. ",
461 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
462 " .XXXXXOOOOOOOOOOXXXXXXXX. ",
463 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
464 " .XXXXXXOOOOOOOOOOXXXXXXX. ",
465 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
466 " .XXXXXOOOOOOOXXXXXXXXXXX. ",
467 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
468 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
469 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
470 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
471 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
472 " ......................... "};
475 //-----------------------------------------------------------------------------
477 //-----------------------------------------------------------------------------
479 wxDropSource
*gs_currentDropSource
= (wxDropSource
*) NULL
;
481 //-----------------------------------------------------------------------------
482 // "drop_enter_event"
483 //-----------------------------------------------------------------------------
485 static void gtk_target_enter_callback( GtkWidget
*WXUNUSED(widget
),
486 GdkEventDropEnter
*WXUNUSED(event
),
487 wxDropTarget
*target
)
493 //-----------------------------------------------------------------------------
494 // "drop_leave_event"
495 //-----------------------------------------------------------------------------
497 static void gtk_target_leave_callback( GtkWidget
*WXUNUSED(widget
),
498 GdkEventDropLeave
*WXUNUSED(event
),
499 wxDropTarget
*target
)
505 //-----------------------------------------------------------------------------
506 // "drop_data_available_event"
507 //-----------------------------------------------------------------------------
509 static void gtk_target_callback( GtkWidget
*widget
,
510 GdkEventDropDataAvailable
*event
,
511 wxDropTarget
*target
)
517 gdk_window_get_pointer( widget
->window
, &x
, &y
, (GdkModifierType
*) NULL
);
519 printf( "Drop data is of type %s.\n", event->data_type );
521 target
->OnDrop( x
, y
, (const void*)event
->data
, (size_t)event
->data_numbytes
);
525 g_free (event->data);
526 g_free (event->data_type);
530 // ----------------------------------------------------------------------------
532 // ----------------------------------------------------------------------------
534 wxDropTarget::wxDropTarget()
536 m_format
= (wxDataFormat
*) NULL
;
539 wxDropTarget::~wxDropTarget()
541 if (m_format
) delete m_format
;
544 wxDataFormat
&wxDropTarget::GetFormat(size_t n
) const
549 void wxDropTarget::UnregisterWidget( GtkWidget
*widget
)
553 gtk_signal_disconnect_by_func( GTK_OBJECT(widget
),
554 GTK_SIGNAL_FUNC(gtk_target_callback
), (gpointer
) this );
556 gtk_widget_dnd_drop_set( widget
, FALSE
, (gchar
**) NULL
, 0, FALSE
);
559 void wxDropTarget::RegisterWidget( GtkWidget
*widget
)
564 for ( size_t i
= 0; i
< GetFormatCount(); i
++ )
566 switch (GetFormat(i
).GetType())
570 if (i
> 0) formats
+= ";";
571 formats
+= "text/plain";
577 if (i
> 0) formats
+= ";";
578 formats
+= "file:ALL";
584 if (i
> 0) formats
+= ";";
585 wxPrivateDropTarget
*pdt
= (wxPrivateDropTarget
*)this;
586 formats
+= pdt
->GetId();
595 char *str
= WXSTRINGCAST formats
;
597 gtk_widget_dnd_drop_set( widget
, TRUE
, &str
, valid
, FALSE
);
599 gtk_signal_connect( GTK_OBJECT(widget
), "drop_data_available_event",
600 GTK_SIGNAL_FUNC(gtk_target_callback
), (gpointer
) this );
602 gtk_signal_connect( GTK_OBJECT(widget
), "drop_enter_event",
603 GTK_SIGNAL_FUNC(gtk_target_enter_callback
), (gpointer
) this );
605 gtk_signal_connect( GTK_OBJECT(widget
), "drop_leave_event",
606 GTK_SIGNAL_FUNC(gtk_target_leave_callback
), (gpointer
) this );
609 // ----------------------------------------------------------------------------
611 // ----------------------------------------------------------------------------
613 wxTextDropTarget::wxTextDropTarget()
615 m_format
= new wxDataFormat( wxDF_TEXT
);
618 bool wxTextDropTarget::OnDrop( long x
, long y
, const void *data
, size_t WXUNUSED(size
) )
620 OnDropText( x
, y
, (const char*)data
);
624 bool wxTextDropTarget::OnDropText( long x
, long y
, const char *psz
)
627 printf( "Got dropped text: %s.\n", psz );
628 printf( "At x: %d, y: %d.\n", (int)x, (int)y );
633 size_t wxTextDropTarget::GetFormatCount() const
638 // ----------------------------------------------------------------------------
639 // wxPrivateDropTarget
640 // ----------------------------------------------------------------------------
642 wxPrivateDropTarget::wxPrivateDropTarget()
644 m_id
= wxTheApp
->GetAppName();
645 m_format
= new wxDataFormat( m_id
);
648 void wxPrivateDropTarget::SetId( const wxString
& id
)
651 m_format
->SetId( id
);
654 size_t wxPrivateDropTarget::GetFormatCount() const
659 // ----------------------------------------------------------------------------
661 // ----------------------------------------------------------------------------
663 wxFileDropTarget::wxFileDropTarget()
665 m_format
= new wxDataFormat( wxDF_FILENAME
);
668 bool wxFileDropTarget::OnDropFiles( long x
, long y
, size_t nFiles
, const char * const aszFiles
[] )
670 printf( "Got %d dropped files.\n", (int)nFiles
);
671 printf( "At x: %d, y: %d.\n", (int)x
, (int)y
);
673 for (size_t i
= 0; i
< nFiles
; i
++)
675 printf( aszFiles
[i
] );
682 bool wxFileDropTarget::OnDrop(long x
, long y
, const void *data
, size_t size
)
686 char *text
= (char*) data
;
687 for ( i
= 0; i
< size
; i
++)
688 if (text
[i
] == 0) number
++;
690 if (number
== 0) return TRUE
;
692 char **files
= new char*[number
];
695 for (i
= 0; i
< number
; i
++)
698 int len
= strlen( text
);
702 bool ret
= OnDropFiles( x
, y
, 1, files
);
709 size_t wxFileDropTarget::GetFormatCount() const
714 //-------------------------------------------------------------------------
716 //-------------------------------------------------------------------------
719 shape_motion (GtkWidget
*widget
,
720 GdkEventMotion
* /*event*/);
722 //-----------------------------------------------------------------------------
723 // "drag_request_event"
724 //-----------------------------------------------------------------------------
726 void gtk_drag_callback( GtkWidget
*widget
, GdkEventDragRequest
*event
, wxDropSource
*source
)
728 wxDataBroker
*data
= source
->m_data
;
732 wxNode
*node
= data
->m_dataObjects
.First();
734 wxDataObject
*dobj
= (wxDataObject
*) node
->Data();
736 if ((strcmp(event
->data_type
,"file:ALL") == 0) &&
737 (dobj
->GetFormat().GetType() == wxDF_FILENAME
))
739 wxFileDataObject
*file_object
= (wxFileDataObject
*) dobj
;
741 wxString text
= file_object
->GetFiles();
743 char *s
= WXSTRINGCAST text
;
745 gtk_widget_dnd_data_set( widget
,
748 (int) text
.Length()+1 );
750 source
->m_retValue
= wxDragCopy
;
755 if ((strcmp(event
->data_type
,"text/plain") == 0) &&
756 (dobj
->GetFormat().GetType() == wxDF_TEXT
))
758 wxTextDataObject
*text_object
= (wxTextDataObject
*) dobj
;
760 wxString text
= text_object
->GetText();
762 char *s
= WXSTRINGCAST text
;
764 gtk_widget_dnd_data_set( widget
,
767 (int) text
.Length()+1 );
769 source
->m_retValue
= wxDragCopy
;
774 if (dobj
->GetFormat().GetType() == wxDF_PRIVATE
)
776 wxPrivateDataObject
*pdo
= (wxPrivateDataObject
*) dobj
;
778 if (pdo
->GetId() == event
->data_type
)
780 gtk_widget_dnd_data_set( widget
,
782 (unsigned char*) pdo
->GetData(),
783 (int) pdo
->GetSize() );
785 source
->m_retValue
= wxDragCopy
;
795 wxDropSource::wxDropSource( wxWindow
*win
, const wxIcon
&go
, const wxIcon
&stop
)
797 g_blockEventsOnDrag
= TRUE
;
800 m_widget
= win
->m_widget
;
801 if (win
->m_wxwindow
) m_widget
= win
->m_wxwindow
;
803 m_data
= (wxDataBroker
*) NULL
;
804 m_retValue
= wxDragCancel
;
806 m_defaultCursor
= wxCursor( wxCURSOR_NO_ENTRY
);
807 m_goaheadCursor
= wxCursor( wxCURSOR_HAND
);
810 if (wxNullIcon
== go
) m_goIcon
= wxIcon( page_xpm
);
812 if (wxNullIcon
== stop
) m_stopIcon
= wxIcon( gv_xpm
);
815 wxDropSource::wxDropSource( wxDataObject
*data
, wxWindow
*win
, const wxIcon
&go
, const wxIcon
&stop
)
817 g_blockEventsOnDrag
= TRUE
;
820 m_widget
= win
->m_widget
;
821 if (win
->m_wxwindow
) m_widget
= win
->m_wxwindow
;
822 m_retValue
= wxDragCancel
;
826 m_data
= new wxDataBroker();
831 m_data
= (wxDataBroker
*) NULL
;
834 m_defaultCursor
= wxCursor( wxCURSOR_NO_ENTRY
);
835 m_goaheadCursor
= wxCursor( wxCURSOR_HAND
);
838 if (wxNullIcon
== go
) m_goIcon
= wxIcon( page_xpm
);
840 if (wxNullIcon
== stop
) m_stopIcon
= wxIcon( gv_xpm
);
843 wxDropSource::wxDropSource( wxDataBroker
*data
, wxWindow
*win
)
845 g_blockEventsOnDrag
= TRUE
;
848 m_widget
= win
->m_widget
;
849 if (win
->m_wxwindow
) m_widget
= win
->m_wxwindow
;
850 m_retValue
= wxDragCancel
;
854 m_defaultCursor
= wxCursor( wxCURSOR_NO_ENTRY
);
855 m_goaheadCursor
= wxCursor( wxCURSOR_HAND
);
858 void wxDropSource::SetData( wxDataObject
*data
)
860 if (m_data
) delete m_data
;
864 m_data
= new wxDataBroker();
869 m_data
= (wxDataBroker
*) NULL
;
873 void wxDropSource::SetData( wxDataBroker
*data
)
875 if (m_data
) delete m_data
;
880 wxDropSource::~wxDropSource(void)
882 if (m_data
) delete m_data
;
884 g_blockEventsOnDrag
= FALSE
;
887 wxDragResult
wxDropSource::DoDragDrop( bool WXUNUSED(bAllowMove
) )
889 if (gdk_dnd
.dnd_grabbed
) return (wxDragResult
) wxDragNone
;
890 if (gdk_dnd
.drag_really
) return (wxDragResult
) wxDragNone
;
892 wxASSERT_MSG( m_data
, "wxDragSource: no data" );
894 if (!m_data
) return (wxDragResult
) wxDragNone
;
896 static GtkWidget
*drag_icon
= (GtkWidget
*) NULL
;
897 static GtkWidget
*drop_icon
= (GtkWidget
*) NULL
;
899 GdkPoint hotspot_1
= {0,-5 };
903 drag_icon
= shape_create_icon ( m_stopIcon
,
904 440, 140, 0,0, GTK_WINDOW_POPUP
);
906 gtk_signal_connect (GTK_OBJECT (drag_icon
), "destroy",
907 GTK_SIGNAL_FUNC(gtk_widget_destroyed
),
910 gtk_widget_hide (drag_icon
);
913 GdkPoint hotspot_2
= {-5,-5};
917 drop_icon
= shape_create_icon ( m_goIcon
,
918 440, 140, 0,0, GTK_WINDOW_POPUP
);
920 gtk_signal_connect (GTK_OBJECT (drop_icon
), "destroy",
921 GTK_SIGNAL_FUNC(gtk_widget_destroyed
),
924 gtk_widget_hide (drop_icon
);
928 gdk_dnd_set_drag_shape( drag_icon
->window
,
934 GdkWindowPrivate
*wp
= (GdkWindowPrivate
*) m_widget
->window
;
938 gdk_dnd
.drag_perhaps
= TRUE
;
940 gdk_dnd
.dnd_drag_start
.x
= 5;
941 gdk_dnd
.dnd_drag_start
.y
= 5;
942 gdk_dnd
.real_sw
= wp
;
944 if (gdk_dnd
.drag_startwindows
)
946 g_free( gdk_dnd
.drag_startwindows
);
947 gdk_dnd
.drag_startwindows
= (GdkWindow
**) NULL
;
949 gdk_dnd
.drag_numwindows
= gdk_dnd
.drag_really
= 0;
951 XWindowAttributes dnd_winattr
;
952 XGetWindowAttributes( gdk_display
, wp
->xwindow
, &dnd_winattr
);
953 wp
->dnd_drag_savedeventmask
= dnd_winattr
.your_event_mask
;
955 gdk_dnd_drag_addwindow( m_widget
->window
);
957 GdkEventDragBegin ev
;
958 ev
.type
= GDK_DRAG_BEGIN
;
959 ev
.window
= m_widget
->window
;
961 ev
.u
.flags
.protocol_version
= DND_PROTOCOL_VERSION
;
963 gdk_event_put( (GdkEvent
*)&ev
);
965 XGrabPointer( gdk_display
, wp
->xwindow
, False
,
966 ButtonMotionMask
| ButtonPressMask
| ButtonReleaseMask
| PointerMotionMask
,
967 GrabModeAsync
, GrabModeAsync
, gdk_root_window
, None
, CurrentTime
);
969 gdk_dnd_set_drag_cursors( m_defaultCursor
.GetCursor(), m_goaheadCursor
.GetCursor() );
971 gdk_dnd
.dnd_grabbed
= TRUE
;
972 gdk_dnd
.drag_really
= 1;
976 wxGetMousePosition( &x
, &y
);
978 gdk_dnd_display_drag_cursor( x
, y
, FALSE
, TRUE
);
980 gs_currentDropSource
= this;
982 while (gdk_dnd
.drag_really
|| gdk_dnd
.drag_perhaps
) wxYield();
984 gs_currentDropSource
= (wxDropSource
*) NULL
;
988 g_blockEventsOnDrag
= FALSE
;
993 void wxDropSource::RegisterWindow(void)
999 wxNode
*node
= m_data
->m_dataObjects
.First();
1002 wxDataObject
* dobj
= (wxDataObject
*) node
->Data();
1004 switch (dobj
->GetFormat().GetType())
1008 formats
+= "text/plain";
1013 formats
+= "file:ALL";
1018 wxPrivateDataObject
* pdo
= (wxPrivateDataObject
*) m_data
;
1019 formats
+= pdo
->GetId();
1025 node
= node
->Next();
1028 char *str
= WXSTRINGCAST formats
;
1030 gtk_widget_dnd_drag_set( m_widget
, TRUE
, &str
, 1 );
1032 gtk_signal_connect( GTK_OBJECT(m_widget
), "drag_request_event",
1033 GTK_SIGNAL_FUNC(gtk_drag_callback
), (gpointer
)this );
1036 void wxDropSource::UnregisterWindow(void)
1038 if (!m_widget
) return;
1040 gtk_widget_dnd_drag_set( m_widget
, FALSE
, (gchar
**) NULL
, 0 );
1042 gtk_signal_disconnect_by_data( GTK_OBJECT(m_widget
), (gpointer
)this );
1049 static GdkWindow
*root_win
= (GdkWindow
*) NULL
;
1051 typedef struct _cursoroffset
{gint x
,y
;} CursorOffset
;
1054 shape_pressed (GtkWidget
*widget
, GdkEventButton
*event
)
1058 /* ignore double and triple click */
1059 if (event
->type
!= GDK_BUTTON_PRESS
)
1062 p
= (CursorOffset
*)gtk_object_get_user_data (GTK_OBJECT(widget
));
1063 p
->x
= (int) event
->x
;
1064 p
->y
= (int) event
->y
;
1066 gtk_grab_add (widget
);
1067 gdk_pointer_grab (widget
->window
, TRUE
,
1069 (GDK_BUTTON_RELEASE_MASK
|
1070 GDK_BUTTON_MOTION_MASK
|
1071 GDK_POINTER_MOTION_HINT_MASK
),
1073 (GdkCursor
*) NULL
, 0);
1078 shape_released (GtkWidget
*widget
)
1080 gtk_grab_remove (widget
);
1081 gdk_pointer_ungrab (0);
1085 shape_motion (GtkWidget
*widget
,
1086 GdkEventMotion
* /*event*/ )
1090 GdkModifierType mask
;
1092 p
= (CursorOffset
*)gtk_object_get_user_data (GTK_OBJECT (widget
));
1095 * Can't use event->x / event->y here
1096 * because I need absolute coordinates.
1099 gdk_window_get_pointer (root_win
, &xp
, &yp
, &mask
);
1100 gtk_widget_set_uposition (widget
, xp
- p
->x
, yp
- p
->y
);
1102 if (gs_currentDropSource
) gs_currentDropSource
->GiveFeedback( wxDragCopy
, FALSE
);
1106 shape_create_icon (const wxIcon
&shape
,
1114 * GDK_WINDOW_TOPLEVEL works also, giving you a title border
1116 GtkWidget
*window
= gtk_window_new ((GtkWindowType
)window_type
);
1118 GtkWidget
*fixed
= gtk_fixed_new ();
1119 gtk_widget_set_usize (fixed
, 100,100);
1120 gtk_container_add (GTK_CONTAINER (window
), fixed
);
1121 gtk_widget_show (fixed
);
1123 gtk_widget_set_events (window
,
1124 gtk_widget_get_events (window
) |
1125 GDK_BUTTON_MOTION_MASK
|
1126 GDK_POINTER_MOTION_HINT_MASK
|
1127 GDK_BUTTON_PRESS_MASK
);
1129 gtk_widget_realize (window
);
1131 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
1132 if (shape
.GetMask()) mask
= shape
.GetMask()->GetBitmap();
1134 GtkWidget
*pixmap
= gtk_pixmap_new (shape
.GetPixmap(), mask
);
1135 gtk_fixed_put (GTK_FIXED (fixed
), pixmap
, px
,py
);
1136 gtk_widget_show (pixmap
);
1138 gtk_widget_shape_combine_mask (window
, mask
, px
,py
);
1141 gtk_signal_connect (GTK_OBJECT (window
), "button_press_event",
1142 GTK_SIGNAL_FUNC (shape_pressed
),NULL
);
1143 gtk_signal_connect (GTK_OBJECT (window
), "button_release_event",
1144 GTK_SIGNAL_FUNC (shape_released
),NULL
);
1145 gtk_signal_connect (GTK_OBJECT (window
), "motion_notify_event",
1146 GTK_SIGNAL_FUNC (shape_motion
),NULL
);
1148 CursorOffset
*icon_pos
= g_new (CursorOffset
, 1);
1149 gtk_object_set_user_data(GTK_OBJECT(window
), icon_pos
);
1151 gtk_widget_set_uposition (window
, x
, y
);
1152 gtk_widget_show (window
);
1162 // wxUSE_DRAG_AND_DROP