[file-roller] fr-window: Improve XDS dnd support
- From: Paolo Bacchilega <paobac src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [file-roller] fr-window: Improve XDS dnd support
- Date: Sun, 27 Oct 2013 12:27:56 +0000 (UTC)
commit 8eaf8a076d0d00492f4eafaa8bee8dc9cea9f4d2
Author: Nelson Benítez León <nbenitezl+gnome gmail com>
Date: Sat Oct 19 17:40:53 2013 +0200
fr-window: Improve XDS dnd support
Improve file-roller XDS dnd support by sending the 'success'
response only after the file(s) has already been extracted, so
the target dnd application can operate on it (eg. gedit may
want to open it, nautilus may want to reveal it).
The XDS spec states that when sending the success ('S') response, the
file should have already been written to disk, but assumed this would
be done in a synchronous (and thus blocking) operation, asynchronous
(callback based) apis were not common when the XDS spec was done so
that's probably the reason.
So as file-roller does, in a right manner, its file operations asynchronously,
thats probably why it didn't care to send the success response at the right time.
This patch workarounds the XDS spec limitation and makes file-roller to wait
for the async operations to complete before sending the success response.
It does so, without blocking the main ui thread, by creating and using a GMainLoop
the same way as it's done by the gtk_dialog_run() call, which shows a dialog and
waits for its response without blocking the ui.
Fixes bug 710546
src/fr-window.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++------
1 files changed, 66 insertions(+), 9 deletions(-)
---
diff --git a/src/fr-window.c b/src/fr-window.c
index f0906ad..929834e 100644
--- a/src/fr-window.c
+++ b/src/fr-window.c
@@ -337,6 +337,8 @@ struct _FrWindowPrivate {
GError *drag_error;
GList *drag_file_list; /* the list of files we are
* dragging*/
+ gboolean dnd_extract_is_running;
+ gboolean dnd_extract_finished_with_error;
/* progress dialog data */
@@ -870,6 +872,8 @@ fr_window_init (FrWindow *window)
{
window->priv = g_new0 (FrWindowPrivate, 1);
window->priv->update_dropped_files = FALSE;
+ window->priv->dnd_extract_is_running = FALSE;
+ window->priv->dnd_extract_finished_with_error = FALSE;
window->priv->filter_mode = FALSE;
window->priv->use_progress_dialog = TRUE;
window->priv->batch_title = NULL;
@@ -4266,14 +4270,6 @@ file_list_drag_end (GtkWidget *widget,
g_clear_error (&window->priv->drag_error);
}
else if (window->priv->drag_destination_folder != NULL) {
- fr_window_archive_extract (window,
- window->priv->drag_file_list,
- window->priv->drag_destination_folder,
- window->priv->drag_base_dir,
- FALSE,
- FR_OVERWRITE_ASK,
- FALSE,
- FALSE);
_g_string_list_free (window->priv->drag_file_list);
window->priv->drag_file_list = NULL;
}
@@ -4454,6 +4450,30 @@ fr_window_folder_tree_drag_data_get (GtkWidget *widget,
return TRUE;
}
+typedef struct
+{
+ FrWindow *window;
+ GMainLoop *loop;
+} DndWaitInfo;
+
+gboolean
+extraction_is_finished (gpointer *data)
+{
+ DndWaitInfo *wait_info;
+ wait_info = (DndWaitInfo *) data;
+
+ return wait_info->window->priv->dnd_extract_is_running;
+}
+
+void
+notify_extraction_finished (gpointer *data)
+{
+ DndWaitInfo *wait_info;
+ wait_info = (DndWaitInfo *) data;
+
+ if (g_main_loop_is_running (wait_info->loop))
+ g_main_loop_quit (wait_info->loop);
+}
gboolean
fr_window_file_list_drag_data_get (FrWindow *window,
@@ -4462,6 +4482,7 @@ fr_window_file_list_drag_data_get (FrWindow *window,
GList *path_list)
{
char *uri;
+ char *xds_response;
GFile *destination;
GFile *destination_folder;
@@ -4525,13 +4546,44 @@ fr_window_file_list_drag_data_get (FrWindow *window,
window->priv->drag_destination_folder = g_object_ref (destination_folder);
window->priv->drag_base_dir = g_strdup (fr_window_get_current_location (window));
window->priv->drag_file_list = fr_window_get_file_list_from_path_list (window, path_list,
NULL);
+
+ window->priv->dnd_extract_is_running = TRUE;
+ window->priv->dnd_extract_finished_with_error = FALSE;
+ fr_window_archive_extract (window,
+ window->priv->drag_file_list,
+ window->priv->drag_destination_folder,
+ window->priv->drag_base_dir,
+ FALSE,
+ FR_OVERWRITE_ASK,
+ FALSE,
+ FALSE);
+
+ DndWaitInfo wait_info = { NULL, NULL };
+ wait_info.loop = g_main_loop_new (NULL, FALSE);
+ wait_info.window = window;
+ g_timeout_add_full (G_PRIORITY_DEFAULT,
+ 500,
+ (GSourceFunc) extraction_is_finished,
+ &wait_info,
+ (GDestroyNotify) notify_extraction_finished);
+
+ gdk_threads_leave ();
+ g_main_loop_run (wait_info.loop);
+ gdk_threads_enter ();
+
+ g_main_loop_unref (wait_info.loop);
+ wait_info.loop = NULL;
+ wait_info.window = NULL;
+ window->priv->dnd_extract_is_running = FALSE;
}
g_object_unref (destination_folder);
/* sends back the response */
+ xds_response = ((window->priv->drag_error == NULL && !window->priv->dnd_extract_finished_with_error)
? "S" : "E");
+ gtk_selection_data_set (selection_data, gtk_selection_data_get_target (selection_data), 8, (guchar *)
xds_response, 1);
- gtk_selection_data_set (selection_data, gtk_selection_data_get_target (selection_data), 8, (guchar *)
((window->priv->drag_error == NULL) ? "S" : "E"), 1);
+ window->priv->dnd_extract_finished_with_error = FALSE;
debug (DEBUG_INFO, "::DragDataGet <--\n");
@@ -6509,6 +6561,11 @@ archive_extraction_ready_cb (GObject *source_object,
fr_archive_operation_finish (FR_ARCHIVE (source_object), result, &error);
_archive_operation_completed (window, FR_ACTION_EXTRACTING_FILES, error);
+ if (window->priv->dnd_extract_is_running == TRUE) {
+ window->priv->dnd_extract_is_running = FALSE;
+ window->priv->dnd_extract_finished_with_error = error != NULL;
+ }
+
if ((error == NULL) && ask_to_open_destination) {
window->priv->quit_with_progress_dialog = window->priv->batch_mode;
open_progress_dialog_with_open_destination (window);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]