X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/8e193f384f7b98daef459653ddb8485173fba8ba..572c6194d35ad2791c71aee05d6996da2761b07a:/src/gtk1/dnd.cpp diff --git a/src/gtk1/dnd.cpp b/src/gtk1/dnd.cpp index 11fcc9c080..a22731b164 100644 --- a/src/gtk1/dnd.cpp +++ b/src/gtk1/dnd.cpp @@ -188,14 +188,18 @@ static gboolean target_drag_motion( GtkWidget *WXUNUSED(widget), this is only valid for the duration of this call */ drop_target->SetDragContext( context ); + bool ret = FALSE; + if (drop_target->m_firstMotion) { /* the first "drag_motion" event substitutes a "drag_enter" event */ - drop_target->OnEnter(); + ret = drop_target->OnEnter( x, y ); + } + else + { + /* give program a chance to react (i.e. to say no by returning FALSE) */ + ret = drop_target->OnMove( x, y ); } - - /* give program a chance to react (i.e. to say no by returning FALSE) */ - bool ret = drop_target->OnMove( x, y ); /* we don't yet handle which "actions" (i.e. copy or move) the target accepts. so far we simply accept the @@ -252,12 +256,37 @@ static gboolean target_drag_drop( GtkWidget *widget, if (!ret) { + wxLogDebug( wxT( "Drop target: OnDrop returned TRUE") ); + /* cancel the whole thing */ gtk_drag_finish( context, FALSE, /* no success */ FALSE, /* don't delete data on dropping side */ time ); } + else + { + wxLogDebug( wxT( "Drop target: OnDrop returned TRUE") ); + +#if wxUSE_THREADS + /* disable GUI threads */ + wxapp_uninstall_thread_wakeup(); +#endif + + GdkAtom format = drop_target->GetMatchingPair(); + wxASSERT( format ); + + /* this should trigger an "drag_data_received" event */ + gtk_drag_get_data( widget, + context, + format, + time ); + +#if wxUSE_THREADS + /* re-enable GUI threads */ + wxapp_install_thread_wakeup(); +#endif + } /* after this, invalidate the drop_target's GdkDragContext */ drop_target->SetDragContext( (GdkDragContext*) NULL ); @@ -289,7 +318,6 @@ static void target_drag_data_received( GtkWidget *WXUNUSED(widget), /* Owen Taylor: "call gtk_drag_finish() with success == TRUE" */ -// printf( "data received.\n" ); if ((data->length <= 0) || (data->format != 8)) { @@ -297,22 +325,26 @@ static void target_drag_data_received( GtkWidget *WXUNUSED(widget), qualifies for junk */ gtk_drag_finish (context, FALSE, FALSE, time); -// printf( "no data.\n" ); - return; } + wxLogDebug( wxT( "Drop target: data received event") ); + /* inform the wxDropTarget about the current GtkSelectionData. this is only valid for the duration of this call */ drop_target->SetDragData( data ); if (drop_target->OnData( x, y )) { + wxLogDebug( wxT( "Drop target: OnData returned TRUE") ); + /* tell GTK that data transfer was successfull */ gtk_drag_finish( context, TRUE, FALSE, time ); } else { + wxLogDebug( wxT( "Drop target: OnData returned FALSE") ); + /* tell GTK that data transfer was not successfull */ gtk_drag_finish( context, FALSE, FALSE, time ); } @@ -325,7 +357,8 @@ static void target_drag_data_received( GtkWidget *WXUNUSED(widget), // wxDropTarget //---------------------------------------------------------------------------- -wxDropTarget::wxDropTarget() +wxDropTarget::wxDropTarget( wxDataObject *data ) + : wxDropTargetBase( data ) { m_firstMotion = TRUE; m_dragContext = (GdkDragContext*) NULL; @@ -334,104 +367,97 @@ wxDropTarget::wxDropTarget() m_dragTime = 0; } -wxDropTarget::~wxDropTarget() -{ -} - -void wxDropTarget::OnEnter() -{ -} - -void wxDropTarget::OnLeave() +bool wxDropTarget::OnEnter( int WXUNUSED(x), int WXUNUSED(y) ) { + if (!m_dataObject) + return FALSE; + + return (GetMatchingPair() != (GdkAtom) 0); } -bool wxDropTarget::OnMove( long WXUNUSED(x), long WXUNUSED(y) ) +bool wxDropTarget::OnMove( int WXUNUSED(x), int WXUNUSED(y) ) { - return TRUE; + if (!m_dataObject) + return FALSE; + + return (GetMatchingPair() != (GdkAtom) 0); } -bool wxDropTarget::OnDrop( long WXUNUSED(x), long WXUNUSED(y) ) +bool wxDropTarget::OnDrop( int WXUNUSED(x), int WXUNUSED(y) ) { - return FALSE; + if (!m_dataObject) + return FALSE; + + return (GetMatchingPair() != (GdkAtom) 0); } -bool wxDropTarget::OnData( long WXUNUSED(x), long WXUNUSED(y) ) +bool wxDropTarget::OnData( int WXUNUSED(x), int WXUNUSED(y) ) { - return FALSE; + if (!m_dataObject) + return FALSE; + + if (GetMatchingPair() == (GdkAtom) 0) + return FALSE; + + return GetData(); } -bool wxDropTarget::RequestData( wxDataFormat format ) +GdkAtom wxDropTarget::GetMatchingPair() { - if (!m_dragContext) return FALSE; - if (!m_dragWidget) return FALSE; + if (!m_dataObject) + return (GdkAtom) 0; -/* - wxPrintf( wxT("format: %s.\n"), format.GetId().c_str() ); - if (format.GetType() == wxDF_PRIVATE) wxPrintf( wxT("private data.\n") ); - if (format.GetType() == wxDF_TEXT) wxPrintf( wxT("text data.\n") ); -*/ - -#if wxUSE_THREADS - /* disable GUI threads */ - wxapp_uninstall_thread_wakeup(); -#endif - - /* this should trigger an "drag_data_received" event */ - gtk_drag_get_data( m_dragWidget, - m_dragContext, - format.GetAtom(), - m_dragTime ); - -#if wxUSE_THREADS - /* re-enable GUI threads */ - wxapp_install_thread_wakeup(); -#endif - - return TRUE; -} - -bool wxDropTarget::IsSupported( wxDataFormat format ) -{ - if (!m_dragContext) return FALSE; + if (!m_dragContext) + return (GdkAtom) 0; GList *child = m_dragContext->targets; while (child) { GdkAtom formatAtom = (GdkAtom) GPOINTER_TO_INT(child->data); + wxDataFormat format( formatAtom ); -// char *name = gdk_atom_name( formatAtom ); -// if (name) printf( "Format available: %s.\n", name ); +#ifdef __WXDEBUG__ + char *name = gdk_atom_name( formatAtom ); + if (name) wxLogDebug( "Drop target: drag has format: %s", name ); +#endif + if (m_dataObject->IsSupportedFormat( format )) + return formatAtom; - if (formatAtom == format.GetAtom()) return TRUE; child = child->next; } - return FALSE; + return (GdkAtom) 0; } -bool wxDropTarget::GetData( wxDataObject *data_object ) +bool wxDropTarget::GetData() { - if (!m_dragData) return FALSE; + if (!m_dragData) + return FALSE; - if (m_dragData->target != data_object->GetFormat().GetAtom()) return FALSE; + if (!m_dataObject) + return FALSE; - if (data_object->GetFormat().GetType() == wxDF_TEXT) - { - wxTextDataObject *text_object = (wxTextDataObject*)data_object; - text_object->SetText( (const char*)m_dragData->data ); - } else + wxDataFormat dragFormat( m_dragData->target ); + + if (!m_dataObject->IsSupportedFormat( dragFormat )) + return FALSE; - if (data_object->GetFormat().GetType() == wxDF_FILENAME) + if (dragFormat.GetType() == wxDF_TEXT) { - } else + wxTextDataObject *text_object = (wxTextDataObject*)m_dataObject; + text_object->SetText( (const char*)m_dragData->data ); + return TRUE; + } - if (data_object->GetFormat().GetType() == wxDF_PRIVATE) + if (dragFormat.GetType() == wxDF_FILENAME) { - wxPrivateDataObject *priv_object = (wxPrivateDataObject*)data_object; - priv_object->SetData( (const char*)m_dragData->data, (size_t)m_dragData->length ); + wxFileDataObject *file_object = (wxFileDataObject*)m_dataObject; + file_object->SetData( 0, (const char*)m_dragData->data ); + return TRUE; } + m_dataObject->SetData( dragFormat, (size_t)m_dragData->length, (const void*)m_dragData->data ); + return TRUE; } @@ -487,128 +513,39 @@ void wxDropTarget::RegisterWidget( GtkWidget *widget ) GTK_SIGNAL_FUNC(target_drag_data_received), (gpointer) this ); } -//------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- // wxTextDropTarget -//------------------------------------------------------------------------- - -bool wxTextDropTarget::OnMove( long WXUNUSED(x), long WXUNUSED(y) ) -{ - return IsSupported( wxDF_TEXT ); -} - -bool wxTextDropTarget::OnDrop( long WXUNUSED(x), long WXUNUSED(y) ) -{ - if (IsSupported( wxDF_TEXT )) - { - RequestData( wxDF_TEXT ); - return TRUE; - } - - return FALSE; -} - -bool wxTextDropTarget::OnData( long x, long y ) -{ - wxTextDataObject data; - if (!GetData( &data )) return FALSE; - - OnDropText( x, y, data.GetText() ); - - return TRUE; -} - -//------------------------------------------------------------------------- -// wxPrivateDropTarget -//------------------------------------------------------------------------- - -wxPrivateDropTarget::wxPrivateDropTarget() -{ - m_id = wxTheApp->GetAppName(); -} - -wxPrivateDropTarget::wxPrivateDropTarget( const wxString &id ) -{ - m_id = id; -} +// ---------------------------------------------------------------------------- -bool wxPrivateDropTarget::OnMove( long WXUNUSED(x), long WXUNUSED(y) ) +wxTextDropTarget::wxTextDropTarget() + : wxDropTarget(new wxTextDataObject) { - return IsSupported( m_id ); } -bool wxPrivateDropTarget::OnDrop( long WXUNUSED(x), long WXUNUSED(y) ) +bool wxTextDropTarget::OnData(wxCoord x, wxCoord y) { - if (!IsSupported( m_id )) - { - RequestData( m_id ); + if ( !GetData() ) return FALSE; - } - - return FALSE; -} - -bool wxPrivateDropTarget::OnData( long x, long y ) -{ - if (!IsSupported( m_id )) return FALSE; - wxPrivateDataObject data; - if (!GetData( &data )) return FALSE; - - OnDropData( x, y, data.GetData(), data.GetSize() ); - - return TRUE; + return OnDropText(x, y, ((wxTextDataObject *)m_dataObject)->GetText()); } -//---------------------------------------------------------------------------- -// A drop target which accepts files (dragged from File Manager or Explorer) -//---------------------------------------------------------------------------- - -bool wxFileDropTarget::OnMove( long WXUNUSED(x), long WXUNUSED(y) ) -{ - return IsSupported( wxDF_FILENAME ); -} +// ---------------------------------------------------------------------------- +// wxFileDropTarget +// ---------------------------------------------------------------------------- -bool wxFileDropTarget::OnDrop( long x, long y ) +wxFileDropTarget::wxFileDropTarget() + : wxDropTarget(new wxFileDataObject) { - if (IsSupported( wxDF_FILENAME )) - { - RequestData( wxDF_FILENAME ); - return TRUE; - } - - return FALSE; } -bool wxFileDropTarget::OnData( long x, long y ) +bool wxFileDropTarget::OnData(wxCoord x, wxCoord y) { - wxFileDataObject data; - if (!GetData( &data )) return FALSE; - - /* get number of substrings /root/mytext.txt/0/root/myothertext.txt/0/0 */ - size_t number = 0; - size_t i; - size_t size = data.GetFiles().Length(); - wxChar *text = WXSTRINGCAST data.GetFiles(); - for ( i = 0; i < size; i++) - if (text[i] == 0) number++; - - if (number == 0) return FALSE; - - wxChar **files = new wxChar*[number]; - - text = WXSTRINGCAST data.GetFiles(); - for (i = 0; i < number; i++) - { - files[i] = text; - int len = wxStrlen( text ); - text += len+1; - } - - OnDropFiles( x, y, number, files ); - - free( files ); + if ( !GetData() ) + return FALSE; - return TRUE; + return OnDropFiles(x, y, + ((wxFileDataObject *)m_dataObject)->GetFilenames()); } //---------------------------------------------------------------------------- @@ -625,56 +562,64 @@ source_drag_data_get (GtkWidget *WXUNUSED(widget), { if (g_isIdle) wxapp_install_idle_handler(); -// printf( "Provide data!\n" ); + wxDataFormat format( selection_data->target ); + + wxLogDebug( wxT("Drop source: format requested: %s"), format.GetId().c_str() ); -// char *name = gdk_atom_name( selection_data->target ); -// if (name) printf( "Format requested: %s.\n", name ); + drop_source->m_retValue = wxDragCancel; + + wxDataObject *data = drop_source->GetDataObject(); + + if (!data) + { + wxLogDebug( wxT("Drop source: no data object") ); + return; + } - wxNode *node = drop_source->m_data->m_dataObjects.First(); - while (node) + if (!data->IsSupportedFormat(format)) { - wxDataObject *data_object = (wxDataObject*) node->Data(); - if (data_object->GetFormat().GetAtom() == selection_data->target) - { -// printf( "format found.\n" ); + wxLogDebug( wxT("Drop source: unsupported format") ); + return; + } - size_t data_size = data_object->GetSize(); + if (data->GetDataSize(format) == 0) + { + wxLogDebug( wxT("Drop source: empty data") ); + return; + } + + size_t size = data->GetDataSize(format); - if (data_size > 0) - { -// printf( "data size: %d.\n", (int)data_size ); +// printf( "data size: %d.\n", (int)data_size ); - guchar *buffer = new guchar[data_size]; - data_object->WriteData( buffer ); + guchar *d = new guchar[size]; + + if (!data->GetDataHere( format, (void*)d )) + { + delete[] d; + return; + } #if wxUSE_THREADS - /* disable GUI threads */ - wxapp_uninstall_thread_wakeup(); + /* disable GUI threads */ + wxapp_uninstall_thread_wakeup(); #endif gtk_selection_data_set( selection_data, selection_data->target, 8, // 8-bit - buffer, - data_size ); + d, + size ); #if wxUSE_THREADS - /* enable GUI threads */ - wxapp_install_thread_wakeup(); + /* enable GUI threads */ + wxapp_install_thread_wakeup(); #endif - free( buffer ); - /* so far only copy, no moves. TODO. */ - drop_source->m_retValue = wxDragCopy; - - return; - } - } - - node = node->Next(); - } - - drop_source->m_retValue = wxDragCancel; + delete[] d; + + /* so far only copy, no moves. TODO. */ + drop_source->m_retValue = wxDragCopy; } //---------------------------------------------------------------------------- @@ -733,7 +678,6 @@ wxDropSource::wxDropSource( wxWindow *win, const wxIcon &go, const wxIcon &stop m_widget = win->m_widget; if (win->m_wxwindow) m_widget = win->m_wxwindow; - m_data = (wxDataBroker*) NULL; m_retValue = wxDragCancel; m_defaultCursor = wxCursor( wxCURSOR_NO_ENTRY ); @@ -749,15 +693,14 @@ wxDropSource::wxDropSource( wxDataObject& data, wxWindow *win, const wxIcon &go, const wxIcon &stop ) { m_waiting = TRUE; + + SetData( data ); m_window = win; m_widget = win->m_widget; if (win->m_wxwindow) m_widget = win->m_wxwindow; m_retValue = wxDragCancel; - m_data = new wxDataBroker; - m_data->Add(&data); - m_defaultCursor = wxCursor( wxCURSOR_NO_ENTRY ); m_goaheadCursor = wxCursor( wxCURSOR_HAND ); @@ -767,54 +710,8 @@ wxDropSource::wxDropSource( wxDataObject& data, wxWindow *win, if (wxNullIcon == stop) m_stopIcon = wxIcon( gv_xpm ); } -wxDropSource::wxDropSource( wxDataBroker *data, wxWindow *win ) -{ - m_window = win; - m_widget = win->m_widget; - if (win->m_wxwindow) m_widget = win->m_wxwindow; - m_retValue = wxDragCancel; - - m_data = data; - - m_defaultCursor = wxCursor( wxCURSOR_NO_ENTRY ); - m_goaheadCursor = wxCursor( wxCURSOR_HAND ); -} - -void wxDropSource::SetData( wxDataObject& data ) -{ - if ( m_data ) - delete m_data; - - m_data = new wxDataBroker; - m_data->Add(&data); -} - -void wxDropSource::SetData( wxDataObject *data ) -{ - if (m_data) delete m_data; - - if (data) - { - m_data = new wxDataBroker(); - m_data->Add( data ); - } - else - { - m_data = (wxDataBroker*) NULL; - } -} - -void wxDropSource::SetData( wxDataBroker *data ) -{ - if (m_data) delete m_data; - - m_data = data; -} - wxDropSource::~wxDropSource() { - if (m_data) delete m_data; - g_blockEventsOnDrag = FALSE; } @@ -822,19 +719,29 @@ wxDragResult wxDropSource::DoDragDrop( bool WXUNUSED(bAllowMove) ) { wxASSERT_MSG( m_data, wxT("wxDragSource: no data") ); - if (!m_data) return (wxDragResult) wxDragNone; + if (!m_data) + return (wxDragResult) wxDragNone; + if (m_data->GetFormatCount() == 0) + return (wxDragResult) wxDragNone; + g_blockEventsOnDrag = TRUE; RegisterWindow(); m_waiting = TRUE; - GdkAtom atom = gdk_atom_intern( "STRING", FALSE ); -// printf( "atom id: %d.\n", (int)atom ); - GtkTargetList *target_list = gtk_target_list_new( (GtkTargetEntry*) NULL, 0 ); - gtk_target_list_add( target_list, atom, 0, 0 ); + + wxDataFormat *array = new wxDataFormat[ m_data->GetFormatCount() ]; + m_data->GetAllFormats( array ); + for (size_t i = 0; i < m_data->GetFormatCount(); i++) + { + GdkAtom atom = array[i]; + wxLogDebug( wxT("Supported atom %s"), gdk_atom_name( atom ) ); + gtk_target_list_add( target_list, atom, 0, 0 ); + } + delete[] array; GdkEventMotion event; event.window = m_widget->window;