diff --git a/thunar/thunar-io-jobs.c b/thunar/thunar-io-jobs.c
index 4f6418402edbc298656f5535cb647057e1279bb6..34cc33a3a9b03d830f5df6c17ae40e4efda3a880 100644
--- a/thunar/thunar-io-jobs.c
+++ b/thunar/thunar-io-jobs.c
@@ -582,6 +582,7 @@ thunar_io_jobs_move_files (GList *source_file_list,
 
   job = thunar_transfer_job_new (source_file_list, target_file_list,
                                  THUNAR_TRANSFER_JOB_MOVE);
+  thunar_job_set_pausable (job, TRUE);
 
   return THUNAR_JOB (exo_job_launch (EXO_JOB (job)));
 }
@@ -600,6 +601,7 @@ thunar_io_jobs_copy_files (GList *source_file_list,
 
   job = thunar_transfer_job_new (source_file_list, target_file_list,
                                  THUNAR_TRANSFER_JOB_COPY);
+  thunar_job_set_pausable (job, TRUE);
 
   return THUNAR_JOB (exo_job_launch (EXO_JOB (job)));
 }
diff --git a/thunar/thunar-job.c b/thunar/thunar-job.c
index 88cc36d7118c4d230795737b3e130b9d464a50cb..7945693477f7ed48e9b900c338795cf3471fba3c 100644
--- a/thunar/thunar-job.c
+++ b/thunar/thunar-job.c
@@ -68,6 +68,8 @@ struct _ThunarJobPrivate
   ThunarJobResponse earlier_ask_skip_response;
   GList            *total_files;
   guint             n_total_files;
+  gboolean          pausable;
+  gboolean          paused;
 };
 
 
@@ -210,6 +212,8 @@ thunar_job_init (ThunarJob *job)
   job->priv->earlier_ask_delete_response = 0;
   job->priv->earlier_ask_skip_response = 0;
   job->priv->n_total_files = 0;
+  job->priv->pausable = FALSE;
+  job->priv->paused = FALSE;
 }
 
 
@@ -657,6 +661,52 @@ thunar_job_set_total_files (ThunarJob *job,
 
 
 
+void
+thunar_job_set_pausable (ThunarJob *job,
+                         gboolean   pausable)
+{
+  _thunar_return_if_fail (THUNAR_IS_JOB (job));
+  job->priv->pausable = pausable;
+}
+
+
+
+gboolean
+thunar_job_is_pausable (ThunarJob *job)
+{
+  _thunar_return_val_if_fail (THUNAR_IS_JOB (job), FALSE);
+  return job->priv->pausable;
+}
+
+
+
+void
+thunar_job_pause (ThunarJob *job)
+{
+  _thunar_return_if_fail (THUNAR_IS_JOB (job));
+  job->priv->paused = TRUE;
+}
+
+
+
+void
+thunar_job_resume (ThunarJob *job)
+{
+  _thunar_return_if_fail (THUNAR_IS_JOB (job));
+  job->priv->paused = FALSE;
+}
+
+
+
+gboolean
+thunar_job_is_paused (ThunarJob *job)
+{
+  _thunar_return_val_if_fail (THUNAR_IS_JOB (job), FALSE);
+  return job->priv->paused;
+}
+
+
+
 void
 thunar_job_processing_file (ThunarJob *job,
                             GList     *current_file,
diff --git a/thunar/thunar-job.h b/thunar/thunar-job.h
index 9c0a7b41582eecc649f0f8e6933b46936f276985..b9e7f26d6a2601b663b56d1c5a0dfc985fc5e126 100644
--- a/thunar/thunar-job.h
+++ b/thunar/thunar-job.h
@@ -68,6 +68,12 @@ struct _ThunarJob
 GType             thunar_job_get_type               (void) G_GNUC_CONST;
 void              thunar_job_set_total_files        (ThunarJob       *job,
                                                      GList           *total_files);
+void              thunar_job_set_pausable           (ThunarJob       *job,
+                                                     gboolean         pausable);
+gboolean          thunar_job_is_pausable            (ThunarJob       *job);
+void              thunar_job_pause                  (ThunarJob       *job);
+void              thunar_job_resume                 (ThunarJob       *job);
+gboolean          thunar_job_is_paused              (ThunarJob       *job);
 void              thunar_job_processing_file        (ThunarJob       *job,
                                                      GList           *current_file,
                                                      guint            n_processed);
diff --git a/thunar/thunar-progress-view.c b/thunar/thunar-progress-view.c
index 299b1c23d7779a5637f7da502d2bb19af8a14bee..b9384ca31231cb1b975e27b2727d81cee81c953b 100644
--- a/thunar/thunar-progress-view.c
+++ b/thunar/thunar-progress-view.c
@@ -55,6 +55,8 @@ static void              thunar_progress_view_set_property (GObject            *
                                                             guint               prop_id,
                                                             const GValue       *value,
                                                             GParamSpec         *pspec);
+static void              thunar_progress_view_pause_job    (ThunarProgressView *view);
+static void              thunar_progress_view_unpause_job  (ThunarProgressView *view);
 static void              thunar_progress_view_cancel_job   (ThunarProgressView *view);
 static ThunarJobResponse thunar_progress_view_ask          (ThunarProgressView *view,
                                                             const gchar        *message,
@@ -95,6 +97,8 @@ struct _ThunarProgressView
   GtkWidget *progress_bar;
   GtkWidget *progress_label;
   GtkWidget *message_label;
+  GtkWidget *pause_button;
+  GtkWidget *unpause_button;
 
   gchar     *icon_name;
   gchar     *title;
@@ -173,7 +177,7 @@ thunar_progress_view_init (ThunarProgressView *view)
 {
   GtkWidget *image;
   GtkWidget *label;
-  GtkWidget *button;
+  GtkWidget *cancel_button;
   GtkWidget *vbox;
   GtkWidget *vbox2;
   GtkWidget *vbox3;
@@ -228,12 +232,26 @@ thunar_progress_view_init (ThunarProgressView *view)
   gtk_box_pack_start (GTK_BOX (vbox3), view->progress_label, FALSE, TRUE, 0);
   gtk_widget_show (view->progress_label);
 
-  button = gtk_button_new_from_icon_name ("process-stop", GTK_ICON_SIZE_BUTTON);
-  gtk_button_set_label (GTK_BUTTON (button), _("Cancel"));
-  g_signal_connect_swapped (button, "clicked", G_CALLBACK (thunar_progress_view_cancel_job), view);
-  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
-  gtk_widget_set_can_focus (button, FALSE);
-  gtk_widget_show (button);
+  view->pause_button = gtk_button_new_from_icon_name ("media-playback-pause", GTK_ICON_SIZE_BUTTON);
+  gtk_button_set_label (GTK_BUTTON (view->pause_button), _("Pause"));
+  g_signal_connect_swapped (view->pause_button, "clicked", G_CALLBACK (thunar_progress_view_pause_job), view);
+  gtk_box_pack_start (GTK_BOX (hbox), view->pause_button, FALSE, FALSE, 0);
+  gtk_widget_set_can_focus (view->pause_button, FALSE);
+  gtk_widget_hide (view->pause_button);
+
+  view->unpause_button = gtk_button_new_from_icon_name ("media-playback-start", GTK_ICON_SIZE_BUTTON);
+  gtk_button_set_label (GTK_BUTTON (view->unpause_button), _("Resume"));
+  g_signal_connect_swapped (view->unpause_button, "clicked", G_CALLBACK (thunar_progress_view_unpause_job), view);
+  gtk_box_pack_start (GTK_BOX (hbox), view->unpause_button, FALSE, FALSE, 0);
+  gtk_widget_set_can_focus (view->unpause_button, FALSE);
+  gtk_widget_hide (view->unpause_button);
+
+  cancel_button = gtk_button_new_from_icon_name ("process-stop", GTK_ICON_SIZE_BUTTON);
+  gtk_button_set_label (GTK_BUTTON (cancel_button), _("Cancel"));
+  g_signal_connect_swapped (cancel_button, "clicked", G_CALLBACK (thunar_progress_view_cancel_job), view);
+  gtk_box_pack_start (GTK_BOX (hbox), cancel_button, FALSE, FALSE, 0);
+  gtk_widget_set_can_focus (cancel_button, FALSE);
+  gtk_widget_show (cancel_button);
 
   /* connect the view title to the action label */
   exo_binding_new (G_OBJECT (view), "title", G_OBJECT (label), "label");
@@ -331,6 +349,46 @@ thunar_progress_view_set_property (GObject      *object,
 
 
 
+static void
+thunar_progress_view_pause_job (ThunarProgressView *view)
+{
+  _thunar_return_if_fail (THUNAR_IS_PROGRESS_VIEW (view));
+  _thunar_return_if_fail (THUNAR_IS_JOB (view->job));
+
+  if (view->job != NULL)
+    {
+      /* pause the job */
+      thunar_job_pause (view->job);
+
+      /* update the UI */
+      gtk_widget_hide (view->pause_button);
+      gtk_widget_show (view->unpause_button);
+      gtk_label_set_text (GTK_LABEL (view->progress_label), _("Paused"));
+    }
+}
+
+
+
+static void
+thunar_progress_view_unpause_job (ThunarProgressView *view)
+{
+  _thunar_return_if_fail (THUNAR_IS_PROGRESS_VIEW (view));
+  _thunar_return_if_fail (THUNAR_IS_JOB (view->job));
+
+  if (view->job != NULL)
+    {
+      /* unpause the job */
+      thunar_job_resume (view->job);
+
+      /* update the UI */
+      gtk_widget_hide (view->unpause_button);
+      gtk_widget_show (view->pause_button);
+      gtk_label_set_text (GTK_LABEL (view->progress_label), _("Resuming..."));
+    }
+}
+
+
+
 static void
 thunar_progress_view_cancel_job (ThunarProgressView *view)
 {
@@ -564,6 +622,10 @@ thunar_progress_view_set_job (ThunarProgressView *view,
       g_signal_connect_swapped (job, "finished", G_CALLBACK (thunar_progress_view_finished), view);
       g_signal_connect_swapped (job, "info-message", G_CALLBACK (thunar_progress_view_info_message), view);
       g_signal_connect_swapped (job, "percent", G_CALLBACK (thunar_progress_view_percent), view);
+      if (thunar_job_is_pausable (job))
+        {
+          gtk_widget_show (view->pause_button);
+        }
     }
 
   g_object_notify (G_OBJECT (view), "job");
diff --git a/thunar/thunar-transfer-job.c b/thunar/thunar-transfer-job.c
index f7d7559879766ccbd38d6d51258686091e995a3b..3ec41546cc9cc3ad7a3e8d42fc55af967887d78e 100644
--- a/thunar/thunar-transfer-job.c
+++ b/thunar/thunar-transfer-job.c
@@ -223,6 +223,18 @@ thunar_transfer_job_set_property (GObject      *object,
 
 
 
+static void
+thunar_transfer_job_check_pause (ThunarTransferJob *job)
+{
+  _thunar_return_if_fail (THUNAR_IS_TRANSFER_JOB (job));
+  while (thunar_job_is_paused (THUNAR_JOB (job)) && !exo_job_is_cancelled (EXO_JOB (job)))
+    {
+      g_usleep (500 * 1000); /* 500ms pause */
+    }
+}
+
+
+
 static void
 thunar_transfer_job_progress (goffset  current_num_bytes,
                               goffset  total_num_bytes,
@@ -236,6 +248,8 @@ thunar_transfer_job_progress (goffset  current_num_bytes,
 
   _thunar_return_if_fail (THUNAR_IS_TRANSFER_JOB (job));
 
+  thunar_transfer_job_check_pause (job);
+
   if (G_LIKELY (job->total_size > 0))
     {
       /* update total progress */
@@ -316,6 +330,8 @@ thunar_transfer_job_collect_node (ThunarTransferJob  *job,
       /* add children to the transfer node */
       for (lp = file_list; err == NULL && lp != NULL; lp = lp->next)
         {
+          thunar_transfer_job_check_pause (job);
+
           /* allocate a new transfer node for the child */
           child_node = g_slice_new0 (ThunarTransferNode);
           child_node->source_file = g_object_ref (lp->data);
@@ -370,18 +386,21 @@ ttj_copy_file (ThunarTransferJob *job,
 
   if (exo_job_set_error_if_cancelled (EXO_JOB (job), error))
     return FALSE;
+  thunar_transfer_job_check_pause (job);
 
   source_type = g_file_query_file_type (source_file, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
                                         exo_job_get_cancellable (EXO_JOB (job)));
 
   if (exo_job_set_error_if_cancelled (EXO_JOB (job), error))
     return FALSE;
+  thunar_transfer_job_check_pause (job);
 
   target_type = g_file_query_file_type (target_file, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
                                         exo_job_get_cancellable (EXO_JOB (job)));
 
   if (exo_job_set_error_if_cancelled (EXO_JOB (job), error))
     return FALSE;
+  thunar_transfer_job_check_pause (job);
 
   /* check if the target is a symlink and we are in overwrite mode */
   if (target_type == G_FILE_TYPE_SYMBOLIC_LINK && (copy_flags & G_FILE_COPY_OVERWRITE) != 0)
@@ -517,6 +536,7 @@ thunar_transfer_job_copy_file (ThunarTransferJob *job,
   /* various attempts to copy the file */
   while (err == NULL)
     {
+      thunar_transfer_job_check_pause (job);
       if (G_LIKELY (!g_file_equal (source_file, target_file)))
         {
           /* try to copy the file from source_file to the target_file */
@@ -655,6 +675,8 @@ thunar_transfer_job_copy_node (ThunarTransferJob  *job,
       exo_job_info_message (EXO_JOB (job), "%s", g_file_info_get_display_name (info));
 
 retry_copy:
+      thunar_transfer_job_check_pause (job);
+
       /* copy the item specified by this node (not recursively) */
       real_target_file = thunar_transfer_job_copy_file (job, node->source_file,
                                                         target_file, node->replace_confirmed, &err);
@@ -697,6 +719,8 @@ retry_copy:
                 }
 
 retry_remove:
+              thunar_transfer_job_check_pause (job);
+
               /* try to remove the source directory if we are on copy+remove fallback for move */
               if (job->type == THUNAR_TRANSFER_JOB_MOVE)
                 {
@@ -887,6 +911,8 @@ thunar_transfer_job_execute (ExoJob  *job,
        sp != NULL && tp != NULL && err == NULL;
        sp = snext, tp = tnext)
     {
+      thunar_transfer_job_check_pause (transfer_job);
+
       /* determine the next list items */
       snext = sp->next;
       tnext = tp->next;