diff -cr Thunar-1.4.0.org/thunar/thunar-io-jobs.c Thunar-1.4.0/thunar/thunar-io-jobs.c
*** Thunar-1.4.0.org/thunar/thunar-io-jobs.c	2012-04-28 22:16:39.000000000 +0200
--- Thunar-1.4.0/thunar/thunar-io-jobs.c	2012-08-27 12:42:54.000000000 +0200
***************
*** 958,963 ****
--- 958,987 ----
  
  
  ThunarJob *
+ thunar_io_jobs_change_owner (GFile    *file,
+                              guint32   uid,
+                              gboolean  recursive)
+ {
+   GList file_list;
+ 
+   _thunar_return_val_if_fail (G_IS_FILE (file), NULL);
+ 
+   file_list.data = g_object_ref (file);
+   file_list.next = NULL; 
+   file_list.prev = NULL;
+   
+   return thunar_simple_job_launch (_thunar_io_jobs_chown, 4,
+                                    THUNAR_TYPE_G_FILE_LIST, &file_list,
+                                    G_TYPE_INT, (gint) uid,
+                                    G_TYPE_INT, -1,
+                                    G_TYPE_BOOLEAN, recursive);
+ 
+   g_object_unref (file_list.data);
+ }
+ 
+ 
+ 
+ ThunarJob *
  thunar_io_jobs_change_group (GFile    *file,
                               guint32   gid,
                               gboolean  recursive)
diff -cr Thunar-1.4.0.org/thunar/thunar-io-jobs.h Thunar-1.4.0/thunar/thunar-io-jobs.h
*** Thunar-1.4.0.org/thunar/thunar-io-jobs.h	2012-04-28 22:16:39.000000000 +0200
--- Thunar-1.4.0/thunar/thunar-io-jobs.h	2012-08-27 12:43:09.000000000 +0200
***************
*** 38,43 ****
--- 38,46 ----
  ThunarJob *thunar_io_jobs_trash_files      (GList         *file_list) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
  ThunarJob *thunar_io_jobs_restore_files    (GList         *source_file_list,
                                              GList         *target_file_list) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+ ThunarJob *thunar_io_jobs_change_owner      (GFile         *file,
+                                             guint32        uid,
+                                             gboolean       recursive) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
  ThunarJob *thunar_io_jobs_change_group     (GFile         *file,
                                              guint32        gid,
                                              gboolean       recursive) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
diff -cr Thunar-1.4.0.org/thunar/thunar-permissions-chooser.c Thunar-1.4.0/thunar/thunar-permissions-chooser.c
*** Thunar-1.4.0.org/thunar/thunar-permissions-chooser.c	2012-04-28 22:16:39.000000000 +0200
--- Thunar-1.4.0/thunar/thunar-permissions-chooser.c	2012-08-27 13:50:01.000000000 +0200
***************
*** 62,67 ****
--- 62,75 ----
    PROP_MUTABLE,
  };
  
+ /* Column identifiers for the owner combo box */
+ enum
+ {
+   THUNAR_PERMISSIONS_STORE_OWNER_COLUMN_NAME,
+   THUNAR_PERMISSIONS_STORE_OWNER_COLUMN_UID,
+   THUNAR_PERMISSIONS_STORE_OWNER_N_COLUMNS,
+ };
+ 
  /* Column identifiers for the group combo box */
  enum
  {
***************
*** 93,98 ****
--- 101,108 ----
                                                                           GtkWidget                      *combo);
  static void                 thunar_permissions_chooser_file_changed     (ThunarPermissionsChooser       *chooser,
                                                                           ThunarFile                     *file);
+ static void                 thunar_permissions_chooser_owner_changed     (ThunarPermissionsChooser       *chooser,
+                                                                          GtkWidget                      *combo);
  static void                 thunar_permissions_chooser_group_changed    (ThunarPermissionsChooser       *chooser,
                                                                           GtkWidget                      *combo);
  static void                 thunar_permissions_chooser_program_toggled  (ThunarPermissionsChooser       *chooser,
***************
*** 115,120 ****
--- 125,133 ----
  static void                 thunar_permissions_chooser_job_start        (ThunarPermissionsChooser       *chooser,
                                                                           ThunarJob                      *job,
                                                                           gboolean                        recursive);
+ static gboolean             thunar_permissions_chooser_row_separator_owner    (GtkTreeModel                   *model,
+                                                                          GtkTreeIter                    *iter,
+                                                                          gpointer                        data);
  static gboolean             thunar_permissions_chooser_row_separator    (GtkTreeModel                   *model,
                                                                           GtkTreeIter                    *iter,
                                                                           gpointer                        data);
***************
*** 135,141 ****
    /* the main table widget, which contains everything but the job control stuff */
    GtkWidget  *table;
  
!   GtkWidget  *user_label;
    GtkWidget  *group_combo;
    GtkWidget  *access_combos[3];
    GtkWidget  *program_button;
--- 148,154 ----
    /* the main table widget, which contains everything but the job control stuff */
    GtkWidget  *table;
  
!   GtkWidget  *owner_combo;
    GtkWidget  *group_combo;
    GtkWidget  *access_combos[3];
    GtkWidget  *program_button;
***************
*** 237,247 ****
    gtk_table_attach (GTK_TABLE (chooser->table), hbox, 1, 2, row, row + 1, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 6);
    gtk_widget_show (hbox);
  
!   chooser->user_label = gtk_label_new (_("Unknown"));
!   gtk_misc_set_alignment (GTK_MISC (chooser->user_label), 0.0f, 0.5f);
!   gtk_box_pack_start (GTK_BOX (hbox), chooser->user_label, TRUE, TRUE, 0);
!   thunar_gtk_label_set_a11y_relation (GTK_LABEL (label), chooser->user_label);
!   gtk_widget_show (chooser->user_label);
  
    row += 1;
  
--- 250,264 ----
    gtk_table_attach (GTK_TABLE (chooser->table), hbox, 1, 2, row, row + 1, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 6);
    gtk_widget_show (hbox);
  
!   chooser->owner_combo = gtk_combo_box_new ();
!   gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (chooser->owner_combo), renderer_text, TRUE);
!   gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (chooser->owner_combo), renderer_text, "text", THUNAR_PERMISSIONS_STORE_OWNER_COLUMN_NAME);
!   gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (chooser->owner_combo), thunar_permissions_chooser_row_separator_owner, NULL, NULL);
!   exo_binding_new (G_OBJECT (chooser), "mutable", G_OBJECT (chooser->owner_combo), "sensitive");
!   g_signal_connect_swapped (G_OBJECT (chooser->owner_combo), "changed", G_CALLBACK (thunar_permissions_chooser_owner_changed), chooser);
!   gtk_table_attach (GTK_TABLE (chooser->table), chooser->owner_combo, 1, 2, row, row + 1, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
!   thunar_gtk_label_set_a11y_relation (GTK_LABEL (label), chooser->owner_combo);
!   gtk_widget_show (chooser->owner_combo);
  
    row += 1;
  
***************
*** 598,603 ****
--- 615,659 ----
  
  
  static void
+ thunar_permissions_chooser_change_owner (ThunarPermissionsChooser *chooser,
+                                          guint32                   uid)
+ {
+   ThunarJob *job;
+   gboolean   recursive = FALSE;
+   gint       response;
+ 
+   _thunar_return_if_fail (THUNAR_IS_PERMISSIONS_CHOOSER (chooser));
+   _thunar_return_if_fail (THUNAR_IS_FILE (chooser->file));
+ 
+   /* check if we should operate recursively */
+   if (thunar_file_is_directory (chooser->file))
+     {
+       response = thunar_permissions_chooser_ask_recursive (chooser);
+       switch (response)
+         {
+         case GTK_RESPONSE_YES:
+           recursive = TRUE;
+           break;
+ 
+         case GTK_RESPONSE_NO:
+           recursive = FALSE;
+           break;
+ 
+         default:  /* cancelled by the user */
+           thunar_file_changed (chooser->file);
+           return;
+         }
+     }
+ 
+   /* try to allocate the new job */
+   job = thunar_io_jobs_change_owner (thunar_file_get_file (chooser->file), uid, recursive);
+   thunar_permissions_chooser_job_start (chooser, job, recursive);
+   g_object_unref (job);
+ }
+ 
+ 
+ 
+ static void
  thunar_permissions_chooser_change_group (ThunarPermissionsChooser *chooser,
                                           guint32                   gid)
  {
***************
*** 718,723 ****
--- 774,811 ----
  
  
  static gint
+ user_compare (gconstpointer user_a,
+                gconstpointer user_b,
+                gpointer      user_primary)
+ {
+   guint32 user_primary_id = thunar_user_get_id (THUNAR_USER (user_primary));
+   guint32 user_a_id = thunar_user_get_id (THUNAR_USER (user_a));
+   guint32 user_b_id = thunar_user_get_id (THUNAR_USER (user_b));
+ 
+   /* check if the userss are equal */
+   if (user_a_id == user_b_id)
+     return 0;
+ 
+   /* the primary user is always sorted first */
+   if (user_a_id == user_primary_id)
+     return -1;
+   else if (user_b_id == user_primary_id)
+     return 1;
+ 
+   /* system users (< 100) are always sorted last */
+   if (user_a_id < 100 && user_b_id >= 100)
+     return 1;
+   else if (user_b_id < 100 && user_a_id >= 100)
+     return -1;
+ 
+   /* otherwise just sort by name */
+   return g_ascii_strcasecmp (thunar_user_get_name (THUNAR_USER (user_a)), 
+                              thunar_user_get_name (THUNAR_USER (user_b)));
+ }
+ 
+ 
+ 
+ static gint
  group_compare (gconstpointer group_a,
                 gconstpointer group_b,
                 gpointer      group_primary)
***************
*** 757,766 ****
--- 845,856 ----
    ThunarFileMode     mode;
    ThunarGroup       *group;
    ThunarUser        *user;
+   GtkListStore      *store_owner;
    GtkListStore      *store;
    GtkTreeIter        iter;
    const gchar       *user_name;
    const gchar       *real_name;
+   GList             *users;
    GList             *groups;
    GList             *lp;
    gchar              buffer[1024];
***************
*** 770,775 ****
--- 860,870 ----
    _thunar_return_if_fail (THUNAR_IS_FILE (file));
    _thunar_return_if_fail (chooser->file == file);
  
+   /* allocate a new store for the owner combo box */
+   g_signal_handlers_block_by_func (G_OBJECT (chooser->owner_combo), thunar_permissions_chooser_owner_changed, chooser);
+   store_owner = gtk_list_store_new (THUNAR_PERMISSIONS_STORE_OWNER_N_COLUMNS, G_TYPE_STRING, G_TYPE_UINT);
+   gtk_combo_box_set_model (GTK_COMBO_BOX (chooser->owner_combo), GTK_TREE_MODEL (store_owner));
+ 
    /* allocate a new store for the group combo box */
    g_signal_handlers_block_by_func (G_OBJECT (chooser->group_combo), thunar_permissions_chooser_group_changed, chooser);
    store = gtk_list_store_new (THUNAR_PERMISSIONS_STORE_N_COLUMNS, G_TYPE_STRING, G_TYPE_UINT);
***************
*** 779,784 ****
--- 874,941 ----
    user = thunar_file_get_user (file);
    if (G_LIKELY (user != NULL))
      {
+       /* check if we have superuser privileges */
+       if (G_UNLIKELY (geteuid () == 0))
+         {
+           /* determine all users in the system */
+           user_manager = thunar_user_manager_get_default ();
+           users = thunar_user_manager_get_all_users (user_manager);
+           g_object_unref (G_OBJECT (user_manager));
+         }
+       else
+         {
+           /* determine only the file owner */
+           users = g_list_prepend (users, g_object_ref (G_OBJECT (user)));
+         }
+ 
+       /* make sure that the user list includes the file owner */
+       if (G_UNLIKELY (g_list_find (users, user) == NULL))
+         users = g_list_prepend (users, g_object_ref (G_OBJECT (user)));
+ 
+       /* sort the users according to user_compare() */
+       users = g_list_sort_with_data (users, user_compare, user);
+ 
+       /* add the users to the store */
+       for (lp = users, n = 0; lp != NULL; lp = lp->next)
+         {
+           /* append a separator after the file owner and after the normal users (not system users) */
+           if (thunar_user_get_id (users->data) == thunar_user_get_id (user) 
+               && lp != users && n == 0)
+             {
+               gtk_list_store_append (store_owner, &iter);
+               n += 1;
+             }
+           else if (lp != users && thunar_user_get_id (lp->data) < 100 && n == 1)
+             {
+               gtk_list_store_append (store_owner, &iter);
+               n += 1;
+             }
+ 
+           /* determine sane display name for the file owner */
+           user_name = thunar_user_get_name (lp->data);
+           real_name = thunar_user_get_real_name (lp->data);
+           if (G_LIKELY (real_name != NULL))
+             g_snprintf (buffer, sizeof (buffer), "%s (%s)", real_name, user_name);
+           else
+             g_strlcpy (buffer, user_name, sizeof (buffer));
+ 
+           /* append a new item for the group */
+           gtk_list_store_append (store_owner, &iter);
+           gtk_list_store_set (store_owner, &iter,
+                               THUNAR_PERMISSIONS_STORE_OWNER_COLUMN_NAME, buffer,
+                               THUNAR_PERMISSIONS_STORE_OWNER_COLUMN_UID, thunar_user_get_id (lp->data),
+                               -1);
+ 
+           /* set the active iter for the combo box if this user is the file owner */
+           if (G_UNLIKELY (lp->data == user))
+             gtk_combo_box_set_active_iter (GTK_COMBO_BOX (chooser->owner_combo), &iter);
+         }
+ 
+       /* cleanup */
+       g_list_foreach (users, (GFunc) g_object_unref, NULL);
+       g_object_unref (G_OBJECT (user));
+       g_list_free (users);
+ 
        /* determine the group of the new file */
        group = thunar_file_get_group (file);
        if (G_LIKELY (group != NULL))
***************
*** 838,857 ****
            g_object_unref (G_OBJECT (group));
            g_list_free (groups);
          }
- 
-       /* determine sane display name for the owner */
-       user_name = thunar_user_get_name (user);
-       real_name = thunar_user_get_real_name (user);
-       if (G_LIKELY (real_name != NULL))
-         g_snprintf (buffer, sizeof (buffer), "%s (%s)", real_name, user_name);
-       else
-         g_strlcpy (buffer, user_name, sizeof (buffer));
-       gtk_label_set_text (GTK_LABEL (chooser->user_label), buffer);
-       g_object_unref (G_OBJECT (user));
-     }
-   else
-     {
-       gtk_label_set_text (GTK_LABEL (chooser->user_label), _("Unknown file owner"));
      }
  
    /* determine the file mode and update the combo boxes */
--- 995,1000 ----
***************
*** 890,895 ****
--- 1033,1039 ----
      }
  
    /* release our reference on the new combo store and unblock the combo */
+   g_signal_handlers_unblock_by_func (G_OBJECT (chooser->owner_combo), thunar_permissions_chooser_owner_changed, chooser);
    g_signal_handlers_unblock_by_func (G_OBJECT (chooser->group_combo), thunar_permissions_chooser_group_changed, chooser);
    g_object_unref (G_OBJECT (store));
  
***************
*** 900,905 ****
--- 1044,1081 ----
  
  
  static void
+ thunar_permissions_chooser_owner_changed (ThunarPermissionsChooser *chooser,
+                                           GtkWidget                *combo)
+ {
+   GtkTreeModel *model;
+   GtkTreeIter   iter;
+   guint32       uid;
+ 
+   _thunar_return_if_fail (THUNAR_IS_PERMISSIONS_CHOOSER (chooser));
+   _thunar_return_if_fail (chooser->user_combo == combo);
+   _thunar_return_if_fail (GTK_IS_COMBO_BOX (combo));
+ 
+   /* verify that we have a valid file */
+   if (G_UNLIKELY (chooser->file == NULL))
+     return;
+ 
+   /* determine the tree model from the combo box */
+   model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
+ 
+   /* determine the iterator for the selected item */
+   if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter))
+     {
+       /* determine the user id for the selected item... */
+       gtk_tree_model_get (model, &iter, THUNAR_PERMISSIONS_STORE_OWNER_COLUMN_UID, &uid, -1);
+ 
+       /* ...and try to change the user to the new uid */
+       thunar_permissions_chooser_change_owner (chooser, uid);
+     }
+ }
+ 
+ 
+ 
+ static void
  thunar_permissions_chooser_group_changed (ThunarPermissionsChooser *chooser,
                                            GtkWidget                *combo)
  {
***************
*** 1151,1156 ****
--- 1327,1352 ----
  }
  
  
+ 
+ static gboolean
+ thunar_permissions_chooser_row_separator_owner (GtkTreeModel *model,
+                                           GtkTreeIter  *iter,
+                                           gpointer      data)
+ {
+   gchar *name;
+ 
+   /* determine the value of the "name" column */
+   gtk_tree_model_get (model, iter, THUNAR_PERMISSIONS_STORE_OWNER_COLUMN_NAME, &name, -1);
+   if (G_LIKELY (name != NULL))
+     {
+       g_free (name);
+       return FALSE;
+     }
+ 
+   return TRUE;
+ }
+ 
+ 
  
  static gboolean
  thunar_permissions_chooser_row_separator (GtkTreeModel *model,
diff -cr Thunar-1.4.0.org/thunar/thunar-user.c Thunar-1.4.0/thunar/thunar-user.c
*** Thunar-1.4.0.org/thunar/thunar-user.c	2012-04-28 22:16:39.000000000 +0200
--- Thunar-1.4.0/thunar/thunar-user.c	2012-08-27 11:19:50.000000000 +0200
***************
*** 729,734 ****
--- 729,780 ----
  
  
  /**
+  * thunar_user_manager_get_all_users:
+  * @manager : a #ThunarUserManager.
+  *
+  * Returns the list of all #ThunarUser<!---->s in the system
+  * that are known to the @manager.
+  *
+  * The caller is responsible to free the returned list using:
+  * <informalexample><programlisting>
+  * g_list_foreach (list, (GFunc) g_object_unref, NULL);
+  * g_list_free (list);
+  * </programlisting></informalexample>
+  *
+  * Return value: the list of all users known to the @manager.
+  **/
+ GList*
+ thunar_user_manager_get_all_users (ThunarUserManager *manager)
+ {
+   ThunarUser  *user;
+   struct passwd *psw;
+   GList        *users = NULL;
+ 
+   g_return_val_if_fail (THUNAR_IS_USER_MANAGER (manager), NULL);
+ 
+   /* make sure we reload the users list */
+   endpwent ();
+ 
+   /* iterate through all users in the system */
+   for (;;)
+     {
+       /* lookup the next user */
+       psw = getpwent ();
+       if (G_UNLIKELY (psw == NULL))
+         break;
+ 
+       /* lookup our version of the user */
+       user = thunar_user_manager_get_user_by_id (manager, psw->pw_uid);
+       if (G_LIKELY (user != NULL))
+         users = g_list_append (users, user);
+     }
+ 
+   return users;
+ }
+ 
+ 
+ 
+ /**
   * thunar_user_manager_get_all_groups:
   * @manager : a #ThunarUserManager.
   *
diff -cr Thunar-1.4.0.org/thunar/thunar-user.h Thunar-1.4.0/thunar/thunar-user.h
*** Thunar-1.4.0.org/thunar/thunar-user.h	2012-04-28 22:16:39.000000000 +0200
--- Thunar-1.4.0/thunar/thunar-user.h	2012-08-27 11:28:19.000000000 +0200
***************
*** 81,86 ****
--- 81,88 ----
  ThunarUser        *thunar_user_manager_get_user_by_id  (ThunarUserManager *manager,
                                                          guint32            id) G_GNUC_WARN_UNUSED_RESULT;
  
+ GList             *thunar_user_manager_get_all_users   (ThunarUserManager *manager) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+ 
  GList             *thunar_user_manager_get_all_groups  (ThunarUserManager *manager) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
  
  G_END_DECLS;
