diff --git a/ChangeLog b/ChangeLog
index d980ed7af1dbb121f42b6bf1c6d1a8f7883c77b2..991b82d663d1ede0ed8020ffed0e454b53f7bc48 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2008-11-29	Nick Schermer <nick@xfce.org>
+
+	* thunar/thunar-tree-model.c, thunar/thunar-tree-model.h,
+	  thunar/thunar-tree-view.c: Instead of unloading folders
+	  when their ref count is zero, we schedule a tree cleanup when
+	  a row is collapsed. The reason is simple: the reffing the
+	  treeview does is weird which results in glitches when scrolling
+	  a large tree.
+	  Also added some extra debug code.
+
 2008-11-28	Nick Schermer <nick@xfce.org>
 
 	* Revert pervious commit, not a good way to fix this.
diff --git a/thunar/thunar-tree-model.c b/thunar/thunar-tree-model.c
index e09a1b8765055a8c47eb5c1e44c1eddc24b0bbb9..94d8ffdcd8f1dca874a0a7e8f8f5f33872296b51 100644
--- a/thunar/thunar-tree-model.c
+++ b/thunar/thunar-tree-model.c
@@ -109,9 +109,8 @@ static gint                 thunar_tree_model_cmp_array               (gconstpoi
                                                                        gpointer                user_data);
 static void                 thunar_tree_model_sort                    (ThunarTreeModel        *model,
                                                                        GNode                  *node);
-static void                 thunar_tree_model_unload                  (ThunarTreeModel        *model);
-static gboolean             thunar_tree_model_unload_idle             (gpointer                user_data);
-static void                 thunar_tree_model_unload_idle_destroy     (gpointer                user_data);
+static gboolean             thunar_tree_model_cleanup_idle            (gpointer                user_data);
+static void                 thunar_tree_model_cleanup_idle_destroy    (gpointer                user_data);
 static void                 thunar_tree_model_file_changed            (ThunarFileMonitor      *file_monitor,
                                                                        ThunarFile             *file,
                                                                        ThunarTreeModel        *model);
@@ -148,7 +147,7 @@ static void                 thunar_tree_model_node_insert_dummy       (GNode
                                                                        ThunarTreeModel        *model);
 static void                 thunar_tree_model_node_drop_dummy         (GNode                  *node,
                                                                        ThunarTreeModel        *model);
-static gboolean             thunar_tree_model_node_traverse_unload    (GNode                  *node,
+static gboolean             thunar_tree_model_node_traverse_cleanup   (GNode                  *node,
                                                                        gpointer                user_data);
 static gboolean             thunar_tree_model_node_traverse_changed   (GNode                  *node,
                                                                        gpointer                user_data);
@@ -193,7 +192,7 @@ struct _ThunarTreeModel
 
   GNode                      *root;
 
-  guint                       unload_idle_id;
+  guint                       cleanup_idle_id;
 };
 
 struct _ThunarTreeModelItem
@@ -253,7 +252,7 @@ thunar_tree_model_get_type (void)
       type = g_type_register_static (G_TYPE_OBJECT, I_("ThunarTreeModel"), &info, 0);
       g_type_add_interface_static (type, GTK_TYPE_TREE_MODEL, &tree_model_info);
     }
-  
+
   return type;
 }
 
@@ -329,6 +328,7 @@ thunar_tree_model_init (ThunarTreeModel *model)
   model->sort_case_sensitive = TRUE;
   model->visible_func = (ThunarTreeModelVisibleFunc) exo_noop_true;
   model->visible_data = NULL;
+  model->cleanup_idle_id = 0;
 
   /* connect to the file monitor */
   model->file_monitor = thunar_file_monitor_get_default ();
@@ -381,9 +381,9 @@ thunar_tree_model_finalize (GObject *object)
   ThunarTreeModel *model = THUNAR_TREE_MODEL (object);
   GList           *lp;
 
-  /* remove unload idle */
-  if (model->unload_idle_id != 0)
-    g_source_remove (model->unload_idle_id);
+  /* remove the cleanup idle */
+  if (model->cleanup_idle_id != 0)
+    g_source_remove (model->cleanup_idle_id);
 
   /* disconnect from the file monitor */
   g_signal_handlers_disconnect_by_func (G_OBJECT (model->file_monitor), thunar_tree_model_file_changed, model);
@@ -800,8 +800,8 @@ thunar_tree_model_ref_node (GtkTreeModel *tree_model,
     }
   else
     {
-      /* schedule a reload of the folder if it is unloaded earlier */
-      if (item->ref_count == 0)
+      /* schedule a reload of the folder if it is cleaned earlier */
+      if (G_UNLIKELY (item->ref_count == 0))
         thunar_tree_model_item_load_folder (item);
 
       /* increment the reference count */
@@ -827,17 +827,14 @@ thunar_tree_model_unref_node (GtkTreeModel *tree_model,
   if (G_UNLIKELY (node == model->root))
     return;
 
-  /* check if this a non-dummy item */
+  /* check if this a non-dummy item, if so, decrement the reference count */
   item = node->data;
   if (G_LIKELY (item != NULL))
-    {
-      /* decrement the reference count */
-      item->ref_count -= 1;
+    item->ref_count -= 1;
 
-      /* schedule an unload of the tree if an item is released by the treeview */
-      if (G_UNLIKELY (item->ref_count == 0))
-        thunar_tree_model_unload (model);
-    }
+  /* NOTE: we don't cleanup nodes when the item ref count is zero,
+   * because GtkTreeView also does a lot of reffing when scrolling the
+   * tree, which results in all sorts for glitches */
 }
 
 
@@ -920,24 +917,8 @@ thunar_tree_model_sort (ThunarTreeModel *model,
 
 
 
-static void
-thunar_tree_model_unload (ThunarTreeModel *model)
-{
-  /* schedule an idle unload, if not already done */
-  if (model->unload_idle_id == 0)
-    {
-      /* the unload idle has a delay of 500 ms to make sure all the nodes
-       * are unreffed by the treeview. this allows the traverse unref work
-       * more efficiently */
-      model->unload_idle_id = g_timeout_add_full (G_PRIORITY_LOW, 500, thunar_tree_model_unload_idle,
-                                                  model, thunar_tree_model_unload_idle_destroy);
-    }
-}
-
-
-
 static gboolean
-thunar_tree_model_unload_idle (gpointer user_data)
+thunar_tree_model_cleanup_idle (gpointer user_data)
 {
   ThunarTreeModel *model = THUNAR_TREE_MODEL (user_data);
 
@@ -945,7 +926,7 @@ thunar_tree_model_unload_idle (gpointer user_data)
 
   /* walk through the tree and release all the nodes with a ref count of 0 */
   g_node_traverse (model->root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
-                   thunar_tree_model_node_traverse_unload, model);
+                   thunar_tree_model_node_traverse_cleanup, model);
 
   GDK_THREADS_LEAVE ();
 
@@ -955,9 +936,9 @@ thunar_tree_model_unload_idle (gpointer user_data)
 
 
 static void
-thunar_tree_model_unload_idle_destroy (gpointer user_data)
+thunar_tree_model_cleanup_idle_destroy (gpointer user_data)
 {
-  THUNAR_TREE_MODEL (user_data)->unload_idle_id = 0;
+  THUNAR_TREE_MODEL (user_data)->cleanup_idle_id = 0;
 }
 
 
@@ -1065,6 +1046,9 @@ thunar_tree_model_volume_changed (ThunarVfsVolume *volume,
             {
               /* try to determine the file for the mount point */
               item->file = thunar_file_get_for_path (thunar_vfs_volume_get_mount_point (volume), NULL);
+
+              /* because the volume node is already reffed, we need to load the folder manually here */
+              thunar_tree_model_item_load_folder (item);
             }
           else if (!thunar_vfs_volume_is_mounted (volume) && item->file != NULL)
             {
@@ -1298,8 +1282,10 @@ thunar_tree_model_item_reset (ThunarTreeModelItem *item)
 static void
 thunar_tree_model_item_load_folder (ThunarTreeModelItem *item)
 {
+  _thunar_return_if_fail (item->file != NULL || item->volume != NULL);
+
   /* schedule the "load" idle source (if not already done) */
-  if (G_LIKELY (item->folder == NULL && item->load_idle_id == 0))
+  if (G_LIKELY (item->load_idle_id == 0 && item->folder == NULL))
     {
       item->load_idle_id = g_idle_add_full (G_PRIORITY_HIGH, thunar_tree_model_item_load_idle,
                                             item, thunar_tree_model_item_load_idle_destroy);
@@ -1346,6 +1332,7 @@ thunar_tree_model_item_files_added (ThunarTreeModelItem *item,
       /* lookup the node for the item (on-demand) */
       if (G_UNLIKELY (node == NULL))
         node = g_node_find (model->root, G_POST_ORDER, G_TRAVERSE_ALL, item);
+      _thunar_return_if_fail (node != NULL);
 
       /* allocate a new item for the file */
       child_item = thunar_tree_model_item_new_with_file (model, file);
@@ -1408,6 +1395,7 @@ thunar_tree_model_item_files_removed (ThunarTreeModelItem *item,
 
   /* determine the node for the folder */
   node = g_node_find (model->root, G_POST_ORDER, G_TRAVERSE_ALL, item);
+  _thunar_return_if_fail (node != NULL);
 
   /* check if the node has any visible children */
   if (G_LIKELY (node->children != NULL))
@@ -1468,12 +1456,14 @@ thunar_tree_model_item_notify_loading (ThunarTreeModelItem *item,
 
   _thunar_return_if_fail (THUNAR_IS_FOLDER (folder));
   _thunar_return_if_fail (item->folder == folder);
+  _thunar_return_if_fail (THUNAR_IS_TREE_MODEL (item->model));
 
   /* be sure to drop the dummy child node once the folder is loaded */
   if (G_LIKELY (!thunar_folder_get_loading (folder)))
     {
       /* lookup the node for the item... */
       node = g_node_find (item->model->root, G_POST_ORDER, G_TRAVERSE_ALL, item);
+      _thunar_return_if_fail (node != NULL);
 
       /* ...and drop the dummy for the node */
       if (G_NODE_HAS_DUMMY (node))
@@ -1490,7 +1480,7 @@ thunar_tree_model_item_load_idle (gpointer user_data)
   GList               *files;
 
   _thunar_return_val_if_fail (item->folder == NULL, FALSE);
-  
+
 #ifndef NDEBUG
       /* find the node in the tree */
       GNode *node = g_node_find (item->model->root, G_POST_ORDER, G_TRAVERSE_ALL, item);
@@ -1581,7 +1571,7 @@ thunar_tree_model_node_drop_dummy (GNode           *node,
   GtkTreeIter  iter;
 
   _thunar_return_if_fail (THUNAR_IS_TREE_MODEL (model));
-  _thunar_return_if_fail (G_NODE_HAS_DUMMY (node));
+  _thunar_return_if_fail (G_NODE_HAS_DUMMY (node) && g_node_n_children (node) == 1);
 
   /* determine the iterator for the dummy */
   GTK_TREE_ITER_INIT (iter, model->stamp, node->children);
@@ -1613,8 +1603,8 @@ thunar_tree_model_node_drop_dummy (GNode           *node,
 
 
 static gboolean
-thunar_tree_model_node_traverse_unload (GNode *node,
-                                        gpointer user_data)
+thunar_tree_model_node_traverse_cleanup (GNode    *node,
+                                         gpointer  user_data)
 {
   ThunarTreeModelItem *item = node->data;
   ThunarTreeModel     *model = THUNAR_TREE_MODEL (user_data);
@@ -1693,6 +1683,8 @@ thunar_tree_model_node_traverse_remove (GNode   *node,
   GtkTreeIter      iter;
   GtkTreePath     *path;
 
+  _thunar_return_val_if_fail (node->children == NULL, FALSE);
+
   /* determine the iterator for the node */
   GTK_TREE_ITER_INIT (iter, model->stamp, node);
 
@@ -1967,3 +1959,26 @@ thunar_tree_model_refilter (ThunarTreeModel *model)
   g_node_traverse (model->root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
                    thunar_tree_model_node_traverse_visible, model);
 }
+
+
+
+/**
+ * thunar_tree_model_cleanup:
+ * @model : a #ThunarTreeModel.
+ *
+ * Walks all the folders in the #ThunarTreeModel and release them when
+ * they are unused by the treeview.
+ **/
+void
+thunar_tree_model_cleanup (ThunarTreeModel *model)
+{
+  _thunar_return_if_fail (THUNAR_IS_TREE_MODEL (model));
+
+  /* schedule an idle cleanup, if not already done */
+  if (model->cleanup_idle_id == 0)
+    {
+      model->cleanup_idle_id = g_timeout_add_full (G_PRIORITY_LOW, 500, thunar_tree_model_cleanup_idle,
+                                                   model, thunar_tree_model_cleanup_idle_destroy);
+    }
+}
+
diff --git a/thunar/thunar-tree-model.h b/thunar/thunar-tree-model.h
index a08f83f20bb20b74a0fdc766f2bafeee3d227759..e040dc5b2dcdd6f0650c20d3071d35ace932700b 100644
--- a/thunar/thunar-tree-model.h
+++ b/thunar/thunar-tree-model.h
@@ -70,6 +70,8 @@ void             thunar_tree_model_set_visible_func   (ThunarTreeModel
                                                        gpointer                    data);
 void             thunar_tree_model_refilter           (ThunarTreeModel            *model);
 
+void             thunar_tree_model_cleanup            (ThunarTreeModel            *model);
+
 G_END_DECLS;
 
 #endif /* !__THUNAR_TREE_MODEL_H__ */
diff --git a/thunar/thunar-tree-view.c b/thunar/thunar-tree-view.c
index 828b5418a47d35ecfc12a9f211e4b8cabb869ddf..def8d141d2c4e1077363b85ed557c72000ccf3c7 100644
--- a/thunar/thunar-tree-view.c
+++ b/thunar/thunar-tree-view.c
@@ -115,6 +115,9 @@ static void             thunar_tree_view_row_activated              (GtkTreeView
 static gboolean         thunar_tree_view_test_expand_row            (GtkTreeView          *tree_view,
                                                                      GtkTreeIter          *iter,
                                                                      GtkTreePath          *path);
+static void             thunar_tree_view_row_collapsed              (GtkTreeView          *tree_view,
+                                                                     GtkTreeIter          *iter,
+                                                                     GtkTreePath          *path);
 static gboolean         thunar_tree_view_delete_selected_files      (ThunarTreeView       *view);
 static void             thunar_tree_view_context_menu               (ThunarTreeView       *view,
                                                                      GdkEventButton       *event,
@@ -299,6 +302,7 @@ thunar_tree_view_class_init (ThunarTreeViewClass *klass)
   gtktree_view_class = GTK_TREE_VIEW_CLASS (klass);
   gtktree_view_class->row_activated = thunar_tree_view_row_activated;
   gtktree_view_class->test_expand_row = thunar_tree_view_test_expand_row;
+  gtktree_view_class->row_collapsed = thunar_tree_view_row_collapsed;
 
   klass->delete_selected_files = thunar_tree_view_delete_selected_files;
 
@@ -978,6 +982,17 @@ thunar_tree_view_test_expand_row (GtkTreeView *tree_view,
 
 
 
+static void
+thunar_tree_view_row_collapsed (GtkTreeView *tree_view,
+                                GtkTreeIter *iter,
+                                GtkTreePath *path)
+{
+  /* schedule a cleanup of the tree model */
+  thunar_tree_model_cleanup (THUNAR_TREE_VIEW (tree_view)->model);
+}
+
+
+
 static gboolean
 thunar_tree_view_delete_selected_files (ThunarTreeView *view)
 {