summaryrefslogtreecommitdiff
path: root/libraries/libfm/patches/0003-3584608-Fix-for-rarely-broken-DnD-due-to-FmDndDest-s.patch
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/libfm/patches/0003-3584608-Fix-for-rarely-broken-DnD-due-to-FmDndDest-s.patch')
-rw-r--r--libraries/libfm/patches/0003-3584608-Fix-for-rarely-broken-DnD-due-to-FmDndDest-s.patch139
1 files changed, 139 insertions, 0 deletions
diff --git a/libraries/libfm/patches/0003-3584608-Fix-for-rarely-broken-DnD-due-to-FmDndDest-s.patch b/libraries/libfm/patches/0003-3584608-Fix-for-rarely-broken-DnD-due-to-FmDndDest-s.patch
new file mode 100644
index 0000000000..3837ed62a0
--- /dev/null
+++ b/libraries/libfm/patches/0003-3584608-Fix-for-rarely-broken-DnD-due-to-FmDndDest-s.patch
@@ -0,0 +1,139 @@
+From e098be34aa96bbcddb786a09b13da877d2d709ad Mon Sep 17 00:00:00 2001
+From: Andriy Grytsenko <andrej@rep.kiev.ua>
+Date: Tue, 6 Nov 2012 05:49:19 +0200
+Subject: [PATCH 03/22] [#3584608]Fix for rarely broken DnD due to FmDndDest
+ source caching.
+
+The previous behavior was to cache data and reset cache when drag leaves
+widget. This is completely wrong - we never get informed if we refuse drop
+(for example, on wrong target) therefore drag source kept the same while
+it was already changed. The only valid behavior is to keep drag context
+referenced and compare it with one we get in handler and if it's changed
+then reset our cache. This way we don't have to requery data again when
+pointer leaves widget but still inside of application window - the drag
+context is still the same, i.e. we get some optimization as a side effect.
+---
+ src/gtk/fm-dnd-dest.c | 44 ++++++++++++++------------------------------
+ 1 file changed, 14 insertions(+), 30 deletions(-)
+
+diff --git a/src/gtk/fm-dnd-dest.c b/src/gtk/fm-dnd-dest.c
+index 37686ce..21cf2c0 100644
+--- a/src/gtk/fm-dnd-dest.c
++++ b/src/gtk/fm-dnd-dest.c
+@@ -108,10 +108,10 @@ struct _FmDndDest
+
+ int info_type; /* type of src_files */
+ FmPathList* src_files;
++ GdkDragContext* context;
+ guint32 src_dev; /* UNIX dev of source fs */
+ const char* src_fs_id; /* filesystem id of source fs */
+ FmFileInfo* dest_file;
+- guint idle; /* idle handler */
+
+ gboolean waiting_data;
+ gboolean has_handlers;
+@@ -211,11 +211,6 @@ static void fm_dnd_dest_dispose(GObject *object)
+
+ fm_dnd_dest_set_widget(dd, NULL);
+
+- if(dd->idle)
+- {
+- g_source_remove(dd->idle);
+- dd->idle = 0;
+- }
+ clear_src_cache(dd);
+
+ G_OBJECT_CLASS(fm_dnd_dest_parent_class)->dispose(object);
+@@ -388,6 +383,11 @@ static gboolean fm_dnd_dest_files_dropped(FmDndDest* dd, int x, int y,
+ static void clear_src_cache(FmDndDest* dd)
+ {
+ /* free cached source files */
++ if(dd->context)
++ {
++ g_object_unref(dd->context);
++ dd->context = NULL;
++ }
+ if(dd->src_files)
+ {
+ fm_path_list_unref(dd->src_files);
+@@ -405,16 +405,6 @@ static void clear_src_cache(FmDndDest* dd)
+ dd->waiting_data = FALSE;
+ }
+
+-static gboolean clear_src_cache_on_idle(gpointer user_data)
+-{
+- GDK_THREADS_ENTER();
+- /* check if dd is still valid */
+- if(!g_source_is_destroyed(g_main_current_source()))
+- clear_src_cache((FmDndDest*)user_data);
+- GDK_THREADS_LEAVE();
+- return FALSE;
+-}
+-
+ #if 0
+ /* the returned list can be either FmPathList or FmFileInfoList */
+ /* check with fm_list_is_path_list() and fm_list_is_file_info_list(). */
+@@ -581,6 +571,10 @@ gboolean _on_drag_data_received(FmDndDest* dd, GdkDragContext *drag_context,
+ dd->src_files = files;
+ dd->waiting_data = FALSE;
+ dd->info_type = info;
++ /* keep context to verify if it's changed */
++ if(G_UNLIKELY(dd->context))
++ g_object_unref(dd->context);
++ dd->context = g_object_ref(drag_context);
+ return (files != NULL);
+ }
+
+@@ -718,7 +712,7 @@ gboolean _on_drag_drop(FmDndDest* dd, GdkDragContext *drag_context,
+ }
+
+ /* see if the dragged files are cached by "drag-motion" handler */
+- if(dd->src_files)
++ if(dd->src_files && drag_context == dd->context)
+ {
+ GdkDragAction action = gdk_drag_context_get_selected_action(drag_context);
+ /* emit files-dropped signal */
+@@ -777,14 +771,6 @@ GdkDragAction fm_dnd_dest_get_default_action(FmDndDest* dd,
+ /* query drag sources in any case */
+ goto query_sources;
+
+- /* we may have another data already so clear the cache */
+- if(dd->idle)
+- {
+- g_source_remove(dd->idle);
+- dd->idle = 0;
+- clear_src_cache(dd);
+- }
+-
+ /* special support for dropping onto desktop entry */
+ if(fm_file_info_is_desktop_entry(dest))
+ {
+@@ -802,8 +788,10 @@ GdkDragAction fm_dnd_dest_get_default_action(FmDndDest* dd,
+ if(target == dest_target_atom[FM_DND_DEST_TARGET_XDS])
+ return GDK_ACTION_COPY;
+
+- if(!dd->src_files) /* we didn't have any data, cache it */
++ /* we have no valid data, query it now */
++ if(!dd->src_files || dd->context != drag_context)
+ {
++ clear_src_cache(dd);
+ query_sources:
+ action = 0;
+ if(!dd->waiting_data) /* we're still waiting for "drag-data-received" signal */
+@@ -886,13 +874,9 @@ query_sources:
+ */
+ void fm_dnd_dest_drag_leave(FmDndDest* dd, GdkDragContext* drag_context, guint time)
+ {
+- if(dd->idle == 0)
+- dd->idle = g_idle_add_full(G_PRIORITY_LOW, clear_src_cache_on_idle, dd, NULL);
+ }
+
+ static void on_drag_leave(GtkWidget *widget, GdkDragContext *drag_context,
+ guint time, FmDndDest* dd)
+ {
+- if(dd->idle == 0)
+- dd->idle = g_idle_add_full(G_PRIORITY_LOW, clear_src_cache_on_idle, dd, NULL);
+ }
+--
+1.8.0.1
+