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"
15 #include "wx/window.h"
17 #include "wx/gdicmn.h"
20 #include "gdk/gdkprivate.h"
24 // ----------------------------------------------------------------------------
26 // ----------------------------------------------------------------------------
28 extern bool g_blockEventsOnDrag
;
30 #ifdef NEW_GTK_DND_CODE
32 #include "gtk/gtkdnd.h"
33 #include "gtk/gtkselection.h"
35 // ----------------------------------------------------------------------------
37 // ----------------------------------------------------------------------------
39 static void target_drag_leave( GtkWidget
*WXUNUSED(widget
),
40 GdkDragContext
*WXUNUSED(context
),
41 guint
WXUNUSED(time
) )
46 // ----------------------------------------------------------------------------
48 // ----------------------------------------------------------------------------
50 static gboolean
target_drag_motion( GtkWidget
*WXUNUSED(widget
),
51 GdkDragContext
*context
,
56 printf( "motion.\n" );
57 gdk_drag_status( context
, context
->suggested_action
, time
);
61 // ----------------------------------------------------------------------------
63 // ----------------------------------------------------------------------------
65 static gboolean
target_drag_drop( GtkWidget
*widget
,
66 GdkDragContext
*context
,
71 printf( "drop at: %d,%d.\n", x
, y
);
75 gtk_drag_get_data( widget
,
77 GPOINTER_TO_INT (context
->targets
->data
),
83 // ----------------------------------------------------------------------------
84 // "drag_data_received"
85 // ----------------------------------------------------------------------------
87 static void target_drag_data_received( GtkWidget
*WXUNUSED(widget
),
88 GdkDragContext
*context
,
91 GtkSelectionData
*data
,
95 printf( "data receive at: %d,%d.\n", x
, y
);
97 if ((data
->length
>= 0) && (data
->format
== 8))
99 wxString str
= (const char*)data
->data
;
100 printf( "Received %s\n.", WXSTRINGCAST str
);
101 gtk_drag_finish( context
, TRUE
, FALSE
, time
);
105 gtk_drag_finish (context
, FALSE
, FALSE
, time
);
108 // ----------------------------------------------------------------------------
110 // ----------------------------------------------------------------------------
112 wxDropTarget::wxDropTarget()
116 wxDropTarget::~wxDropTarget()
120 void wxDropTarget::UnregisterWidget( GtkWidget
*widget
)
122 wxCHECK_RET( widget
!= NULL
, "unregister widget is NULL" );
124 gtk_drag_dest_set( widget
,
126 (GtkTargetEntry
*) NULL
,
130 gtk_signal_disconnect_by_func( GTK_OBJECT(widget
),
131 GTK_SIGNAL_FUNC(target_drag_leave
), (gpointer
) this );
133 gtk_signal_disconnect_by_func( GTK_OBJECT(widget
),
134 GTK_SIGNAL_FUNC(target_drag_motion
), (gpointer
) this );
136 gtk_signal_disconnect_by_func( GTK_OBJECT(widget
),
137 GTK_SIGNAL_FUNC(target_drag_drop
), (gpointer
) this );
139 gtk_signal_disconnect_by_func( GTK_OBJECT(widget
),
140 GTK_SIGNAL_FUNC(target_drag_data_received
), (gpointer
) this );
143 void wxDropTarget::RegisterWidget( GtkWidget
*widget
)
145 wxCHECK_RET( widget
!= NULL
, "register widget is NULL" );
147 GtkTargetEntry format
;
152 for ( size_t i
= 0; i
< GetFormatCount(); i
++ )
154 wxDataFormat df
= GetFormat( i
);
158 format
.target
= "text/plain";
162 format
.target
= "file:ALL";
170 wxASSERT_MSG( valid
!= 0, "No valid DnD format supported." );
172 gtk_drag_dest_set( widget
,
173 GTK_DEST_DEFAULT_ALL
,
176 (GdkDragAction
)(GDK_ACTION_COPY
| GDK_ACTION_MOVE
) );
178 gtk_signal_connect( GTK_OBJECT(widget
), "drag_leave",
179 GTK_SIGNAL_FUNC(target_drag_leave
), (gpointer
) this );
181 gtk_signal_connect( GTK_OBJECT(widget
), "drag_motion",
182 GTK_SIGNAL_FUNC(target_drag_motion
), (gpointer
) this );
184 gtk_signal_connect( GTK_OBJECT(widget
), "drag_drop",
185 GTK_SIGNAL_FUNC(target_drag_drop
), (gpointer
) this );
187 gtk_signal_connect( GTK_OBJECT(widget
), "drag_data_received",
188 GTK_SIGNAL_FUNC(target_drag_data_received
), (gpointer
) this );
191 // ----------------------------------------------------------------------------
193 // ----------------------------------------------------------------------------
195 bool wxTextDropTarget::OnDrop( long x
, long y
, const void *data
, size_t WXUNUSED(size
) )
197 OnDropText( x
, y
, (const char*)data
);
201 bool wxTextDropTarget::OnDropText( long x
, long y
, const char *psz
)
203 printf( "Got dropped text: %s.\n", psz
);
204 printf( "At x: %d, y: %d.\n", (int)x
, (int)y
);
208 size_t wxTextDropTarget::GetFormatCount() const
213 wxDataFormat
wxTextDropTarget::GetFormat(size_t WXUNUSED(n
)) const
218 // ----------------------------------------------------------------------------
220 // ----------------------------------------------------------------------------
222 bool wxFileDropTarget::OnDropFiles( long x
, long y
, size_t nFiles
, const char * const aszFiles
[] )
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
++)
228 printf( aszFiles
[i
] );
234 bool wxFileDropTarget::OnDrop(long x
, long y
, const void *data
, size_t size
)
237 char *text
= (char*) data
;
238 for (size_t i
= 0; i
< size
; i
++)
239 if (text
[i
] == 0) number
++;
241 if (number
== 0) return TRUE
;
243 char **files
= new char*[number
];
246 for (size_t i
= 0; i
< number
; i
++)
249 int len
= strlen( text
);
253 bool ret
= OnDropFiles( x
, y
, 1, files
);
260 size_t wxFileDropTarget::GetFormatCount() const
265 wxDataFormat
wxFileDropTarget::GetFormat(size_t WXUNUSED(n
)) const
267 return wxDF_FILENAME
;
270 //-------------------------------------------------------------------------
272 //-------------------------------------------------------------------------
274 wxDropSource::wxDropSource( wxWindow
*win
)
276 g_blockEventsOnDrag
= TRUE
;
279 m_widget
= win
->m_widget
;
280 if (win
->m_wxwindow
) m_widget
= win
->m_wxwindow
;
282 m_data
= (wxDataObject
*) NULL
;
283 m_retValue
= wxDragCancel
;
285 m_defaultCursor
= wxCursor( wxCURSOR_NO_ENTRY
);
286 m_goaheadCursor
= wxCursor( wxCURSOR_HAND
);
289 wxDropSource::wxDropSource( wxDataObject
&data
, wxWindow
*win
)
291 g_blockEventsOnDrag
= TRUE
;
294 m_widget
= win
->m_widget
;
295 if (win
->m_wxwindow
) m_widget
= win
->m_wxwindow
;
296 m_retValue
= wxDragCancel
;
300 m_defaultCursor
= wxCursor( wxCURSOR_NO_ENTRY
);
301 m_goaheadCursor
= wxCursor( wxCURSOR_HAND
);
304 void wxDropSource::SetData( wxDataObject
&data
)
309 wxDropSource::~wxDropSource(void)
311 // if (m_data) delete m_data;
313 g_blockEventsOnDrag
= FALSE
;
316 wxDragResult
wxDropSource::DoDragDrop( bool WXUNUSED(bAllowMove
) )
318 wxASSERT_MSG( m_data
, "wxDragSource: no data" );
320 if (!m_data
) return (wxDragResult
) wxDragNone
;
321 if (m_data
->GetDataSize() == 0) return (wxDragResult
) wxDragNone
;
329 g_blockEventsOnDrag
= FALSE
;
334 void wxDropSource::RegisterWindow(void)
340 wxDataFormat df
= m_data
->GetPreferredFormat();
345 formats
+= "text/plain";
348 formats
+= "file:ALL";
354 char *str
= WXSTRINGCAST formats
;
359 void wxDropSource::UnregisterWindow(void)
361 if (!m_widget
) return;
371 //-----------------------------------------------------------------------------
372 // "drop_data_available_event"
373 //-----------------------------------------------------------------------------
375 static void gtk_target_callback( GtkWidget
*widget
,
376 GdkEventDropDataAvailable
*event
,
377 wxDropTarget
*target
)
383 gdk_window_get_pointer( widget
->window
, &x
, &y
, (GdkModifierType
*) NULL
);
385 printf( "Drop data is of type %s.\n", event
->data_type
);
387 target
->OnDrop( x
, y
, (const void*)event
->data
, (size_t)event
->data_numbytes
);
391 g_free (event->data);
392 g_free (event->data_type);
396 // ----------------------------------------------------------------------------
398 // ----------------------------------------------------------------------------
400 wxDropTarget::wxDropTarget()
404 wxDropTarget::~wxDropTarget()
408 void wxDropTarget::UnregisterWidget( GtkWidget
*widget
)
412 gtk_signal_disconnect_by_func( GTK_OBJECT(widget
),
413 GTK_SIGNAL_FUNC(gtk_target_callback
), (gpointer
) this );
415 gtk_widget_dnd_drop_set( widget
, FALSE
, (gchar
**) NULL
, 0, FALSE
);
418 void wxDropTarget::RegisterWidget( GtkWidget
*widget
)
423 for ( size_t i
= 0; i
< GetFormatCount(); i
++ )
425 wxDataFormat df
= GetFormat( i
);
429 if (i
> 0) formats
+= ";";
430 formats
+= "text/plain";
434 if (i
> 0) formats
+= ";";
435 formats
+= "file:ALL";
443 char *str
= WXSTRINGCAST formats
;
445 gtk_widget_dnd_drop_set( widget
, TRUE
, &str
, valid
, FALSE
);
447 gtk_signal_connect( GTK_OBJECT(widget
), "drop_data_available_event",
448 GTK_SIGNAL_FUNC(gtk_target_callback
), (gpointer
) this );
451 // ----------------------------------------------------------------------------
453 // ----------------------------------------------------------------------------
455 bool wxTextDropTarget::OnDrop( long x
, long y
, const void *data
, size_t WXUNUSED(size
) )
457 OnDropText( x
, y
, (const char*)data
);
461 bool wxTextDropTarget::OnDropText( long x
, long y
, const char *psz
)
463 printf( "Got dropped text: %s.\n", psz
);
464 printf( "At x: %d, y: %d.\n", (int)x
, (int)y
);
468 size_t wxTextDropTarget::GetFormatCount() const
473 wxDataFormat
wxTextDropTarget::GetFormat(size_t WXUNUSED(n
)) const
478 // ----------------------------------------------------------------------------
480 // ----------------------------------------------------------------------------
482 bool wxFileDropTarget::OnDropFiles( long x
, long y
, size_t nFiles
, const char * const aszFiles
[] )
484 printf( "Got %d dropped files.\n", (int)nFiles
);
485 printf( "At x: %d, y: %d.\n", (int)x
, (int)y
);
486 for (size_t i
= 0; i
< nFiles
; i
++)
488 printf( aszFiles
[i
] );
494 bool wxFileDropTarget::OnDrop(long x
, long y
, const void *data
, size_t size
)
497 char *text
= (char*) data
;
498 for (size_t i
= 0; i
< size
; i
++)
499 if (text
[i
] == 0) number
++;
501 if (number
== 0) return TRUE
;
503 char **files
= new char*[number
];
506 for (size_t i
= 0; i
< number
; i
++)
509 int len
= strlen( text
);
513 bool ret
= OnDropFiles( x
, y
, 1, files
);
520 size_t wxFileDropTarget::GetFormatCount() const
525 wxDataFormat
wxFileDropTarget::GetFormat(size_t WXUNUSED(n
)) const
527 return wxDF_FILENAME
;
530 //-------------------------------------------------------------------------
532 //-------------------------------------------------------------------------
534 //-----------------------------------------------------------------------------
537 void gtk_drag_callback( GtkWidget
*widget
, GdkEvent
*event
, wxDropSource
*source
)
539 printf( "Data requested for dropping.\n" );
541 wxDataObject
*data
= source
->m_data
;
543 size_t size
= data
->GetDataSize();
544 char *ptr
= new char[size
];
545 data
->GetDataHere( ptr
);
547 gtk_widget_dnd_data_set( widget
, event
, ptr
, size
);
551 source
->m_retValue
= wxDragCopy
;
554 wxDropSource::wxDropSource( wxWindow
*win
)
556 g_blockEventsOnDrag
= TRUE
;
559 m_widget
= win
->m_widget
;
560 if (win
->m_wxwindow
) m_widget
= win
->m_wxwindow
;
562 m_data
= (wxDataObject
*) NULL
;
563 m_retValue
= wxDragCancel
;
565 m_defaultCursor
= wxCursor( wxCURSOR_NO_ENTRY
);
566 m_goaheadCursor
= wxCursor( wxCURSOR_HAND
);
569 wxDropSource::wxDropSource( wxDataObject
&data
, wxWindow
*win
)
571 g_blockEventsOnDrag
= TRUE
;
574 m_widget
= win
->m_widget
;
575 if (win
->m_wxwindow
) m_widget
= win
->m_wxwindow
;
576 m_retValue
= wxDragCancel
;
580 m_defaultCursor
= wxCursor( wxCURSOR_NO_ENTRY
);
581 m_goaheadCursor
= wxCursor( wxCURSOR_HAND
);
584 void wxDropSource::SetData( wxDataObject
&data
)
589 wxDropSource::~wxDropSource(void)
591 // if (m_data) delete m_data;
593 g_blockEventsOnDrag
= FALSE
;
596 wxDragResult
wxDropSource::DoDragDrop( bool WXUNUSED(bAllowMove
) )
598 if (gdk_dnd
.dnd_grabbed
) return (wxDragResult
) wxDragNone
;
599 if (gdk_dnd
.drag_really
) return (wxDragResult
) wxDragNone
;
601 wxASSERT_MSG( m_data
, "wxDragSource: no data" );
603 if (!m_data
) return (wxDragResult
) wxDragNone
;
604 if (m_data
->GetDataSize() == 0) return (wxDragResult
) wxDragNone
;
606 GdkWindowPrivate
*wp
= (GdkWindowPrivate
*) m_widget
->window
;
610 gdk_dnd
.drag_perhaps
= TRUE
;
612 gdk_dnd
.dnd_drag_start
.x
= 5;
613 gdk_dnd
.dnd_drag_start
.y
= 5;
614 gdk_dnd
.real_sw
= wp
;
616 if (gdk_dnd
.drag_startwindows
)
618 g_free( gdk_dnd
.drag_startwindows
);
619 gdk_dnd
.drag_startwindows
= (GdkWindow
**) NULL
;
621 gdk_dnd
.drag_numwindows
= gdk_dnd
.drag_really
= 0;
623 XWindowAttributes dnd_winattr
;
624 XGetWindowAttributes( gdk_display
, wp
->xwindow
, &dnd_winattr
);
625 wp
->dnd_drag_savedeventmask
= dnd_winattr
.your_event_mask
;
627 gdk_dnd_drag_addwindow( m_widget
->window
);
629 GdkEventDragBegin ev
;
630 ev
.type
= GDK_DRAG_BEGIN
;
631 ev
.window
= m_widget
->window
;
633 ev
.u
.flags
.protocol_version
= DND_PROTOCOL_VERSION
;
635 gdk_event_put( (GdkEvent
*)&ev
);
637 XGrabPointer( gdk_display
, wp
->xwindow
, False
,
638 ButtonMotionMask
| ButtonPressMask
| ButtonReleaseMask
| PointerMotionMask
,
639 GrabModeAsync
, GrabModeAsync
, gdk_root_window
, None
, CurrentTime
);
641 gdk_dnd_set_drag_cursors( m_defaultCursor
.GetCursor(), m_goaheadCursor
.GetCursor() );
643 gdk_dnd
.dnd_grabbed
= TRUE
;
644 gdk_dnd
.drag_really
= 1;
648 gdk_window_get_pointer( m_widget
->window
, &x
, &y
, (GdkModifierType
*) NULL
);
650 gdk_dnd_display_drag_cursor( x
, y
, FALSE
, TRUE
);
652 while (gdk_dnd
.drag_really
|| gdk_dnd
.drag_perhaps
) wxYield();
656 g_blockEventsOnDrag
= FALSE
;
661 void wxDropSource::RegisterWindow(void)
667 wxDataFormat df
= m_data
->GetPreferredFormat();
672 formats
+= "text/plain";
675 formats
+= "file:ALL";
681 char *str
= WXSTRINGCAST formats
;
683 gtk_widget_dnd_drag_set( m_widget
, TRUE
, &str
, 1 );
685 gtk_signal_connect( GTK_OBJECT(m_widget
), "drag_request_event",
686 GTK_SIGNAL_FUNC(gtk_drag_callback
), (gpointer
)this );
689 void wxDropSource::UnregisterWindow(void)
691 if (!m_widget
) return;
693 gtk_widget_dnd_drag_set( m_widget
, FALSE
, (gchar
**) NULL
, 0 );
695 gtk_signal_disconnect_by_data( GTK_OBJECT(m_widget
), (gpointer
)this );