From d0d22874c8e97ad61a20afc6229779ee336818c7 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 30 Jan 2014 19:40:35 +0000 Subject: [PATCH] Correctly detect cancelled drag-and-drop operations in wxGTK. The status of the drop operation wasn't propagated back to the initiator of drag and drop, so failing to drop data over a possibly accepting recipient could result in wrong behaviour and even data loss. Closes #15930. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@75745 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/changes.txt | 1 + src/gtk/dnd.cpp | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/docs/changes.txt b/docs/changes.txt index 4f1df26741..0261e42783 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -33,6 +33,7 @@ All (GUI): wxGTK: - Support building wxGTK3 under Windows (Kolya Kosenko). +- Correctly detect cancelled drag-and-drop operations (Kinaou Hervé). wxMSW: diff --git a/src/gtk/dnd.cpp b/src/gtk/dnd.cpp index ddcf5cd0d1..3acababeaf 100644 --- a/src/gtk/dnd.cpp +++ b/src/gtk/dnd.cpp @@ -311,6 +311,9 @@ static gboolean target_drag_drop( GtkWidget *widget, { wxLogTrace(TRACE_DND, wxT( "Drop target: OnDrop returned FALSE") ); + // change drag and drop status if drop operation failed + gdk_drag_status( context, (GdkDragAction)0, time ); + /* cancel the whole thing */ gtk_drag_finish( context, FALSE, /* no success */ @@ -365,6 +368,9 @@ static void target_drag_data_received( GtkWidget *WXUNUSED(widget), if (gtk_selection_data_get_length(data) <= 0 || gtk_selection_data_get_format(data) != 8) { + // change drag and drop status if drop operation failed + gdk_drag_status( context, (GdkDragAction)0, time ); + /* negative data length and non 8-bit data format qualifies for junk */ gtk_drag_finish (context, FALSE, FALSE, time); @@ -384,6 +390,9 @@ static void target_drag_data_received( GtkWidget *WXUNUSED(widget), { wxLogTrace(TRACE_DND, wxT( "Drop target: OnData returned true") ); + // change drag and drop status if drop operation failed + gdk_drag_status( context, (GdkDragAction)0, time ); + /* tell GTK that data transfer was successful */ gtk_drag_finish( context, TRUE, FALSE, time ); } @@ -880,6 +889,14 @@ wxDragResult wxDropSource::DoDragDrop(int flags) while (m_waiting) gtk_main_iteration(); + if ( m_retValue != wxDragCancel && + m_retValue != wxDragError ) + { + // if wxDropTarget::OnDrop has been processed and has succeeded + // check the return value of wxDropTarget::OnData + m_retValue = ConvertFromGTK( context->action ); + } + g_signal_handlers_disconnect_by_func (m_iconWindow, (gpointer) gtk_dnd_window_configure_callback, this);