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 //----------------------------------------------------------------------------
38 //----------------------------------------------------------------------------
41 static char * gv_xpm
[] = {
55 " ....XX....XX....XX. ",
56 " .XXX.XXX..XXXX..XXX.... ",
57 " .XXXXXXXXXXXXXXXXXXX.XXX. ",
58 " .XXXXXXXXXXXXXXXXXXXXXXXX. ",
59 " .XXXXXXXXXXXXXXXXXXXXXXXX. ",
60 " ..XXXXXXXXXXXXXXXXXXXXXX. ",
61 " .XXXXXXXXXXXXXXXXXX... ",
62 " ..XXXXXXXXXXXXXXXX. ",
63 " .XXXXXXXXXXXXXXXX. ",
64 " .XXXXXXXXXXXXXXXX. ",
65 " .XXXXXXXXXXXXXXXXX. ",
66 " .XXXXXXXXXXXXXXXXX. ",
67 " .XXXXXXXXXXXXXXXXXX. ",
68 " .XXXXXXXXXXXXXXXXXXX. ",
69 " .XXXXXXXXXXXXXXXXXXXXX. ",
70 " .XXXXXXXXXXXXXX.XXXXXXX. ",
71 " .XXXXXXX.XXXXXXX.XXXXXXX. ",
72 " .XXXXXXXX.XXXXXXX.XXXXXXX. ",
73 " .XXXXXXX...XXXXX...XXXXX. ",
74 " .XXXXXXX. ..... ..... ",
82 static char * page_xpm
[] = {
83 /* width height ncolors chars_per_pixel */
92 " ................... ",
93 " .XXXXXXXXXXXXXXXXX.. ",
94 " .XXXXXXXXXXXXXXXXX.o. ",
95 " .XXXXXXXXXXXXXXXXX.oo. ",
96 " .XXXXXXXXXXXXXXXXX.ooo. ",
97 " .XXXXXXXXXXXXXXXXX.oooo. ",
98 " .XXXXXXXXXXXXXXXXX....... ",
99 " .XXXXXOOOOOOOOOOXXXooooo. ",
100 " .XXXXXXXXXXXXXXXXXXooooo. ",
101 " .XXXXXOOOOOOOOOOXXXXXXXX. ",
102 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
103 " .XXXXXXXOOOOOOOOOXXXXXXX. ",
104 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
105 " .XXXXXXOOOOOOOOOOXXXXXXX. ",
106 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
107 " .XXXXXOOOOOOOOOOXXXXXXXX. ",
108 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
109 " .XXXXXXXOOOOOOOOOXXXXXXX. ",
110 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
111 " .XXXXXXOOOOOOOOOOXXXXXXX. ",
112 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
113 " .XXXXXOOOOOOOOOOXXXXXXXX. ",
114 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
115 " .XXXXXXOOOOOOOOOOXXXXXXX. ",
116 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
117 " .XXXXXOOOOOOOXXXXXXXXXXX. ",
118 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
119 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
120 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
121 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
122 " .XXXXXXXXXXXXXXXXXXXXXXX. ",
123 " ......................... "};
126 #if (GTK_MINOR_VERSION > 0)
128 #include "gtk/gtkdnd.h"
129 #include "gtk/gtkselection.h"
131 // ----------------------------------------------------------------------------
133 // ----------------------------------------------------------------------------
135 static void target_drag_leave( GtkWidget
*WXUNUSED(widget
),
136 GdkDragContext
*context
,
137 guint
WXUNUSED(time
),
140 dt
->SetDragContext( context
);
142 dt
->SetDragContext( (GdkDragContext
*) NULL
);
145 // ----------------------------------------------------------------------------
147 // ----------------------------------------------------------------------------
149 static gboolean
target_drag_motion( GtkWidget
*WXUNUSED(widget
),
150 GdkDragContext
*context
,
156 dt
->SetDragContext( context
);
158 if (dt
->OnMove( x
, y
))
160 gdk_drag_status( context
, context
->suggested_action
, time
);
164 gdk_drag_status( context
, (GdkDragAction
)0, time
);
167 dt
->SetDragContext( (GdkDragContext
*) NULL
);
171 // ----------------------------------------------------------------------------
173 // ----------------------------------------------------------------------------
175 static gboolean
target_drag_drop( GtkWidget
*widget
,
176 GdkDragContext
*context
,
181 printf( "drop at: %d,%d.\n", x
, y
);
183 if (context
->targets
)
185 gtk_drag_get_data( widget
,
187 GPOINTER_TO_INT (context
->targets
->data
),
193 // ----------------------------------------------------------------------------
194 // "drag_data_received"
195 // ----------------------------------------------------------------------------
197 static void target_drag_data_received( GtkWidget
*WXUNUSED(widget
),
198 GdkDragContext
*context
,
201 GtkSelectionData
*data
,
202 guint
WXUNUSED(info
),
205 printf( "data receive at: %d,%d.\n", x
, y
);
207 if ((data
->length
>= 0) && (data
->format
== 8))
209 wxString str
= (const char*)data
->data
;
210 printf( "Received %s\n.", WXSTRINGCAST str
);
211 gtk_drag_finish( context
, TRUE
, FALSE
, time
);
215 gtk_drag_finish (context
, FALSE
, FALSE
, time
);
218 // ----------------------------------------------------------------------------
220 // ----------------------------------------------------------------------------
222 wxDropTarget::wxDropTarget()
226 wxDropTarget::~wxDropTarget()
230 void wxDropTarget::OnEnter()
234 void wxDropTarget::OnLeave()
238 bool wxDropTarget::OnMove( int x
, int y
)
240 printf( "generic move %d %d.\n", x
, y
);
245 bool wxDropTarget::OnDrop( int x
, int y
)
247 printf( "generic drop %d %d.\n", x
, y
);
252 bool wxDropTarget::IsSupported( wxDataFormat format
)
254 printf( "generic is supported.\n" );
256 if (!m_dragContext
) return FALSE
;
258 GList
*child
= m_dragContext
->targets
;
261 GdkAtom formatAtom
= (GdkAtom
) GPOINTER_TO_INT(child
->data
);
262 char *name
= gdk_atom_name( formatAtom
);
263 if (name
) printf( "Format available: %s.\n", name
);
272 bool wxDropTarget::GetData( wxDataObject
*data
)
277 void wxDropTarget::UnregisterWidget( GtkWidget
*widget
)
279 wxCHECK_RET( widget
!= NULL
, "unregister widget is NULL" );
281 gtk_drag_dest_set( widget
,
283 (GtkTargetEntry
*) NULL
,
287 gtk_signal_disconnect_by_func( GTK_OBJECT(widget
),
288 GTK_SIGNAL_FUNC(target_drag_leave
), (gpointer
) this );
290 gtk_signal_disconnect_by_func( GTK_OBJECT(widget
),
291 GTK_SIGNAL_FUNC(target_drag_motion
), (gpointer
) this );
293 gtk_signal_disconnect_by_func( GTK_OBJECT(widget
),
294 GTK_SIGNAL_FUNC(target_drag_drop
), (gpointer
) this );
296 gtk_signal_disconnect_by_func( GTK_OBJECT(widget
),
297 GTK_SIGNAL_FUNC(target_drag_data_received
), (gpointer
) this );
300 void wxDropTarget::RegisterWidget( GtkWidget
*widget
)
302 wxCHECK_RET( widget
!= NULL
, "register widget is NULL" );
304 GtkTargetEntry format
;
308 strcpy( buf
, "text/plain" );
311 gtk_drag_dest_set( widget
,
312 GTK_DEST_DEFAULT_ALL
,
315 (GdkDragAction
)(GDK_ACTION_COPY
| GDK_ACTION_MOVE
) );
317 gtk_signal_connect( GTK_OBJECT(widget
), "drag_leave",
318 GTK_SIGNAL_FUNC(target_drag_leave
), (gpointer
) this );
320 gtk_signal_connect( GTK_OBJECT(widget
), "drag_motion",
321 GTK_SIGNAL_FUNC(target_drag_motion
), (gpointer
) this );
323 gtk_signal_connect( GTK_OBJECT(widget
), "drag_drop",
324 GTK_SIGNAL_FUNC(target_drag_drop
), (gpointer
) this );
326 gtk_signal_connect( GTK_OBJECT(widget
), "drag_data_received",
327 GTK_SIGNAL_FUNC(target_drag_data_received
), (gpointer
) this );
330 //-------------------------------------------------------------------------
332 //-------------------------------------------------------------------------
334 bool wxTextDropTarget::OnMove( int WXUNUSED(x
), int WXUNUSED(y
) )
336 printf( "text move.\n" );
338 return IsSupported( wxDF_TEXT
); // same as "TEXT"
341 bool wxTextDropTarget::OnDrop( int x
, int y
)
343 printf( "text drop.\n" );
345 if (!IsSupported( wxDF_TEXT
)) return FALSE
;
347 wxTextDataObject data
;
348 if (!GetData( &data
)) return FALSE
;
350 return OnDropText( x
, y
, data
.GetText() );
353 //-------------------------------------------------------------------------
354 // wxPrivateDropTarget
355 //-------------------------------------------------------------------------
357 wxPrivateDropTarget::wxPrivateDropTarget()
359 m_id
= wxTheApp
->GetAppName();
362 wxPrivateDropTarget::wxPrivateDropTarget( const wxString
&id
)
367 bool wxPrivateDropTarget::OnMove( int WXUNUSED(x
), int WXUNUSED(y
) )
369 return IsSupported( m_id
);
372 bool wxPrivateDropTarget::OnDrop( int x
, int y
)
374 if (!IsSupported( m_id
)) return FALSE
;
376 wxPrivateDataObject data
;
377 if (!GetData( &data
)) return FALSE
;
379 return OnDropData( x
, y
, data
.GetData(), data
.GetSize() );
382 //----------------------------------------------------------------------------
383 // A drop target which accepts files (dragged from File Manager or Explorer)
384 //----------------------------------------------------------------------------
386 bool wxFileDropTarget::OnMove( int WXUNUSED(x
), int WXUNUSED(y
) )
388 return IsSupported( wxDF_FILENAME
); // same as "file:ALL"
391 bool wxFileDropTarget::OnDrop( int x
, int y
)
393 if (!IsSupported( wxDF_FILENAME
)) return FALSE
;
395 wxFileDataObject data
;
396 if (!GetData( &data
)) return FALSE
;
398 /* get number of substrings /root/mytext.txt/0/root/myothertext.txt/0/0 */
401 size_t size
= data
.GetFiles().Length();
402 char *text
= WXSTRINGCAST data
.GetFiles();
403 for ( i
= 0; i
< size
; i
++)
404 if (text
[i
] == 0) number
++;
406 if (number
== 0) return TRUE
;
408 char **files
= new char*[number
];
410 text
= WXSTRINGCAST data
.GetFiles();
411 for (i
= 0; i
< number
; i
++)
414 int len
= strlen( text
);
418 bool ret
= OnDropFiles( x
, y
, number
, files
);
425 //-------------------------------------------------------------------------
427 //-------------------------------------------------------------------------
430 wxDropSource::wxDropSource( wxWindow
*win
, const wxIcon
&go
, const wxIcon
&stop
)
432 g_blockEventsOnDrag
= TRUE
;
435 m_widget
= win
->m_widget
;
436 if (win
->m_wxwindow
) m_widget
= win
->m_wxwindow
;
438 m_data
= (wxDataBroker
*) NULL
;
439 m_retValue
= wxDragCancel
;
441 m_defaultCursor
= wxCursor( wxCURSOR_NO_ENTRY
);
442 m_goaheadCursor
= wxCursor( wxCURSOR_HAND
);
445 if (wxNullIcon
== go
) m_goIcon
= wxIcon( page_xpm
);
447 if (wxNullIcon
== stop
) m_stopIcon
= wxIcon( gv_xpm
);
450 wxDropSource::wxDropSource( wxDataObject
*data
, wxWindow
*win
, const wxIcon
&go
, const wxIcon
&stop
)
452 g_blockEventsOnDrag
= TRUE
;
455 m_widget
= win
->m_widget
;
456 if (win
->m_wxwindow
) m_widget
= win
->m_wxwindow
;
457 m_retValue
= wxDragCancel
;
461 m_data
= new wxDataBroker();
466 m_data
= (wxDataBroker
*) NULL
;
469 m_defaultCursor
= wxCursor( wxCURSOR_NO_ENTRY
);
470 m_goaheadCursor
= wxCursor( wxCURSOR_HAND
);
473 if (wxNullIcon
== go
) m_goIcon
= wxIcon( page_xpm
);
475 if (wxNullIcon
== stop
) m_stopIcon
= wxIcon( gv_xpm
);
478 wxDropSource::wxDropSource( wxDataBroker
*data
, wxWindow
*win
)
480 g_blockEventsOnDrag
= TRUE
;
483 m_widget
= win
->m_widget
;
484 if (win
->m_wxwindow
) m_widget
= win
->m_wxwindow
;
485 m_retValue
= wxDragCancel
;
489 m_defaultCursor
= wxCursor( wxCURSOR_NO_ENTRY
);
490 m_goaheadCursor
= wxCursor( wxCURSOR_HAND
);
493 void wxDropSource::SetData( wxDataObject
*data
)
495 if (m_data
) delete m_data
;
499 m_data
= new wxDataBroker();
504 m_data
= (wxDataBroker
*) NULL
;
508 void wxDropSource::SetData( wxDataBroker
*data
)
510 if (m_data
) delete m_data
;
515 wxDropSource::~wxDropSource(void)
517 if (m_data
) delete m_data
;
519 g_blockEventsOnDrag
= FALSE
;
522 wxDragResult
wxDropSource::DoDragDrop( bool WXUNUSED(bAllowMove
) )
524 wxASSERT_MSG( m_data
, "wxDragSource: no data" );
526 if (!m_data
) return (wxDragResult
) wxDragNone
;
528 static GtkWidget
*drag_icon
= (GtkWidget
*) NULL
;
529 static GtkWidget
*drop_icon
= (GtkWidget
*) NULL
;
531 GdkPoint hotspot_1
= {0,-5 };
536 drag_icon = shape_create_icon ( m_stopIcon,
537 440, 140, 0,0, GTK_WINDOW_POPUP);
539 gtk_signal_connect (GTK_OBJECT (drag_icon), "destroy",
540 GTK_SIGNAL_FUNC(gtk_widget_destroyed),
543 gtk_widget_hide (drag_icon);
547 GdkPoint hotspot_2
= {-5,-5};
552 drop_icon = shape_create_icon ( m_goIcon,
553 440, 140, 0,0, GTK_WINDOW_POPUP);
555 gtk_signal_connect (GTK_OBJECT (drop_icon), "destroy",
556 GTK_SIGNAL_FUNC(gtk_widget_destroyed),
559 gtk_widget_hide (drop_icon);
567 void wxDropSource::RegisterWindow(void)
572 void wxDropSource::UnregisterWindow(void)
574 if (!m_widget
) return;
580 //----------------------------------------------------------------------------
582 //----------------------------------------------------------------------------
584 GtkWidget
*shape_create_icon ( const wxIcon
&shape
,
591 //-----------------------------------------------------------------------------
593 //-----------------------------------------------------------------------------
595 wxDropSource
*gs_currentDropSource
= (wxDropSource
*) NULL
;
597 //-----------------------------------------------------------------------------
598 // "drop_enter_event"
599 //-----------------------------------------------------------------------------
601 static void gtk_target_enter_callback( GtkWidget
*WXUNUSED(widget
),
602 GdkEventDropEnter
*WXUNUSED(event
),
603 wxDropTarget
*target
)
609 //-----------------------------------------------------------------------------
610 // "drop_leave_event"
611 //-----------------------------------------------------------------------------
613 static void gtk_target_leave_callback( GtkWidget
*WXUNUSED(widget
),
614 GdkEventDropLeave
*WXUNUSED(event
),
615 wxDropTarget
*target
)
621 //-----------------------------------------------------------------------------
622 // "drop_data_available_event"
623 //-----------------------------------------------------------------------------
625 static void gtk_target_callback( GtkWidget
*widget
,
626 GdkEventDropDataAvailable
*event
,
627 wxDropTarget
*target
)
633 gdk_window_get_pointer( widget
->window
, &x
, &y
, (GdkModifierType
*) NULL
);
635 printf( "Drop data is of type %s.\n", event->data_type );
637 target
->OnDrop( x
, y
, (const void*)event
->data
, (size_t)event
->data_numbytes
);
641 g_free (event->data);
642 g_free (event->data_type);
646 // ----------------------------------------------------------------------------
648 // ----------------------------------------------------------------------------
650 wxDropTarget::wxDropTarget()
652 m_format
= (wxDataFormat
*) NULL
;
655 wxDropTarget::~wxDropTarget()
657 if (m_format
) delete m_format
;
660 wxDataFormat
&wxDropTarget::GetFormat(size_t n
) const
665 void wxDropTarget::UnregisterWidget( GtkWidget
*widget
)
669 gtk_signal_disconnect_by_func( GTK_OBJECT(widget
),
670 GTK_SIGNAL_FUNC(gtk_target_callback
), (gpointer
) this );
672 gtk_widget_dnd_drop_set( widget
, FALSE
, (gchar
**) NULL
, 0, FALSE
);
675 void wxDropTarget::RegisterWidget( GtkWidget
*widget
)
680 for ( size_t i
= 0; i
< GetFormatCount(); i
++ )
682 switch (GetFormat(i
).GetType())
686 if (i
> 0) formats
+= ";";
687 formats
+= "text/plain";
693 if (i
> 0) formats
+= ";";
694 formats
+= "file:ALL";
700 if (i
> 0) formats
+= ";";
701 wxPrivateDropTarget
*pdt
= (wxPrivateDropTarget
*)this;
702 formats
+= pdt
->GetId();
711 char *str
= WXSTRINGCAST formats
;
713 gtk_widget_dnd_drop_set( widget
, TRUE
, &str
, valid
, FALSE
);
715 gtk_signal_connect( GTK_OBJECT(widget
), "drop_data_available_event",
716 GTK_SIGNAL_FUNC(gtk_target_callback
), (gpointer
) this );
718 gtk_signal_connect( GTK_OBJECT(widget
), "drop_enter_event",
719 GTK_SIGNAL_FUNC(gtk_target_enter_callback
), (gpointer
) this );
721 gtk_signal_connect( GTK_OBJECT(widget
), "drop_leave_event",
722 GTK_SIGNAL_FUNC(gtk_target_leave_callback
), (gpointer
) this );
725 // ----------------------------------------------------------------------------
727 // ----------------------------------------------------------------------------
729 wxTextDropTarget::wxTextDropTarget()
731 m_format
= new wxDataFormat( wxDF_TEXT
);
734 bool wxTextDropTarget::OnDrop( long x
, long y
, const void *data
, size_t WXUNUSED(size
) )
736 OnDropText( x
, y
, (const char*)data
);
740 bool wxTextDropTarget::OnDropText( long x
, long y
, const char *psz
)
743 printf( "Got dropped text: %s.\n", psz );
744 printf( "At x: %d, y: %d.\n", (int)x, (int)y );
749 size_t wxTextDropTarget::GetFormatCount() const
754 // ----------------------------------------------------------------------------
755 // wxPrivateDropTarget
756 // ----------------------------------------------------------------------------
758 wxPrivateDropTarget::wxPrivateDropTarget()
760 m_id
= wxTheApp
->GetAppName();
761 m_format
= new wxDataFormat( m_id
);
764 void wxPrivateDropTarget::SetId( const wxString
& id
)
767 m_format
->SetId( id
);
770 size_t wxPrivateDropTarget::GetFormatCount() const
775 // ----------------------------------------------------------------------------
777 // ----------------------------------------------------------------------------
779 wxFileDropTarget::wxFileDropTarget()
781 m_format
= new wxDataFormat( wxDF_FILENAME
);
784 bool wxFileDropTarget::OnDropFiles( long x
, long y
, size_t nFiles
, const char * const aszFiles
[] )
786 printf( "Got %d dropped files.\n", (int)nFiles
);
787 printf( "At x: %d, y: %d.\n", (int)x
, (int)y
);
789 for (size_t i
= 0; i
< nFiles
; i
++)
791 printf( aszFiles
[i
] );
798 bool wxFileDropTarget::OnDrop(long x
, long y
, const void *data
, size_t size
)
802 char *text
= (char*) data
;
803 for ( i
= 0; i
< size
; i
++)
804 if (text
[i
] == 0) number
++;
806 if (number
== 0) return TRUE
;
808 char **files
= new char*[number
];
811 for (i
= 0; i
< number
; i
++)
814 int len
= strlen( text
);
818 bool ret
= OnDropFiles( x
, y
, 1, files
);
825 size_t wxFileDropTarget::GetFormatCount() const
830 //-------------------------------------------------------------------------
832 //-------------------------------------------------------------------------
835 shape_motion (GtkWidget
*widget
,
836 GdkEventMotion
* /*event*/);
838 //-----------------------------------------------------------------------------
839 // "drag_request_event"
840 //-----------------------------------------------------------------------------
842 void gtk_drag_callback( GtkWidget
*widget
, GdkEventDragRequest
*event
, wxDropSource
*source
)
844 wxDataBroker
*data
= source
->m_data
;
848 wxNode
*node
= data
->m_dataObjects
.First();
850 wxDataObject
*dobj
= (wxDataObject
*) node
->Data();
852 if ((strcmp(event
->data_type
,"file:ALL") == 0) &&
853 (dobj
->GetFormat().GetType() == wxDF_FILENAME
))
855 wxFileDataObject
*file_object
= (wxFileDataObject
*) dobj
;
857 wxString text
= file_object
->GetFiles();
859 char *s
= WXSTRINGCAST text
;
861 gtk_widget_dnd_data_set( widget
,
864 (int) text
.Length()+1 );
866 source
->m_retValue
= wxDragCopy
;
871 if ((strcmp(event
->data_type
,"text/plain") == 0) &&
872 (dobj
->GetFormat().GetType() == wxDF_TEXT
))
874 wxTextDataObject
*text_object
= (wxTextDataObject
*) dobj
;
876 wxString text
= text_object
->GetText();
878 char *s
= WXSTRINGCAST text
;
880 gtk_widget_dnd_data_set( widget
,
883 (int) text
.Length()+1 );
885 source
->m_retValue
= wxDragCopy
;
890 if (dobj
->GetFormat().GetType() == wxDF_PRIVATE
)
892 wxPrivateDataObject
*pdo
= (wxPrivateDataObject
*) dobj
;
894 if (pdo
->GetId() == event
->data_type
)
896 gtk_widget_dnd_data_set( widget
,
898 (unsigned char*) pdo
->GetData(),
899 (int) pdo
->GetSize() );
901 source
->m_retValue
= wxDragCopy
;
911 wxDropSource::wxDropSource( wxWindow
*win
, const wxIcon
&go
, const wxIcon
&stop
)
913 g_blockEventsOnDrag
= TRUE
;
916 m_widget
= win
->m_widget
;
917 if (win
->m_wxwindow
) m_widget
= win
->m_wxwindow
;
919 m_data
= (wxDataBroker
*) NULL
;
920 m_retValue
= wxDragCancel
;
922 m_defaultCursor
= wxCursor( wxCURSOR_NO_ENTRY
);
923 m_goaheadCursor
= wxCursor( wxCURSOR_HAND
);
926 if (wxNullIcon
== go
) m_goIcon
= wxIcon( page_xpm
);
928 if (wxNullIcon
== stop
) m_stopIcon
= wxIcon( gv_xpm
);
931 wxDropSource::wxDropSource( wxDataObject
*data
, wxWindow
*win
, const wxIcon
&go
, const wxIcon
&stop
)
933 g_blockEventsOnDrag
= TRUE
;
936 m_widget
= win
->m_widget
;
937 if (win
->m_wxwindow
) m_widget
= win
->m_wxwindow
;
938 m_retValue
= wxDragCancel
;
942 m_data
= new wxDataBroker();
947 m_data
= (wxDataBroker
*) NULL
;
950 m_defaultCursor
= wxCursor( wxCURSOR_NO_ENTRY
);
951 m_goaheadCursor
= wxCursor( wxCURSOR_HAND
);
954 if (wxNullIcon
== go
) m_goIcon
= wxIcon( page_xpm
);
956 if (wxNullIcon
== stop
) m_stopIcon
= wxIcon( gv_xpm
);
959 wxDropSource::wxDropSource( wxDataBroker
*data
, wxWindow
*win
)
961 g_blockEventsOnDrag
= TRUE
;
964 m_widget
= win
->m_widget
;
965 if (win
->m_wxwindow
) m_widget
= win
->m_wxwindow
;
966 m_retValue
= wxDragCancel
;
970 m_defaultCursor
= wxCursor( wxCURSOR_NO_ENTRY
);
971 m_goaheadCursor
= wxCursor( wxCURSOR_HAND
);
974 void wxDropSource::SetData( wxDataObject
*data
)
976 if (m_data
) delete m_data
;
980 m_data
= new wxDataBroker();
985 m_data
= (wxDataBroker
*) NULL
;
989 void wxDropSource::SetData( wxDataBroker
*data
)
991 if (m_data
) delete m_data
;
996 wxDropSource::~wxDropSource(void)
998 if (m_data
) delete m_data
;
1000 g_blockEventsOnDrag
= FALSE
;
1003 wxDragResult
wxDropSource::DoDragDrop( bool WXUNUSED(bAllowMove
) )
1005 if (gdk_dnd
.dnd_grabbed
) return (wxDragResult
) wxDragNone
;
1006 if (gdk_dnd
.drag_really
) return (wxDragResult
) wxDragNone
;
1008 wxASSERT_MSG( m_data
, "wxDragSource: no data" );
1010 if (!m_data
) return (wxDragResult
) wxDragNone
;
1012 static GtkWidget
*drag_icon
= (GtkWidget
*) NULL
;
1013 static GtkWidget
*drop_icon
= (GtkWidget
*) NULL
;
1015 GdkPoint hotspot_1
= {0,-5 };
1019 drag_icon
= shape_create_icon ( m_stopIcon
,
1020 440, 140, 0,0, GTK_WINDOW_POPUP
);
1022 gtk_signal_connect (GTK_OBJECT (drag_icon
), "destroy",
1023 GTK_SIGNAL_FUNC(gtk_widget_destroyed
),
1026 gtk_widget_hide (drag_icon
);
1029 GdkPoint hotspot_2
= {-5,-5};
1033 drop_icon
= shape_create_icon ( m_goIcon
,
1034 440, 140, 0,0, GTK_WINDOW_POPUP
);
1036 gtk_signal_connect (GTK_OBJECT (drop_icon
), "destroy",
1037 GTK_SIGNAL_FUNC(gtk_widget_destroyed
),
1040 gtk_widget_hide (drop_icon
);
1044 gdk_dnd_set_drag_shape( drag_icon
->window
,
1050 GdkWindowPrivate
*wp
= (GdkWindowPrivate
*) m_widget
->window
;
1054 gdk_dnd
.drag_perhaps
= TRUE
;
1056 gdk_dnd
.dnd_drag_start
.x
= 5;
1057 gdk_dnd
.dnd_drag_start
.y
= 5;
1058 gdk_dnd
.real_sw
= wp
;
1060 if (gdk_dnd
.drag_startwindows
)
1062 g_free( gdk_dnd
.drag_startwindows
);
1063 gdk_dnd
.drag_startwindows
= (GdkWindow
**) NULL
;
1065 gdk_dnd
.drag_numwindows
= gdk_dnd
.drag_really
= 0;
1067 XWindowAttributes dnd_winattr
;
1068 XGetWindowAttributes( gdk_display
, wp
->xwindow
, &dnd_winattr
);
1069 wp
->dnd_drag_savedeventmask
= dnd_winattr
.your_event_mask
;
1071 gdk_dnd_drag_addwindow( m_widget
->window
);
1073 GdkEventDragBegin ev
;
1074 ev
.type
= GDK_DRAG_BEGIN
;
1075 ev
.window
= m_widget
->window
;
1077 ev
.u
.flags
.protocol_version
= DND_PROTOCOL_VERSION
;
1079 gdk_event_put( (GdkEvent
*)&ev
);
1081 XGrabPointer( gdk_display
, wp
->xwindow
, False
,
1082 ButtonMotionMask
| ButtonPressMask
| ButtonReleaseMask
| PointerMotionMask
,
1083 GrabModeAsync
, GrabModeAsync
, gdk_root_window
, None
, CurrentTime
);
1085 gdk_dnd_set_drag_cursors( m_defaultCursor
.GetCursor(), m_goaheadCursor
.GetCursor() );
1087 gdk_dnd
.dnd_grabbed
= TRUE
;
1088 gdk_dnd
.drag_really
= 1;
1092 wxGetMousePosition( &x
, &y
);
1094 gdk_dnd_display_drag_cursor( x
, y
, FALSE
, TRUE
);
1096 gs_currentDropSource
= this;
1098 while (gdk_dnd
.drag_really
|| gdk_dnd
.drag_perhaps
) wxYield();
1100 gs_currentDropSource
= (wxDropSource
*) NULL
;
1104 g_blockEventsOnDrag
= FALSE
;
1109 void wxDropSource::RegisterWindow(void)
1111 if (!m_data
) return;
1115 wxNode
*node
= m_data
->m_dataObjects
.First();
1118 wxDataObject
* dobj
= (wxDataObject
*) node
->Data();
1120 switch (dobj
->GetFormat().GetType())
1124 formats
+= "text/plain";
1129 formats
+= "file:ALL";
1134 wxPrivateDataObject
* pdo
= (wxPrivateDataObject
*) m_data
;
1135 formats
+= pdo
->GetId();
1141 node
= node
->Next();
1144 char *str
= WXSTRINGCAST formats
;
1146 gtk_widget_dnd_drag_set( m_widget
, TRUE
, &str
, 1 );
1148 gtk_signal_connect( GTK_OBJECT(m_widget
), "drag_request_event",
1149 GTK_SIGNAL_FUNC(gtk_drag_callback
), (gpointer
)this );
1152 void wxDropSource::UnregisterWindow(void)
1154 if (!m_widget
) return;
1156 gtk_widget_dnd_drag_set( m_widget
, FALSE
, (gchar
**) NULL
, 0 );
1158 gtk_signal_disconnect_by_data( GTK_OBJECT(m_widget
), (gpointer
)this );
1165 static GdkWindow
*root_win
= (GdkWindow
*) NULL
;
1167 typedef struct _cursoroffset
{gint x
,y
;} CursorOffset
;
1170 shape_pressed (GtkWidget
*widget
, GdkEventButton
*event
)
1174 /* ignore double and triple click */
1175 if (event
->type
!= GDK_BUTTON_PRESS
)
1178 p
= (CursorOffset
*)gtk_object_get_user_data (GTK_OBJECT(widget
));
1179 p
->x
= (int) event
->x
;
1180 p
->y
= (int) event
->y
;
1182 gtk_grab_add (widget
);
1183 gdk_pointer_grab (widget
->window
, TRUE
,
1185 (GDK_BUTTON_RELEASE_MASK
|
1186 GDK_BUTTON_MOTION_MASK
|
1187 GDK_POINTER_MOTION_HINT_MASK
),
1189 (GdkCursor
*) NULL
, 0);
1194 shape_released (GtkWidget
*widget
)
1196 gtk_grab_remove (widget
);
1197 gdk_pointer_ungrab (0);
1201 shape_motion (GtkWidget
*widget
,
1202 GdkEventMotion
* /*event*/ )
1206 GdkModifierType mask
;
1208 p
= (CursorOffset
*)gtk_object_get_user_data (GTK_OBJECT (widget
));
1211 * Can't use event->x / event->y here
1212 * because I need absolute coordinates.
1215 gdk_window_get_pointer (root_win
, &xp
, &yp
, &mask
);
1216 gtk_widget_set_uposition (widget
, xp
- p
->x
, yp
- p
->y
);
1218 if (gs_currentDropSource
) gs_currentDropSource
->GiveFeedback( wxDragCopy
, FALSE
);
1222 shape_create_icon (const wxIcon
&shape
,
1230 * GDK_WINDOW_TOPLEVEL works also, giving you a title border
1232 GtkWidget
*window
= gtk_window_new ((GtkWindowType
)window_type
);
1234 GtkWidget
*fixed
= gtk_fixed_new ();
1235 gtk_widget_set_usize (fixed
, 100,100);
1236 gtk_container_add (GTK_CONTAINER (window
), fixed
);
1237 gtk_widget_show (fixed
);
1239 gtk_widget_set_events (window
,
1240 gtk_widget_get_events (window
) |
1241 GDK_BUTTON_MOTION_MASK
|
1242 GDK_POINTER_MOTION_HINT_MASK
|
1243 GDK_BUTTON_PRESS_MASK
);
1245 gtk_widget_realize (window
);
1247 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
1248 if (shape
.GetMask()) mask
= shape
.GetMask()->GetBitmap();
1250 GtkWidget
*pixmap
= gtk_pixmap_new (shape
.GetPixmap(), mask
);
1251 gtk_fixed_put (GTK_FIXED (fixed
), pixmap
, px
,py
);
1252 gtk_widget_show (pixmap
);
1254 gtk_widget_shape_combine_mask (window
, mask
, px
,py
);
1257 gtk_signal_connect (GTK_OBJECT (window
), "button_press_event",
1258 GTK_SIGNAL_FUNC (shape_pressed
),NULL
);
1259 gtk_signal_connect (GTK_OBJECT (window
), "button_release_event",
1260 GTK_SIGNAL_FUNC (shape_released
),NULL
);
1261 gtk_signal_connect (GTK_OBJECT (window
), "motion_notify_event",
1262 GTK_SIGNAL_FUNC (shape_motion
),NULL
);
1264 CursorOffset
*icon_pos
= g_new (CursorOffset
, 1);
1265 gtk_object_set_user_data(GTK_OBJECT(window
), icon_pos
);
1267 gtk_widget_set_uposition (window
, x
, y
);
1268 gtk_widget_show (window
);
1278 // wxUSE_DRAG_AND_DROP