diff options
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.patch | 139 |
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 + |