X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/9f39393d9efe16244c8d213076582dfd996cb129..1978421a6d8b81c1f8a961da4b8ddf544fec7b1b:/src/gtk/dnd.cpp diff --git a/src/gtk/dnd.cpp b/src/gtk/dnd.cpp index 83dd2e4f3d..2181646be5 100644 --- a/src/gtk/dnd.cpp +++ b/src/gtk/dnd.cpp @@ -7,12 +7,17 @@ // Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "dnd.h" #endif -#include "wx/dnd.h" +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" +#include "wx/dnd.h" +#include "wx/log.h" + + #if wxUSE_DRAG_AND_DROP #include "wx/window.h" @@ -21,8 +26,8 @@ #include "wx/intl.h" #include "wx/utils.h" -#include -#include +#include "wx/gtk/private.h" + #include #include @@ -40,8 +45,6 @@ extern bool g_isIdle; //----------------------------------------------------------------------------- #if wxUSE_THREADS -extern void wxapp_install_thread_wakeup(); -extern void wxapp_uninstall_thread_wakeup(); #endif //---------------------------------------------------------------------------- @@ -50,6 +53,9 @@ extern void wxapp_uninstall_thread_wakeup(); extern bool g_blockEventsOnDrag; +// the flags used for the last DoDragDrop() +static long gs_flagsForDrag = 0; + // the trace mask we use with wxLogTrace() - call // wxLog::AddTraceMask(TRACE_DND) to enable the trace messages from here // (there are quite a few of them, so don't enable this by default) @@ -60,7 +66,7 @@ static const wxChar *TRACE_DND = _T("dnd"); //---------------------------------------------------------------------------- /* XPM */ -static char * page_xpm[] = { +static const char * page_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 5 1", /* colors */ @@ -104,6 +110,30 @@ static char * page_xpm[] = { " ......................... "}; +// ============================================================================ +// private functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// convert between GTK+ and wxWindows DND constants +// ---------------------------------------------------------------------------- + +static wxDragResult ConvertFromGTK(long action) +{ + switch ( action ) + { + case GDK_ACTION_COPY: + return wxDragCopy; + + case GDK_ACTION_LINK: + return wxDragLink; + + case GDK_ACTION_MOVE: + return wxDragMove; + } + + return wxDragNone; +} // ---------------------------------------------------------------------------- // "drag_leave" @@ -152,11 +182,28 @@ static gboolean target_drag_motion( GtkWidget *WXUNUSED(widget), this is only valid for the duration of this call */ drop_target->SetDragContext( context ); + // GTK+ always supposes that we want to copy the data by default while we + // might want to move it, so examine not only suggested_action - which is + // only good if we don't have our own preferences - but also the actions + // field wxDragResult result; - if ( context->suggested_action == GDK_ACTION_COPY ) - result = wxDragCopy; - else + if ( (gs_flagsForDrag & wxDrag_DefaultMove) == wxDrag_DefaultMove && + (context->actions & GDK_ACTION_MOVE ) ) + { + // move is requested by the program and allowed by GTK+ - do it, even + // though suggested_action may be currently wxDragCopy result = wxDragMove; + } + else // use whatever GTK+ says we should + { + result = ConvertFromGTK(context->suggested_action); + + if ( (result == wxDragMove) && !(gs_flagsForDrag & wxDrag_AllowMove) ) + { + // we're requested to move but we can't + result = wxDragCopy; + } + } if (drop_target->m_firstMotion) { @@ -175,6 +222,8 @@ static gboolean target_drag_motion( GtkWidget *WXUNUSED(widget), GdkDragAction action; if (result == wxDragCopy) action = GDK_ACTION_COPY; + else if (result == wxDragLink) + action = GDK_ACTION_LINK; else action = GDK_ACTION_MOVE; @@ -254,11 +303,12 @@ static gboolean target_drag_drop( GtkWidget *widget, #if wxUSE_THREADS /* disable GUI threads */ - wxapp_uninstall_thread_wakeup(); #endif GdkAtom format = drop_target->GetMatchingPair(); - wxASSERT( format ); + + // this does happen somehow, see bug 555111 + wxCHECK_MSG( format, FALSE, _T("no matching GdkAtom for format?") ) /* GdkDragAction action = GDK_ACTION_MOVE; @@ -273,7 +323,6 @@ static gboolean target_drag_drop( GtkWidget *widget, #if wxUSE_THREADS /* re-enable GUI threads */ - wxapp_install_thread_wakeup(); #endif } @@ -322,11 +371,7 @@ static void target_drag_data_received( GtkWidget *WXUNUSED(widget), this is only valid for the duration of this call */ drop_target->SetDragData( data ); - wxDragResult result; - if ( context->suggested_action == GDK_ACTION_COPY ) - result = wxDragCopy; - else - result = wxDragMove; + wxDragResult result = ConvertFromGTK(context->suggested_action); if ( wxIsDragResultOk( drop_target->OnData( x, y, result ) ) ) { @@ -549,7 +594,6 @@ source_drag_data_get (GtkWidget *WXUNUSED(widget), #if wxUSE_THREADS /* disable GUI threads */ - wxapp_uninstall_thread_wakeup(); #endif gtk_selection_data_set( selection_data, @@ -560,7 +604,6 @@ source_drag_data_get (GtkWidget *WXUNUSED(widget), #if wxUSE_THREADS /* enable GUI threads */ - wxapp_install_thread_wakeup(); #endif delete[] d; @@ -619,11 +662,7 @@ gtk_dnd_window_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigur if (g_isIdle) wxapp_install_idle_handler(); - wxDragResult action = wxDragNone; - if (source->m_dragContext->action == GDK_ACTION_COPY) action = wxDragCopy; - if (source->m_dragContext->action == GDK_ACTION_MOVE) action = wxDragMove; - - source->GiveFeedback( action ); + source->GiveFeedback( ConvertFromGTK(source->m_dragContext->action) ); return 0; } @@ -742,19 +781,14 @@ void wxDropSource::PrepareIcon( int action, GdkDragContext *context ) gtk_drag_set_icon_widget( context, m_iconWindow, 0, 0 ); } -wxDragResult wxDropSource::DoDragDrop( bool allowMove ) +wxDragResult wxDropSource::DoDragDrop(int flags) { - wxASSERT_MSG( m_data, wxT("Drop source: no data") ); - - if (!m_data) - return (wxDragResult) wxDragNone; - - if (m_data->GetFormatCount() == 0) - return (wxDragResult) wxDragNone; + wxCHECK_MSG( m_data && m_data->GetFormatCount(), wxDragNone, + wxT("Drop source: no data") ); // still in drag if (g_blockEventsOnDrag) - return (wxDragResult) wxDragNone; + return wxDragNone; // disabled for now g_blockEventsOnDrag = TRUE; @@ -767,7 +801,8 @@ wxDragResult wxDropSource::DoDragDrop( bool allowMove ) wxDataFormat *array = new wxDataFormat[ m_data->GetFormatCount() ]; m_data->GetAllFormats( array ); - for (size_t i = 0; i < m_data->GetFormatCount(); i++) + size_t count = m_data->GetFormatCount(); + for (size_t i = 0; i < count; i++) { GdkAtom atom = array[i]; wxLogTrace(TRACE_DND, wxT("Drop source: Supported atom %s"), gdk_atom_name( atom )); @@ -794,18 +829,23 @@ wxDragResult wxDropSource::DoDragDrop( bool allowMove ) #if wxUSE_THREADS /* disable GUI threads */ - wxapp_uninstall_thread_wakeup(); #endif /* don't start dragging if no button is down */ if (button_number) { int action = GDK_ACTION_COPY; - if ( allowMove ) + if ( flags & wxDrag_AllowMove ) action |= GDK_ACTION_MOVE; + + // VZ: as we already use g_blockEventsOnDrag it shouldn't be that bad + // to use a global to pass the flags to the drop target but I'd + // surely prefer a better way to do it + gs_flagsForDrag = flags; + GdkDragContext *context = gtk_drag_begin( m_widget, target_list, - action, + (GdkDragAction)action, button_number, /* number of mouse button which started drag */ (GdkEvent*) &event ); @@ -813,17 +853,16 @@ wxDragResult wxDropSource::DoDragDrop( bool allowMove ) PrepareIcon( action, context ); - while (m_waiting) gtk_main_iteration(); + while (m_waiting) + gtk_main_iteration(); - if (context->action == GDK_ACTION_COPY) - m_retValue = wxDragCopy; - if (context->action == GDK_ACTION_MOVE) - m_retValue = wxDragMove; + m_retValue = ConvertFromGTK(context->action); + if ( m_retValue == wxDragNone ) + m_retValue = wxDragCancel; } #if wxUSE_THREADS /* re-enable GUI threads */ - wxapp_install_thread_wakeup(); #endif g_blockEventsOnDrag = FALSE;