summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon the Sorcerer <neuron@mail.uni-paderborn.de>2017-12-26 12:40:24 +0100
committerSimon the Sorcerer <neuron@mail.uni-paderborn.de>2017-12-26 12:40:24 +0100
commit2a98c847ba99c2819f2df62187bafd79094734e9 (patch)
tree0ef890e004cb2b825fecc63941fc0d1c0216082e /xfce-base/thunar
parentfixed app-misc/oneko nobsd.patch. (diff)
downloaddarkelf-2a98c847ba99c2819f2df62187bafd79094734e9.tar.gz
darkelf-2a98c847ba99c2819f2df62187bafd79094734e9.tar.bz2
darkelf-2a98c847ba99c2819f2df62187bafd79094734e9.zip
added xfce-base/thunar with queued file transfer patch.
Diffstat (limited to 'xfce-base/thunar')
-rw-r--r--xfce-base/thunar/Manifest5
-rw-r--r--xfce-base/thunar/files/thunar-1.16.2-integer-overflow.patch29
-rw-r--r--xfce-base/thunar/files/thunar-queuedtransfer-20160702.patch721
-rw-r--r--xfce-base/thunar/metadata.xml12
-rw-r--r--xfce-base/thunar/thunar-1.6.13_p1.ebuild83
5 files changed, 850 insertions, 0 deletions
diff --git a/xfce-base/thunar/Manifest b/xfce-base/thunar/Manifest
new file mode 100644
index 0000000..c8d9696
--- /dev/null
+++ b/xfce-base/thunar/Manifest
@@ -0,0 +1,5 @@
+AUX thunar-1.16.2-integer-overflow.patch 1160 SHA256 e88ceeefc3a93ac44b95684febd2816be59adc813df1b1e1c7c10a1023b88a9b SHA512 eaefb709e03902cc97be41d4c670ded910234fd1536aae8597cbd9224e0d61badfee912eba81ee2e1a6c308ccd12b26961634e24b8b64fc8457b9d31ba57a843 WHIRLPOOL 89736ac87f23180871c6d316575036037ba083d8ba0119687596e40bc0f527f1ff43dadc5d820c9a69e8838951db307705b87474057b4b53d937916496582d50
+AUX thunar-queuedtransfer-20160702.patch 29353 SHA256 a31507e15fdcd3a869d3680fb0f72d0d9f5bcddbfa1affff15faf4441041fb6d SHA512 a5fd11c7d58082ddce0895020ef8aff5e243400d7343d60af99e01b7aa65ddd3fdc7a61287201022b1598460bc1ee6f08da8d4e7027769e2fdf081197ed8bfec WHIRLPOOL 202944871672b16805085e7cab75926900b4d7def63617c3aa244858b7ef1d99020299877041f0ca0da580e29a0001b03d45f7f494cbaba83c332430c67759b3
+DIST Thunar-1.6.13.tar.bz2 1937341 SHA256 a2900acfa92f965aff86cd7728d88a3836b3d21fb85d3355a8c5119c9975f93f SHA512 d1ae8efd0652c21b14ff45be9eef2ccf6b4400c744b08b2096a47b1af4eade2df1a237d03ede3e5dccea018b626dd67ffda2ed946b31fc2d3ff214c79e30168f WHIRLPOOL 7b7debc04d298ce1575924ee01fef45341f7fc63020985e3d68790ded03bbe3e501d6e072b077f388b6e8d70c38cb6ef3ece0d1a1a85c998312cf8e8b097900b
+EBUILD thunar-1.6.13_p1.ebuild 2131 SHA256 0fc72f7a6d7e7e128259812fe98ca818779edc3a6e0c03a56ce81e97837ac9b0 SHA512 33d2a28fa2909a8fdd39e9f4e2c1d0a0de63130f70c88b3ffeca12b69a399c6e3062aa58853bf55a0b541fa37e54e9eaa4a8093b806896bc3fecd166c024ffe3 WHIRLPOOL a92fdcb32096969fcdb25c5fdff8fddf8a9d273ea798458184f7c5a3252f1d3abca6bdc39084fadacca99665b7a889477ea353e134215e5acad911ddcdab739d
+MISC metadata.xml 372 SHA256 c79517f1436518a816ff7335e5e342411b5ce9a2e1ef2279ecc60c4d5e2fa233 SHA512 3ecb379e314ff3f9c745b61707c6df0a912b1466bd56abeebdba0ee138e14ee331fcd61acb3c5b64ace4daa42cbaaec8331cc83d6ae5d0bdc1fa5a69a258ef17 WHIRLPOOL 67ce77734c8d88994c73eee383689f0e6ed7fc2dfe936b3866ec52cb791b6b1d9ac7eaf9871ac6617c507b73738ded310a3a35eb1772ec307b3802e9dc5a6ac6
diff --git a/xfce-base/thunar/files/thunar-1.16.2-integer-overflow.patch b/xfce-base/thunar/files/thunar-1.16.2-integer-overflow.patch
new file mode 100644
index 0000000..09f4b93
--- /dev/null
+++ b/xfce-base/thunar/files/thunar-1.16.2-integer-overflow.patch
@@ -0,0 +1,29 @@
+From 1736b1f69ecf3e44a1b957d8090fb04c6bc5fd95 Mon Sep 17 00:00:00 2001
+From: Mikhail Efremov <sem@altlinux.org>
+Date: Thu, 11 Feb 2016 18:59:27 +0300
+Subject: [PATCH] Fix potential buffer overflow
+
+Use g_malloc_n() instead of g_malloc to avoid integer overflow.
+This fixes CVE-2013-7447, see
+http://www.openwall.com/lists/oss-security/2016/02/10/2
+for details.
+---
+ thunar/thunar-gdk-extensions.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/thunar/thunar-gdk-extensions.c b/thunar/thunar-gdk-extensions.c
+index 50ecb4a..775eca3 100644
+--- a/thunar/thunar-gdk-extensions.c
++++ b/thunar/thunar-gdk-extensions.c
+@@ -75,7 +75,7 @@ thunar_gdk_cairo_create_surface (const GdkPixbuf *pixbuf)
+
+ /* prepare pixel data and surface */
+ cairo_stride = cairo_format_stride_for_width (format, width);
+- cairo_pixels = g_malloc (height * cairo_stride);
++ cairo_pixels = g_malloc_n (height, cairo_stride);
+ surface = cairo_image_surface_create_for_data (cairo_pixels, format,
+ width, height, cairo_stride);
+ cairo_surface_set_user_data (surface, &cairo_key, cairo_pixels, g_free);
+--
+2.6.5
+
diff --git a/xfce-base/thunar/files/thunar-queuedtransfer-20160702.patch b/xfce-base/thunar/files/thunar-queuedtransfer-20160702.patch
new file mode 100644
index 0000000..3cbccee
--- /dev/null
+++ b/xfce-base/thunar/files/thunar-queuedtransfer-20160702.patch
@@ -0,0 +1,721 @@
+From 50c67c23cd9bfeb0bb4f0cdd5b5ec614c850c8bd Mon Sep 17 00:00:00 2001
+From: Cyrille Pontvieux <jrd@enialis.net>
+Date: Wed, 29 Jun 2016 05:43:26 +0200
+Subject: Simultaneous or queued copies
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+When a new copy process occurs and another copy process exists,
+the source devices and target devices are compared.
+If one match (either source or target), then the files are appended to
+the currently running copy process instead of trying to simultaneous
+copy them.
+Some thresholds are defined though:
+- 100 MB minumum for the new copy process, if less, the copy is done
+aside.
+- 10 seconds minimum of estimated remaining time for the running copy
+process.
+One can change some settings using three preferences:
+- Simultaneous max file copies (0 for ∞, default value)
+- Copying files from same devices behavior:
+ - Ask everytime
+ - Copy simultaneously (default value)
+ - Queue files
+- Copying files to same devices behavior: same values as "from"
+
+The default behavior is the same as the current Thunar.
+---
+ thunar/thunar-enum-types.c | 23 +
+ thunar/thunar-enum-types.h | 20 +
+ thunar/thunar-job.c | 24 +
+ thunar/thunar-job.h | 3 +
+ thunar/thunar-preferences-dialog.c | 57 ++
+ thunar/thunar-preferences.c | 46 ++
+ thunar/thunar-transfer-job.c | 333 +++++++++-
+ 7 files changed, 1221 insertions(+), 510 deletions(-)
+
+diff --git a/thunar/thunar-enum-types.c b/thunar/thunar-enum-types.c
+index 479bbcf..d97128e 100644
+--- a/thunar/thunar-enum-types.c
++++ b/thunar/thunar-enum-types.c
+@@ -162,6 +162,29 @@ thunar_recursive_permissions_get_type (void)
+
+
+ GType
++thunar_copy_same_device_get_type (void)
++{
++ static GType type = G_TYPE_INVALID;
++
++ if (G_UNLIKELY (type == G_TYPE_INVALID))
++ {
++ static const GEnumValue values[] =
++ {
++ { THUNAR_COPY_SAME_DEVICE_ASK, "THUNAR_COPY_SAME_DEVICE_ASK", "ask", },
++ { THUNAR_COPY_SAME_DEVICE_SIMULTANEOUSLY, "THUNAR_COPY_SAME_DEVICE_SIMULTANEOUSLY", "simultaneous", },
++ { THUNAR_COPY_SAME_DEVICE_QUEUE, "THUNAR_COPY_SAME_DEVICE_QUEUE", "queue", },
++ { 0, NULL, NULL, },
++ };
++
++ type = g_enum_register_static (I_("ThunarCopySameDeviceMode"), values);
++ }
++
++ return type;
++}
++
++
++
++GType
+ thunar_zoom_level_get_type (void)
+ {
+ static GType type = G_TYPE_INVALID;
+diff --git a/thunar/thunar-enum-types.h b/thunar/thunar-enum-types.h
+index 9fb34a7..8d293b3 100644
+--- a/thunar/thunar-enum-types.h
++++ b/thunar/thunar-enum-types.h
+@@ -180,6 +180,26 @@ typedef enum
+ GType thunar_recursive_permissions_get_type (void) G_GNUC_CONST;
+
+
++#define THUNAR_TYPE_COPY_SAME_DEVICE (thunar_copy_same_device_get_type ())
++
++/**
++ * ThunarCopySameDeviceMode:
++ * @THUNAR_COPY_SAME_DEVICE_ASK : ask the user for simultaneous copy (or not) everytime a copy is done using a same device.
++ * @THUNAR_COPY_SAME_DEVICE_SIMULTANEOUSLY : always copy simultaneously when using a same device (if not max simultaneous copies reached).
++ * @THUNAR_COPY_SAME_DEVICE_QUEUE : always queue the copy when using a same device.
++ *
++ * Modus operandi when copying using a same device.
++ **/
++typedef enum
++{
++ THUNAR_COPY_SAME_DEVICE_ASK,
++ THUNAR_COPY_SAME_DEVICE_SIMULTANEOUSLY,
++ THUNAR_COPY_SAME_DEVICE_QUEUE,
++} ThunarCopySameDeviceMode;
++
++GType thunar_copy_same_device_get_type (void) G_GNUC_CONST;
++
++
+ #define THUNAR_TYPE_ZOOM_LEVEL (thunar_zoom_level_get_type ())
+
+ /**
+diff --git a/thunar/thunar-job.c b/thunar/thunar-job.c
+index f4ce28e..d692f0d 100644
+--- a/thunar/thunar-job.c
++++ b/thunar/thunar-job.c
+@@ -546,6 +546,30 @@ thunar_job_ask_no_size (ThunarJob *job,
+
+
+
++ThunarJobResponse
++thunar_job_ask_queue_copy (ThunarJob *job,
++ const gchar *format,
++ ...)
++{
++ ThunarJobResponse response;
++ va_list var_args;
++ _thunar_return_val_if_fail (THUNAR_IS_JOB (job), THUNAR_JOB_RESPONSE_CANCEL);
++ _thunar_return_val_if_fail (format != NULL, THUNAR_JOB_RESPONSE_CANCEL);
++ /* check if the user already cancelled the job */
++ if (G_UNLIKELY (exo_job_is_cancelled (EXO_JOB (job))))
++ return THUNAR_JOB_RESPONSE_CANCEL;
++ /* ask the user what he wants to do */
++ va_start (var_args, format);
++ response = _thunar_job_ask_valist (job, format, var_args,
++ _("Do you want to queue this copy?"),
++ THUNAR_JOB_RESPONSE_YES
++ | THUNAR_JOB_RESPONSE_NO);
++ va_end (var_args);
++ return response;
++}
++
++
++
+ gboolean
+ thunar_job_files_ready (ThunarJob *job,
+ GList *file_list)
+diff --git a/thunar/thunar-job.h b/thunar/thunar-job.h
+index f1f636b..f1372ed 100644
+--- a/thunar/thunar-job.h
++++ b/thunar/thunar-job.h
+@@ -84,6 +84,9 @@ ThunarJobResponse thunar_job_ask_replace (ThunarJob *job,
+ ThunarJobResponse thunar_job_ask_skip (ThunarJob *job,
+ const gchar *format,
+ ...);
++ThunarJobResponse thunar_job_ask_queue_copy (ThunarJob *job,
++ const gchar *format,
++ ...);
+ gboolean thunar_job_ask_no_size (ThunarJob *job,
+ const gchar *format,
+ ...);
+diff --git a/thunar/thunar-preferences-dialog.c b/thunar/thunar-preferences-dialog.c
+index 057766e..8db1e56 100644
+--- a/thunar/thunar-preferences-dialog.c
++++ b/thunar/thunar-preferences-dialog.c
+@@ -206,6 +206,7 @@ thunar_preferences_dialog_init (ThunarPreferencesDialog *dialog)
+ GtkWidget *button;
+ GtkWidget *align;
+ GtkWidget *combo;
++ GtkWidget *spinbutton;
+ GtkWidget *frame;
+ GtkWidget *label;
+ GtkWidget *range;
+@@ -626,6 +627,62 @@ thunar_preferences_dialog_init (ThunarPreferencesDialog *dialog)
+ gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
+ gtk_widget_show (frame);
+
++ label = gtk_label_new (_("Simultaneous file copies"));
++ gtk_label_set_attributes (GTK_LABEL (label), thunar_pango_attr_list_bold ());
++ gtk_frame_set_label_widget (GTK_FRAME (frame), label);
++ gtk_widget_show (label);
++
++ table = gtk_table_new (3, 2, FALSE);
++ gtk_table_set_row_spacings (GTK_TABLE (table), 6);
++ gtk_table_set_col_spacings (GTK_TABLE (table), 12);
++ gtk_container_set_border_width (GTK_CONTAINER (table), 12);
++ gtk_container_add (GTK_CONTAINER (frame), table);
++ gtk_widget_show (table);
++
++ label = gtk_label_new_with_mnemonic (_("Simultaneous _max file copies:"));
++ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
++ gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
++ gtk_widget_show (label);
++
++ spinbutton = gtk_spin_button_new_with_range (0, 100, 1);
++ exo_mutual_binding_new (G_OBJECT (dialog->preferences), "misc-max-simultaneous-copies", G_OBJECT (spinbutton), "value");
++ gtk_table_attach (GTK_TABLE (table), spinbutton, 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
++ thunar_gtk_label_set_a11y_relation (GTK_LABEL (label), spinbutton);
++ gtk_label_set_mnemonic_widget (GTK_LABEL (label), spinbutton);
++ gtk_widget_show (spinbutton);
++
++ label = gtk_label_new_with_mnemonic (_("Copying files _from same devices:"));
++ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
++ gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
++ gtk_widget_show (label);
++
++ combo = gtk_combo_box_text_new ();
++ gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), _("Ask everytime"));
++ gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), _("Copy simultaneously"));
++ gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), _("Queue files"));
++ exo_mutual_binding_new (G_OBJECT (dialog->preferences), "misc-copy-from-same-device", G_OBJECT (combo), "active");
++ gtk_table_attach (GTK_TABLE (table), combo, 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
++ thunar_gtk_label_set_a11y_relation (GTK_LABEL (label), combo);
++ gtk_widget_show (combo);
++
++ label = gtk_label_new_with_mnemonic (_("Copying files _to same devices:"));
++ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
++ gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3, GTK_FILL, GTK_FILL, 0, 0);
++ gtk_widget_show (label);
++
++ combo = gtk_combo_box_text_new ();
++ gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), _("Ask everytime"));
++ gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), _("Copy simultaneously"));
++ gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), _("Queue files"));
++ exo_mutual_binding_new (G_OBJECT (dialog->preferences), "misc-copy-to-same-device", G_OBJECT (combo), "active");
++ gtk_table_attach (GTK_TABLE (table), combo, 1, 2, 2, 3, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
++ thunar_gtk_label_set_a11y_relation (GTK_LABEL (label), combo);
++ gtk_widget_show (combo);
++
++ frame = g_object_new (GTK_TYPE_FRAME, "border-width", 0, "shadow-type", GTK_SHADOW_NONE, NULL);
++ gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
++ gtk_widget_show (frame);
++
+ label = gtk_label_new (_("Volume Management"));
+ gtk_label_set_attributes (GTK_LABEL (label), thunar_pango_attr_list_bold ());
+ gtk_frame_set_label_widget (GTK_FRAME (frame), label);
+diff --git a/thunar/thunar-preferences.c b/thunar/thunar-preferences.c
+index 9a86ae1..8db7ac3 100644
+--- a/thunar/thunar-preferences.c
++++ b/thunar/thunar-preferences.c
+@@ -82,6 +82,9 @@ enum
+ PROP_MISC_IMAGE_SIZE_IN_STATUSBAR,
+ PROP_MISC_MIDDLE_CLICK_IN_TAB,
+ PROP_MISC_RECURSIVE_PERMISSIONS,
++ PROP_MISC_MAX_SIMULTANEOUS_COPIES,
++ PROP_MISC_COPY_FROM_SAME_DEVICE,
++ PROP_MISC_COPY_TO_SAME_DEVICE,
+ PROP_MISC_REMEMBER_GEOMETRY,
+ PROP_MISC_SHOW_ABOUT_TEMPLATES,
+ PROP_MISC_SINGLE_CLICK,
+@@ -587,6 +590,49 @@ thunar_preferences_class_init (ThunarPreferencesClass *klass)
+ EXO_PARAM_READWRITE);
+
+ /**
++ * ThunarPreferences:misc-max-simultaneous-copies:
++ *
++ * Max number of simultaneous file copies than can occur.
++ * 0 means infinite (default value)
++ * When the max number occurs, any new copy will be appended
++ * to the last running copy.
++ **/
++ preferences_props[PROP_MISC_MAX_SIMULTANEOUS_COPIES] =
++ g_param_spec_uint ("misc-max-simultaneous-copies",
++ "MiscMaxSimultaneousCopies",
++ NULL,
++ 0,
++ 100,
++ 0,
++ EXO_PARAM_READWRITE);
++
++ /**
++ * ThunarPreferences:misc-copy-from-same-device:
++ *
++ * Specify what to do when copying files from the same device.
++ **/
++ preferences_props[PROP_MISC_COPY_FROM_SAME_DEVICE] =
++ g_param_spec_enum ("misc-copy-from-same-device",
++ "MiscCopyFromSameDevice",
++ NULL,
++ THUNAR_TYPE_COPY_SAME_DEVICE,
++ THUNAR_COPY_SAME_DEVICE_SIMULTANEOUSLY,
++ EXO_PARAM_READWRITE);
++
++ /**
++ * ThunarPreferences:misc-copy-to-same-device:
++ *
++ * Specify what to do when copying files to the same device.
++ **/
++ preferences_props[PROP_MISC_COPY_TO_SAME_DEVICE] =
++ g_param_spec_enum ("misc-copy-to-same-device",
++ "MiscCopyToSameDevice",
++ NULL,
++ THUNAR_TYPE_COPY_SAME_DEVICE,
++ THUNAR_COPY_SAME_DEVICE_SIMULTANEOUSLY,
++ EXO_PARAM_READWRITE);
++
++ /**
+ * ThunarPreferences:misc-remember-geometry:
+ *
+ * Whether Thunar should remember the size of windows and apply
+diff --git a/thunar/thunar-transfer-job.c b/thunar/thunar-transfer-job.c
+index 82482e0..a432c93 100644
+--- a/thunar/thunar-transfer-job.c
++++ b/thunar/thunar-transfer-job.c
+@@ -26,6 +26,7 @@
+ #include <gio/gio.h>
+
+ #include <thunar/thunar-application.h>
++#include <thunar/thunar-enum-types.h>
+ #include <thunar/thunar-gio-extensions.h>
+ #include <thunar/thunar-io-scan-directory.h>
+ #include <thunar/thunar-io-jobs-util.h>
+@@ -39,7 +40,9 @@
+
+ /* seconds before we show the transfer rate + remaining time */
+ #define MINIMUM_TRANSFER_TIME (10 * G_USEC_PER_SEC) /* 10 seconds */
+-
++/* minimum size (in bytes) for one job to be queued in another */
++#define QUEUE_MIN_SIZE (100 * 1024 * 1024) /* 100 MB */
++#define QUEUE_MIN_SEC 10
+
+
+ /* Property identifiers */
+@@ -47,6 +50,9 @@ enum
+ {
+ PROP_0,
+ PROP_FILE_SIZE_BINARY,
++ PROP_MAX_SIMULTANEOUS_COPIES,
++ PROP_COPY_FROM_SAME_DEVICE,
++ PROP_COPY_TO_SAME_DEVICE,
+ };
+
+
+@@ -84,6 +90,7 @@ struct _ThunarTransferJob
+ ThunarTransferJobType type;
+ GList *source_node_list;
+ GList *target_file_list;
++ GList *added_jobs;
+
+ gint64 start_time;
+ gint64 last_update_time;
+@@ -96,6 +103,9 @@ struct _ThunarTransferJob
+
+ ThunarPreferences *preferences;
+ gboolean file_size_binary;
++ guint16 max_simultaneous_copies;
++ guint16 copy_from_same_device;
++ guint16 copy_to_same_device;
+ };
+
+ struct _ThunarTransferNode
+@@ -109,6 +119,9 @@ struct _ThunarTransferNode
+
+ G_DEFINE_TYPE (ThunarTransferJob, thunar_transfer_job, THUNAR_TYPE_JOB)
+
++G_LOCK_DEFINE_STATIC(active_jobs);
++static GList *active_jobs = NULL;
++
+
+
+ static void
+@@ -137,6 +150,33 @@ thunar_transfer_job_class_init (ThunarTransferJobClass *klass)
+ NULL,
+ FALSE,
+ EXO_PARAM_READWRITE));
++ /*
++ g_object_class_install_property (gobject_class,
++ PROP_MAX_SIMULTANEOUS_COPIES,
++ g_param_spec_uint ("max-simultaneous-copies",
++ "MaxSimultaneousCopies",
++ NULL,
++ 0,
++ 100,
++ 0,
++ EXO_PARAM_READWRITE));
++ g_object_class_install_property (gobject_class,
++ PROP_COPY_FROM_SAME_DEVICE,
++ g_param_spec_enum ("copy-from-same-device",
++ "CopyFromSameDevice",
++ NULL,
++ THUNAR_TYPE_COPY_SAME_DEVICE,
++ THUNAR_COPY_SAME_DEVICE_SIMULTANEOUSLY,
++ EXO_PARAM_READWRITE));
++ g_object_class_install_property (gobject_class,
++ PROP_COPY_TO_SAME_DEVICE,
++ g_param_spec_enum ("copy-to-same-device",
++ "CopyToSameDevice",
++ NULL,
++ THUNAR_TYPE_COPY_SAME_DEVICE,
++ THUNAR_COPY_SAME_DEVICE_SIMULTANEOUSLY,
++ EXO_PARAM_READWRITE));
++ */
+ }
+
+
+@@ -147,10 +187,10 @@ thunar_transfer_job_init (ThunarTransferJob *job)
+ job->preferences = thunar_preferences_get ();
+ exo_binding_new (G_OBJECT (job->preferences), "misc-file-size-binary",
+ G_OBJECT (job), "file-size-binary");
+-
+ job->type = 0;
+ job->source_node_list = NULL;
+ job->target_file_list = NULL;
++ job->added_jobs = NULL;
+ job->total_size = 0;
+ job->total_progress = 0;
+ job->file_progress = 0;
+@@ -163,16 +203,32 @@ thunar_transfer_job_init (ThunarTransferJob *job)
+
+
+ static void
++thunar_transfer_job_free (gpointer data)
++{
++ ThunarTransferJob *job = data;
++ g_object_unref (job);
++}
++
++
++
++static void
+ thunar_transfer_job_finalize (GObject *object)
+ {
+ ThunarTransferJob *job = THUNAR_TRANSFER_JOB (object);
++ GList *ljob;
+
+ g_list_free_full (job->source_node_list, thunar_transfer_node_free);
+-
+ thunar_g_file_list_free (job->target_file_list);
+-
+ g_object_unref (job->preferences);
+-
++ if (job->added_jobs != NULL)
++ g_list_free_full(job->added_jobs, thunar_transfer_job_free);
++ G_LOCK (active_jobs);
++ ljob = g_list_find (active_jobs, job);
++ if (G_LIKELY (ljob != NULL))
++ {
++ active_jobs = g_list_remove_link (active_jobs, ljob);
++ }
++ G_UNLOCK (active_jobs);
+ (*G_OBJECT_CLASS (thunar_transfer_job_parent_class)->finalize) (object);
+ }
+
+@@ -846,26 +902,207 @@ thunar_transfer_job_verify_destination (ThunarTransferJob *transfer_job,
+
+
+
++static GList *
++thunar_transfer_job_list (void)
++{
++ GList *job_list;
++ G_LOCK (active_jobs);
++ job_list = g_list_copy(active_jobs);
++ G_UNLOCK (active_jobs);
++ return job_list;
++}
++
++
++
++static gboolean
++thunar_transfer_job_matching_fs(ThunarTransferJob *newjob,
++ GFile *file1,
++ GFile *file2)
++{
++ GFileInfo *info1;
++ GFileInfo *info2;
++ guint32 unix_device1;
++ guint32 unix_device2;
++ GError *err = NULL;
++
++ info1 = g_file_query_info (file1,
++ G_FILE_ATTRIBUTE_UNIX_DEVICE,
++ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
++ exo_job_get_cancellable (EXO_JOB (newjob)),
++ &err);
++ if (G_UNLIKELY (info1 == NULL || err != NULL))
++ return FALSE;
++ unix_device1 = g_file_info_get_attribute_uint32(info1, G_FILE_ATTRIBUTE_UNIX_DEVICE);
++ err = NULL;
++ info2 = g_file_query_info (file2,
++ G_FILE_ATTRIBUTE_UNIX_DEVICE,
++ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
++ exo_job_get_cancellable (EXO_JOB (newjob)),
++ &err);
++ if (G_UNLIKELY (info2 == NULL || err != NULL))
++ return FALSE;
++ unix_device2 = g_file_info_get_attribute_uint32(info2, G_FILE_ATTRIBUTE_UNIX_DEVICE);
++ return (unix_device1 == unix_device2);
++}
++
++
++
++static gboolean
++thunar_transfer_job_matching_source_fs(ThunarTransferJob *job,
++ ThunarTransferJob *newjob)
++{
++ ThunarTransferNode *node;
++ GFile *file1;
++ GFile *file2;
++
++ _thunar_return_val_if_fail (job != NULL, FALSE);
++ _thunar_return_val_if_fail (newjob != NULL, FALSE);
++ node = job->source_node_list->data;
++ file1 = node->source_file;
++ node = newjob->source_node_list->data;
++ file2 = node->source_file;
++ return thunar_transfer_job_matching_fs (newjob, file1, file2);
++}
++
++
++
++static gboolean
++thunar_transfer_job_matching_target_fs(ThunarTransferJob *job,
++ ThunarTransferJob *newjob)
++{
++ GFile *file1;
++ GFile *file2;
++
++ _thunar_return_val_if_fail (job != NULL, FALSE);
++ _thunar_return_val_if_fail (newjob != NULL, FALSE);
++ file1 = job->target_file_list->data;
++ file2 = newjob->target_file_list->data;
++ return thunar_transfer_job_matching_fs (newjob, file1, file2);
++}
++
++
++
++/**
++ * thunar_transfer_job_find_one_to_queue:
++ * @job : a #ThunarTransferJob.
++ * @max_simultaneous_copies : 0 = infinite, other = number of
++ * concurrent simultaneous copies allowed
++ * @copy_from_same_device : behavior when the source device is the
++ * same as another
++ * @copy_to_same_device : behavior when the target device is the
++ * same as another
++ *
++ * Tries to find a job to queue current file copy,
++ * rather than executing it on this job.
++ *
++ * Return value: the job to queue onto, or %NULL if none found matching
++ * the preferences.
++ **/
++static ThunarTransferJob *
++thunar_transfer_job_find_one_to_queue (ThunarTransferJob *job,
++ guint max_simultaneous_copies,
++ ThunarCopySameDeviceMode copy_from_same_device_mode,
++ ThunarCopySameDeviceMode copy_to_same_device_mode)
++{
++ ThunarTransferJob *queue_job = NULL;
++ GList *job_list;
++ GList *ljob;
++ ThunarTransferJob *inspected_job;
++ guint64 remaining_time_sec;
++ gboolean should_ask = FALSE;
++ ThunarJobResponse response;
++
++ job_list = thunar_transfer_job_list();
++ if (max_simultaneous_copies == 0 || g_list_length (job_list) < max_simultaneous_copies)
++ {
++ if (copy_from_same_device_mode == THUNAR_COPY_SAME_DEVICE_ASK || copy_to_same_device_mode == THUNAR_COPY_SAME_DEVICE_ASK)
++ {
++ for (ljob = job_list;
++ ljob != NULL;
++ ljob = ljob->next)
++ {
++ inspected_job = ljob->data;
++ remaining_time_sec = inspected_job->transfer_rate == 0 ? QUEUE_MIN_SEC + 1 : (inspected_job->total_size - inspected_job->total_progress) / inspected_job->transfer_rate;
++ if (inspected_job->total_size > QUEUE_MIN_SIZE && remaining_time_sec > QUEUE_MIN_SEC
++ && (
++ (copy_from_same_device_mode == THUNAR_COPY_SAME_DEVICE_ASK && thunar_transfer_job_matching_source_fs (inspected_job, job))
++ || (copy_to_same_device_mode == THUNAR_COPY_SAME_DEVICE_ASK && thunar_transfer_job_matching_target_fs (inspected_job, job))
++ ))
++ {
++ should_ask = TRUE;
++ break;
++ }
++ }
++ }
++ if (should_ask)
++ {
++ // ask the user for simultaneous or queue
++ response = thunar_job_ask_queue_copy (THUNAR_JOB (job),
++ _("This copy share source or target device to another copy in progress."));
++ if (response == THUNAR_JOB_RESPONSE_YES)
++ {
++ copy_from_same_device_mode = copy_to_same_device_mode = THUNAR_COPY_SAME_DEVICE_QUEUE;
++ }
++ else
++ {
++ copy_from_same_device_mode = copy_to_same_device_mode = THUNAR_COPY_SAME_DEVICE_SIMULTANEOUSLY;
++ }
++ g_list_free (job_list);
++ job_list = thunar_transfer_job_list();
++ }
++ if (!should_ask || max_simultaneous_copies == 0 || g_list_length (job_list) < max_simultaneous_copies)
++ {
++ for (ljob = job_list;
++ ljob != NULL;
++ ljob = ljob->next)
++ {
++ inspected_job = ljob->data;
++ remaining_time_sec = inspected_job->transfer_rate == 0 ? QUEUE_MIN_SEC + 1 : (inspected_job->total_size - inspected_job->total_progress) / inspected_job->transfer_rate;
++ if (inspected_job->total_size > QUEUE_MIN_SIZE && remaining_time_sec > QUEUE_MIN_SEC)
++ {
++ if ((copy_from_same_device_mode == THUNAR_COPY_SAME_DEVICE_QUEUE && thunar_transfer_job_matching_source_fs (inspected_job, job))
++ || (copy_to_same_device_mode == THUNAR_COPY_SAME_DEVICE_QUEUE && thunar_transfer_job_matching_target_fs (inspected_job, job)))
++ {
++ queue_job = inspected_job;
++ break;
++ }
++ }
++ }
++ }
++ }
++ g_list_free (job_list);
++ return queue_job;
++}
++
++
++
+ static gboolean
+ thunar_transfer_job_execute (ExoJob *job,
+ GError **error)
+ {
+- ThunarThumbnailCache *thumbnail_cache;
+- ThunarTransferNode *node;
+- ThunarApplication *application;
+- ThunarJobResponse response;
+- ThunarTransferJob *transfer_job = THUNAR_TRANSFER_JOB (job);
+- GFileInfo *info;
+- gboolean parent_exists;
+- GError *err = NULL;
+- GList *new_files_list = NULL;
+- GList *snext;
+- GList *sp;
+- GList *tnext;
+- GList *tp;
+- GFile *target_parent;
+- gchar *base_name;
+- gchar *parent_display_name;
++ guint max_simultaneous_copies;
++ ThunarCopySameDeviceMode copy_from_same_device_mode;
++ ThunarCopySameDeviceMode copy_to_same_device_mode;
++ ThunarThumbnailCache *thumbnail_cache;
++ ThunarTransferNode *node;
++ ThunarApplication *application;
++ ThunarJobResponse response;
++ ThunarTransferJob *transfer_job = THUNAR_TRANSFER_JOB (job);
++ ThunarTransferJob *queue_job = NULL;
++ ThunarTransferJob *added_job = NULL;
++ GFileInfo *info;
++ gboolean parent_exists;
++ GError *err = NULL;
++ GList *new_files_list = NULL;
++ GList *snext;
++ GList *sp;
++ GList *sp_added;
++ GList *tnext;
++ GList *tp;
++ GList *tp_added;
++ GFile *target_parent;
++ gchar *base_name;
++ gchar *parent_display_name;
+
+ _thunar_return_val_if_fail (THUNAR_IS_TRANSFER_JOB (job), FALSE);
+ _thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+@@ -1050,16 +1287,52 @@ thunar_transfer_job_execute (ExoJob *job,
+ }
+ }
+
+- /* transfer starts now */
+- transfer_job->start_time = g_get_real_time ();
+-
+- /* perform the copy recursively for all source transfer nodes */
+- for (sp = transfer_job->source_node_list, tp = transfer_job->target_file_list;
+- sp != NULL && tp != NULL && err == NULL;
+- sp = sp->next, tp = tp->next)
++ g_object_get (G_OBJECT (transfer_job->preferences), "misc-max-simultaneous-copies", &max_simultaneous_copies, "misc-copy-from-same-device", &copy_from_same_device_mode, "misc-copy-to-same-device", &copy_to_same_device_mode, NULL);
++ queue_job = thunar_transfer_job_find_one_to_queue (transfer_job, max_simultaneous_copies, copy_from_same_device_mode, copy_to_same_device_mode);
++ if (queue_job == NULL)
++ {
++ G_LOCK (active_jobs);
++ active_jobs = g_list_prepend (active_jobs, transfer_job);
++ G_UNLOCK (active_jobs);
++ /* transfer starts now */
++ transfer_job->start_time = g_get_real_time ();
++ /* perform the copy recursively for all source transfer nodes */
++ for (sp = transfer_job->source_node_list, tp = transfer_job->target_file_list;
++ sp != NULL && tp != NULL && err == NULL;
++ sp = sp->next, tp = tp->next)
++ {
++ thunar_transfer_job_copy_node (transfer_job, sp->data, tp->data, NULL,
++ &new_files_list, &err);
++ }
++ while (transfer_job->added_jobs != NULL)
++ {
++ added_job = transfer_job->added_jobs->data;
++ transfer_job->added_jobs = g_list_remove_link(transfer_job->added_jobs, transfer_job->added_jobs);
++ if (G_LIKELY (err == NULL))
++ {
++ for (sp_added = added_job->source_node_list, tp_added = added_job->target_file_list;
++ sp_added != NULL && tp_added != NULL && err == NULL;
++ sp_added = sp_added->next, tp_added = tp_added->next)
++ {
++ thunar_transfer_job_copy_node (transfer_job, sp_added->data, tp_added->data, NULL,
++ &new_files_list, &err);
++ }
++ }
++ g_object_unref (added_job);
++ }
++ }
++ else
+ {
+- thunar_transfer_job_copy_node (transfer_job, sp->data, tp->data, NULL,
+- &new_files_list, &err);
++ added_job = g_object_new (THUNAR_TYPE_TRANSFER_JOB, NULL);
++ added_job->type = transfer_job->type;
++ added_job->source_node_list = transfer_job->source_node_list;
++ added_job->target_file_list = transfer_job->target_file_list;
++ // transfer_job will be finalized/free and same for its resources
++ // fake it to have no resource
++ transfer_job->source_node_list = NULL;
++ transfer_job->target_file_list = NULL;
++ queue_job->added_jobs = g_list_append(queue_job->added_jobs, added_job);
++ queue_job->total_size += transfer_job->total_size;
+ }
+ }
+
+--
+2.8.2
diff --git a/xfce-base/thunar/metadata.xml b/xfce-base/thunar/metadata.xml
new file mode 100644
index 0000000..d844c26
--- /dev/null
+++ b/xfce-base/thunar/metadata.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<pkgmetadata>
+ <maintainer type="project">
+ <email>xfce@gentoo.org</email>
+ <name>XFCE Team</name>
+ </maintainer>
+ <use>
+ <flag name='trash-panel-plugin'>Build the trash status indicator plugin for
+ the XFCE panel</flag>
+ </use>
+</pkgmetadata>
diff --git a/xfce-base/thunar/thunar-1.6.13_p1.ebuild b/xfce-base/thunar/thunar-1.6.13_p1.ebuild
new file mode 100644
index 0000000..2b6cec3
--- /dev/null
+++ b/xfce-base/thunar/thunar-1.6.13_p1.ebuild
@@ -0,0 +1,83 @@
+# Copyright 1999-2017 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=6
+inherit gnome2-utils virtualx xdg-utils
+
+MY_P=${P^}
+MY_P=${MY_P%_p1}
+
+DESCRIPTION="File manager for the Xfce desktop environment and queued file transfer patch"
+HOMEPAGE="https://www.xfce.org/projects/ https://docs.xfce.org/xfce/thunar/start"
+SRC_URI="mirror://xfce/src/xfce/${PN}/${PV%.*}/${MY_P}.tar.bz2"
+
+LICENSE="GPL-2 LGPL-2"
+SLOT="0"
+KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~ia64 ~mips ~ppc ~ppc64 ~sparc ~x86 ~x86-fbsd ~amd64-linux ~x86-linux ~x86-solaris"
+IUSE="+dbus exif libnotify pcre test +trash-panel-plugin udisks"
+
+GVFS_DEPEND=">=gnome-base/gvfs-1.18.3"
+COMMON_DEPEND=">=dev-lang/perl-5.6
+ >=dev-libs/glib-2.30:=
+ >=x11-libs/gdk-pixbuf-2.14:=
+ >=x11-libs/gtk+-2.24:2=
+ >=xfce-base/exo-0.10:=
+ >=xfce-base/libxfce4ui-4.10:=
+ >=xfce-base/libxfce4util-4.10.1:=
+ >=xfce-base/xfconf-4.10:=
+ dbus? ( >=dev-libs/dbus-glib-0.100:= )
+ exif? ( >=media-libs/libexif-0.6.19:= )
+ libnotify? ( >=x11-libs/libnotify-0.7:= )
+ pcre? ( >=dev-libs/libpcre-6:= )
+ trash-panel-plugin? ( >=xfce-base/xfce4-panel-4.10:= )
+ udisks? ( virtual/libgudev:= )"
+RDEPEND="${COMMON_DEPEND}
+ >=dev-util/desktop-file-utils-0.20-r1
+ x11-misc/shared-mime-info
+ dbus? ( ${GVFS_DEPEND} )
+ trash-panel-plugin? ( ${GVFS_DEPEND} )
+ udisks? (
+ virtual/udev
+ ${GVFS_DEPEND}[udisks,udev]
+ )"
+DEPEND="${COMMON_DEPEND}
+ dev-util/intltool
+ sys-devel/gettext
+ virtual/pkgconfig"
+REQUIRED_USE="trash-panel-plugin? ( dbus )"
+
+S=${WORKDIR}/${MY_P}
+
+DOCS=( AUTHORS ChangeLog FAQ HACKING NEWS README THANKS TODO )
+
+PATCHES=(
+ "${FILESDIR}"/thunar-1.16.2-integer-overflow.patch
+ "${FILESDIR}"/thunar-queuedtransfer-20160702.patch
+)
+
+src_configure() {
+ local myconf=(
+ $(use_enable dbus)
+ $(use_enable udisks gudev)
+ $(use_enable libnotify notifications)
+ $(use_enable exif)
+ $(use_enable pcre)
+ $(use_enable trash-panel-plugin tpa-plugin)
+ )
+
+ econf "${myconf[@]}"
+}
+
+src_test() {
+ virtx emake check
+}
+
+pkg_postinst() {
+ xdg_desktop_database_update
+ gnome2_icon_cache_update
+}
+
+pkg_postrm() {
+ xdg_desktop_database_update
+ gnome2_icon_cache_update
+}