From e5aa4256d2e54218ea10406541ce9cc6cff59059 Mon Sep 17 00:00:00 2001
From: Benedikt Meurer <benny@xfce.org>
Date: Sun, 26 Jun 2005 01:12:14 +0000
Subject: [PATCH] 2005-06-26	Benedikt Meurer <benny@xfce.org>

	* thunar-vfs/thunar-vfs-uri.{c,h}: Don't use a GObject for the
	  ThunarVfsURI class. GObject is really overhead here, as we don't need
	  anything of whats provided by GObject.
	* TODO: Add note about missing GValue handling for ThunarVfsURI.
	* TODO: Add note to fix ThunarVfsInfo to not implicitly query the
	  link target.
	* thunar-vfs/*.[ch], thunar/*.[ch]: Use thunar_vfs_uri_unref() and
	  thunar_vfs_uri_ref() instead of g_object_unref() and g_object_ref(),
	  as ThunarVfsURI is no longer a GObject derived type.
	* thunar/thunar-window.c: Make loading new directories look and feel
	  "smoother". Still not perfect.




(Old svn revision: 16357)
---
 ChangeLog                          |  14 ++
 TODO                               |   6 +
 thunar-vfs/thunar-vfs-info.c       |   5 +-
 thunar-vfs/thunar-vfs-info.h       |   2 +-
 thunar-vfs/thunar-vfs-trash.c      |   2 +-
 thunar-vfs/thunar-vfs-uri.c        | 198 ++++++++++++++++++++++++-----
 thunar-vfs/thunar-vfs-uri.h        |  15 ++-
 thunar-vfs/thunar-vfs-volume-bsd.c |  11 +-
 thunar-vfs/thunar-vfs-volume.c     |  19 +--
 thunar/main.c                      |   2 +-
 thunar/thunar-computer-folder.c    |   9 +-
 thunar/thunar-details-view.c       |   1 +
 thunar/thunar-favourites-model.c   |   8 +-
 thunar/thunar-file.c               |  50 +++++++-
 thunar/thunar-icon-view.c          |   1 +
 thunar/thunar-local-file.c         |   2 +-
 thunar/thunar-local-folder.c       |   4 +-
 thunar/thunar-trash-file.c         |   8 +-
 thunar/thunar-trash-folder.c       |  12 +-
 thunar/thunar-window.c             | 110 ++++++++++++----
 20 files changed, 358 insertions(+), 121 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index d94fdee6f..10d8c6d76 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2005-06-26	Benedikt Meurer <benny@xfce.org>
+
+	* thunar-vfs/thunar-vfs-uri.{c,h}: Don't use a GObject for the
+	  ThunarVfsURI class. GObject is really overhead here, as we don't need
+	  anything of whats provided by GObject.
+	* TODO: Add note about missing GValue handling for ThunarVfsURI.
+	* TODO: Add note to fix ThunarVfsInfo to not implicitly query the
+	  link target.
+	* thunar-vfs/*.[ch], thunar/*.[ch]: Use thunar_vfs_uri_unref() and
+	  thunar_vfs_uri_ref() instead of g_object_unref() and g_object_ref(),
+	  as ThunarVfsURI is no longer a GObject derived type.
+	* thunar/thunar-window.c: Make loading new directories look and feel
+	  "smoother". Still not perfect.
+
 2005-06-25	Benedikt Meurer <benny@xfce.org>
 
 	* thunar/thunar-local-file.c: Use a static variable for the VFS monitor
diff --git a/TODO b/TODO
index 7ff80e5ff..0b8630b81 100644
--- a/TODO
+++ b/TODO
@@ -1,6 +1,12 @@
 Important for Thunar 1.0
 ========================
 
+ - Do NOT automatically determine the link target for ThunarVfsInfo objects.
+   Instead provide a method to do this on-demand.
+
+ - ThunarVfsURI should have it's own parameter specification, that
+   can be used for GValue handling.
+
  - The ThunarTrashFile constructor needs some rework, as it's currently
    mostly brain-dead. Should probably be splitted into several functions.
    In addition the ThunarTrashFile should enable the monitoring on the
diff --git a/thunar-vfs/thunar-vfs-info.c b/thunar-vfs/thunar-vfs-info.c
index f9d1c15de..ed135d377 100644
--- a/thunar-vfs/thunar-vfs-info.c
+++ b/thunar-vfs/thunar-vfs-info.c
@@ -62,12 +62,11 @@ thunar_vfs_info_query (ThunarVfsInfo  *info,
   g_return_val_if_fail (info->target == NULL, FALSE);
   g_return_val_if_fail (THUNAR_VFS_IS_URI (uri), FALSE);
 
-  g_object_ref (G_OBJECT (uri));
-  info->uri = uri;
+  info->uri = thunar_vfs_uri_ref (uri);
 
   if (thunar_vfs_info_update (info, error) == THUNAR_VFS_INFO_RESULT_ERROR)
     {
-      g_object_unref (G_OBJECT (info->uri));
+      thunar_vfs_uri_unref (uri);
       info->uri = NULL;
       return FALSE;
     }
diff --git a/thunar-vfs/thunar-vfs-info.h b/thunar-vfs/thunar-vfs-info.h
index 92e1b72c8..3ccd8085a 100644
--- a/thunar-vfs/thunar-vfs-info.h
+++ b/thunar-vfs/thunar-vfs-info.h
@@ -202,7 +202,7 @@ G_STMT_START {                                                              \
     }                                                                       \
   if (G_LIKELY ((info)->uri != NULL))                                       \
     {                                                                       \
-      g_object_unref (G_OBJECT ((info)->uri));                              \
+      thunar_vfs_uri_unref ((info)->uri);                                   \
       (info)->uri = NULL;                                                   \
     }                                                                       \
   (info)->type = THUNAR_VFS_FILE_TYPE_UNKNOWN;                              \
diff --git a/thunar-vfs/thunar-vfs-trash.c b/thunar-vfs/thunar-vfs-trash.c
index b1a1402b4..84d9c7567 100644
--- a/thunar-vfs/thunar-vfs-trash.c
+++ b/thunar-vfs/thunar-vfs-trash.c
@@ -561,7 +561,7 @@ thunar_vfs_trash_get_path (ThunarVfsTrash *trash,
  *
  * Generates a 'trash://' URI that refers to the @file in @trash.
  *
- * You'll need to call #g_object_unref() on the returned
+ * You'll need to call #thunar_vfs_uri_unref() on the returned
  * object when you are done with it.
  *
  * Return value: the generated #ThunarVfsURI.
diff --git a/thunar-vfs/thunar-vfs-uri.c b/thunar-vfs/thunar-vfs-uri.c
index 58b426bd7..c3d8feb02 100644
--- a/thunar-vfs/thunar-vfs-uri.c
+++ b/thunar-vfs/thunar-vfs-uri.c
@@ -35,15 +35,17 @@
 
 
 
-static void thunar_vfs_uri_class_init   (ThunarVfsURIClass  *klass);
-static void thunar_vfs_uri_init         (ThunarVfsURI       *uri);
-static void thunar_vfs_uri_finalize     (GObject            *object);
+static void thunar_vfs_uri_base_init      (ThunarVfsURIClass  *klass);
+static void thunar_vfs_uri_base_finalize  (ThunarVfsURIClass  *klass);
+#ifndef G_DISABLE_CHECKS
+static void thunar_vfs_uri_init           (ThunarVfsURI       *uri);
+#endif
 
 
 
 struct _ThunarVfsURIClass
 {
-  GObjectClass __parent__;
+  GTypeClass __parent__;
 
   const gchar *home_path;
   gchar       *localhost;
@@ -51,8 +53,9 @@ struct _ThunarVfsURIClass
 
 struct _ThunarVfsURI
 {
-  GObject __parent__;
+  GTypeInstance __parent__;
 
+  guint              ref_count;
   gchar             *host;
   gchar             *path;
   const gchar       *name;
@@ -70,47 +73,119 @@ static const gchar *scheme_names[] =
 
 
 
-G_DEFINE_TYPE (ThunarVfsURI, thunar_vfs_uri, G_TYPE_OBJECT);
+#ifndef G_DISABLE_CHECKS
+G_LOCK_DEFINE_STATIC (debug_uris);
+static GList *debug_uris = NULL;
+#endif
 
 
 
-static void
-thunar_vfs_uri_class_init (ThunarVfsURIClass *klass)
+GType
+thunar_vfs_uri_get_type (void)
 {
-  GObjectClass *gobject_class;
+  static GType type = G_TYPE_INVALID;
+
+  if (G_UNLIKELY (type == G_TYPE_INVALID))
+    {
+      static const GTypeFundamentalInfo finfo =
+      {
+        G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE
+      };
+
+      static const GTypeInfo info =
+      {
+        sizeof (ThunarVfsURIClass),
+        (GBaseInitFunc) thunar_vfs_uri_base_init,
+        (GBaseFinalizeFunc) thunar_vfs_uri_base_finalize,
+        NULL,
+        NULL,
+        NULL,
+        sizeof (ThunarVfsURI),
+        256u,
+#ifndef G_DISABLE_CHECKS
+        (GInstanceInitFunc) thunar_vfs_uri_init,
+#else
+        NULL,
+#endif
+        NULL,
+      };
+
+      type = g_type_register_fundamental (g_type_fundamental_next (), "ThunarVfsURI", &info, &finfo, 0);
+    }
+
+  return type;
+}
+
+
 
+static void
+thunar_vfs_uri_base_init (ThunarVfsURIClass *klass)
+{
   /* determine the path to the current user's homedir */
   klass->home_path = xfce_get_homedir ();
 
   /* determine the local host's name */
   klass->localhost = xfce_gethostname ();
-
-  gobject_class = G_OBJECT_CLASS (klass);
-  gobject_class->finalize = thunar_vfs_uri_finalize;
 }
 
 
 
 static void
-thunar_vfs_uri_init (ThunarVfsURI *uri)
+thunar_vfs_uri_base_finalize (ThunarVfsURIClass *klass)
 {
+  /* free class data */
+  g_free (klass->localhost);
 }
 
 
 
+#ifndef G_DISABLE_CHECKS
 static void
-thunar_vfs_uri_finalize (GObject *object)
+thunar_vfs_uri_atexit (void)
 {
-  ThunarVfsURI *uri = THUNAR_VFS_URI (object);
+  ThunarVfsURI *uri;
+  GList        *lp;
+  gchar        *s;
 
-  g_return_if_fail (THUNAR_VFS_IS_URI (uri));
+  G_LOCK (debug_uris);
 
-  if (G_UNLIKELY (uri->host != NULL))
-    g_free (uri->host);
-  g_free (uri->path);
+  if (G_UNLIKELY (debug_uris != NULL))
+    {
+      g_print ("--- Leaked a total of %u ThunarVfsURI objects:\n", g_list_length (debug_uris));
+
+      for (lp = debug_uris; lp != NULL; lp = lp->next)
+        {
+          uri = THUNAR_VFS_URI (lp->data);
+          s = thunar_vfs_uri_to_string (uri, 0);
+          g_print ("--> %s (%u)\n", s, uri->ref_count);
+          g_free (s);
+        }
+
+      g_print ("\n");
+    }
+
+  G_UNLOCK (debug_uris);
+}
+
+static void
+thunar_vfs_uri_init (ThunarVfsURI *uri)
+{
+  static gboolean registered = FALSE;
 
-  G_OBJECT_CLASS (thunar_vfs_uri_parent_class)->finalize (object);
+  G_LOCK (debug_uris);
+
+  /* register the check function to be called at program exit */
+  if (!registered)
+    {
+      g_atexit (thunar_vfs_uri_atexit);
+      registered = TRUE;
+    }
+
+  debug_uris = g_list_prepend (debug_uris, uri);
+
+  G_UNLOCK (debug_uris);
 }
+#endif
 
 
 
@@ -155,7 +230,8 @@ thunar_vfs_uri_new (const gchar *identifier,
         return NULL;
 
       /* allocate the URI instance */
-      uri = g_object_new (THUNAR_VFS_TYPE_URI, NULL);
+      uri = (ThunarVfsURI *) g_type_create_instance (THUNAR_VFS_TYPE_URI);
+      uri->ref_count = 1;
       uri->scheme = THUNAR_VFS_URI_SCHEME_FILE;
       uri->path = path;
 
@@ -202,7 +278,8 @@ thunar_vfs_uri_new (const gchar *identifier,
           }
 
       /* allocate the URI instance */
-      uri = g_object_new (THUNAR_VFS_TYPE_URI, NULL);
+      uri = (ThunarVfsURI *) g_type_create_instance (THUNAR_VFS_TYPE_URI);
+      uri->ref_count = 1;
       uri->scheme = THUNAR_VFS_URI_SCHEME_TRASH;
       uri->path = g_strdup ((*p == '/') ? p : "/");
     }
@@ -235,7 +312,8 @@ thunar_vfs_uri_new (const gchar *identifier,
           }
 
       /* allocate the URI instance */
-      uri = g_object_new (THUNAR_VFS_TYPE_URI, NULL);
+      uri = (ThunarVfsURI *) g_type_create_instance (THUNAR_VFS_TYPE_URI);
+      uri->ref_count = 1;
       uri->scheme = THUNAR_VFS_URI_SCHEME_COMPUTER;
       uri->path = g_strdup ((*p == '/') ? p : "/");
     }
@@ -277,7 +355,8 @@ thunar_vfs_uri_new_for_path (const gchar *path)
   g_return_val_if_fail (g_path_is_absolute (path), NULL);
 
   /* allocate the URI instance */
-  uri = g_object_new (THUNAR_VFS_TYPE_URI, NULL);
+  uri = (ThunarVfsURI *) g_type_create_instance (THUNAR_VFS_TYPE_URI);
+  uri->ref_count = 1;
   uri->scheme = THUNAR_VFS_URI_SCHEME_FILE;
   uri->path = g_strdup (path);
 
@@ -307,6 +386,64 @@ thunar_vfs_uri_new_for_path (const gchar *path)
 
 
 
+/**
+ * thunar_vfs_uri_ref:
+ * @uri : a #ThunarVfsURI instance.
+ *
+ * Increments the reference count on @uri by 1 and
+ * returns @uri.
+ *
+ * Return value: pointer to @uri.
+ **/
+ThunarVfsURI*
+thunar_vfs_uri_ref (ThunarVfsURI *uri)
+{
+  g_return_val_if_fail (THUNAR_VFS_IS_URI (uri), NULL);
+  g_return_val_if_fail (uri->ref_count > 0, NULL);
+
+  ++uri->ref_count;
+
+  return uri;
+}
+
+
+
+/**
+ * thunar_vfs_uri_unref:
+ * @uri : a #ThunarVfsURI instance.
+ *
+ * Decreases the reference count on @uri by 1. If the
+ * reference count drops to 0, the resources allocated
+ * for @uri will be freed.
+ **/
+void
+thunar_vfs_uri_unref (ThunarVfsURI *uri)
+{
+  g_return_if_fail (THUNAR_VFS_IS_URI (uri));
+  g_return_if_fail (uri->ref_count > 0);
+
+  if (--uri->ref_count == 0)
+    {
+#ifndef G_DISABLE_CHECKS
+      G_LOCK (debug_uris);
+      if (G_UNLIKELY (uri->host != NULL))
+        memset (uri->host, 0xaa, strlen (uri->host));
+      memset (uri->path, 0xaa, strlen (uri->path));
+      debug_uris = g_list_remove (debug_uris, uri);
+      G_UNLOCK (debug_uris);
+#endif
+
+      if (G_UNLIKELY (uri->host != NULL))
+        g_free (uri->host);
+
+      g_free (uri->path);
+
+      g_type_free_instance ((GTypeInstance *) uri);
+    }
+}
+
+
+
 /**
  * thunar_vfs_uri_is_home:
  * @uri : a #ThunarVfsURI instance.
@@ -483,7 +620,8 @@ thunar_vfs_uri_parent (ThunarVfsURI *uri)
     return NULL;
 
   /* allocate the new object */
-  parent = g_object_new (THUNAR_VFS_TYPE_URI, NULL);
+  parent = (ThunarVfsURI *) g_type_create_instance (THUNAR_VFS_TYPE_URI);
+  parent->ref_count = 1;
   parent->host = g_strdup (uri->host);
   parent->path = g_path_get_dirname (uri->path);
   parent->scheme = uri->scheme;
@@ -516,7 +654,8 @@ thunar_vfs_uri_relative (ThunarVfsURI *uri,
   g_return_val_if_fail (name != NULL, NULL);
 
   /* allocate the new object */
-  relative = g_object_new (THUNAR_VFS_TYPE_URI, NULL);
+  relative = (ThunarVfsURI *) g_type_create_instance (THUNAR_VFS_TYPE_URI);
+  relative->ref_count = 1;
   relative->host = g_strdup (uri->host);
   relative->path = g_build_filename (uri->path, name, NULL);
   relative->scheme = uri->scheme;
@@ -788,8 +927,6 @@ thunar_vfs_uri_list_to_string (GList                  *uri_list,
    */
   for (lp = uri_list; lp != NULL; lp = lp->next)
     {
-      g_assert (THUNAR_VFS_IS_URI (lp->data));
-
       uri_string = thunar_vfs_uri_to_string (THUNAR_VFS_URI (lp->data), hide_options);
       new_list = g_strconcat (string_list, uri_string, "\r\n", NULL);
       g_free (string_list);
@@ -815,10 +952,7 @@ thunar_vfs_uri_list_free (GList *uri_list)
   GList *lp;
 
   for (lp = uri_list; lp != NULL; lp = lp->next)
-    {
-      g_assert (THUNAR_VFS_IS_URI (lp->data));
-      g_object_unref (G_OBJECT (lp->data));
-    }
+    thunar_vfs_uri_unref (lp->data);
 
   g_list_free (uri_list);
 }
diff --git a/thunar-vfs/thunar-vfs-uri.h b/thunar-vfs/thunar-vfs-uri.h
index 70603fb6f..6590379eb 100644
--- a/thunar-vfs/thunar-vfs-uri.h
+++ b/thunar-vfs/thunar-vfs-uri.h
@@ -66,8 +66,11 @@ typedef enum
 GType              thunar_vfs_uri_get_type          (void) G_GNUC_CONST;
 
 ThunarVfsURI      *thunar_vfs_uri_new               (const gchar            *identifier,
-                                                     GError                **error);
-ThunarVfsURI      *thunar_vfs_uri_new_for_path      (const gchar            *path);
+                                                     GError                **error) G_GNUC_MALLOC;
+ThunarVfsURI      *thunar_vfs_uri_new_for_path      (const gchar            *path) G_GNUC_MALLOC;
+
+ThunarVfsURI      *thunar_vfs_uri_ref               (ThunarVfsURI           *uri);
+void               thunar_vfs_uri_unref             (ThunarVfsURI           *uri);
 
 gboolean           thunar_vfs_uri_is_home           (ThunarVfsURI           *uri);
 gboolean           thunar_vfs_uri_is_local          (ThunarVfsURI           *uri);
@@ -79,9 +82,9 @@ const gchar       *thunar_vfs_uri_get_name          (ThunarVfsURI           *uri
 const gchar       *thunar_vfs_uri_get_path          (ThunarVfsURI           *uri);
 ThunarVfsURIScheme thunar_vfs_uri_get_scheme        (ThunarVfsURI           *uri);
 
-ThunarVfsURI      *thunar_vfs_uri_parent            (ThunarVfsURI           *uri);
+ThunarVfsURI      *thunar_vfs_uri_parent            (ThunarVfsURI           *uri) G_GNUC_MALLOC;
 ThunarVfsURI      *thunar_vfs_uri_relative          (ThunarVfsURI           *uri,
-                                                     const gchar            *name);
+                                                     const gchar            *name) G_GNUC_MALLOC;
 
 gchar             *thunar_vfs_uri_to_string         (ThunarVfsURI           *uri,
                                                      ThunarVfsURIHideOptions hide_options);
@@ -98,9 +101,9 @@ gchar             *thunar_vfs_uri_list_to_string    (GList                  *uri
 void               thunar_vfs_uri_list_free         (GList                  *uri_list);
 
 #define thunar_vfs_uri_list_append(uri_list, uri) \
-  g_list_append ((uri_list), g_object_ref (G_OBJECT ((uri))))
+  g_list_append ((uri_list), thunar_vfs_uri_ref ((uri)))
 #define thunar_vfs_uri_list_prepend(uri_list, uri) \
-  g_list_prepend ((uri_list), g_object_ref (G_OBJECT ((uri))))
+  g_list_prepend ((uri_list), thunar_vfs_uri_ref ((uri)))
 
 G_END_DECLS;
 
diff --git a/thunar-vfs/thunar-vfs-volume-bsd.c b/thunar-vfs/thunar-vfs-volume-bsd.c
index a4246dcc8..0379cc721 100644
--- a/thunar-vfs/thunar-vfs-volume-bsd.c
+++ b/thunar-vfs/thunar-vfs-volume-bsd.c
@@ -54,7 +54,6 @@ enum
   PROP_KIND,
   PROP_NAME,
   PROP_STATUS,
-  PROP_MOUNT_POINT,
 };
 
 
@@ -128,10 +127,6 @@ thunar_vfs_volume_bsd_class_init (ThunarVfsVolumeBSDClass *klass)
   g_object_class_override_property (gobject_class,
                                     PROP_STATUS,
                                     "status");
-
-  g_object_class_override_property (gobject_class,
-                                    PROP_MOUNT_POINT,
-                                    "mount-point");
 }
 
 
@@ -162,7 +157,7 @@ thunar_vfs_volume_bsd_finalize (GObject *object)
   g_return_if_fail (THUNAR_VFS_IS_VOLUME_BSD (volume_bsd));
 
   if (G_LIKELY (volume_bsd->mount_point != NULL))
-    g_object_unref (G_OBJECT (volume_bsd->mount_point));
+    thunar_vfs_uri_unref (volume_bsd->mount_point);
   g_free (volume_bsd->device_path);
 
   G_OBJECT_CLASS (thunar_vfs_volume_bsd_parent_class)->finalize (object);
@@ -192,10 +187,6 @@ thunar_vfs_volume_bsd_get_property (GObject    *object,
       g_value_set_enum (value, thunar_vfs_volume_get_status (volume));
       break;
 
-    case PROP_MOUNT_POINT:
-      g_value_set_object (value, thunar_vfs_volume_get_mount_point (volume));
-      break;
-
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
diff --git a/thunar-vfs/thunar-vfs-volume.c b/thunar-vfs/thunar-vfs-volume.c
index c884f3354..aa957ee21 100644
--- a/thunar-vfs/thunar-vfs-volume.c
+++ b/thunar-vfs/thunar-vfs-volume.c
@@ -120,7 +120,7 @@ thunar_vfs_volume_class_init (gpointer klass)
                                                           _("The kind of the volume"),
                                                           THUNAR_VFS_TYPE_VFS_VOLUME_KIND,
                                                           THUNAR_VFS_VOLUME_KIND_UNKNOWN,
-                                                          G_PARAM_READABLE));
+                                                          EXO_PARAM_READABLE));
 
   /**
    * ThunarVfsVolume:name:
@@ -133,7 +133,7 @@ thunar_vfs_volume_class_init (gpointer klass)
                                                            _("Name"),
                                                            _("The name of the volume"),
                                                            NULL,
-                                                           G_PARAM_READABLE));
+                                                           EXO_PARAM_READABLE));
 
   /**
    * ThunarVfsVolume:status:
@@ -146,20 +146,7 @@ thunar_vfs_volume_class_init (gpointer klass)
                                                            _("Status"),
                                                            _("The status of the volume"),
                                                            THUNAR_VFS_TYPE_VFS_VOLUME_STATUS,
-                                                           0, G_PARAM_READABLE));
-
-  /**
-   * ThunarVfsVolume:mount-point:
-   *
-   * The path in the file system where this volume is mounted
-   * or will be mounted.
-   **/
-  g_object_interface_install_property (klass,
-                                       g_param_spec_object ("mount-point",
-                                                            _("Mount point"),
-                                                            _("The mount point of the volume"),
-                                                            THUNAR_VFS_TYPE_URI,
-                                                            G_PARAM_READABLE));
+                                                           0, EXO_PARAM_READABLE));
 }
 
 
diff --git a/thunar/main.c b/thunar/main.c
index 931b3491f..9b3ee446d 100644
--- a/thunar/main.c
+++ b/thunar/main.c
@@ -61,7 +61,7 @@ main (int argc, char **argv)
   if (G_LIKELY (uri != NULL))
     {
       file = thunar_file_get_for_uri (uri, &error);
-      g_object_unref (G_OBJECT (uri));
+      thunar_vfs_uri_unref (uri);
     }
 
   if (uri == NULL || file == NULL)
diff --git a/thunar/thunar-computer-folder.c b/thunar/thunar-computer-folder.c
index 15b31c73a..195cb1157 100644
--- a/thunar/thunar-computer-folder.c
+++ b/thunar/thunar-computer-folder.c
@@ -120,7 +120,7 @@ thunar_computer_folder_finalize (GObject *object)
   g_slist_free (computer_folder->files);
 
   /* release the folder's URI */
-  g_object_unref (G_OBJECT (computer_folder->uri));
+  thunar_vfs_uri_unref (computer_folder->uri);
 
   G_OBJECT_CLASS (thunar_computer_folder_parent_class)->finalize (object);
 }
@@ -217,7 +217,7 @@ thunar_computer_folder_get_files (ThunarFolder *folder)
               file = thunar_file_get_for_uri (uri, NULL);
               if (G_LIKELY (file != NULL))
                 computer_folder->files = g_slist_append (computer_folder->files, file);
-              g_object_unref (G_OBJECT (uri));
+              thunar_vfs_uri_unref (uri);
             }
         }
     }
@@ -259,10 +259,7 @@ thunar_computer_folder_new (ThunarVfsURI *uri,
 
   /* allocate the new object */
   computer_folder = g_object_new (THUNAR_TYPE_COMPUTER_FOLDER, NULL);
-  computer_folder->uri = uri;
-
-  /* take an additional reference on the uri */
-  g_object_ref (G_OBJECT (uri));
+  computer_folder->uri = thunar_vfs_uri_ref (uri);
 
   return THUNAR_FILE (computer_folder);
 }
diff --git a/thunar/thunar-details-view.c b/thunar/thunar-details-view.c
index bf2f41f37..ba35e6198 100644
--- a/thunar/thunar-details-view.c
+++ b/thunar/thunar-details-view.c
@@ -224,6 +224,7 @@ thunar_details_view_row_activated (GtkTreeView       *tree_view,
   gtk_tree_model_get_iter (model, &iter, path);
   file = thunar_list_model_get_file (THUNAR_LIST_MODEL (model), &iter);
   thunar_view_file_activated (THUNAR_VIEW (tree_view), file);
+  g_object_unref (G_OBJECT (file));
 
   /* invoke the row activated method on the parent class */
   if (GTK_TREE_VIEW_CLASS (thunar_details_view_parent_class)->row_activated != NULL)
diff --git a/thunar/thunar-favourites-model.c b/thunar/thunar-favourites-model.c
index 5f6b3bffb..c4ecd85af 100644
--- a/thunar/thunar-favourites-model.c
+++ b/thunar/thunar-favourites-model.c
@@ -189,7 +189,7 @@ thunar_favourites_model_init (ThunarFavouritesModel *model)
       thunar_favourites_model_add_favourite (model, favourite, path);
       gtk_tree_path_next (path);
     }
-  g_object_unref (G_OBJECT (uri));
+  thunar_vfs_uri_unref (uri);
 
   /* append the 'Trash' favourite */
   uri = thunar_vfs_uri_new ("trash:", NULL);
@@ -205,7 +205,7 @@ thunar_favourites_model_init (ThunarFavouritesModel *model)
       thunar_favourites_model_add_favourite (model, favourite, path);
       gtk_tree_path_next (path);
     }
-  g_object_unref (G_OBJECT (uri));
+  thunar_vfs_uri_unref (uri);
 
   /* append the 'Filesystem' favourite */
   uri = thunar_vfs_uri_new_for_path ("/");
@@ -221,7 +221,7 @@ thunar_favourites_model_init (ThunarFavouritesModel *model)
       thunar_favourites_model_add_favourite (model, favourite, path);
       gtk_tree_path_next (path);
     }
-  g_object_unref (G_OBJECT (uri));
+  thunar_vfs_uri_unref (uri);
 
   /* prepend the removable media volumes */
   volumes = thunar_vfs_volume_manager_get_volumes (model->volume_manager);
@@ -284,7 +284,7 @@ thunar_favourites_model_init (ThunarFavouritesModel *model)
 
           /* try to open the file corresponding to the uri */
           file = thunar_file_get_for_uri (uri, NULL);
-          g_object_unref (G_OBJECT (uri));
+          thunar_vfs_uri_unref (uri);
           if (G_UNLIKELY (file == NULL))
             continue;
 
diff --git a/thunar/thunar-file.c b/thunar/thunar-file.c
index 6654253e2..9a6f8a877 100644
--- a/thunar/thunar-file.c
+++ b/thunar/thunar-file.c
@@ -87,6 +87,7 @@ thunar_file_get_type (void)
         sizeof (ThunarFile),
         0,
         NULL,
+        NULL,
       };
 
       type = g_type_register_static (GTK_TYPE_OBJECT,
@@ -99,11 +100,51 @@ thunar_file_get_type (void)
 
 
 
+#ifndef G_DISABLE_CHECKS
+static gboolean thunar_file_atexit_registered = FALSE;
+
+static void
+thunar_file_atexit_foreach (gpointer key,
+                            gpointer value,
+                            gpointer user_data)
+{
+  gchar *s;
+
+  s = thunar_vfs_uri_to_string (THUNAR_VFS_URI (key), 0);
+  g_print ("--> %s (%u)\n", s, G_OBJECT (value)->ref_count);
+  g_free (s);
+}
+
+static void
+thunar_file_atexit (void)
+{
+  if (file_cache == NULL || g_hash_table_size (file_cache) == 0)
+    return;
+
+  g_print ("--- Leaked a total of %u ThunarFile objects:\n",
+           g_hash_table_size (file_cache));
+
+  g_hash_table_foreach (file_cache, thunar_file_atexit_foreach, NULL);
+
+  g_print ("\n");
+}
+#endif
+
+
+
 static void
 thunar_file_class_init (ThunarFileClass *klass)
 {
   GObjectClass *gobject_class;
 
+#ifndef G_DISABLE_CHECKS
+  if (G_UNLIKELY (!thunar_file_atexit_registered))
+    {
+      g_atexit (thunar_file_atexit);
+      thunar_file_atexit_registered = TRUE;
+    }
+#endif
+
   thunar_file_parent_class = g_type_class_peek_parent (klass);
 
   gobject_class = G_OBJECT_CLASS (klass);
@@ -189,7 +230,7 @@ thunar_file_real_get_parent (ThunarFile *file,
   parent_file = thunar_file_get_for_uri (parent_uri, error);
 
   /* release the reference on the parent_uri */
-  g_object_unref (G_OBJECT (parent_uri));
+  thunar_vfs_uri_unref (parent_uri);
 
   return parent_file;
 }
@@ -283,7 +324,7 @@ thunar_file_destroyed (gpointer data,
   g_hash_table_remove (file_cache, uri);
 
   /* drop the reference on the uri */
-  g_object_unref (G_OBJECT (uri));
+  thunar_vfs_uri_unref (uri);
 }
 
 
@@ -335,8 +376,7 @@ thunar_file_get_for_uri (ThunarVfsURI *uri,
 
           /* insert the file into the cache */
           g_object_weak_ref (G_OBJECT (file), thunar_file_destroyed, uri);
-          g_hash_table_insert (file_cache, uri, file);
-          g_object_ref (G_OBJECT (uri));
+          g_hash_table_insert (file_cache, thunar_vfs_uri_ref (uri), file);
         }
     }
   else
@@ -436,7 +476,7 @@ thunar_file_open_as_folder (ThunarFile *file,
  * Note, that there's no reference taken for the caller on the
  * returned #ThunarVfsURI, so if you need the object for a longer
  * period, you'll need to take a reference yourself using the
- * #g_object_ref() function.
+ * #thunar_vfs_uri_ref() function.
  *
  * Return value: the URI to the @file.
  **/
diff --git a/thunar/thunar-icon-view.c b/thunar/thunar-icon-view.c
index c5816f13b..b53fbd34f 100644
--- a/thunar/thunar-icon-view.c
+++ b/thunar/thunar-icon-view.c
@@ -127,6 +127,7 @@ thunar_icon_view_item_activated (ExoIconView *view,
   gtk_tree_model_get_iter (model, &iter, path);
   file = thunar_list_model_get_file (THUNAR_LIST_MODEL (model), &iter);
   thunar_view_file_activated (THUNAR_VIEW (view), file);
+  g_object_unref (G_OBJECT (file));
 
   /* invoke the item_activated method on the parent class */
   if (EXO_ICON_VIEW_CLASS (thunar_icon_view_parent_class)->item_activated != NULL)
diff --git a/thunar/thunar-local-file.c b/thunar/thunar-local-file.c
index 936c9e8af..dc5884482 100644
--- a/thunar/thunar-local-file.c
+++ b/thunar/thunar-local-file.c
@@ -159,7 +159,7 @@ thunar_local_file_get_parent (ThunarFile *file,
       if (G_LIKELY (computer_uri != NULL))
         {
           computer_file = thunar_file_get_for_uri (computer_uri, error);
-          g_object_unref (G_OBJECT (computer_uri));
+          thunar_vfs_uri_unref (computer_uri);
         }
       else
         {
diff --git a/thunar/thunar-local-folder.c b/thunar/thunar-local-folder.c
index 906650e71..f5a9f7741 100644
--- a/thunar/thunar-local-folder.c
+++ b/thunar/thunar-local-folder.c
@@ -198,7 +198,7 @@ thunar_local_folder_rescan (ThunarLocalFolder *local_folder,
           /* we discovered a new file */
           file_uri = thunar_vfs_uri_relative (folder_uri, name);
           file = thunar_file_get_for_uri (file_uri, NULL);
-          g_object_unref (G_OBJECT (file_uri));
+          thunar_vfs_uri_unref (file_uri);
 
           if (G_UNLIKELY (file == NULL))
             continue;
@@ -348,7 +348,7 @@ thunar_local_folder_get_for_file (ThunarLocalFile *local_file,
       /* try to scan the new folder */
       if (G_UNLIKELY (!thunar_local_folder_rescan (local_folder, error)))
         {
-          gtk_object_sink (GTK_OBJECT (local_folder));
+          g_object_unref (G_OBJECT (local_folder));
           return NULL;
         }
     }
diff --git a/thunar/thunar-trash-file.c b/thunar/thunar-trash-file.c
index 65d9f0e63..04481c3eb 100644
--- a/thunar/thunar-trash-file.c
+++ b/thunar/thunar-trash-file.c
@@ -121,7 +121,7 @@ thunar_trash_file_finalize (GObject *object)
   g_object_unref (G_OBJECT (trash_file->real_file));
   g_object_unref (G_OBJECT (trash_file->manager));
   g_object_unref (G_OBJECT (trash_file->trash));
-  g_object_unref (G_OBJECT (trash_file->uri));
+  thunar_vfs_uri_unref (trash_file->uri);
   g_free (trash_file->display_name);
 
   G_OBJECT_CLASS (thunar_trash_file_parent_class)->finalize (object);
@@ -279,8 +279,8 @@ thunar_trash_file_new (ThunarVfsURI *uri,
   if (G_UNLIKELY (real_file == NULL))
     {
       g_object_unref (G_OBJECT (trash_manager));
-      g_object_unref (G_OBJECT (real_uri));
       g_object_unref (G_OBJECT (trash));
+      thunar_vfs_uri_unref (real_uri);
       thunar_vfs_trash_info_free (info);
       g_free (path);
       return NULL;
@@ -291,7 +291,7 @@ thunar_trash_file_new (ThunarVfsURI *uri,
   trash_file->display_name = g_path_get_basename (thunar_vfs_trash_info_get_path (info));
   trash_file->manager = trash_manager;
   trash_file->real_file = real_file;
-  trash_file->uri = g_object_ref (G_OBJECT (uri));
+  trash_file->uri = thunar_vfs_uri_ref (uri);
   trash_file->trash = trash;
 
   /* watch the real file */
@@ -300,8 +300,8 @@ thunar_trash_file_new (ThunarVfsURI *uri,
   thunar_file_watch (real_file);
 
   /* cleanup */
-  g_object_unref (G_OBJECT (real_uri));
   thunar_vfs_trash_info_free (info);
+  thunar_vfs_uri_unref (real_uri);
   g_free (path);
 
   return THUNAR_FILE (trash_file);
diff --git a/thunar/thunar-trash-folder.c b/thunar/thunar-trash-folder.c
index d45d9814a..b32eae5f2 100644
--- a/thunar/thunar-trash-folder.c
+++ b/thunar/thunar-trash-folder.c
@@ -128,6 +128,9 @@ thunar_trash_folder_finalize (GObject *object)
   g_signal_handlers_disconnect_by_func (G_OBJECT (trash_folder->manager), thunar_file_changed, trash_folder);
   g_object_unref (G_OBJECT (trash_folder->manager));
 
+  /* release the trash URI */
+  thunar_vfs_uri_unref (trash_folder->uri);
+
   G_OBJECT_CLASS (thunar_trash_folder_parent_class)->finalize (object);
 }
 
@@ -145,7 +148,7 @@ thunar_trash_folder_get_parent (ThunarFile *file,
   if (G_LIKELY (computer_uri != NULL))
     {
       computer_file = thunar_file_get_for_uri (computer_uri, error);
-      g_object_unref (G_OBJECT (computer_uri));
+      thunar_vfs_uri_unref (computer_uri);
     }
   else
     {
@@ -267,7 +270,7 @@ thunar_trash_folder_get_files (ThunarFolder *folder)
               file = thunar_file_get_for_uri (uri, NULL);
               if (file != NULL)
                 trash_folder->files = g_slist_prepend (trash_folder->files, file);
-              g_object_unref (G_OBJECT (uri));
+              thunar_vfs_uri_unref (uri);
             }
           g_object_unref (G_OBJECT (trash));
         }
@@ -311,10 +314,7 @@ thunar_trash_folder_new (ThunarVfsURI *uri,
 
   /* allocate the new object */
   trash_folder = g_object_new (THUNAR_TYPE_TRASH_FOLDER, NULL);
-  trash_folder->uri = uri;
-
-  /* take an additional reference on the uri */
-  g_object_ref (G_OBJECT (uri));
+  trash_folder->uri = thunar_vfs_uri_ref (uri);
 
   return THUNAR_FILE (trash_folder);
 }
diff --git a/thunar/thunar-window.c b/thunar/thunar-window.c
index e7d381199..24e76fb48 100644
--- a/thunar/thunar-window.c
+++ b/thunar/thunar-window.c
@@ -39,25 +39,27 @@ enum
 
 
 
-static void thunar_window_class_init      (ThunarWindowClass  *klass);
-static void thunar_window_init            (ThunarWindow       *window);
-static void thunar_window_dispose         (GObject            *object);
-static void thunar_window_finalize        (GObject            *object);
-static void thunar_window_get_property    (GObject            *object,
-                                           guint               prop_id,
-                                           GValue             *value,
-                                           GParamSpec         *pspec);
-static void thunar_window_set_property    (GObject            *object,
-                                           guint               prop_id,
-                                           const GValue       *value,
-                                           GParamSpec         *pspec);
-static void thunar_window_action_close    (GtkAction          *action,
-                                           ThunarWindow       *window);
-static void thunar_window_action_go_up    (GtkAction          *action,
-                                           ThunarWindow       *window);
-static void thunar_window_file_activated  (ThunarView         *view,
-                                           ThunarFile         *file,
-                                           ThunarWindow       *window);
+static void     thunar_window_class_init          (ThunarWindowClass  *klass);
+static void     thunar_window_init                (ThunarWindow       *window);
+static void     thunar_window_dispose             (GObject            *object);
+static void     thunar_window_finalize            (GObject            *object);
+static void     thunar_window_get_property        (GObject            *object,
+                                                   guint               prop_id,
+                                                   GValue             *value,
+                                                   GParamSpec         *pspec);
+static void     thunar_window_set_property        (GObject            *object,
+                                                   guint               prop_id,
+                                                   const GValue       *value,
+                                                   GParamSpec         *pspec);
+static void     thunar_window_action_close        (GtkAction          *action,
+                                                   ThunarWindow       *window);
+static void     thunar_window_action_go_up        (GtkAction          *action,
+                                                   ThunarWindow       *window);
+static void     thunar_window_file_activated      (ThunarView         *view,
+                                                   ThunarFile         *file,
+                                                   ThunarWindow       *window);
+static gboolean thunar_window_cursor_idle         (gpointer            user_data);
+static void     thunar_window_cursor_idle_destroy (gpointer            user_data);
 
 
 
@@ -79,6 +81,8 @@ struct _ThunarWindow
   GtkWidget       *statusbar;
 
   ThunarFile      *current_directory;
+
+  gint             cursor_idle_id;
 };
 
 
@@ -152,6 +156,8 @@ thunar_window_init (ThunarWindow *window)
   GtkWidget       *swin;
   GtkWidget       *box;
 
+  window->cursor_idle_id = -1;
+
   window->action_group = gtk_action_group_new ("thunar-window");
   gtk_action_group_add_actions (window->action_group, action_entries,
                                 G_N_ELEMENTS (action_entries),
@@ -243,6 +249,10 @@ thunar_window_finalize (GObject *object)
 {
   ThunarWindow *window = THUNAR_WINDOW (object);
 
+  /* stop the reset cursor idle source */
+  if (G_UNLIKELY (window->cursor_idle_id >= 0))
+    g_source_remove (window->cursor_idle_id);
+
   g_object_unref (G_OBJECT (window->action_group));
   g_object_unref (G_OBJECT (window->ui_manager));
 
@@ -299,7 +309,7 @@ static void
 thunar_window_action_close (GtkAction    *action,
                             ThunarWindow *window)
 {
-  gtk_main_quit ();
+  gtk_object_destroy (GTK_OBJECT (window));
 }
 
 
@@ -336,6 +346,33 @@ thunar_window_file_activated (ThunarView   *view,
 
 
 
+static gboolean
+thunar_window_cursor_idle (gpointer user_data)
+{
+  GtkWidget *widget = user_data;
+
+  GDK_THREADS_ENTER ();
+
+  if (GTK_WIDGET_REALIZED (widget))
+    gdk_window_set_cursor (widget->window, NULL);
+
+  GDK_THREADS_LEAVE ();
+
+  return FALSE;
+}
+
+
+
+static void
+thunar_window_cursor_idle_destroy (gpointer user_data)
+{
+  GDK_THREADS_ENTER ();
+  THUNAR_WINDOW (user_data)->cursor_idle_id = -1;
+  GDK_THREADS_LEAVE ();
+}
+
+
+
 /**
  * thunar_window_new:
  *
@@ -385,6 +422,7 @@ thunar_window_set_current_directory (ThunarWindow *window,
   GtkAction       *action;
   GtkWidget       *dialog;
   GdkPixbuf       *icon;
+  GdkCursor       *cursor;
   GError          *error = NULL;
 
   g_return_if_fail (THUNAR_IS_WINDOW (window));
@@ -423,6 +461,12 @@ thunar_window_set_current_directory (ThunarWindow *window,
                     NULL);
     }
 
+  /* tell everybody that we have a new "current-directory",
+   * we do this first so other widgets display the new
+   * state already while the folder view is loading.
+   */
+  g_object_notify (G_OBJECT (window), "current-directory");
+
   /* setup the folder for the view, we use a simple but very effective
    * trick here to speed up the folder change: we completely disconnect
    * the model from the view, load the folder into the model and afterwards
@@ -436,6 +480,29 @@ thunar_window_set_current_directory (ThunarWindow *window,
   thunar_view_set_model (THUNAR_VIEW (window->view), NULL);
   if (G_LIKELY (current_directory != NULL))
     {
+      if (GTK_WIDGET_REALIZED (window))
+        {
+          /* set watch cursor */
+          cursor = gdk_cursor_new (GDK_WATCH);
+          gdk_window_set_cursor (GTK_WIDGET (window)->window, cursor);
+          gdk_cursor_unref (cursor);
+
+          /* be sure to display the watch cursor and the empty view
+           * (FIXME: This seems to cause some ugly flickering!)
+           */
+          while (gtk_events_pending ())
+            gtk_main_iteration ();
+
+          /* register an idle function to reset the cursor once
+           * everything below is done.
+           */
+          if (G_LIKELY (window->cursor_idle_id < 0))
+            {
+              window->cursor_idle_id = g_idle_add_full (G_PRIORITY_LOW + 100, thunar_window_cursor_idle,
+                                                        window, thunar_window_cursor_idle_destroy);
+            }
+        }
+
       /* try to open the directory */
       folder = thunar_file_open_as_folder (current_directory, &error);
       if (G_LIKELY (folder != NULL))
@@ -473,9 +540,6 @@ thunar_window_set_current_directory (ThunarWindow *window,
     }
   thunar_view_set_model (THUNAR_VIEW (window->view), model);
   g_object_unref (G_OBJECT (model));
-
-  /* tell everybody that we have a new "current-directory" */
-  g_object_notify (G_OBJECT (window), "current-directory");
 }
 
 
-- 
GitLab